コード例 #1
0
ファイル: traditional.py プロジェクト: Michael0x2a/bonsai
def triangle_koch(d: int = 400) -> LSystem:
    c = 1
    p = 0.3
    q = c - p
    h = (p * q)**0.5

    FORWARD = BranchKind(1)
    tp = Branch(angle=86, length=0)
    tn = Branch(angle=-86, length=0)

    def forward(d: float) -> Branch:
        return Branch(angle=0, length=d, kind=FORWARD)

    system = LSystem([forward(d)], recommended_depth=4)

    @system.add_rule(FORWARD)
    def f_replace(snapshot: BranchSnapshot) -> List[Command]:
        x = snapshot.branch.length
        return [
            forward(x * p), tp,
            forward(x * h), tn, tn,
            forward(x * h), tp,
            forward(x * q)
        ]

    return system
コード例 #2
0
ファイル: organic.py プロジェクト: Michael0x2a/bonsai
 def handle_start(_: BranchSnapshot) -> List[Command]:
     out = [Branch(angle=0, length=start_length, energy=start_energy)]
     for _ in range(2):
         out.append(
             Branch(
                 angle=random.randint(-10, 10),
                 length=start_length,
                 energy=start_energy,
             ))
     out[-1].kind = BRANCH
     return out
コード例 #3
0
ファイル: traditional.py プロジェクト: Michael0x2a/bonsai
def koch_island(d: int = 10) -> LSystem:
    FORWARD = BranchKind(1)

    f = Branch(angle=0, length=d, kind=FORWARD)
    tp = Branch(angle=90, length=0)
    tn = Branch(angle=-90, length=0)

    system = LSystem([f, tn, f, tn, f, tn, f], recommended_depth=4)

    @system.add_rule(FORWARD)
    def f_replace(_: BranchSnapshot) -> List[Command]:
        return [f, tn, f, tp, f, tp, f, f, tn, f, tn, f, tp, f]

    return system
コード例 #4
0
 def handler(t: TurtleSnapshot, branch: Branch) -> List[Command]:
     new_heading = interpolate_headings(
         t.heading + branch.angle,
         global_heading,
         branch.resistance,
         force,
     )
     angle = new_heading - t.heading
     return [branch.clone(angle=angle)]
コード例 #5
0
ファイル: traditional.py プロジェクト: Michael0x2a/bonsai
def bushy_tree(d: int = 10) -> LSystem:
    FORWARD = BranchKind(1)

    f = Branch(angle=0, length=d, kind=FORWARD)
    tp = Branch(angle=22.5, length=0)
    tn = Branch(angle=-22.5, length=0)
    push = Push()
    pop = Pop()

    system = LSystem([f], recommended_depth=4)

    @system.add_rule(FORWARD)
    def f_replace(_: BranchSnapshot) -> List[Command]:
        return [
            f, f, tn, push, tn, f, tp, f, tp, f, pop, tp, push, tp, f, tn, f,
            tn, f, pop
        ]

    return system
コード例 #6
0
ファイル: traditional.py プロジェクト: Michael0x2a/bonsai
def dragon_curve(d: int = 10) -> LSystem:
    T1 = BranchKind(1)
    T2 = BranchKind(2)

    f1 = Branch(angle=0, length=d, kind=T1)
    f2 = Branch(angle=0, length=d, kind=T2)
    tp = Branch(angle=90, length=0)
    tn = Branch(angle=-90, length=0)

    system = LSystem([f1], recommended_depth=10)

    @system.add_rule(T1)
    def f1_replace(_: BranchSnapshot) -> List[Command]:
        return [f1, tp, f2, tp]

    @system.add_rule(T2)
    def f2_replace(_: BranchSnapshot) -> List[Command]:
        return [tn, f1, tn, f2]

    return system
コード例 #7
0
ファイル: traditional.py プロジェクト: Michael0x2a/bonsai
def flower_field(d: int = 10) -> LSystem:
    FORWARD = BranchKind(1)

    f = Branch(angle=0, length=d, kind=FORWARD)
    tp = Branch(angle=30, length=0)
    tn = Branch(angle=-30, length=0)
    push = Push()
    pop = Pop()

    system = LSystem([f], recommended_depth=4)

    @system.add_rule(FORWARD)
    def f_replace(_: BranchSnapshot) -> List[Command]:
        r = random.random()
        if r <= 0.33:
            return [f, push, tp, f, pop, f, push, tn, f, pop, f]
        elif r <= 0.66:
            return [f, push, tp, f, pop, f]
        else:
            return [f, push, tn, f, pop, f]

    return system
