Skip to content

Commit d3bf0a8

Browse files
Merge pull request #34 from ibois-epfl/fix/ease_of_life_fixes_autumn2025
Small fixes before autumn 2025 semester
2 parents 606d344 + 599d505 commit d3bf0a8

10 files changed

+117
-37
lines changed

src/Carnutes/create_mesh.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
"""
2+
This function creates a mesh from a Rhino point cloud.
3+
"""
4+
15
#! python3
2-
# r: numpy==1.26.4
3-
# r: open3d==0.18.0
6+
7+
# r: numpy==2.0.2
8+
# r: open3d==0.19.0
49
# r: ZODB==6.0
510
# r: igraph==0.11.6
611

src/Carnutes/database_recap.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
"""
44

55
#! python3
6-
# r: numpy==1.26.4
7-
# r: open3d==0.18.0
6+
7+
# r: numpy==2.0.2
8+
# r: open3d==0.19.0
89
# r: ZODB==6.0
910
# r: igraph==0.11.6
1011

src/Carnutes/draw_connectivity_grah.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
#! python3
66

7-
# r: numpy==1.26.4
8-
# r: open3d==0.18.0
7+
# r: numpy==2.0.2
8+
# r: open3d==0.19.0
99
# r: ZODB==6.0
1010
# r: igraph==0.11.6
1111

src/Carnutes/find_multiple_trees_with_optimisation.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
"""
2+
This function finds multiple trees in the database that best fit the given element, starting by the element that has the most connections to make. It also optimizes for the tree usage.
3+
"""
4+
15
#! python3
2-
# r: numpy==1.26.4
3-
# r: open3d==0.18.0
6+
7+
# r: numpy==2.0.2
8+
# r: open3d==0.19.0
49
# r: ZODB==6.0
510
# r: igraph==0.11.6
611

@@ -59,20 +64,32 @@ def main():
5964
)
6065

6166
# Create the model
62-
current_model = interact_with_rhino.create_model_from_rhino_selection()
67+
current_model, layer_ids = interact_with_rhino.create_model_from_rhino_selection()
6368

6469
# For each element in the model, replace it with a point cloud. Starting from the elements with the highest degree.
6570
db_path = os.path.dirname(os.path.realpath(__file__)) + "/database/tree_database.fs"
6671

6772
all_rmse = []
6873

69-
for element in current_model.elements:
74+
for i, element in enumerate(current_model.elements):
7075
if element.type == elem.ElementType.Point:
7176
continue
72-
reference_pc_as_list = []
77+
reference_pc_as_list = [
78+
[
79+
element.geometry.PointAtStart.X,
80+
element.geometry.PointAtStart.Y,
81+
element.geometry.PointAtStart.Z,
82+
],
83+
[
84+
element.geometry.PointAtEnd.X,
85+
element.geometry.PointAtEnd.Y,
86+
element.geometry.PointAtEnd.Z,
87+
],
88+
]
7389
element_guid = element.GUID
7490
target_diameter = element.diameter
75-
reference_pc_as_list = element.locations
91+
for location in element.locations:
92+
reference_pc_as_list.append(location)
7693

7794
# at this point the reference_pc_as_list should contain the points, but they are not ordered. We need to order them.
7895
reference_pc_as_list = geometry.sort_points(reference_pc_as_list)
@@ -101,7 +118,9 @@ def main():
101118
best_tree.create_mesh()
102119

103120
tree_mesh = conversions.convert_carnutes_mesh_to_rhino_mesh(best_tree.mesh)
104-
scriptcontext.doc.Objects.AddMesh(tree_mesh)
121+
attributes = Rhino.DocObjects.ObjectAttributes()
122+
attributes.LayerIndex = layer_ids[i]
123+
scriptcontext.doc.Objects.AddMesh(tree_mesh, attributes)
105124

106125
return all_rmse
107126

src/Carnutes/find_multiple_trees_without_optimisation.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
"""
2+
This function finds multiple trees in the database that best fit the given element, starting by the element that has the most connections to make. It does not optimize for the tree usage.
3+
"""
4+
15
#! python3
2-
# r: numpy==1.26.4
3-
# r: open3d==0.18.0
6+
7+
# r: numpy==2.0.2
8+
# r: open3d==0.19.0
49
# r: ZODB==6.0
510
# r: igraph==0.11.6
611

@@ -48,19 +53,34 @@ def crop(tree: tree, bounding_volume: Rhino.Geometry.Brep):
4853

4954
def main():
5055
# Create the model
51-
current_model = interact_with_rhino.create_model_from_rhino_selection()
56+
current_model, layer_ids = interact_with_rhino.create_model_from_rhino_selection()
5257

5358
# For each element in the model, replace it with a point cloud. Starting from the elements with the highest degree.
5459
db_path = os.path.dirname(os.path.realpath(__file__)) + "/database/tree_database.fs"
5560

5661
all_rmse = []
5762

58-
for element in current_model.elements:
63+
for i, element in enumerate(current_model.elements):
5964
if element.type == elem.ElementType.Point:
6065
continue
6166

6267
# at this point the reference_pc_as_list should contain the points, but they are not ordered. We need to order them.
63-
reference_pc_as_list = geometry.sort_points(element.locations)
68+
reference_pc_as_list = [
69+
[
70+
element.geometry.PointAtStart.X,
71+
element.geometry.PointAtStart.Y,
72+
element.geometry.PointAtStart.Z,
73+
],
74+
[
75+
element.geometry.PointAtEnd.X,
76+
element.geometry.PointAtEnd.Y,
77+
element.geometry.PointAtEnd.Z,
78+
],
79+
]
80+
for location in element.locations:
81+
reference_pc_as_list.append(location)
82+
reference_pc_as_list = geometry.sort_points(reference_pc_as_list)
83+
print(reference_pc_as_list)
6484
reference_skeleton = geometry.Pointcloud(reference_pc_as_list)
6585
best_tree, best_rmse, init_rotation = element.allocate_trees(
6686
db_path=db_path, optimized=False
@@ -80,7 +100,9 @@ def main():
80100
best_tree.create_mesh()
81101

82102
tree_mesh = conversions.convert_carnutes_mesh_to_rhino_mesh(best_tree.mesh)
83-
scriptcontext.doc.Objects.AddMesh(tree_mesh)
103+
attributes = Rhino.DocObjects.ObjectAttributes()
104+
attributes.LayerIndex = layer_ids[i]
105+
scriptcontext.doc.Objects.AddMesh(tree_mesh, attributes)
84106

85107
return all_rmse
86108

src/Carnutes/find_single_tree.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
"""
2-
This is a dummy function, to test out the bones of the project.
2+
This function finds a single tree in the database that best fits the given element.
33
"""
44

55
#! python3
6-
# r: numpy==1.26.4
7-
# r: open3d==0.18.0
6+
7+
# r: numpy==2.0.2
8+
# r: open3d==0.19.0
89
# r: ZODB==6.0
910
# r: igraph==0.11.6
1011

@@ -59,14 +60,15 @@ def main():
5960
"""
6061

