【问题标题】:Koch Snowflake in Python won't workPython中的科赫雪花不起作用
【发布时间】:2014-06-19 13:15:38
【问题描述】:

我遇到了这个 Python 程序的问题。它应该用 n 次迭代绘制一个 Koch-Snowflake。代码可以编译,但它不会画雪花,我找不到我的错误。

如果有人能帮我解决这个问题,我将非常感激!

from math import sqrt
from matplotlib import pyplot as plt

class vector:
    def __init__(self,one,two):
        self.x = one
        self.y = two

    def printV(self):
        s = "(" + str(self.x) + "," + str(self.y) + ")"
        print s

    def __len__(self):
        l = sqrt(self.x**2 + self.y**2)
        return l

def kochSnowflakeImpl(p1,p2):
    u = vector(p1.x + p2.x - p1.x, p1.y + p2.y - p1.y)
    array = []

    #calculate n1
    n1 = vector(p1.x + 1.0/3.0 * u.x, p1.y + (1.0/3.0) * u.y)

    #calculate n2
    n2 = vector(p1.x + 2.0/3.0 * u.x,p1.y + 2.0/3.0 * u.y)

    v = vector(n1.y + n2.y - n1.y, -(n1.x + n2.x - n1.x)) #is an  orthogonal vector to u

    #calculate n3
    n3 = vector(n1.x + 0.5*u.x + sqrt(3.0)/2.0 * v.x, p1.y + 0.5*u.y + sqrt(3.0)/2.0* v.y)

    array.append([n1.x,n1.y])
    array.append([n2.x,n2.y])
    array.append([n3.x,n3.y])
    return n1,n2,n3,array

def kochSnowflake(level):
    p1 = vector(0,0) #format: p = (x,y)
    p2 = vector(1,0)
    p3 = vector(0.5,sqrt(3)/2)
    array = [[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y],[p1.x,p1.y]]

    while level > 0:
        if level == 1:
            n1,n2,n3,array1 = kochSnowflakeImpl(p1,p2)
            n4,n5,n6,array2 = kochSnowflakeImpl(p2,p3)
            n7,n8,n9,array3 = kochSnowflakeImpl(p3,p2)
            for i in array1:
                array.append(i)
            for j in array2:
                array.append(j)
            for k in array3:
                array.append(k)
        else:
            n1,n2,n3,array1 = kochSnowflakeImpl(p1,p2)
            n11,n21,n31,array11 = kochSnowflakeImpl(n1,n3)
            n12,n22,n32,array12 = kochSnowflakeImpl(n3,n2)

            n4,n5,n6,array2 = kochSnowflakeImpl(p2,p3)
            n41,n52,n61,array21 = kochSnowflakeImpl(n4,n6)
            n42,n52,n62,array22 = kochSnowflakeImpl(n6,n5)

            n7,n8,n9,array3 = kochSnowflakeImpl(p1,p3)
            n71,n81,n91,array31 = kochSnowflakeImpl(n7,n9)
            n72,n82,n92,array32 = kochSnowflakeImpl(n9,n8)

            for i in array1:
                array.append(i)
            for i in array11:
                array.append(i)
            for i in array12:
                array.append(i)
            for j in array2:
                array.append(j)
            for j in array21:
                array.append(j)
            for j in array22:
                array.append(j)
            for k in array3:
                array.append(k)
            for k in array31:
                array.append(k)
            for k in array32:
                array.append(k)
        level -= 1
    return array

if __name__=='__main__':
    points = kochSnowflake(5)
    x,y = zip(*points)
    plt.plot(x, y)
    plt.show()

【问题讨论】:

  • 你做了哪些测试?什么有效,什么无效? xy 是否包含正确的值(也可以只使用 x, y = zip(*points))?
  • 您的代码中的缩进不正确 - 所以不要写 "I really hope the code indentation is still correct" 而是更正它。
  • 如果您在论坛格式化时遇到问题 - 在您的编辑器中格式化(使用 4 个空格代替制表符)并复制粘贴正确的版本。
  • @jonrsharpe:我没有做过任何真正的测试,因为我不知道我该怎么做。我没有一个函数可以生成所有需要的点,我可以用它来检查我的结果。如果我的计算有效,我 x 和 y 应该包含正确的值。似乎正在工作的是将我的初始三角形的边分成 3 个等长的部分 - 所以主要问题可能是计算“角落”并正确绘制它,即删除中间部分。我确实可以使用 'x,y = zip(*points)' 并绘制相同的内容。感谢您的回复!
  • @furas:我编辑了代码。感谢您让我知道这是错误的。

标签: python matplotlib fractals


【解决方案1】:

我决定是时候将这段代码的输出从 70 年代的一段糟糕的弦乐艺术变成科赫雪花的时候了。

一个问题是 OP 在kochSnowflakeImpl() 中向数组添加了新点,但忘记添加原始起点和终点。下一个问题是n3 计算,因为相加得出每个坐标的两项来自同一个坐标,而一项应该来自另一个坐标。而kochSnowflake() 中的关卡逻辑是无望的。

为了简化代码,我抛弃了 OP 的 vector 类(这是合理的),并用 Python turtle 替换了更完整的 Vec2D 类:

from turtle import Vec2D
from matplotlib import pyplot as plt

SQRT_3 = 3.0 ** 0.5

def kochSnowflakeImpl(p1, p2):
    u = p2 - p1
    v = Vec2D(-u[1], u[0])

    n1 = p1 + u * (1.0 / 3.0)
    n2 = n1 + u * (1.0 / 6.0) + v * (SQRT_3 / 6.0)
    n3 = p1 + u * (2.0 / 3.0)

    return [p1, n1, n2, n3, p2]

def kochSnowflake(level):
    p1 = Vec2D(0.0, 0.0)
    p2 = Vec2D(0.5, SQRT_3 / 2.0)
    p3 = Vec2D(1.0, 0.0)

    array = [p1, p2, p3, p1]

    for _ in range(level):
        new_array = []

        for (p1, p2) in zip(array, array[1:]):
            new_array.extend(kochSnowflakeImpl(p1, p2))

        array = new_array

    return array

if __name__ == '__main__':
    points = kochSnowflake(4)
    x, y = zip(*points)
    plt.plot(x, y)
    plt.show()

我认为这段代码不太正确,因为雪花看起来有点矮,但我相信它达到了原始代码的目标,并且足够干净,可以在此基础上进行构建。

【讨论】:

  • 把轴设为相等会更好看
猜你喜欢
  • 2017-09-03
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
  • 2022-01-12
  • 2022-10-15
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
相关资源
最近更新 更多