需求
写一个maya插(wǎn)件(jv),生成如下分形
实现
通过维基百科,我们知道Sierpinski triangle有许多种生成方式。
其中L系统生成法仅用一条曲线:
变数:A , B
常数:+ , -
公理:A
规则:A → B-A-B, B → A+B+A
- A, B : 向前
- - : 左转60°
- + : 右转60°
我的理解:
L系统生成的谢尔宾斯基三角就是一条曲线。初始时,我们叫它A,一条向前(在我的代码中,角度为0的向前=向右)的曲线。
经过2次迭代,曲线A变成+B-A-B,也就是一条+60°、向前延申、-60°、向前、-60°、向前的曲线BAB。
经过3次迭代,曲线BAB变成曲线ABA BAB ABA,其中B变成-A+B+A,也就是一条-60°、向前延申、+60°、向前、+60°、向前的曲线。
迭代次数越多,三角越成型,速度越慢(控制点以3n+1的数量级增长)。
from maya import cmds
import math
from PySide2 import QtWidgets
def get_points(length = 1, depth = 1):
points = [[0,0,0]]
points += get_points_sub('A', points[0], length, 0, depth)
return points
def get_points_sub(state, beginPosition, length, angle, depth):
if depth == 1:
# print state, beginPosition, length, angle, depth
point = [beginPosition[0] + length * math.cos(math.radians(angle)),
beginPosition[1] + length * math.sin(math.radians(angle)),
0]
return [point]
if state == 'A':
angle += 60
p1 = get_points_sub('B', beginPosition, length/2, angle, depth-1)
angle -= 60
p2 = get_points_sub('A', p1[-1], length/2, angle, depth-1)
angle -= 60
p3 = get_points_sub('B', p2[-1], length/2, angle, depth-1)
elif state == 'B':
angle -= 60
p1 = get_points_sub('A', beginPosition, length/2, angle, depth-1)
angle += 60
p2 = get_points_sub('B', p1[-1], length/2, angle, depth-1)
angle += 60
p3 = get_points_sub('A', p2[-1], length/2, angle, depth-1)
points = p1 + p2 + p3
return points
class Fractal(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Fractal, self).__init__(parent)
self.create_ui()
def create_ui(self):
self.resize(400, 150)
self.setWindowTitle("Fractal")
# length
length_label = QtWidgets.QLabel()
length_label.setText("length")
self.length = QtWidgets.QDoubleSpinBox()
self.length.setRange(0.0, 1000.0)
self.length.setSingleStep(10)
self.length.setValue(1.0)
length_layout = QtWidgets.QHBoxLayout()
length_layout.addWidget(length_label)
length_layout.addWidget(self.length)
# depth
depth_label = QtWidgets.QLabel()
depth_label.setText("depth(<=10)")
self.depth = QtWidgets.QSpinBox()
self.depth = QtWidgets.QSpinBox()
self.depth.setRange(0, 10)
self.depth.setSingleStep(1)
self.depth.setValue(1)
depth_layout = QtWidgets.QHBoxLayout()
depth_layout.addWidget(depth_label)
depth_layout.addWidget(self.depth)
# layout
button = QtWidgets.QPushButton("Generate", self)
button.clicked.connect(self.generate)
layout = QtWidgets.QVBoxLayout()
layout.addLayout(length_layout)
layout.addLayout(depth_layout)
layout.addWidget(button)
self.setLayout(layout)
def generate(self):
length = self.length.value()
depth = self.depth.value()
points = get_points(length, depth)
# print points
curve = cmds.curve(d=1, p=points)
cmds.select(curve)
if __name__ == '__main__':
fractal = Fractal()
fractal.show()
怎么运行
-
首先你需要安装maya。理论上任何一个版本都行,我用的是maya 2018。
-
打开“脚本编辑器”面板
-
创建一个运行python脚本的窗口
-
拷贝本文的代码进去,点击运行