11个不稳定版本
0.6.3 | 2021年5月17日 |
---|---|
0.6.2 | 2020年2月10日 |
0.6.1 | 2019年11月2日 |
#366 in 算法
33 每月下载次数
69KB
1K SLoC
dcc-lsystem
一个用于处理Lindenmayer系统的crate。
背景
L-系统由一组可以用来生成字符串的符号组成,一个将每个符号扩展成更大符号字符串的生产规则集合,一个开始构建的初始公理字符串,以及将生成的字符串转换为几何结构的一种机制。
藻类示例
Lindenmayer最初用于模拟藻类生长的L-系统有变量A
和B
,公理A
,以及生产规则A -> AB
,B -> A
。迭代这个系统会产生以下输出
A
AB
ABA
ABAAB
基本用法
将以下内容放入您的Cargo.toml
dcc-lsystem = "0.6"
LSystemBuilder
L-系统由LSystem
的一个实例表示。要创建一个裸骨LSystem
,可以使用LSystemBuilder
结构。以下示例显示了Lindenmayer的藻类系统的实现。
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。通常这通过海龟来完成 - L-系统状态中的每个标记都与海龟的某种移动或旋转(或者可能是更复杂的东西)相关联。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) |
使龟向前移动。 |
推入 |
将龟的当前朝向和位置推入栈中。 |
弹出 |
从栈中弹出龟的朝向和位置。 |
随机旋转(框<动态分布>) |
通过某些概率分布指定的角度旋转龟。 |
随机前进(框<动态分布>) |
通过某些概率分布指定的距离使龟向前移动。 |
Distribution
特性如下
pub trait Distribution: dyn_clone::DynClone {
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
。
谢宾斯基箭头
科赫曲线
龙曲线
分形植物
许可证
根据您的要求,许可协议可以是以下之一
- Apache License,版本2.0(LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT 协议(LICENSE-MIT 或 http://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则根据 Apache-2.0 许可证定义的,您有意提交以包含在作品中的任何贡献,将根据上述协议双许可,没有任何额外的条款或条件。
依赖关系
~5–20MB
~238K SLoC