Skip to content

Commit ef21e66

Browse files
committed
New looking trees
1 parent b90259a commit ef21e66

File tree

8 files changed

+190
-144
lines changed

8 files changed

+190
-144
lines changed

.gitignore

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
__pycache__/
33
*.py[cod]
44
*$py.class
5-
5+
*.~lpy
6+
*.pyc
67
# C extensions
78
*.so
89

@@ -162,4 +163,4 @@ cython_debug/
162163
#.idea/
163164

164165
dataset*/
165-
.DS_Store
166+
.DS_Store
6 Bytes
Binary file not shown.

examples/Envy_tie_prune_label.lpy

Lines changed: 127 additions & 102 deletions
Large diffs are not rendered by default.

examples/UFO_tie_prune_label.lpy

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import numpy as np
88
import random as rd
99
import copy
1010
import gc
11-
import time
11+
import times
1212
from helper import *
1313

1414
# Used to set the contour back to a circle after it has been changed for a branch
@@ -33,10 +33,12 @@ class Spur(BasicWood):
3333
self.contour = create_noisy_circle_curve(1, .2, 30)
3434

3535
def is_bud_break(self, num_buds_segment):
36-
return (rd.random() < 0.1)
36+
if num_buds_segment >= self.max_buds_segment:
37+
return False
38+
return (rd.random() < 0.1)
3739

3840
def create_branch(self):
39-
return None
41+
return None
4042

4143
def grow(self):
4244
pass
@@ -58,13 +60,15 @@ class LittleBranch(BasicWood):
5860
if not name:
5961
self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count)
6062
LittleBranch.count+=1
61-
self.num_buds_segment = 0
63+
self.num_buds = 0
6264
self.contour = create_noisy_circle_curve(1, .2, 30)
6365

6466
def is_bud_break(self, num_buds_segment):
65-
if (rd.random() < 0.005*self.growth_length*(1 - self.num_buds_segment/self.max_buds_segment)):
66-
self.num_buds_segment +=1
67-
return True
67+
if num_buds_segment >= 2:
68+
return False
69+
if (rd.random() < 0.005*self.growth_length*(1 - self.num_buds/self.max_buds_segment)):
70+
self.num_buds +=1
71+
return True
6872

6973
def create_branch(self):
7074
if rd.random()>0.8:
@@ -92,12 +96,14 @@ class Branch(BasicWood):
9296
if not name:
9397
self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count)
9498
Branch.count+=1
95-
self.num_buds_segment = 0
99+
self.num_buds = 0
96100
self.contour = create_noisy_circle_curve(1, .2, 30)
97101

98102
def is_bud_break(self, num_buds_segment):
99-
if (rd.random() < 0.2*self.growth_length*(1 - self.num_buds_segment/self.max_buds_segment)):
100-
self.num_buds_segment +=1
103+
if num_buds_segment >= 2:
104+
return False
105+
if (rd.random() < 0.2*(1 - self.num_buds/self.max_buds_segment)):
106+
101107
return True
102108

103109
def create_branch(self):
@@ -130,19 +136,19 @@ class Trunk(BasicWood):
130136
if not name:
131137
self.name = str(self.__class__.__name__) +'_'+ str(self.__class__.count)
132138
Trunk.count+=1
133-
self.num_buds_segment = 0
139+
self.num_buds = 0
134140
self.contour = create_noisy_circle_curve(1, .2, 30)
135141

136142
def is_bud_break(self, num_buds_segment):
137-
if (rd.random() > 0.05*self.growth_length*(1 - self.num_buds_segment/self.max_buds_segment)):
143+
if num_buds_segment >= self.max_buds_segment:
138144
return False
139-
self.num_buds_segment+=1
145+
if (rd.random() > 0.05*self.length/self.max_length*(1 - self.num_buds/self.max_buds_segment)):
146+
return False
147+
self.num_buds+=1
140148
return True
141149

142150
def create_branch(self):
143-
if rd.random() > 0.9:
144-
return Spur(copy_from = self.prototype_dict['spur'])
145-
else:
151+
if rd.random() > 0.1:
146152
return Branch(copy_from = self.prototype_dict['branch'])
147153

148154
def grow(self):
@@ -152,20 +158,20 @@ class Trunk(BasicWood):
152158

153159

154160
#Pass transition probabs? --> solve with abstract classes
155-
growth_length = 0.06
161+
growth_length = 0.1
156162
basicwood_prototypes = {}
157-
basicwood_prototypes['spur'] = Spur(tie_axis = (0,1,1), max_length = 0.06, thickness = 0.003, growth_length = growth_length, thickness_increment = 0., prototype_dict = basicwood_prototypes, color = 2)
158-
basicwood_prototypes['side_branch'] = LittleBranch(tie_axis = (1,1,0), max_length = 0.25, thickness = 0.003, growth_length =growth_length, thickness_increment = 0.0001*growth_length, prototype_dict = basicwood_prototypes, color = 1)
163+
basicwood_prototypes['spur'] = Spur(tie_axis = (0,1,1), max_length = 0.1, thickness = 0.003, growth_length = growth_length/2, thickness_increment = 0., prototype_dict = basicwood_prototypes, color = [0, 255, 0])
164+
basicwood_prototypes['side_branch'] = LittleBranch(tie_axis = (1,1,0), max_length = 0.25, thickness = 0.003, growth_length =growth_length/2, thickness_increment = 0.00001, prototype_dict = basicwood_prototypes, color = [0, 255, 0])
159165

