我想在 Lindenmayer 系统中绘制矢量的路径。如何将函数应用于向量并获取要绘制的位置?

问题描述 投票:0回答:2

这是我关于堆栈溢出的第一个问题。我正在编写一个脚本来绘制 Lindenmayer 系统。我已经想出如何使用 turtle 包来完成它,但我想使用 matplotlib.pyplot 来完成 我有一个向量中的所有转角和向前移动

np.array[move,angle,move,angle,move,angle......]
向量的长度是迭代次数的函数。例如
L=1/3**N
,其中N是迭代次数,L是长度。 矢量的方向由

给出
d=np.dot(np.array([[cos(angle[i],-sin(angle[i])],sin(angle[i]),cos(angle[i])),d)

第一个d应该在哪里

np.array[1,0]

第一个位置是

x=(0,0)
然后
x=x+L*d
等等 但我无法正确迭代

我已经创建了几个脚本来让我的 LindenmayerSystem 变成我想要的矢量形式。

import numpy as np
import math
from math import cos, sin
import matplotlib.pyplot as plt
System="Koch"
N=1
def LindIter(System, N):

    if System == "Koch":
        LindenmayerString = "S"
        for i in range(N):
            newseq = ""
            for element in LindenmayerString:
                newseq = newseq + {"S": "SLSRSLS"}.get(element, element)
            LindenmayerString = newseq
    elif System == "Sierpinski":
        LindenmayerString = "A"
        for i in range(N):
            newseq = ""
            for element in LindenmayerString:
                newseq = newseq + {"A": "BRARB",
                                   "B": "ALBLA"}.get(element, element)
            LindenmayerString = newseq
        # replace("A",{"A":"BRARB","B":"ALBLA"},N)

    return LindenmayerString
def TurtleGraph(LindenmayerString):

    TC = ""
    if System == "Koch":
        x = np.asarray(list(LindenmayerString), dtype=object)
        x[x == "S"] = float(1/(3**N))
        x[x == "L"] = float(1/3*math.pi)
        x[x == "R"] = float(-2/3*math.pi)
        TurtleCommands = x.astype(float)
    elif System == "Sierpinski":
        x = np.asarray(list(LindenmayerString), dtype=object)
        x[x == "B"] = float(1/(2**N))
        x[x == "A"] = float(1/(2**N))
        x[x == "L"] = float(1/3*math.pi)
        x[x == "R"] = float(-1/3*math.pi)
        TurtleCommands = x.astype(float)
    return TurtleCommands

对于 1 次迭代的 Koch 系统,我现在想要的操作是这样的,但我想对其进行扩展,以便我可以进行更多迭代:

vector=np.array([1/3,1/3*math.pi,1/3,-2/3*math.pi,1/3,1/3*math.pi,1/3])
N=1
Rads=TurtleCommands[1::2]
d0=np.array([1,0])
d1=np.dot(np.array([[cos(Rads[0]),-sin(Rads[0])],[sin(Rads[0]),cos(Rads[0])]]),d0)
d2=np.dot(np.array([[cos(Rads[1]),-sin(Rads[1])],[sin(Rads[1]),cos(Rads[1])]]),d1)
d3=np.dot(np.array([[cos(Rads[2]),-sin(Rads[2])],[sin(Rads[2]),cos(Rads[2])]]),d2)
x0=(0,0)
x1=x0+1/3**N*d0
x2=x1+1/3**N*d1
x3=x2+1/3**N*d2
x4=x3+1/3**N*d3
plotvals=np.append(x0,(x1,x2,x3,x4))
x=plotvals[0::2]
y=plotvals[1::2]
plt.plot(x,y)
plt.show()
[Plot of first iteration](https://i.stack.imgur.com/9w6Cx.png)

在我尝试创建的许多函数中,我遇到了这个错误:

"    d=np.dot(np.array([[cos(Rads[i]),-sin(Rads[i])],[sin(Rads[i]),cos(Rads[i])]]),d)

IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices"

我希望有人能提供帮助,并且我的要求在这个精彩的论坛上是合理的。

numpy loops matplotlib math vector-graphics
2个回答
0
投票

我建议您可以立即创建一个图形点数组,而不是创建一个

TurtleCommands
数组,假设称为
Points
。我写了函数
TurtleGraph
,而不是函数
GraphPoints
,它实现了这个想法。我从维基百科 here.

获得了有关 Koch 和 Sierpinski Lindenmayer 系统的基本信息
import numpy as np
import math
from math import cos, sin
import matplotlib.pyplot as plt

def LindIter(System, N):

    if System == "Koch":
        LindenmayerString = "F"
        for i in range(N):
            newseq = ""
            for element in LindenmayerString:
                newseq = newseq + {"F": "F+F-F-F+F"}.get(element, element)
            LindenmayerString = newseq
    elif System == "Sierpinski":
        LindenmayerString = "F-G-G"
        for i in range(N):
            newseq = ""
            for element in LindenmayerString:
                newseq = newseq + {"F": "F-G+F+G-F",
                                   "G": "GG"}.get(element, element)
            LindenmayerString = newseq

    return LindenmayerString

def GraphPoints(System, N, LindenmayerString):
    L = 1 / 3 ** N
    X = np.array([0, 0])
    Points = np.array([X])
    if System == "Koch":
        alpha = 0
        for i in LindenmayerString:
            if i == 'F':
                X = X + L * np.array([cos(alpha), sin(alpha)])
                Points = np.append(Points, [X], axis=0)
            elif i == '+':
                alpha += math.pi/2
            elif i == '-':
                alpha -= math.pi/2
    elif System == "Sierpinski":
        alpha = 2/3 * math.pi
        for i in LindenmayerString:
            if i == 'F':
                X = X + L * np.array([cos(alpha), sin(alpha)])
                Points = np.append(Points, [X], axis=0)
            elif i == 'G':
                X = X + L * np.array([cos(alpha), sin(alpha)])
                Points = np.append(Points, [X], axis=0)
            elif i == '+':
                alpha += 2/3 * math.pi
            elif i == '-':
                alpha -= 2/3 * math.pi
    return Points


System = "Koch" # "Sierpinski"
N = 3
LindenmayerString = LindIter(System, N)
Points = GraphPoints(System, N, LindenmayerString)
plt.plot(Points[:,0],Points[:,1])
plt.show()

0
投票

我找到了如何做我想做的事,尽管有一些帮助功能。

def Get_d(TurtleCommands):
#the [1::2] slicer takes every second argument, starting from position 1
angles = TurtleCommands[1::2]
#our initial direction vector
d = np.array([1,0])
#Settining up a list to add vectors
dstart = [[1,0]]
#we apply the operation for calculating subsequent d's and append them
for theta in angles:
    d=list(np.dot(np.array([[cos(theta),-sin(theta)],[sin(theta),cos(theta)]]),d))
    dstart.append(d)
 
return dstart

然后我们得到积分:

def Get_x(dstart,System,N):
#setting first position
xstart = (0,0)
#initializing a list of points
points = [(0,0)]
#setting length scaling of vector
if System=="Koch":
    l=1/3**N
   
elif System=="Sierpinski":
    l=1/2**N

#the points[-1] takes the last set in points
#the [0]'s specify x coordinates and the [1]'s are y's
for i in range(len(dstart)):
     x = points[-1][0] + l * dstart[i][0]
     y = points[-1][1] + l * dstart[i][1]
     points.append((x,y))

return points

可以压缩或切片 :)

© www.soinside.com 2019 - 2024. All rights reserved.