Skip to content

Commit 9449c71

Browse files
committed
Move to nodes per segment and fixed cylinder length
1 parent bfee2ce commit 9449c71

File tree

6 files changed

+61
-42
lines changed

6 files changed

+61
-42
lines changed

examples/Envy/Envy.lpy

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,12 @@ grow_object(plant_segment) :
195195
# Add color visualization if labeling is enabled -- Can this be moved to the start of building the segment?
196196
r, g, b = plant_segment.info.color
197197
nproduce SetColor(r,g,b)
198-
#Produce internode segment
199-
nproduce I(plant_segment.growth.growth_length, plant_segment.growth.thickness, plant_segment)
200-
#Produce bud
198+
#Produce internode segments (n cylinders per growth step)
199+
n_cylinders = int(plant_segment.growth.growth_length / plant_segment.growth.cylinder_length)
200+
for i in range(n_cylinders):
201+
nproduce I(plant_segment.growth.cylinder_length, plant_segment.growth.thickness, plant_segment)
202+
203+
#Produce bud (after all cylinders in this growth step)
201204
if plant_segment.pre_bud_rule(plant_segment, simulation_config):
202205
for module in plant_segment.post_bud_rule(plant_segment, simulation_config):
203206
nproduce new(module[0], *module[1])

examples/Envy/Envy_prototypes.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ def __init__(self, config=None, copy_from=None, prototype_dict: dict = {}):
1414
super().__init__(config, copy_from, prototype_dict)
1515

1616
def is_bud_break(self, num_buds_segment):
17-
return (rd.random() < 0.1)
17+
if num_buds_segment >= self.growth.max_buds_segment:
18+
return False
19+
return (rd.random() < 0.1 * (1 - num_buds_segment / self.growth.max_buds_segment))
1820

1921
def create_branch(self):
2022
return None
@@ -29,15 +31,13 @@ def post_bud_rule(self, plant_segment, simulation_config):
2931
class Branch(TreeBranch):
3032
def __init__(self, config=None, copy_from=None, prototype_dict: dict = {}):
3133
super().__init__(config, copy_from, prototype_dict)
32-
self.num_buds_segment = 0
3334

3435
def is_bud_break(self, num_break_buds):
35-
if num_break_buds >= 1:
36+
if num_break_buds >= self.growth.max_buds_segment:
3637
return False
37-
return (rd.random() < 0.5*(1 - self.num_buds_segment/self.growth.max_buds_segment))
38+
return (rd.random() < 0.5 * (1 - num_break_buds / self.growth.max_buds_segment))
3839

3940
def create_branch(self):
40-
self.num_buds_segment += 1
4141
if rd.random() > 0.8:
4242
new_ob = NonTrunk(copy_from=self.prototype_dict['nontrunk'])
4343
else:
@@ -57,7 +57,9 @@ def __init__(self, config=None, copy_from=None, prototype_dict: dict = {}):
5757
super().__init__(config, copy_from, prototype_dict)
5858

5959
def is_bud_break(self, num_buds_segment):
60-
if (rd.random() > 0.1*(1 - num_buds_segment/self.growth.max_buds_segment)):
60+
if num_buds_segment >= self.growth.max_buds_segment:
61+
return False
62+
if (rd.random() > 0.1 * (1 - num_buds_segment / self.growth.max_buds_segment)):
6163
return False
6264
return True
6365

@@ -79,7 +81,9 @@ def __init__(self, config=None, copy_from=None, prototype_dict: dict = {}):
7981
super().__init__(config, copy_from, prototype_dict)
8082

8183
def is_bud_break(self, num_buds_segment):
82-
return (rd.random() < 0.5*(1 - num_buds_segment/self.growth.max_buds_segment))
84+
if num_buds_segment >= self.growth.max_buds_segment:
85+
return False
86+
return (rd.random() < 0.5 * (1 - num_buds_segment / self.growth.max_buds_segment))
8387

8488
def create_branch(self):
8589
if rd.random() > 0.3:
@@ -104,7 +108,8 @@ def post_bud_rule(self, plant_segment, simulation_config):
104108
tie_axis=None,
105109
max_length=0.2,
106110
thickness=0.003,
107-
growth_length=0.05, # growth_length/2 from original
111+
growth_length=0.05,
112+
cylinder_length=0.05,
108113
thickness_increment=0.,
109114
color=[0, 255, 0],
110115
bud_spacing_age=2,
@@ -115,11 +120,12 @@ def post_bud_rule(self, plant_segment, simulation_config):
115120
)
116121