コード例 #8
0
ファイル: organic.py プロジェクト: Michael0x2a/bonsai
def weed_plant(start_energy: float = 100) -> LSystem:
    def energy_to_length(energy: float) -> int:
        return int(round(energy / 4))

    START = BranchKind(1)
    BRANCH = BranchKind(2)
    LEAF = BranchKind(3)

    start_length = energy_to_length(start_energy)

    system = LSystem(
        seed=[
            Branch(angle=0,
                   length=start_length,
                   resistance=1.0,
                   energy=start_energy,
                   kind=START)
        ],
        recommended_depth=20,
    )

    @system.add_rule(START)
    def handle_start(_: BranchSnapshot) -> List[Command]:
        out = [Branch(angle=0, length=start_length, energy=start_energy)]
        for _ in range(2):
            out.append(
                Branch(
                    angle=random.randint(-10, 10),
                    length=start_length,
                    energy=start_energy,
                ))
        out[-1].kind = BRANCH
        return out

    @system.add_rule(BRANCH)
    def handle_branch(snapshot: BranchSnapshot) -> List[Command]:
        def constrain_heading(relative_angle: float) -> float:
            new_global_heading = snapshot.heading + relative_angle
            too_large = True
            while too_large:
                if new_global_heading >= 190:
                    new_global_heading = 190 - random.uniform(0, 10)
                elif new_global_heading <= -10:
                    new_global_heading = -10 + random.uniform(0, 10)
                else:
                    too_large = False
            new_relative_heading = new_global_heading - snapshot.heading
            return new_relative_heading

        branch = snapshot.branch
        energy = branch.energy
        if energy <= 30:
            return [branch.clone(kind=LEAF)]

        if random.random() <= 0.6:
            left_energy = branch.energy * random.uniform(0.85, 0.9)
            right_energy = branch.energy * random.uniform(0.85, 0.9)
            gap_energy = random.uniform(
                0, branch.energy * random.uniform(0.85, 0.9))

            # Branch into two
            left = [
                Push(),
                Branch(
                    angle=constrain_heading(random.randint(-30, -20)),
                    length=energy_to_length(left_energy),
                    energy=left_energy,
                    kind=BRANCH,
                ),
                Pop(),
            ]
            right = [
                Push(),
                Branch(
                    angle=constrain_heading(random.randint(20, 30)),
                    length=energy_to_length(right_energy),
                    energy=right_energy,
                    kind=BRANCH,
                ),
                Pop(),
            ]
            gap = Branch(angle=0,
                         length=energy_to_length(gap_energy),
                         energy=gap_energy)

            if random.random() <= 5:
                return [branch.clone(kind=DEFAULT_KIND), *left, gap, *right]
            else:
                return [branch.clone(kind=DEFAULT_KIND), *right, gap, *left]
        else:
            # Continue straight-ish
            new_energy = branch.energy * 0.95
            return [
                branch.clone(kind=DEFAULT_KIND),
                Branch(
                    angle=constrain_heading(random.randint(-10, 10)),
                    length=energy_to_length(new_energy),
                    energy=new_energy,
                    kind=BRANCH,
                ),
            ]

    @system.add_render_rule(LEAF)
    def render_leaf(t: TurtleWrapper, branch: Branch) -> None:
        t.shape("circle")
        t.shapesize(0.2, 1.0, 0)
        t.fillcolor(0.8, 1.0, 0.8)
        t.left(branch.angle)
        t.forward(branch.length // 2)
        t.pendown()
        t.stamp()
        t.penup()

    return system
コード例 #9
0
ファイル: organic.py プロジェクト: Michael0x2a/bonsai
    def handle_branch(snapshot: BranchSnapshot) -> List[Command]:
        def constrain_heading(relative_angle: float) -> float:
            new_global_heading = snapshot.heading + relative_angle
            too_large = True
            while too_large:
                if new_global_heading >= 190:
                    new_global_heading = 190 - random.uniform(0, 10)
                elif new_global_heading <= -10:
                    new_global_heading = -10 + random.uniform(0, 10)
                else:
                    too_large = False
            new_relative_heading = new_global_heading - snapshot.heading
            return new_relative_heading

        branch = snapshot.branch
        energy = branch.energy
        if energy <= 30:
            return [branch.clone(kind=LEAF)]

        if random.random() <= 0.6:
            left_energy = branch.energy * random.uniform(0.85, 0.9)
            right_energy = branch.energy * random.uniform(0.85, 0.9)
            gap_energy = random.uniform(
                0, branch.energy * random.uniform(0.85, 0.9))

            # Branch into two
            left = [
                Push(),
                Branch(
                    angle=constrain_heading(random.randint(-30, -20)),
                    length=energy_to_length(left_energy),
                    energy=left_energy,
                    kind=BRANCH,
                ),
                Pop(),
            ]
            right = [
                Push(),
                Branch(
                    angle=constrain_heading(random.randint(20, 30)),
                    length=energy_to_length(right_energy),
                    energy=right_energy,
                    kind=BRANCH,
                ),
                Pop(),
            ]
            gap = Branch(angle=0,
                         length=energy_to_length(gap_energy),
                         energy=gap_energy)

            if random.random() <= 5:
                return [branch.clone(kind=DEFAULT_KIND), *left, gap, *right]
            else:
                return [branch.clone(kind=DEFAULT_KIND), *right, gap, *left]
        else:
            # Continue straight-ish
            new_energy = branch.energy * 0.95
            return [
                branch.clone(kind=DEFAULT_KIND),
                Branch(
                    angle=constrain_heading(random.randint(-10, 10)),
                    length=energy_to_length(new_energy),
                    energy=new_energy,
                    kind=BRANCH,
                ),
            ]
コード例 #10
0
ファイル: traditional.py プロジェクト: Michael0x2a/bonsai
 def forward(d: float) -> Branch:
     return Branch(angle=0, length=d, kind=FORWARD)