6162
# Create the model
62-
current_model = interact_with_rhino.create_model_from_rhino_selection()
63+
current_model, layer_ids = interact_with_rhino.create_model_from_rhino_selection()
6364
if current_model is None:
6465
return
6566

6667
# Ask user which element (s)he wants to replace with a point cloud
6768
(
6869
element_geometry,
6970
element_guid,
71+
layer_index,
7072
) = interact_with_rhino.select_single_element_to_replace()
7173

7274
for element in current_model.elements:
@@ -75,7 +77,18 @@ def main():
7577
reference_diameter = element.diameter
7678
break
7779

78-
reference_pc_as_list = []
80+
reference_pc_as_list = [
81+
[
82+
target.geometry.PointAtStart.X,
83+
target.geometry.PointAtStart.Y,
84+
target.geometry.PointAtStart.Z,
85+
],
86+
[
87+
target.geometry.PointAtEnd.X,
88+
target.geometry.PointAtEnd.Y,
89+
target.geometry.PointAtEnd.Z,
90+
],
91+
]
7992
# if isinstance(target.geometry, Rhino.Geometry.NurbsCurve):
8093
for vertex in current_model.connectivity_graph.graph.vs:
8194
if vertex["guid"] == target.GUID:
@@ -117,7 +130,9 @@ def main():
117130
my_tree.create_mesh()
118131

119132
tree_mesh = conversions.convert_carnutes_mesh_to_rhino_mesh(my_tree.mesh)
120-
scriptcontext.doc.Objects.AddMesh(tree_mesh)
133+
attributes = Rhino.DocObjects.ObjectAttributes()
134+
attributes.LayerIndex = layer_index
135+
scriptcontext.doc.Objects.AddMesh(tree_mesh, attributes)
121136

