Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/Carnutes/create_mesh.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""
This function creates a mesh from a Rhino point cloud.
"""

#! python3
# r: numpy==1.26.4
# r: open3d==0.18.0

# r: numpy==2.0.2
# r: open3d==0.19.0
# r: ZODB==6.0
# r: igraph==0.11.6

Expand Down
5 changes: 3 additions & 2 deletions src/Carnutes/database_recap.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
"""

#! python3
# r: numpy==1.26.4
# r: open3d==0.18.0

# r: numpy==2.0.2
# r: open3d==0.19.0
# r: ZODB==6.0
# r: igraph==0.11.6

Expand Down
4 changes: 2 additions & 2 deletions src/Carnutes/draw_connectivity_grah.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

#! python3

# r: numpy==1.26.4
# r: open3d==0.18.0
# r: numpy==2.0.2
# r: open3d==0.19.0
# r: ZODB==6.0
# r: igraph==0.11.6

Expand Down
33 changes: 26 additions & 7 deletions src/Carnutes/find_multiple_trees_with_optimisation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""
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.
"""

#! python3
# r: numpy==1.26.4
# r: open3d==0.18.0

# r: numpy==2.0.2
# r: open3d==0.19.0
# r: ZODB==6.0
# r: igraph==0.11.6

Expand Down Expand Up @@ -59,20 +64,32 @@ def main():
)

# Create the model
current_model = interact_with_rhino.create_model_from_rhino_selection()
current_model, layer_ids = interact_with_rhino.create_model_from_rhino_selection()

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

all_rmse = []

for element in current_model.elements:
for i, element in enumerate(current_model.elements):
if element.type == elem.ElementType.Point:
continue
reference_pc_as_list = []
reference_pc_as_list = [
[
element.geometry.PointAtStart.X,
element.geometry.PointAtStart.Y,
element.geometry.PointAtStart.Z,
],
[
element.geometry.PointAtEnd.X,
element.geometry.PointAtEnd.Y,
element.geometry.PointAtEnd.Z,
],
]
element_guid = element.GUID
target_diameter = element.diameter
reference_pc_as_list = element.locations
for location in element.locations:
reference_pc_as_list.append(location)

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

tree_mesh = conversions.convert_carnutes_mesh_to_rhino_mesh(best_tree.mesh)
scriptcontext.doc.Objects.AddMesh(tree_mesh)
attributes = Rhino.DocObjects.ObjectAttributes()
attributes.LayerIndex = layer_ids[i]
scriptcontext.doc.Objects.AddMesh(tree_mesh, attributes)

return all_rmse

Expand Down
34 changes: 28 additions & 6 deletions src/Carnutes/find_multiple_trees_without_optimisation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""
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.
"""

#! python3
# r: numpy==1.26.4
# r: open3d==0.18.0

# r: numpy==2.0.2
# r: open3d==0.19.0
# r: ZODB==6.0
# r: igraph==0.11.6

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

def main():
# Create the model
current_model = interact_with_rhino.create_model_from_rhino_selection()
current_model, layer_ids = interact_with_rhino.create_model_from_rhino_selection()

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

all_rmse = []

for element in current_model.elements:
for i, element in enumerate(current_model.elements):
if element.type == elem.ElementType.Point:
continue