117122
branch_config = BasicWoodConfig(
118-
max_buds_segment=30,
123+
max_buds_segment=2,
119124
tie_axis=(1, 0, 0),
120125
max_length=2.2,
121126
thickness=0.01,
122127
growth_length=0.1,
128+
cylinder_length=0.05,
123129
thickness_increment=0.00001,
124130
color=[255, 150, 0],
125131
bud_spacing_age=2,
@@ -135,6 +141,7 @@ def post_bud_rule(self, plant_segment, simulation_config):
135141
max_length=4,
136142
thickness=0.01,
137143
growth_length=0.1,
144+
cylinder_length=0.05,
138145
thickness_increment=0.00001,
139146
color=[255, 0, 0],
140147
bud_spacing_age=2,
@@ -149,7 +156,8 @@ def post_bud_rule(self, plant_segment, simulation_config):
149156
tie_axis=None,
150157
max_length=0.3,
151158
thickness=0.003,
152-
growth_length=0.05, # growth_length/2 from original
159+
growth_length=0.05,
160+
cylinder_length=0.05,
153161
thickness_increment=0.00001,
154162
color=[0, 255, 0],
155163
bud_spacing_age=2,

examples/UFO/UFO.lpy

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ def EndEach(lstring):
115115
while tie(lstring, simulation_config):
116116
pass # Continue until no more tying operations are possible
117117

118-
# Check if this is also a pruning iteration
119-
if current_iteration % pruning_interval_iterations == 0:
120-
# Prune branches until no more can be pruned
121-
while prune(lstring, simulation_config):
122-
pass
118+
# Check if this is also a pruning iteration
119+
if current_iteration % pruning_interval_iterations == 0:
120+
# Prune branches until no more can be pruned
121+
while prune(lstring, simulation_config):
122+
pass
123123

124124
return lstring
125125

@@ -195,9 +195,12 @@ grow_object(plant_segment) :
195195
# Add color visualization if labeling is enabled -- Can this be moved to the start of building the segment?
196196
r, g, b = plant_segment.info.color
197197
nproduce SetColor(r,g,b)
198-
#Produce internode segment
199-
nproduce I(plant_segment.growth.growth_length, plant_segment.growth.thickness, plant_segment)
200-
#Produce bud
198+
#Produce internode segments (n cylinders per growth step)
199+
n_cylinders = int(plant_segment.growth.growth_length / plant_segment.growth.cylinder_length)
200+
for i in range(n_cylinders):
201+
nproduce I(plant_segment.growth.cylinder_length, plant_segment.growth.thickness, plant_segment)
202+
203+
#Produce bud (after all cylinders in this growth step)
201204
if plant_segment.pre_bud_rule(plant_segment, simulation_config):
202205
for module in plant_segment.post_bud_rule(plant_segment, simulation_config):
203206
nproduce new(module[0], *module[1])

examples/UFO/UFO_prototypes.py

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def __init__(self, config=None, copy_from=None, prototype_dict: dict = {}):
1515
def is_bud_break(self, num_buds_segment):
1616
if num_buds_segment >= self.growth.max_buds_segment:
1717
return False
18-
return (rd.random() < 0.1)
18+
return (rd.random() < 0.1 * (1 - num_buds_segment / self.growth.max_buds_segment))
1919

2020
def create_branch(self):
2121
return None
@@ -36,10 +36,9 @@ def __init__(self, config=None, copy_from=None, prototype_dict: dict = {}):
3636
super().__init__(config, copy_from, prototype_dict)
3737

3838
def is_bud_break(self, num_buds_segment):
39-
if num_buds_segment >= 2:
39+
if num_buds_segment >= self.growth.max_buds_segment:
4040
return False
41-
if (rd.random() < 0.005*self.growth.growth_length*(1 - self.num_buds/self.growth.max_buds_segment)):
42-
self.num_buds +=1
41+
if (rd.random() < 0.005*self.growth.growth_length * (1 - num_buds_segment / self.growth.max_buds_segment)):
4342
return True
4443

4544
def create_branch(self):
@@ -60,9 +59,9 @@ def __init__(self, config=None, copy_from=None, prototype_dict: dict = {}):
6059
super().__init__(config, copy_from, prototype_dict)
6160

6261
def is_bud_break(self, num_buds_segment):
63-
if num_buds_segment >= 2:
62+
if num_buds_segment >= self.growth.max_buds_segment:
6463
return False
65-
if (rd.random() < 0.2*(1 - self.num_buds/self.growth.max_buds_segment)):
64+
if (rd.random() < 0.2 * (1 - num_buds_segment / self.growth.max_buds_segment)):
6665

6766
return True
6867

@@ -91,9 +90,8 @@ def __init__(self, config=None, copy_from=None, prototype_dict: dict = {}):
9190
def is_bud_break(self, num_buds_segment):
9291
if num_buds_segment >= self.growth.max_buds_segment:
9392
return False
94-
if (rd.random() > 0.05*self.length/self.growth.max_length*(1 - self.num_buds/self.growth.max_buds_segment)):
93+
if (rd.random() > 0.05*self.length/self.growth.max_length * (1 - num_buds_segment / self.growth.max_buds_segment)):
9594
return False
96-
self.num_buds+=1
9795
return True
9896

9997
def create_branch(self):
@@ -113,12 +111,13 @@ def post_bud_rule(self, plant_segment, simulation_config ):
113111

114112
# Create configs for cleaner prototype setup
115113
spur_config = BasicWoodConfig(
116-
max_buds_segment=5,
114+
max_buds_segment=2,
117115
tie_axis=None,
118116
max_length=0.1,
119117
thickness=0.003,
120-
growth_length=0.05,
121-
thickness_increment=0.,
118+
growth_length=0.05,
119+
cylinder_length=0.01,
120+
thickness_increment=0.,
122121
color=[0, 255, 0],
123122
bud_spacing_age=1, # Spurs bud every 1 age unit
124123
curve_x_range=(-0.2, 0.2), # Tighter bounds for spur curves
@@ -127,12 +126,13 @@ def post_bud_rule(self, plant_segment, simulation_config ):
127126
)
128127

129128
side_branch_config = BasicWoodConfig(
130-
max_buds_segment=40,
129+
max_buds_segment=2,
131130
tie_axis=None,
132131
max_length=0.25,
133132
thickness=0.003,
134-
growth_length=0.05,
135-
thickness_increment=0.00001,
133+
growth_length=0.05,
134+
cylinder_length=0.01,
135+
thickness_increment=0.00001,
136136
color=[0, 255, 0],
137137
bud_spacing_age=2, # Tertiary branches bud every 3 age units
138138
curve_x_range=(-0.5, 0.5), # Moderate bounds for tertiary branches
@@ -141,12 +141,13 @@ def post_bud_rule(self, plant_segment, simulation_config ):
141141
)
142142

143143
trunk_config = BasicWoodConfig(
144-
max_buds_segment=60,
144+
max_buds_segment=5,
145145
tie_axis=(1, 0, 0),
146146
max_length=3,
147147
thickness=0.02,
148148
thickness_increment=0.00001,
149-
growth_length=0.1,
149+
growth_length=0.1,
150+
cylinder_length=0.02,
150151
color=[255, 0, 0],
151152
bud_spacing_age=2, # Trunk buds every 4 age units
152153
curve_x_range=(-0.3, 0.3), # Conservative bounds for trunk
@@ -156,12 +157,13 @@ def post_bud_rule(self, plant_segment, simulation_config ):
156157
)
157158

158159
branch_config = BasicWoodConfig(
159-
max_buds_segment=140,
160+
max_buds_segment=2,
160161
tie_axis=(0, 0, 1),
161162
max_length=2.5,
162163
thickness=0.01,
163164
thickness_increment=0.00001,
164-
growth_length=0.1,
165+
growth_length=0.1,
166+
cylinder_length=0.02,
165167
color=[255, 150, 0],
166168
bud_spacing_age=2, # Branches bud every 2 age units
167169
curve_x_range=(-0.4, 0.4), # Moderate bounds for primary branches

simulation_base.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,6 @@ def tie(self, lstring):
305305
if branch.tying.guide_points:
306306
# Perform the tying operation
307307
branch.tying.tie_updated = False
308-
branch.tying.guide_target.add_branch()
309308

310309
# Update the L-System string with tying modifications
311310
lstring, modifications_count = branch.tie_lstring(lstring, position)

stochastic_tree.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,11 @@ def __post_init__(self):
4848
@dataclass
4949
class GrowthState:
5050
"""Growth parameters for a wood object."""
51-
max_buds_segment: int = 5
51+
max_buds_segment: int = 5 # Total cumulative buds allowed across the entire branch segment (not per node)
5252
thickness: float = 0.1
5353
thickness_increment: float = 0.01
5454
growth_length: float = 1.0
55+
cylinder_length: float = 0.1
5556
max_length: float = 7.0
5657

5758
@dataclass
@@ -75,10 +76,11 @@ def __post_init__(self):
7576
class BasicWoodConfig:
7677
"""Configuration parameters for BasicWood initialization."""
7778
copy_from: any = None
78-
max_buds_segment: int = 5
79+
max_buds_segment: int = 5 # Total cumulative buds allowed across the entire branch segment (not per node)
7980
thickness: float = 0.1
8081
thickness_increment: float = 0.01
8182
growth_length: float = 1.0
83+
cylinder_length: float = 0.1 # Length of each individual cylinder
8284
max_length: float = 7.0
8385
tie_axis: tuple = None
8486
order: int = 0
@@ -130,6 +132,7 @@ def __init__(self, config=None, copy_from=None, **kwargs):
130132
curve_x_range = config.curve_x_range
131133
curve_y_range = config.curve_y_range
132134
curve_z_range = config.curve_z_range
135+
cylinder_length = config.cylinder_length
133136
elif copy_from is None:
134137
raise ValueError("config must be provided when copy_from is None")
135138

@@ -150,6 +153,7 @@ def __init__(self, config=None, copy_from=None, **kwargs):
150153
thickness=thickness,
151154
thickness_increment=thickness_increment,
152155
growth_length=growth_length,
156+
cylinder_length=cylinder_length,
153157
max_length=max_length
154158
)
155159
# Bud spacing for L-System rules

0 commit comments

Comments
 (0)