Implementing the Koch Curve?

混江龙づ霸主 提交于 2019-12-05 02:12:53

问题


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


回答1:


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;-).




回答2:


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!




回答3:


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



回答4:


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.



来源:https://stackoverflow.com/questions/932222/implementing-the-koch-curve

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!