160-
basicwood_prototypes['trunk'] = Trunk(tie_axis = (0,1,1), max_length = 3, thickness = 0.02, thickness_increment = 0.0002*growth_length, growth_length = growth_length, prototype_dict = basicwood_prototypes, color = 3)
161-
basicwood_prototypes['branch'] = Branch(tie_axis = (1,1,0), max_length = 2.5, thickness = 0.01, thickness_increment = 0.00001*growth_length, growth_length = 0.01, prototype_dict = basicwood_prototypes, color = 0)
166+
basicwood_prototypes['trunk'] = Trunk(tie_axis = (0,1,1), max_length = 3, thickness = 0.02, thickness_increment = 0.00001, growth_length = growth_length, prototype_dict = basicwood_prototypes, color = [255, 0, 0])
167+
basicwood_prototypes['branch'] = Branch(tie_axis = (1,1,0), max_length = 2.5, thickness = 0.01, thickness_increment = 0.00001, growth_length = growth_length, prototype_dict = basicwood_prototypes, color = [255, 150, 0])
162168

163169
#init
164170
trunk_base = Trunk(copy_from = basicwood_prototypes['trunk'])
165171
time_count = 0
166172

167173
def generate_points_ufo():
168-
x = np.arange(0.65, 3, 0.25).astype(float)
174+
x = np.arange(0.65, 3, 0.3).astype(float)
169175
z = np.full((x.shape[0],), 1.4).astype(float)
170176
y = np.full((x.shape[0],), 0).astype(float)
171177
pts = []
@@ -179,7 +185,9 @@ def generate_points_ufo():
179185

180186

181187
support = Support(generate_points_ufo(), 7 , 1 , (0.6,0,0.4), (0,1,1), (0,1,1))
182-
num_iteration_tie = 25
188+
num_iteration_tie = 8
189+
num_iteration_prune = 16
190+
bud_spacing_age = 2
183191
trunk_base.guide_target = support.trunk_wire
184192
###Tying stuff begins
185193

@@ -196,7 +204,7 @@ def get_energy_mat(branches, arch):
196204
for wire_id, wire in arch.branch_supports.items():
197205
if wire.num_branch>=1:
198206
continue
199-
energy_matrix[branch_id][wire_id] = ed(wire.point,branch.end)/2+ed(wire.point,branch.start)/2#+v.num_branches*10+branch.bend_energy(deflection, curr_branch.age)
207+
energy_matrix[branch_id][wire_id] = ed(wire.point, branch.start)/2+ed(wire.point,branch.end)/2#,+v.num_branches*10+branch.bend_energy(deflection, curr_branch.age)
200208
return energy_matrix
201209

202210
def decide_guide(energy_matrix, branches, arch):
@@ -206,6 +214,8 @@ def decide_guide(energy_matrix, branches, arch):
206214
return
207215
if not (branches[min_arg[0][0]].has_tied == True):# and not (arch.branch_supports[min_arg[0][1]].num_branch >=1):
208216
branches[min_arg[0][0]].guide_target = arch.branch_supports[min_arg[0][1]]#copy.deepcopy(arch.branch_supports[min_arg[0][1]].point)
217+
arch.branch_supports[min_arg[0][1]].add_branch() # Increment the number of branches tied to the wire
218+
209219
#trellis_wires.trellis_pts[min_arg[0][1]].num_branches+=1
210220
for j in range(energy_matrix.shape[1]):
211221
energy_matrix[min_arg[0][0]][j] = np.inf
@@ -251,9 +261,9 @@ def EndEach(lstring):
251261
branch.update_guide(branch.guide_target)
252262
while tie(lstring):
253263
pass
254-
while pruning_strategy(lstring):
255-
pass
256-
num_iteration_tie = 50
264+
if (getIterationNb() + 1) % num_iteration_prune == 0:
265+
while pruning_strategy(lstring): # Prune branches until no more can be pruned
266+
pass
257267
return lstring
258268

259269
def pruning_strategy(lstring): #Remove remnants of cut
@@ -276,7 +286,7 @@ module branch
276286
module C
277287
curve = create_bezier_curve(x_range = (-1, 1), y_range = (-1, 1), z_range = (0, 10), seed_val=time.time())
278288
Axiom: Attractors(support)SetGuide(curve, trunk_base.max_length)[GetPos(trunk_base.start)T(ParameterSet(type = trunk_base))&(270)/(0)grow_object(trunk_base)GetPos(trunk_base.end)]
279-
derivation length: 475
289+
derivation length: 160
280290

