3 Stimmen

Die Umsetzung der Koch-Kurve?

Ich habe mir die Wikipedia-Seite über die Koch-Schneeflocke angesehen ( hier ) und störte sich daran, dass alle Beispiele im Logo/Schildkrötenstil gehalten waren. Also machte ich mich auf den Weg, um mein eigenes Programm zu erstellen, das eine Liste oder Koordinaten zurückgibt.

Meine Implementierung ist in Python und ich im Grunde riss aus der Python-Schildkröte-Implementierung, aber ersetzt die Schildkröte-spezifischen Sachen mit grundlegenden trig. Das Ergebnis ist ein hässlicher Code. Meine Herausforderung für euch ist es, entweder meinen Code zu verbessern oder eine elligantere Lösung für euch selbst zu finden. Das kann in Python oder in Ihrer Lieblingssprache sein.

Mein 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: aufgrund von Faulheit beim Kopieren habe ich den Import vergessen

7voto

Alex Martelli Punkte 805329

Ich sehe es nicht als besonders hässlich an und würde es nur schrittweise überarbeiten, z.B. als ersten Schritt (ich habe die try/except weil ich nicht weiß, wogegen Sie sich wehren wollen... wenn es wieder reinkommen soll, sollte es etwas deutlicher sein, 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

Wenn ein zweiter Schritt gerechtfertigt wäre, würde ich diese Funktionalität wahrscheinlich in eine Klasse umwandeln, aber ich bin nicht sicher, ob das die Dinge wesentlich besser machen würde (oder überhaupt besser;-).

2voto

heltonbiker Punkte 24989

Ihre Frage hat mir so gut gefallen, dass ich eine Antwort darauf als neue Frage veröffentlicht habe, damit andere Leute sie verbessern können:

https://stackoverflow.com/questions/7420248

Ich habe kein Logo/Turtle-Zeug verwendet, auch keine Trigonometrie.

Herzlichen Glückwunsch, dass Sie der erste sind, der dieses Problem auf StackOverflow anspricht!

0voto

Per Alexandersson Punkte 2353

Mathematica ist besser, wenn es um mathematische Dinge geht:

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

0voto

cdlane Punkte 36658

Etwas, das Sie in Betracht ziehen sollten, wenn nicht für Ihre Implementierung, dann für das Testen Ihrer Implementierung, ist, dass Python turtle aufzeichnen kann, was es tut und Ihnen die Koordinaten zurückgibt. Sie verwenden begin_poly() y end_poly() um den Code, den Sie aufzeichnen möchten, und verwenden Sie dann get_poly() danach, um die Punkte zu bekommen.

In diesem Beispiel zeichne ich die Schneeflocke auf der Grundlage von Code von dieser Website Dann registriere ich diese Koordinaten wieder als neue Schildkrötenform, die ich nach dem Zufallsprinzip (und schnell) auf dem Bildschirm verteilen werde:

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()

Sie können den Stift während der Polygonerzeugung nach oben halten und die Schildkröte ausblenden, wenn Sie nicht möchten, dass dieser Schritt vom Benutzer gesehen wird.

enter image description here

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X