#l-systems #system #derive #turtle #geometric #structures #dcc-lsystem

dcc-lsystem-derive

#[derive(TurtleContainer)] 的宏实现

3个版本

0.1.2 2019年11月2日
0.1.1 2019年8月17日
0.1.0 2019年8月14日

#l-systems 中排名 8

每月下载量 30
dcc-lsystem 中使用

MIT/Apache

3KB

dcc-lsystem

一个用于处理 林德曼系统 的crate。

背景

一个L-系统由可以用来构成字符串的符号字母表、将每个符号扩展为符号字符串的集合的生成规则、从初始公理字符串开始构建的机制以及将生成的字符串转换为几何结构的机制组成。

海藻示例

林德曼最初的海藻建模L-系统具有变量 AB、公理 A 和生成规则 A -> ABB -> A。迭代此系统产生以下输出

  1. A
  2. AB
  3. ABA
  4. ABAAB

基本用法

将以下内容放入您的 Cargo.toml

dcc-lsystem = "0.6"

LSystemBuilder

一个L-系统由 LSystem 的实例表示。要创建一个基本的 LSystem,使用 LSystemBuilder 结构体是有用的。以下示例展示了林德曼的海藻系统的实现。

use dcc_lsystem::LSystemBuilder;

let mut builder = LSystemBuilder::new();

// Set up the two tokens we use for our system.
let a = builder.token("A");
let b = builder.token("B");

// Set up our axiom (i.e. initial state)
builder.axiom(vec![a]);

// Set the transformation rules
builder.transformation_rule(a, vec![a,b]); // A -> AB
builder.transformation_rule(b, vec![a]);   // B -> A

// Build our LSystem, which should have initial state A
let mut system = builder.finish();
assert_eq!(system.render(), "A");

// system.step() applies our production rules a single time
system.step();
assert_eq!(system.render(), "AB");

system.step();
assert_eq!(system.render(), "ABA");

// system.step_by() applies our production rule a number of times
system.step_by(5);
assert_eq!(system.render(), "ABAABABAABAABABAABABAABAABABAABAAB");

渲染L-系统

可以将L-系统渲染成图像或gif。通常这通过turtle来完成 - L-系统状态的每个标记都与turtle的一些移动或旋转(或许更复杂)相关联。 TurtleLSystemBuilder 结构体提供了构造此类渲染的便捷方式。

图像

柯赫曲线可以使用具有3个符号的L系统生成:F+-,其中F表示向前移动,+表示向左旋转90°,-表示向右旋转90°。该系统具有公理F和转换规则F => F+F-F-F+F。以下示例实现了这一过程。

use image::Rgb;

use dcc_lsystem::turtle::{TurtleLSystemBuilder, TurtleAction};
use dcc_lsystem::renderer::{ImageRendererOptions, Renderer};

let mut builder = TurtleLSystemBuilder::new();

builder
    .token("F", TurtleAction::Forward(30)) // F => go forward 30 units
    .token("+", TurtleAction::Rotate(90))  // + => rotate left 90°
    .token("-", TurtleAction::Rotate(-90)) // - => rotate right 90°
    .axiom("F")
    .rule("F => F + F - F - F + F");

let (mut system, renderer) = builder.finish();
system.step_by(5); // Iterate our L-system 5 times

let options = ImageRendererOptionsBuilder::new()
    .padding(10)
    .thickness(4.0)
    .fill_color(Rgb([255u8, 255u8, 255u8]))
    .line_color(Rgb([0u8, 0u8, 100u8]))
    .build();

renderer
    .render(&system, &options)
    .save("koch_curve.png")
    .expect("Failed to save koch_curve.png");

生成的图像在下面的示例部分中展示。

GIFs

也可以使用L系统渲染GIF。GIF的各个帧对应于L系统状态的局部渲染。

use image::Rgb;

use dcc_lsystem::renderer::{Renderer, VideoRendererOptions};
use dcc_lsystem::turtle::{TurtleAction, TurtleLSystemBuilder};

fn main() {
    let mut builder = TurtleLSystemBuilder::new();

    builder
        .token("F", TurtleAction::Forward(30))
        .token("+", TurtleAction::Rotate(90))
        .token("-", TurtleAction::Rotate(-90))
        .axiom("F")
        .rule("F => F + F - F - F + F");

    let (mut system, renderer) = builder.finish();
    system.step_by(5);

    let options = VideoRendererOptionsBuilder::new()
        .filename("koch_curve.gif")
        .fps(20)
        .skip_by(0)
        .padding(10)
        .thickness(4.0)
        .fill_color(Rgb([255u8, 255u8, 255u8]))
        .line_color(Rgb([0u8, 0u8, 100u8]))
        .progress_bar(true)
        .build();

    renderer
        .render(&system, &options);
}

海龟动作

目前有以下动作可用

TurtleAction 描述
无操作 海龟不执行任何操作。
旋转(i32) 通过一个角度旋转海龟。
前进(i32) 使海龟向前移动。
推入 将海龟的当前朝向和位置推入堆栈。
弹出 从堆栈中弹出海龟的朝向和位置。
随机旋转(Box<dyn Distribution>) 通过某个概率分布指定的角度旋转海龟。
随机前进(Box<dyn Distribution>) 通过某个概率分布指定的距离使海龟前进。

Distribution特质由以下给出

pub trait Distribution: objekt::Clone {
    fn sample(&self) -> i32;
}

以下是对均匀分布的可能实现(使用rand存储库)

use rand::Rng;

#[derive(Clone)]
pub struct Uniform {
    lower: i32,
    upper: i32,
}

impl Uniform {
    pub fn new(lower: i32, upper: i32) -> Self {
        Self { lower, upper }
    }
}

impl Distribution for Uniform {
    fn sample(&self) -> i32 {
        let mut rng = rand::thread_rng();
        rng.gen_range(self.lower, self.upper)
    }
}

示例

示例位于dcc-lsystem/examples

谢尔宾斯基箭头

Sierpinski Arrowhead

柯赫曲线

Koch curve

龙曲线

Dragon curve

分形植物

Fractal plant

许可

在以下任一许可下授权

任选其一。

贡献

除非你明确说明,否则任何有意提交以包含在你工作的贡献,如Apache-2.0许可中定义的,应按上述方式双重许可,不附加任何额外条款或条件。

依赖

~1.5MB
~34K SLoC