122137

123138
if __name__ == "__main__":

src/Carnutes/output_database.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
#! python3
66

7-
# r: numpy==1.26.4
8-
# r: open3d==0.18.0
7+
# r: numpy==2.0.2
8+
# r: open3d==0.19.0
99
# r: ZODB==6.0
1010
# r: igraph==0.11.6
1111

src/Carnutes/reset_database.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,18 @@
33
"""
44

55
#! python3
6-
# r: numpy==1.26.4
7-
# r: open3d==0.18.0
6+
7+
# r: numpy==2.0.2
8+
# r: open3d==0.19.0
89
# r: ZODB==6.0
910
# r: igraph==0.11.6
1011

11-
import ZODB
12-
import ZODB.FileStorage
1312
import open3d as o3d
1413

1514
# import Rhino
1615

1716
import os
1817
import transaction
19-
import BTrees.OOBTree
2018
import time
2119

2220
import utils.tree as tree

src/Carnutes/utils/element.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,21 @@ def allocate_trees(self, db_path: str, optimized: bool = False):
113113
"The diameter of the element is not set. Check the layer name of the element in Rhino."
114114
)
115115
target_diameter = self.diameter
116-
reference_pc_as_list = geometry.sort_points(self.locations)
116+
reference_pc_as_list = [
117+
[
118+
self.geometry.PointAtStart.X,
119+
self.geometry.PointAtStart.Y,
120+
self.geometry.PointAtStart.Z,
121+
],
122+
[
123+
self.geometry.PointAtEnd.X,
124+
self.geometry.PointAtEnd.Y,
125+
self.geometry.PointAtEnd.Z,
126+
],
127+
]
128+
for location in self.locations:
129+
reference_pc_as_list.append(location)
130+
reference_pc_as_list = geometry.sort_points(reference_pc_as_list)
117131
reference_skeleton = geometry.Pointcloud(reference_pc_as_list)
118132
if optimized:
119133
(

src/Carnutes/utils/interact_with_rhino.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from utils import model, warnings, geometry, element
2-
from utils.element import Element
32
import Rhino
43

54

@@ -35,6 +34,8 @@ def create_model_from_rhino_selection(max_elements: int = 100000):
3534
The maximum number of elements that can be selected. Default is 100000.
3635
:return: model.Model
3736
The model created from the selected geometries.
37+
:return: Rhino.DocObjects.Layer.LayerIndex
38+
The layer index of the selected geometries.
3839
"""
3940

4041
go = Rhino.Input.Custom.GetObject()
@@ -73,10 +74,12 @@ def create_model_from_rhino_selection(max_elements: int = 100000):
7374
Rhino.RhinoDoc.ActiveDoc.Layers[layer_id].Name for layer_id in layer_ids
7475
]
7576
elements = [
76-
Element(converted_geometries[i], go.Object(i).ObjectId, float(layer_names[i]))
77+
element.Element(
78+
converted_geometries[i], go.Object(i).ObjectId, float(layer_names[i])
79+
)
7780
for i in range(go.ObjectCount)
7881
]
79-
return model.Model(elements)
82+
return model.Model(elements), layer_ids
8083

8184

8285
def select_single_element_to_replace():
@@ -87,6 +90,8 @@ def select_single_element_to_replace():
8790
The geometry of the selected element.
8891
:return: str
8992
The GUID of the selected element.
93+
:return: int
94+
The layer index of the selected element.
9095
"""
9196
go = Rhino.Input.Custom.GetObject()
9297
go.SetCommandPrompt("Select the element to replace with a point cloud")
@@ -96,10 +101,11 @@ def select_single_element_to_replace():
96101
go.GetMultiple(1, 1)
97102
element_geometry = go.Object(0).Geometry()
98103
element_guid = go.Object(0).ObjectId
104+
layer_index = go.Object(0).Object().Attributes.LayerIndex
99105
if go.CommandResult() != Rhino.Commands.Result.Success:
100106
print("No object selected.")
101107
return
102-
return element_geometry, element_guid
108+
return element_geometry, element_guid, layer_index
103109

104110

105111
def generic_object_getter(

0 commit comments

Comments
 (0)