281291
production:
282292
#Decide whether branch internode vs trunk internode need to be the same size.
@@ -289,17 +299,19 @@ grow_object(o) :
289299
nproduce SetContour(o.contour)
290300
o.grow_one()
291301
if label:
292-
nproduce SetColor(o.color)
302+
r, g, b = o.color
303+
nproduce SetColor(r,g,b)
293304
if 'Spur' in o.name:
294305
produce I(o.growth_length, o.thickness, o)bud(ParameterSet(type = o, num_buds = 0))@O(o.thickness*1.2)grow_object(o)
295306
else:
296-
produce I(o.growth_length, o.thickness, o)bud(ParameterSet(type = o, num_buds = 0))grow_object(o)
307+
nproduce I(o.growth_length, o.thickness, o)
308+
if np.isclose(o.age%bud_spacing_age,0, atol = 0.01):
309+
nproduce bud(ParameterSet(type = o, num_buds = 0))
310+
produce grow_object(o)
297311
#produce I(o.growth_length, o.thickness, o)bud(ParameterSet(type = o, num_buds = 0))grow_object(o)
298312

299313
bud(t) :
300314
if t.type.is_bud_break(t.num_buds):
301-
if t.num_buds > 0:
302-
produce *
303315
new_object = t.type.create_branch()
304316
if new_object == None:
305317
produce *
@@ -319,7 +331,7 @@ bud(t) :
319331
nproduce[SetGuide(curve, new_object.max_length)
320332
else:
321333
nproduce [
322-
nproduce @RGetPos(new_object.start)C(ParameterSet(type = new_object))/(rd.random()*360)&(rd.random()*90)grow_object(new_object)GetPos(new_object.end)]bud(t)
334+
nproduce @RGetPos(new_object.start)C(ParameterSet(type = new_object))/(rd.random()*360)&(rd.random()*360)grow_object(new_object)GetPos(new_object.end)]bud(t)
323335

324336

325337
I(s,r,o) --> I(s,r+o.thickness_increment, o)

stochastic_tree.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ def __init__(self, copy_from = None, max_buds_segment: int = 5, thickness: float
5656
self.current_tied = False
5757
self.guide_target = -1#Vector3(0,0,0)
5858
self.tie_axis = tie_axis
59-
self.tie_updated = True
59+
self.tie_updated = False
6060
#Information Variables
6161
self.__length = 0
6262
self.age = 0
6363
self.cut = False
64+
self.prunable = True
6465
self.order = order
6566
self.num_branches = 0
6667
self.branch_dict = collections.deque()

tree_generation/convert_ply_to_obj.py renamed to tree_generation/convert_ply_to_ext.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,24 @@
55

66
import argparse
77
import glob
8-
from helpers import convert_ply_to_obj
8+
from helpers import convert_ply_to_ext
99

1010
if __name__ == "__main__":
1111
parser = argparse.ArgumentParser()
1212
parser.add_argument('--output_dir', type=str, default='dataset/')
1313
parser.add_argument('--input_dir', type=str, default='examples/UFO_tie_prune_label.lpy')
1414
parser.add_argument('--verbose', action='store_true', default=False)
15+
parser.add_argument('--ext', type=str, default='obj')
1516
args = parser.parse_args()
1617

1718
if not os.path.exists(args.output_dir):
1819
os.makedirs(args.output_dir)
1920

2021
for file in glob.glob(os.path.join(args.input_dir, '*.ply')):
21-
output_path = os.path.join(args.output_dir, os.path.basename(file).replace('.ply', '.obj'))
22+
output_path = os.path.join(args.output_dir, os.path.basename(file).replace('.ply', '.'+args.ext))
2223
if args.verbose:
2324
print("INFO: Converting file: ", file, "and saving to: ", output_path)
24-
convert_ply_to_obj(file, output_path)
25+
convert_ply_to_ext(file, output_path)
2526

2627

2728

tree_generation/helpers.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,14 @@ def write(fname, scene):
6565
f.close()
6666

6767

68-
def convert_ply_to_obj(in_path, out_path):
68+
def convert_ply_to_ext(in_path, out_path):
6969
import pymeshlab
7070
ms = pymeshlab.MeshSet()
7171
ms.load_new_mesh(in_path)
72-
ms.save_current_mesh(out_path)
72+
ms.save_current_mesh(out_path)
73+
74+
# def convert_ply_to_x3d(in_path, out_path):
75+
# import pymeshlab
76+
# ms = pymeshlab.MeshSet()
77+
# ms.load_new_mesh(in_path)
78+
# ms.save_current_mesh(out_path)

tree_generation/make_n_trees.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../')))
55
import random as rd
66
from openalea.lpy import Lsystem
7-
from lpy_treesim.dataset_generation.helpers import write
7+
from lpy_treesim.tree_generation.helpers import write
88
import argparse
99

1010
if __name__ == "__main__":

0 commit comments

Comments
 (0)