Реализация кривой Коха? - PullRequest
3 голосов
/ 31 мая 2009

Я просматривал страницу википедии о снежинке Кох ( здесь ) и был обеспокоен тем, что все примеры в стиле логотипа / черепахи. Поэтому я решил сделать свой собственный, который вернул список или координаты.

Моя реализация в python, и я в основном оторвал реализацию python turtle, но заменил материал, специфичный для turtle, базовым триггером. Это привело к некрасивому коду. Моя задача для вас - либо улучшить мой код, либо придумать более умное собственное решение. Это может быть на 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

РЕДАКТИРОВАТЬ: из-за ленивого копирования я забыл импорт

Ответы [ 4 ]

7 голосов
/ 31 мая 2009

Я не считаю это особенно уродливым, и я бы только рефакторинг его постепенно, например в качестве первого шага (я удалил 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

Если бы потребовался второй шаг, я бы, вероятно, свернул эту функциональность в класс, но я не уверен, что это значительно улучшит ситуацию (или, вообще, лучше; -).

2 голосов
/ 14 сентября 2011

Мне настолько понравился ваш вопрос, что я опубликовал ответ на него как новый вопрос, чтобы другие могли его улучшить:

https://stackoverflow.com/questions/7420248

Я не использовал ни логотип, ни черепаху, ни тригонометрию.

Поздравляю за то, что вы первым столкнулись с этой проблемой в StackOverflow!

0 голосов
/ 01 января 2017

Что нужно учитывать, если не для вашей реализации, то для тестирования вашей реализации, это то, что черепаха 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()

Вы можете скрыть перо и черепаху во время генерации многоугольника, если не хотите, чтобы этот шаг был виден пользователю.

enter image description here

0 голосов
/ 09 октября 2009

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