如何设计L-System生成Penrose P3菱形镶嵌图案?
Penrose P3镶嵌L-System完整实现方案
已定义渲染字符规则
+:逆时针旋转TWO_PI/20(即18°)-:顺时针旋转TWO_PI/20(即18°)A:绘制细菱形(Rhombus-A)B:绘制粗菱形(Rhombus-B)[:入栈当前变换矩阵]:出栈恢复变换矩阵
完整L-System规则
Penrose P3镶嵌的L-System核心规则如下:
- 公理(Axiom):
[X]++++[X]++++[X]++++[X]++++[X] - 替换规则:
X → A-------[B[+++++A]+++++++++A[--[A[++++++A][------A]]][-----B][-------B[+A]][+B[+A]][+++B]++++++A]Y → B++++++[A[-------B]---------B[++[B[-------B][++++++B]]][+++++A][++++++A[-B]][-A[-B]][---A]-------B]
注:你的代码中定义的W、Z规则属于冗余项,标准Penrose P3实现仅需X和Y两个替换规则。
修正后的完整代码
JavaScript(p5.js)实现
function penroseP3(){ this.a = 20; // 菱形边长 this.center = createVector(width/2, height/2); this.theta = TWO_PI/20; // 18° this.axiom = "[X]++++[X]++++[X]++++[X]++++[X]"; this.ruleX = "A-------[B[+++++A]+++++++++A[--[A[++++++A][------A]]][-----B][-------B[+A]][+B[+A]][+++B]++++++A]"; this.ruleY = "B++++++[A[-------B]---------B[++[B[-------B][++++++B]]][+++++A][++++++A[-B]][-A[-B]][---A]-------B]"; this.sentence = this.axiom; this.generations = 0; // 初始化迭代次数 this.substitute = function() { let newSentence = ""; for (let i = 0; i < this.sentence.length; ++i) { let step = this.sentence.charAt(i); if (step == 'X') { newSentence += this.ruleX; } else if (step == 'Y') { newSentence += this.ruleY; } else { newSentence += step; } } this.generations++; this.sentence = newSentence; }; this.LSystem = function(generations) { for (let i = 0; i < generations; i++) { this.substitute(); } }; this.drawRhombusA = function(){ push(); beginShape(); vertex(0, 0); vertex(this.a * sin(2*this.theta), -this.a * cos(2*this.theta)); vertex(0, -2*this.a * cos(2*this.theta)); vertex(-this.a * sin(2*this.theta), -this.a * cos(2*this.theta)); // 修正原代码几何错误 endShape(CLOSE); pop(); }; this.drawRhombusB = function(){ push(); beginShape(); vertex(0, 0); vertex(this.a * sin(this.theta), -this.a * cos(this.theta)); vertex(0, -2*this.a * cos(this.theta)); vertex(-this.a * sin(this.theta), -this.a * cos(this.theta)); endShape(CLOSE); pop(); }; this.draw = function() { let steps = this.sentence; translate(this.center.x, this.center.y); for (let i = 0; i < steps.length; i++) { let step = steps.charAt(i); if (step == 'A') { this.drawRhombusA(); translate(0, -2*this.a*cos(2*this.theta)); } else if (step == 'B') { this.drawRhombusB(); translate(this.a*sin(this.theta), -this.a*cos(this.theta)); } else if (step == '+') { rotate(this.theta); } else if (step == '-') { rotate(-this.theta); } else if (step == '[') { push(); } else if (step == ']') { pop(); } } }; } let p3; function setup() { createCanvas(windowWidth, 600); // 增大画布高度容纳完整图案 p3 = new penroseP3(); p3.LSystem(2); // 迭代次数建议不超过3次,避免性能问题 } function draw() { background(100, 200, 255); p3.draw(); noLoop(); // 仅绘制一次,避免重复渲染 }
HTML引入
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.0/p5.min.js"></script>
注:代码中修正了drawRhombusA的顶点坐标错误,初始化了generations变量修复迭代报错,同时调整画布高度并添加noLoop()优化渲染性能。
参考资料
- 《The Algorithmic Beauty of Plants》:分形与L-System领域权威著作,详细介绍了Penrose镶嵌的L-System实现逻辑
- 经典L-System学术文献:聚焦Penrose非周期镶嵌的分形生成算法研究
内容的提问来源于stack exchange,提问作者Ouss
相关产品推荐
相关产品推荐

