Skip to content

Commit ce3ae67

Browse files
committed
WIP-ADD meshcloud comparison
1 parent d5873d3 commit ce3ae67

File tree

9 files changed

+4175
-6897
lines changed

9 files changed

+4175
-6897
lines changed

src/gh/components/DF_cloud_to_mesh_distance/code.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,17 @@
1111
from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML
1212

1313
import diffCheck
14-
from diffCheck import diffcheck_bindings
1514
from diffCheck import df_cvt_bindings
1615
from diffCheck import df_error_estimation
16+
from diffCheck.df_geometries import DFBeam
1717

1818

1919
class CloudToMeshDistance(component):
2020
def RunScript(self,
21-
i_cloud_source: rg.PointCloud,
22-
i_beam,
23-
i_signed_flag: bool):
21+
i_cloud_source: typing.List[rg.PointCloud],
22+
i_beam: typing.List[DFBeam],
23+
i_signed_flag: bool,
24+
i_swap: bool):
2425
"""
2526
The cloud-to-cloud component computes the distance between each point in the source point cloud and its nearest neighbour in thr target point cloud.
2627
@@ -35,25 +36,23 @@ def RunScript(self,
3536
if i_cloud_source is None or i_beam is None:
3637
ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide an object of type point cloud and an object of type mesh to compare")
3738
return None
39+
3840

3941
# conversion
40-
df_cloud_source = df_cvt_bindings.cvt_rhcloud_2_dfcloud(i_cloud_source)
41-
rhino_mesh_target = i_beam.to_mesh()
42-
df_mesh_target = df_cvt_bindings.cvt_rhmesh_2_dfmesh(rhino_mesh_target)
42+
df_cloud_source_list = [df_cvt_bindings.cvt_rhcloud_2_dfcloud(i_cl_s) for i_cl_s in i_cloud_source]
43+
df_mesh_target_list = [beam.to_mesh() for beam in i_beam]
4344

4445
# calculate distances
45-
o_results = df_error_estimation.cloud_2_mesh_distance(df_cloud_source, df_mesh_target, i_signed_flag)
46-
47-
o_mesh = rhino_mesh_target
48-
49-
return o_distances.tolist(), o_mse, o_max_deviation, o_min_deviation, o_mesh
46+
o_results = df_error_estimation.cloud_2_rhino_mesh_comparison(df_cloud_source_list, df_mesh_target_list, i_signed_flag, i_swap)
5047

48+
return o_results.distances, o_results.distances_mse, o_results.distances_max_deviation, o_results.distances_min_deviation, o_results.distances_sd_deviation, o_results
5149

5250

5351
if __name__ == "__main__":
5452
com = CloudToMeshDistance()
55-
o_distances, o_mse, o_max_deviation, o_min_deviation, o_mesh = com.RunScript(
53+
o_distances, o_mse, o_max_deviation, o_min_deviation, o_std_deviation, o_results = com.RunScript(
5654
i_cloud_source,
57-
i_mesh_target,
58-
i_signed_flag
55+
i_beam,
56+
i_signed_flag,
57+
i_swap
5958
)

src/gh/components/DF_cloud_to_mesh_distance2/code.py renamed to src/gh/components/DF_cloud_to_mesh_distance_archived/code.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,10 @@ def RunScript(self,
3939
# conversion
4040
df_cloud_source = df_cvt_bindings.cvt_rhcloud_2_dfcloud(i_cloud_source)
4141
rhino_mesh_target = i_beam.to_mesh()
42+
df_mesh_target = df_cvt_bindings.cvt_rhmesh_2_dfmesh(rhino_mesh_target)
4243

4344
# calculate distances
44-
o_distances = df_error_estimation.cloud_2_rhino_mesh_distance(df_cloud_source, rhino_mesh_target, i_signed_flag)
45-
o_mse = df_error_estimation.compute_mse(o_distances)
46-
o_max_deviation = df_error_estimation.compute_max_deviation(o_distances)
47-
o_min_deviation = df_error_estimation.compute_min_deviation(o_distances)
45+
o_results = df_error_estimation.cloud_2_mesh_distance(df_cloud_source, df_mesh_target, i_signed_flag)
4846

4947
o_mesh = rhino_mesh_target
5048

src/gh/components/DF_cloud_to_mesh_distance2/icon.png renamed to src/gh/components/DF_cloud_to_mesh_distance_archived/icon.png

File renamed without changes.

src/gh/components/DF_cloud_to_mesh_distance2/metadata.json renamed to src/gh/components/DF_cloud_to_mesh_distance_archived/metadata.json

File renamed without changes.

src/gh/components/DF_vizualization/code.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,9 @@
1010
import Grasshopper as gh
1111
from Grasshopper.Kernel import GH_RuntimeMessageLevel as RML
1212

13-
import diffCheck
1413
from diffCheck import diffcheck_bindings
1514
from diffCheck import df_cvt_bindings
16-
from diffCheck import df_error_estimation, df_vizualization
17-
18-
import diffCheck.df_util
15+
from diffCheck import df_vizualization
1916

2017

2118
class Vizualization(component):
@@ -26,14 +23,6 @@ def RunScript(self,
2623
sth sth
2724
"""
2825