# at this point the reference_pc_as_list should contain the points, but they are not ordered. We need to order them.
reference_pc_as_list = geometry.sort_points(element.locations)
reference_pc_as_list = [
[
element.geometry.PointAtStart.X,
element.geometry.PointAtStart.Y,
element.geometry.PointAtStart.Z,
],
[
element.geometry.PointAtEnd.X,
element.geometry.PointAtEnd.Y,
element.geometry.PointAtEnd.Z,
],
]
for location in element.locations:
reference_pc_as_list.append(location)
reference_pc_as_list = geometry.sort_points(reference_pc_as_list)
print(reference_pc_as_list)
reference_skeleton = geometry.Pointcloud(reference_pc_as_list)
best_tree, best_rmse, init_rotation = element.allocate_trees(
db_path=db_path, optimized=False
Expand All @@ -80,7 +100,9 @@ def main():
best_tree.create_mesh()

tree_mesh = conversions.convert_carnutes_mesh_to_rhino_mesh(best_tree.mesh)
scriptcontext.doc.Objects.AddMesh(tree_mesh)
attributes = Rhino.DocObjects.ObjectAttributes()
attributes.LayerIndex = layer_ids[i]
scriptcontext.doc.Objects.AddMesh(tree_mesh, attributes)

return all_rmse

Expand Down
27 changes: 21 additions & 6 deletions src/Carnutes/find_single_tree.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"""
This is a dummy function, to test out the bones of the project.
This function finds a single tree in the database that best fits the given element.
"""

#! python3
# r: numpy==1.26.4
# r: open3d==0.18.0

# r: numpy==2.0.2
# r: open3d==0.19.0
# r: ZODB==6.0
# r: igraph==0.11.6

Expand Down Expand Up @@ -59,14 +60,15 @@ def main():
"""

# Create the model
current_model = interact_with_rhino.create_model_from_rhino_selection()
current_model, layer_ids = interact_with_rhino.create_model_from_rhino_selection()
if current_model is None:
return

# Ask user which element (s)he wants to replace with a point cloud
(
element_geometry,
element_guid,
layer_index,
) = interact_with_rhino.select_single_element_to_replace()

for element in current_model.elements:
Expand All @@ -75,7 +77,18 @@ def main():
reference_diameter = element.diameter
break

reference_pc_as_list = []
reference_pc_as_list = [
[
target.geometry.PointAtStart.X,
target.geometry.PointAtStart.Y,
target.geometry.PointAtStart.Z,
],
[
target.geometry.PointAtEnd.X,
target.geometry.PointAtEnd.Y,
target.geometry.PointAtEnd.Z,
],
]
# if isinstance(target.geometry, Rhino.Geometry.NurbsCurve):
for vertex in current_model.connectivity_graph.graph.vs:
if vertex["guid"] == target.GUID:
Expand Down Expand Up @@ -117,7 +130,9 @@ def main():
my_tree.create_mesh()

tree_mesh = conversions.convert_carnutes_mesh_to_rhino_mesh(my_tree.mesh)
scriptcontext.doc.Objects.AddMesh(tree_mesh)
attributes = Rhino.DocObjects.ObjectAttributes()
attributes.LayerIndex = layer_index
scriptcontext.doc.Objects.AddMesh(tree_mesh, attributes)


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions src/Carnutes/output_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

#! python3

# r: numpy==1.26.4
# r: open3d==0.18.0
# r: numpy==2.0.2
# r: open3d==0.19.0
# r: ZODB==6.0
# r: igraph==0.11.6

Expand Down
8 changes: 3 additions & 5 deletions src/Carnutes/reset_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@
"""

#! python3
# r: numpy==1.26.4
# r: open3d==0.18.0

# r: numpy==2.0.2
# r: open3d==0.19.0
# r: ZODB==6.0
# r: igraph==0.11.6

import ZODB
import ZODB.FileStorage
import open3d as o3d

# import Rhino

import os
import transaction
import BTrees.OOBTree
import time

import utils.tree as tree
Expand Down
16 changes: 15 additions & 1 deletion src/Carnutes/utils/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,21 @@ def allocate_trees(self, db_path: str, optimized: bool = False):
"The diameter of the element is not set. Check the layer name of the element in Rhino."
)
target_diameter = self.diameter
reference_pc_as_list = geometry.sort_points(self.locations)
reference_pc_as_list = [
[
self.geometry.PointAtStart.X,
self.geometry.PointAtStart.Y,
self.geometry.PointAtStart.Z,
],
[
self.geometry.PointAtEnd.X,
self.geometry.PointAtEnd.Y,
self.geometry.PointAtEnd.Z,
],
]
for location in self.locations:
reference_pc_as_list.append(location)
reference_pc_as_list = geometry.sort_points(reference_pc_as_list)
reference_skeleton = geometry.Pointcloud(reference_pc_as_list)
if optimized:
(
Expand Down
14 changes: 10 additions & 4 deletions src/Carnutes/utils/interact_with_rhino.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from utils import model, warnings, geometry, element
from utils.element import Element
import Rhino


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

go = Rhino.Input.Custom.GetObject()
Expand Down Expand Up @@ -73,10 +74,12 @@ def create_model_from_rhino_selection(max_elements: int = 100000):
Rhino.RhinoDoc.ActiveDoc.Layers[layer_id].Name for layer_id in layer_ids
]
elements = [
Element(converted_geometries[i], go.Object(i).ObjectId, float(layer_names[i]))
element.Element(
converted_geometries[i], go.Object(i).ObjectId, float(layer_names[i])
)
for i in range(go.ObjectCount)
]
return model.Model(elements)
return model.Model(elements), layer_ids


def select_single_element_to_replace():
Expand All @@ -87,6 +90,8 @@ def select_single_element_to_replace():
The geometry of the selected element.
:return: str
The GUID of the selected element.
:return: int
The layer index of the selected element.
"""
go = Rhino.Input.Custom.GetObject()
go.SetCommandPrompt("Select the element to replace with a point cloud")
Expand All @@ -96,10 +101,11 @@ def select_single_element_to_replace():
go.GetMultiple(1, 1)
element_geometry = go.Object(0).Geometry()
element_guid = go.Object(0).ObjectId
layer_index = go.Object(0).Object().Attributes.LayerIndex
if go.CommandResult() != Rhino.Commands.Result.Success:
print("No object selected.")
return
return element_geometry, element_guid
return element_geometry, element_guid, layer_index


def generic_object_getter(
Expand Down
Loading