numpy 我想画出一个向量在林登迈尔系统中的路径,如何将函数应用于向量并获取要绘制的位置?

qlvxas9a  于 2023-05-07  发布在  其他
关注(0)|答案(2)|浏览(127)

这是我关于堆栈溢出的第一个问题。我正在写一个脚本来绘制一个林登迈尔系统。我已经知道如何使用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"

我希望有人可以帮助,我的要求是合理的,在这个美好的论坛。

sqxo8psd

sqxo8psd1#

我建议您不要创建TurtleCommands数组,而是可以立即创建一个图形点数组,例如称为Points。我写了函数GraphPoints来代替函数TurtleGraph,它实现了这个想法。我从Wikipedia 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()
jc3wubiy

jc3wubiy2#

我发现了如何做我想做的事情,虽然有一些帮助功能。

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

而且可以压缩或切片它们:)

相关问题