Skip to content

Commit badf1db

Browse files
author
Gemini
committed
Intermediate refactor:
1 parent f63e750 commit badf1db

File tree

8 files changed

+751
-198
lines changed

8 files changed

+751
-198
lines changed

examples/Camp_Envy_tie_prune_label.lpy

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class Spur(BasicWood):
8383
self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count)
8484
Spur.count+=1
8585
self.num_leaves = 0
86-
self.contour = create_noisy_circle_curve(1, .2, 30)
86+
self.contour = create_noisy_branch_contour(1, .2, 30)
8787

8888
def is_bud_break(self, num_buds_segment):
8989
return (rd.random() < 0.1)
@@ -119,7 +119,7 @@ class Branch(BasicWood):
119119
self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count)
120120
Branch.count+=1
121121
self.num_buds_segment=0
122-
self.contour = create_noisy_circle_curve(1, .2, 30)
122+
self.contour = create_noisy_branch_contour(1, .2, 30)
123123

124124
def is_bud_break(self, num_buds_segment):
125125
return (rd.random() < 0.01*(1 - self.num_buds_segment/self.growth.max_buds_segment))
@@ -151,7 +151,7 @@ class Trunk(BasicWood):
151151
if not name:
152152
self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count)
153153
Trunk.count+=1
154-
self.contour = create_noisy_circle_curve(1, .2, 30)
154+
self.contour = create_noisy_branch_contour(1, .2, 30)
155155

156156
def is_bud_break(self, num_buds_segment):
157157
if (rd.random() > 0.2*(1 - num_buds_segment/self.growth.max_buds_segment)):
@@ -183,7 +183,7 @@ class NonTrunk(BasicWood):
183183
if not name:
184184
self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count)
185185
Branch.count+=1
186-
self.contour = create_noisy_circle_curve(1, .2, 30)
186+
self.contour = create_noisy_branch_contour(1, .2, 30)
187187

188188
def is_bud_break(self, num_buds_segment):
189189
return (rd.random() < 0.02*(1 - num_buds_segment/self.growth.max_buds_segment))
@@ -335,7 +335,7 @@ rd.seed(seed_val)
335335

336336

337337
# Added by Camp
338-
def create_noisy_circle_curve(radius, noise_factor, num_points=100, seed=None):
338+
def create_noisy_branch_contour(radius, noise_factor, num_points=100, seed=None):
339339
if seed is not None:
340340
rd.seed(seed)
341341
t = np.linspace(0, 2 * np.pi, num_points, endpoint=False)
@@ -463,13 +463,13 @@ def make_leaf_guide():
463463

464464

465465
def reset_contour():
466-
default_curve = create_noisy_circle_curve(1, 0, 30) # Example of a simple default contour
466+
default_curve = create_noisy_branch_contour(1, 0, 30) # Example of a simple default contour
467467
nproduce SetContour(default_curve)
468468

469469
global profile1, profile2, profile3
470-
profile1 = create_noisy_circle_curve(1, .2, 30, 23)
471-
profile2 = create_noisy_circle_curve(1, .2, 30)
472-
profile3 = create_noisy_circle_curve(1, .2, 30)
470+
profile1 = create_noisy_branch_contour(1, .2, 30, 23)
471+
profile2 = create_noisy_branch_contour(1, .2, 30)
472+
profile3 = create_noisy_branch_contour(1, .2, 30)
473473
# print("Labelling: ", label)
474474
# print("Seed ", seed_val)
475475

examples/Envy_tie_prune_label.lpy

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class Spur(BasicWood):
4040

4141
# Every branch gets its own contour when it is constructed to ensure
4242
# branches each having a unique profile curve
43-
self.contour = create_noisy_circle_curve(radius = 2, noise_factor = .2, num_points = 30)
43+
self.contour = create_noisy_branch_contour(radius = 2, noise_factor = .2, num_points = 30)
4444

4545
def is_bud_break(self, num_buds_segment):
4646
return (rd.random() < 0.1)
@@ -72,7 +72,7 @@ class Branch(BasicWood):
7272

7373
# Every branch gets its own contour when it is constructed to ensure
7474
# branches each having a unique profile curve
75-
self.contour = create_noisy_circle_curve(1, .5, 30)
75+
self.contour = create_noisy_branch_contour(1, .5, 30)
7676

7777
def is_bud_break(self, num_break_buds):
7878
if num_break_buds >= 1:
@@ -109,7 +109,7 @@ class Trunk(BasicWood):
109109

110110
# Every branch gets its own contour when it is constructed to ensure
111111
# branches each having a unique profile curve
112-
self.contour = create_noisy_circle_curve(3, 0.05, 30)
112+
self.contour = create_noisy_branch_contour(3, 0.05, 30)
113113

114114
def is_bud_break(self, num_buds_segment):
115115
if (rd.random() > 0.1*(1 - num_buds_segment/self.growth.max_buds_segment)):
@@ -145,7 +145,7 @@ class NonTrunk(BasicWood):
145145

