You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何设计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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 17:56:05