29-
if i_results.source is None or i_results.target is None:
30-
ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide both objects of type point clouds to compare")
31-
return None
32-
33-
# check if target is a pcl
34-
o_source = [df_cvt_bindings.cvt_dfcloud_2_rhcloud(src) for src in i_results.source]
35-
36-
# by default we color the target
3726
distances_flattened = [item for sublist in i_results.distances for item in sublist]
3827

3928
if i_viz_settings.lower_threshold is not None:
@@ -46,12 +35,24 @@ def RunScript(self,
4635
else:
4736
max_value = max(max(sublist) for sublist in i_results.distances)
4837

49-
# we always color the source
50-
# check if source is a pcd
51-
o_colored_geo = [df_vizualization.color_pcd(src, dist, min_value, max_value) for src, dist in zip(o_source, i_results.distances)]
38+
# check if i_results.source is a list of pointclouds or a mesh
39+
if type(i_results.source[0]) is diffcheck_bindings.dfb_geometry.DFPointCloud:
40+
41+
# convert to Rhino PCD
42+
o_source = [df_cvt_bindings.cvt_dfcloud_2_rhcloud(src) for src in i_results.source]
43+
44+
# color geometry
45+
o_colored_geo = [df_vizualization.color_pcd(src, dist, min_value, max_value) for src, dist in zip(o_source, i_results.distances)]
46+
47+
elif type(i_results.source[0]) is rg.Mesh:
48+
# convert to Rhino Mesh
49+
o_source = i_results.source
50+
51+
# color geometry
52+
o_colored_geo = [df_vizualization.color_mesh(src, dist, min_value, max_value) for src, dist in zip(o_source, i_results.distances)]
5253

5354
o_legend = df_vizualization.create_legend(min_value, max_value)
54-
55+
5556
o_histogram = df_vizualization.create_histogram(distances_flattened, min_value, max_value)
5657

5758
return o_source, o_colored_geo, o_legend, o_histogram

src/gh/diffCheck/diffCheck/df_error_estimation.py

Lines changed: 64 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,95 @@
44
"""
55

66
import numpy as np
7-
import open3d as o3d
87
from diffCheck import diffcheck_bindings
98
import Rhino.Geometry as rg
109

1110

12-
def cloud_2_cloud_distance(source, target, invert=False):
11+
def cloud_2_cloud_comparison(source_list, target_list):
1312
"""
1413
Compute the Euclidean distance for every point of a source pcd to its
1514
closest point on a target pointcloud
1615
"""
17-
if invert:
18-
distances = np.asarray(target.compute_distance(source))
19-
else:
20-
distances = np.asarray(source.compute_distance(target))
16+
results = DFVizResults()
17+
for source, target in zip(source_list, target_list):
18+
distances = cloud_2_cloud_distance(source, target)
19+
results.add(source, target, distances)
20+
21+
return results
22+
2123

22-
return distances
24+
def cloud_2_cloud_distance(source, target):
25+
"""
26+
Compute the Euclidean distance for every point of a source pcd to its
27+
closest point on a target pointcloud
28+
"""
29+
30+
return np.asarray(source.compute_distance(target))
2331

2432

25-
def cloud_2_cloud_comparison(source_list, target_list, invert=False):
33+
def cloud_2_rhino_mesh_comparison(cloud_source_list, rhino_mesh_target_list, signed_flag, swap):
2634
"""
2735
Compute the Euclidean distance for every point of a source pcd to its
2836
closest point on a target pointcloud
2937
"""
3038
results = DFVizResults()
31-
for source, target in zip(source_list, target_list):
32-
distances = cloud_2_cloud_distance(source, target, invert)
33-
results.add(source, target, distances)
39+
40+
for source, target in zip(cloud_source_list, rhino_mesh_target_list):
41+
if swap:
42+
# this mean we want to vizualize the result on the target mesh
43+
distances = rhino_mesh_2_cloud_distance(target, source, signed_flag)
44+
else:
45+
# this means we want to vizualize the result on the source pcd
46+
distances = cloud_2_rhino_mesh_distance(source, target, signed_flag)
47+
48+
if swap:
49+
results.add(target, source, distances)
50+
else:
51+
results.add(source, target, distances)
3452

3553
return results
3654

3755

38-
def cloud_2_mesh_distance(source, target, signed=False):
56+
# def cloud_2_mesh_distance(source, target, signed=False):
57+
# """
58+
# Calculate the distance between every point of a source pcd to its closest point on a target DFMesh
59+
# """
60+
61+
# # for every point on the PCD compute the point_2_mesh_distance
62+
# if signed:
63+
# distances = np.asarray(target.compute_distance(source, is_abs=False))
64+
# else:
65+
# distances = np.asarray(target.compute_distance(source, is_abs=True))
66+
67+
# return distances
68+
69+
def rhino_mesh_2_cloud_distance(source, target, signed=False):
3970
"""
40-
Calculate the distance between every point of a source pcd to its closest point on a target DFMesh
71+
Calculate the distance between every vertex of a Rhino Mesh to its closest point on a PCD
4172
"""
73+
#make a Df point cloud containing all the vertices of the source rhino mesh
74+
df_pcd_from_mesh_vertices = diffcheck_bindings.dfb_geometry.DFPointCloud()
75+
df_pcd_from_mesh_vertices.points = [[pt.X, pt.Y, pt.Z] for pt in source.Vertices]
76+
#calculate the distances
77+
distances = np.asarray(df_pcd_from_mesh_vertices.compute_distance(target))
4278

43-
# for every point on the PCD compute the point_2_mesh_distance
4479
if signed:
45-
distances = np.asarray(target.compute_distance(source, is_abs=False))
46-
else:
47-
distances = np.asarray(target.compute_distance(source, is_abs=True))
80+
for p in target.points:
81+
82+
rhp = rg.Point3d(p[0], p[1], p[2])
83+
closest_meshPoint = source.ClosestMeshPoint(rhp, 1000)
84+
closest_point = closest_meshPoint.Point
85+
distance = rhp.DistanceTo(closest_point)
86+
# Calculate the direction from target to source
87+
direction = rhp - closest_point
88+
# Calculate the signed distance
89+
normal = source.NormalAt(closest_meshPoint)
90+
dot_product = direction * normal
91+
if dot_product < 0:
92+
distance = - distance
93+
94+
return np.asarray(distances)
4895

49-
return distances
5096

5197
def cloud_2_rhino_mesh_distance(source, target, signed=False):
5298
"""
@@ -61,7 +107,6 @@ def cloud_2_rhino_mesh_distance(source, target, signed=False):
61107
rhp = rg.Point3d(p[0], p[1], p[2])
62108
closest_meshPoint = target.ClosestMeshPoint(rhp, 1000)
63109
closest_point = closest_meshPoint.Point
64-
face_Index = closest_meshPoint.FaceIndex
65110
distance = rhp.DistanceTo(closest_point)
66111

67112
if signed:
@@ -78,42 +123,6 @@ def cloud_2_rhino_mesh_distance(source, target, signed=False):
78123
return np.asarray(distances)
79124

80125

81-
# def compute_mse(distances):
82-
# """
83-
# Calculate mean squared distance
84-
# """
85-
# mse = np.sqrt(np.mean(distances ** 2))
86-
87-
# return mse
88-
89-
90-
# def compute_max_deviation(distances):
91-
# """
92-
# Calculate max deviation of distances
93-
# """
94-
# max_deviation = np.max(distances)
95-
96-
# return max_deviation
97-
98-
99-
# def compute_min_deviation(distances):
100-
# """
101-
# Calculate min deviation of distances
102-
# """
103-
104-
# min_deviation = np.min(distances)
105-
106-
# return min_deviation
107-
108-
109-
# def compute_standard_deviation(distances):
110-
# """
111-
# Calculate standard deviation of distances
112-
# """
113-
# standard_deviation = np.std(distances)
114-
115-
# return standard_deviation
116-
117126
class DFVizResults:
118127
"""
119128
This class compiles the resluts of the error estimation into one object

src/gh/diffCheck/diffCheck/df_geometries.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def to_mesh(self):
251251

252252
param = rg.MeshingParameters()
253253
scalef = diffCheck.df_util.get_doc_2_meters_unitf()
254-
param.MaximumEdgeLength = 0.01 / scalef
254+
param.MaximumEdgeLength = 0.1 / scalef
255255
mesh_part = rg.Mesh.CreateFromBrep(f, param)[0] #returns a list of meshes with one element
256256
mesh.Append(mesh_part)
257257

src/gh/diffCheck/diffCheck/df_vizualization.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,24 @@ def value_to_color(value, min_value, max_value):
6767
return interpolate_color(color1, color2, t)
6868

6969

70-
def color_pcd(pcd, values, min_value, max_values):
70+
def color_pcd(pcd, values, min_value, max_value):
7171

7272
for i, p in enumerate(pcd):
73-
mapped_color = value_to_color(values[i], min_value, max_values)
73+
mapped_color = value_to_color(values[i], min_value, max_value)
7474
p.Color = mapped_color
7575
return pcd
7676

7777

78+
def color_mesh(mesh, values, min_value, max_value):
79+
mesh.VertexColors.Clear()
80+
for i, vertex in enumerate(mesh.Vertices):
81+
82+
mapped_color = value_to_color(values[i], min_value, max_value)
83+
mesh.VertexColors.Add(mapped_color.R, mapped_color.G, mapped_color.B)
84+
85+
return mesh
86+
87+
7888
def create_legend(min_value, max_value, steps=10, base_point=rg.Point3d(0, 0, 0),
7989
width=0.5, height=1, spacing=0):
8090
"""
@@ -172,7 +182,6 @@ def create_histogram(values, min_value, max_value, steps=100, base_point=rg.Poin
172182
for i in range(steps+1):
173183

174184
bar_height = frequencies[i] * 0.01 * height
175-
print(bar_height)
176185
points.append(rg.Point3d(x - bar_height - 0.15 , y + i * (spacing + height), z))
177186

178187
# Create the polyline and add it to the histogram geometry

0 commit comments

Comments
 (0)