实施科赫曲线?

发布于 2024-07-23 06:48:01 字数 957 浏览 4 评论 0原文

我正在查看科赫雪花的维基百科页面(此处),并被所有这些例子都是标志/海龟风格的。 所以我开始制作自己的返回列表或坐标的组件。

我的实现是用Python编写的,我基本上删除了Python海龟的实现,但用基本的三角函数替换了海龟特定的东西。 它导致了一些丑陋的代码。 我对您的挑战是要么改进我的代码,要么提出您自己的更巧妙的解决方案。 它可以是Python,也可以是你最喜欢的语言。

我的代码:

from math import sin, cos, radians

def grow(steps, length = 200, startPos = (0,0)):
    angle = 0
    try:
        jump = float(length) / (3 ** steps)
    except:
        jump = length

    set="F"
    for i in xrange(steps): set=set.replace("F", "FLFRFLF")

    coords = [startPos]
    for move in set:
        if move is "F": 
            coords.append(
              (coords[-1][0] + jump * cos(angle),
               coords[-1][1] + jump * sin(angle)))
        if move is "L":
            angle += radians(60)
        if move is "R":
            angle -= radians(120)

    return coords

编辑:由于懒惰复制,我忘记了导入

I was looking at the wikipedia page for the Koch Snowflake (here) and was bothered by the all the examples all being in the logo/turtle style. So i set out to make my own that returned a list or coordinates.

My implementation is in python and i basically ripped off the python turtle implementation but replaced the turtle specific stuff with basic trig. It resulted in some ugly code. My challenge for you is to either improve my code or come up with a more elligant solution of your own. It can be in python, or your favorite language.

My Code:

from math import sin, cos, radians

def grow(steps, length = 200, startPos = (0,0)):
    angle = 0
    try:
        jump = float(length) / (3 ** steps)
    except:
        jump = length

    set="F"
    for i in xrange(steps): set=set.replace("F", "FLFRFLF")

    coords = [startPos]
    for move in set:
        if move is "F": 
            coords.append(
              (coords[-1][0] + jump * cos(angle),
               coords[-1][1] + jump * sin(angle)))
        if move is "L":
            angle += radians(60)
        if move is "R":
            angle -= radians(120)

    return coords

EDIT: due to lazy copying, i forgot the import

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

于我来说 2024-07-30 06:48:02

Mathematica 在数学方面表现出色:

points = {{0.0, 1.0}};
koch[pts_] := Join[
    pts/3,
    (RotationMatrix[60 Degree].#/3 + {1/3, 0}) & /@ pts,
    (RotationMatrix[-60 Degree].#/3 + {1/2, 1/Sqrt[12]}) & /@ pts,
    (#/3 + {2/3, 0}) & /@ pts
];
Graphics[Line[Nest[koch, points, 5]], PlotRange -> {{0, 1}, {0, 0.3}}] //Print

Mathematica is superior when it comes to math stuff:

points = {{0.0, 1.0}};
koch[pts_] := Join[
    pts/3,
    (RotationMatrix[60 Degree].#/3 + {1/3, 0}) & /@ pts,
    (RotationMatrix[-60 Degree].#/3 + {1/2, 1/Sqrt[12]}) & /@ pts,
    (#/3 + {2/3, 0}) & /@ pts
];
Graphics[Line[Nest[koch, points, 5]], PlotRange -> {{0, 1}, {0, 0.3}}] //Print
∞觅青森が 2024-07-30 06:48:02

如果不是为了您的实现,那么为了测试您的实现,需要考虑的是 Python 海龟可以记录它正在做什么并返回坐标。 您可以在要记录的代码周围使用 begin_poly()end_poly(),然后使用 get_poly() 来获取点。

在此示例中,我将根据此站点的代码绘制雪花然后将这些坐标注册回新的海龟形状,我将随机(快速)在屏幕上标记它:

import turtle
from random import random, randrange

def koch_curve(turtle, steps, length):
    if steps == 0:
        turtle.forward(length)
    else:
        for angle in [60, -120, 60, 0]:
            koch_curve(turtle, steps - 1, length / 3)
            turtle.left(angle)

def koch_snowflake(turtle, steps, length):
    turtle.begin_poly()

    for _ in range(3):
        koch_curve(turtle, steps, length)
        turtle.right(120)

    turtle.end_poly()

    return turtle.get_poly()

turtle.speed("fastest")

turtle.register_shape("snowflake", koch_snowflake(turtle.getturtle(), 3, 100))

turtle.reset()

turtle.penup()

turtle.shape("snowflake")

width, height = turtle.window_width() / 2, turtle.window_height() / 2

for _ in range(24):
    turtle.color((random(), random(), random()), (random(), random(), random()))
    turtle.goto(randrange(-width, width), randrange(-height, height))
    turtle.stamp()

turtle.done()

如果您不希望用户看到此步骤,则可以在多边形生成过程中将笔抬起并隐藏海龟。

输入图片此处描述

Something to consider, if not for your implementation then for testing your implementation, is that Python turtle can record what it's doing and give you back the coordinates. You use begin_poly() and end_poly() around the code you want to record and then use get_poly() afterwards to get the points.

In this example, I'll draw the snowflake based on code from this site then register those coordinates back as a new turtle shape that I'll randomly (and quickly) stamp about the screen:

import turtle
from random import random, randrange

def koch_curve(turtle, steps, length):
    if steps == 0:
        turtle.forward(length)
    else:
        for angle in [60, -120, 60, 0]:
            koch_curve(turtle, steps - 1, length / 3)
            turtle.left(angle)

def koch_snowflake(turtle, steps, length):
    turtle.begin_poly()

    for _ in range(3):
        koch_curve(turtle, steps, length)
        turtle.right(120)

    turtle.end_poly()

    return turtle.get_poly()

turtle.speed("fastest")

turtle.register_shape("snowflake", koch_snowflake(turtle.getturtle(), 3, 100))

turtle.reset()

turtle.penup()

turtle.shape("snowflake")

width, height = turtle.window_width() / 2, turtle.window_height() / 2

for _ in range(24):
    turtle.color((random(), random(), random()), (random(), random(), random()))
    turtle.goto(randrange(-width, width), randrange(-height, height))
    turtle.stamp()

turtle.done()

You can have the pen up and turtle hidden during polygon generation if you don't want this step to be seen by the user.

enter image description here

一萌ing 2024-07-30 06:48:01

我不认为它特别难看,我只会逐步重构它,例如作为第一步(我删除了 try/ except 因为我不知道你在尝试什么防止......如果它需要返回它应该更明确一点,恕我直言):

import math

angles = [math.radians(60*x) for x in range(6)]
sines = [math.sin(x) for x in angles]
cosin = [math.cos(x) for x in angles]

def L(angle, coords, jump):
    return (angle + 1) % 6
def R(angle, coords, jump):
    return (angle + 4) % 6
def F(angle, coords, jump):
    coords.append(
        (coords[-1][0] + jump * cosin[angle],
         coords[-1][1] + jump * sines[angle]))
    return angle

decode = dict(L=L, R=R, F=F)

def grow(steps, length=200, startPos=(0,0)):
    pathcodes="F"
    for i in xrange(steps):
        pathcodes = pathcodes.replace("F", "FLFRFLF")

    jump = float(length) / (3 ** steps)
    coords = [startPos]
    angle = 0

    for move in pathcodes:
        angle = decode[move](angle, coords, jump)

    return coords

如果有必要采取第二步,我可能会将此功能汇总到一个类中,但我不确定这是否会让事情变得更好(或者,实际上更好;-)。

I don't see it as particularly ugly and I'd only refactor it incrementally, e.g. as a first step (I've removed the try/except because I don't know what you're trying to ward against... if it needs to get back in it should be a bit more explicit, IMHO):

import math

angles = [math.radians(60*x) for x in range(6)]
sines = [math.sin(x) for x in angles]
cosin = [math.cos(x) for x in angles]

def L(angle, coords, jump):
    return (angle + 1) % 6
def R(angle, coords, jump):
    return (angle + 4) % 6
def F(angle, coords, jump):
    coords.append(
        (coords[-1][0] + jump * cosin[angle],
         coords[-1][1] + jump * sines[angle]))
    return angle

decode = dict(L=L, R=R, F=F)

def grow(steps, length=200, startPos=(0,0)):
    pathcodes="F"
    for i in xrange(steps):
        pathcodes = pathcodes.replace("F", "FLFRFLF")

    jump = float(length) / (3 ** steps)
    coords = [startPos]
    angle = 0

    for move in pathcodes:
        angle = decode[move](angle, coords, jump)

    return coords

If a second step was warranted I'd probably roll this functionality up into a class, but I'm not sure that would make things substantially better (or, better at all, in fact;-).

伴梦长久 2024-07-30 06:48:01

我非常喜欢你的问题,所以我将其答案作为一个新问题发布,以便其他人可以改进它:

https://stackoverflow。 com/questions/7420248

我没有使用 Logo/Turtle 的东西,也没有使用三角学。

恭喜您成为第一个将此问题提交到 StackOverflow 的人!

I liked your question so much that I posted an answer to it as a new question, so that other people could improve it:

https://stackoverflow.com/questions/7420248

I used no Logo/Turtle stuff, neither trigonometry.

Congrats for being the first one bringing this problem to StackOverflow!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文