146146
# Every branch gets its own contour when it is constructed to ensure
147147
# branches each having a unique profile curve
148-
self.contour = create_noisy_circle_curve(1, .2, 30)
148+
self.contour = create_noisy_branch_contour(1, .2, 30)
149149

150150
def is_bud_break(self, num_buds_segment):
151151
return (rd.random() < 0.5*(1 - num_buds_segment/self.growth.max_buds_segment))
@@ -304,7 +304,7 @@ rd.seed(seed_val)
304304

305305
# Used to set the contour back to a circle after it has been changed for a branch
306306
def reset_contour():
307-
default_curve = create_noisy_circle_curve(1, 0, 30) # Example of a simple default contour
307+
default_curve = create_noisy_branch_contour(1, 0, 30) # Example of a simple default contour
308308
nproduce SetContour(default_curve)
309309

310310

examples/UFO/UFO.lpy

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
"""
2+
Tying, Pruning and lablelling UFO architecture trees
3+
"""
4+
import sys
5+
sys.path.append('../../')
6+
from stochastic_tree import Support, BasicWood, TreeBranch, BasicWoodConfig
7+
import time
8+
from helper import *
9+
import numpy as np
10+
import random as rd
11+
from examples.UFO.UFOconfigs import basicwood_prototypes, Trunk, Branch, TertiaryBranch, Spur, UFOSimulationConfig
12+
from dataclasses import dataclass
13+
14+
15+
#init
16+
trunk_base = Trunk(copy_from = basicwood_prototypes['trunk'])
17+
time_count = 0
18+
19+
# Create simulation configuration
20+
simulation_config = UFOSimulationConfig()
21+
22+
def generate_points_ufo():
23+
"""
24+
Generate 3D points for the UFO trellis wire structure.
25+
26+
Creates a linear array of wire attachment points along the x-axis at a fixed
27+
height (z) and depth (y). The points are spaced evenly within the configured
28+
x-range and used to construct the trellis support structure.
29+
30+
Returns:
31+
list: List of (x, y, z) tuples representing wire attachment points,
32+
where all points share the same y and z coordinates.
33+
34+
Configuration parameters used:
35+
- ufo_x_range: Tuple (min_x, max_x) defining the range of x coordinates
36+
- ufo_x_spacing: Spacing between consecutive x coordinates
37+
- ufo_z_value: Fixed z-coordinate (height) for all points
38+
- ufo_y_value: Fixed y-coordinate (depth) for all points
39+
"""
40+
x = np.arange(
41+
simulation_config.ufo_x_range[0],
42+
simulation_config.ufo_x_range[1],
43+
simulation_config.ufo_x_spacing
44+
).astype(float)
45+
z = np.full((x.shape[0],), simulation_config.ufo_z_value).astype(float)
46+
y = np.full((x.shape[0],), simulation_config.ufo_y_value).astype(float)
47+
48+
pts = []
49+
for i in range(x.shape[0]):
50+
pts.append((x[i], y[i], z[i]))
51+
52+
return pts
53+
54+
55+
# def is_eligible_for_tying(module):
56+
# """
57+
# Check if a module represents an eligible branch segment for tying operations.
58+
59+
# A module is eligible if it:
60+
# - Is a 'WoodStart' symbol (completed branch segment)
61+
# - Has tying functionality
62+
# - Has a valid tie_axis (not None)
63+
64+
# Args:
65+
# module: L-System module to check
66+
67+
# Returns:
68+
# bool: True if module is eligible for tying
69+
# """
70+
# print("Checking eligibility for tying:", module)
71+
# return (module == 'WoodStart' and
72+
# hasattr(module[0].type, 'tying') and
73+
# getattr(module[0].type.tying, 'tie_axis', None) is not None)
74+
support = Support(generate_points_ufo(), simulation_config.support_num_wires, simulation_config.support_spacing_wires, simulation_config.support_trunk_wire_point)
75+
num_iteration_tie = simulation_config.num_iteration_tie
76+
num_iteration_prune = simulation_config.num_iteration_prune
77+
trunk_base.tying.guide_target = support.trunk_wire
78+
###Tying stuff begins
79+
80+
81+
def tie(lstring):
82+
for j,i in enumerate(lstring):
83+
# print("Evaluating module for tying:", i)
84+
if i == 'WoodStart' and hasattr(i[0].type, 'tying') and getattr(i[0].type.tying, 'tie_axis', None) is not None:
85+
if i[0].type.tying.tie_updated == False:
86+
continue
87+
curr = i[0]
88+
if i[0].type.tying.guide_points:
89+
i[0].type.tying.tie_updated = False
90+
i[0].type.tying.guide_target.add_branch()
91+
lstring, count = i[0].type.tie_lstring(lstring, j)
92+
93+
return True
94+
return False
95+
96+
97+
def StartEach(lstring):
98+
global parent_child_dict, support, trunk_base
99+
if support.trunk_wire and trunk_base.tying.tie_updated == False:
100+
trunk_base.tie_update()
101+
102+
for i in parent_child_dict[trunk_base.name]:
103+
if i.tying.tie_updated == False:
104+
i.tie_update()
105+
106+
107+
def EndEach(lstring):
108+
global parent_child_dict, support, num_iteration_tie
109+
110+
tied = False
111+
if (getIterationNb()+1)%num_iteration_tie == 0:
112+
113+
if support.trunk_wire :
114+
trunk_base.update_guide(trunk_base.tying.guide_target) #Tie trunk one iteration before branches
115+
energy_matrix = get_energy_mat(parent_child_dict[trunk_base.name], support, simulation_config)
116+
decide_guide(energy_matrix, parent_child_dict[trunk_base.name], support, simulation_config)
117+
for branch in parent_child_dict[trunk_base.name]:
118+
branch.update_guide(branch.tying.guide_target)
119+
while tie(lstring):
120+
pass
121+
if (getIterationNb() + 1) % num_iteration_prune == 0:
122+
while pruning_strategy(lstring): # Prune branches until no more can be pruned
123+
pass
124+
return lstring
125+
126+
def pruning_strategy(lstring): #Remove remnants of cut
127+
cut = False
128+
for j,i in enumerate(lstring):
129+
if i.name == 'WoodStart' and i[0].type.info.age > simulation_config.pruning_age_threshold and i[0].type.tying.has_tied == False and i[0].type.info.cut == False:
130+
i[0].type.info.cut = True
131+
lstring = cut_from(j, lstring)
132+
return True
133+
return False
134+
135+
parent_child_dict = {}
136+
parent_child_dict[trunk_base.name] = []
137+
label = simulation_config.label
138+
#Tie trunk
139+
module Attractors
140+
module grow_object
141+
module bud
142+
module WoodStart
143+
curve = create_bezier_curve(x_range = (-1, 1), y_range = (-1, 1), z_range = (0, 10), seed_val=time.time())
144+
Axiom: Attractors(support)SetGuide(curve, trunk_base.growth.max_length)[@GcGetPos(trunk_base.location.start)T(ParameterSet(type = trunk_base))&(270)/(0)grow_object(trunk_base)GetPos(trunk_base.location.end)]
145+
derivation length: simulation_config.derivation_length
146+
147+
production:
148+
#Decide whether branch internode vs trunk internode need to be the same size.
149+
grow_object(o) :
150+
if o == None:
151+
produce *
152+
if o.length >= o.growth.max_length:
153+
nproduce *
154+
else:
155+
nproduce SetContour(o.contour)
156+
o.grow_one()
157+
if label:
158+
r, g, b = o.info.color
159+
nproduce SetColor(r,g,b)
160+
if 'Spur' in o.name:
161+
produce I(o.growth.growth_length, o.growth.thickness, o)bud(ParameterSet(type = o, num_buds = 0))@O(o.growth.thickness*simulation_config.thickness_multiplier)grow_object(o)
162+
else:
163+
nproduce I(o.growth.growth_length, o.growth.thickness, o)
164+
if np.isclose(o.info.age % o.bud_spacing_age, 0, atol=simulation_config.bud_age_tolerance):
165+
nproduce bud(ParameterSet(type = o, num_buds = 0))
166+
produce grow_object(o)
167+
#produce I(o.growth_length, o.thickness, o)bud(ParameterSet(type = o, num_buds = 0))grow_object(o)
168+
169+
bud(t) :
170+
if t.type.is_bud_break(t.num_buds):
171+
new_object = t.type.create_branch()
172+
if new_object == None:
173+
produce *
174+
parent_child_dict[new_object.name] = []
175+
parent_child_dict[t.type.name].append(new_object)
176+
#Store new object somewhere
177+
t.num_buds+=1
178+
t.type.info.num_branches+=1
179+
180+
if hasattr(new_object, 'curve_x_range'):
181+
import time
182+
curve = create_bezier_curve(x_range=new_object.curve_x_range, y_range=new_object.curve_y_range, z_range=new_object.curve_z_range, seed_val=time.time())
183+
nproduce[@GcSetGuide(curve, new_object.growth.max_length)
184+
else:
185+
nproduce [
186+
nproduce @RGetPos(new_object.location.start)WoodStart(ParameterSet(type = new_object))/(rd.random()*360)&(rd.random()*360)grow_object(new_object)GetPos(new_object.location.end)@Ge]bud(t)
187+
188+
189+
I(s,r,o) --> I(s,r+o.growth.thickness_increment, o)
190+
_(r) --> _(r+o.growth.thickness_increment)
191+
192+
homomorphism:
193+
194+
I(a,r,o) --> F(a,r)
195+
S(a,r,o) --> F(a,r)
196+
197+
production:
198+
Attractors(support):
199+
pttodisplay = support.attractor_grid.get_enabled_points()
200+
if len(pttodisplay) > 0:
201+
produce [,(3) @g(PointSet(pttodisplay,width=simulation_config.attractor_point_width))]

0 commit comments

Comments
 (0)