Skip to content

Commit 6bfa7f6

Browse files
committed
WIP-ADD: use Rhino rTree to find the index of the closest neighbor
1 parent 58fcd31 commit 6bfa7f6

File tree

11 files changed

+204
-138
lines changed

11 files changed

+204
-138
lines changed

src/gh/components/DF_cloud_to_cloud_distance/code.py renamed to src/gh/components/DF_cloud_cloud_distance/code.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import diffCheck.df_util
1818

1919

20-
class CloudToCloudDistance(component):
20+
class CloudCloudDistance(component):
2121
def RunScript(self,
2222
i_cloud_source: typing.List[rg.PointCloud],
2323
i_cloud_target: typing.List[rg.PointCloud],
@@ -26,25 +26,26 @@ def RunScript(self,
2626
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.
2727
2828
:param i_cloud_source: a list of source point cloud
29-
:param i_cloud_target: a list of target point cloud to align to
29+
:param i_cloud_target: a list of target point cloud to calculate distances to
3030
3131
:return o_distances : list of calculated distances for each point
3232
:return o_mse: the average squared difference between corresponding points of source and target
33-
:return o_max_deviation: the max deviation between source and target (Hausdorff Distance)
33+
:return o_max_deviation: the max deviation between source and target
3434
:return o_min_deviation: the min deviation between source and target
3535
:return o_std_deviation: the standard deviation between source and target
36+
:returns o_resluts: the results of the comparison all in one object
3637
"""
3738

3839
if i_cloud_source is None or i_cloud_target is None:
3940
ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide both objects of type point clouds to compare")
4041
return None
41-
42+
4243
# swap
4344
if i_swap is True:
4445
temp = i_cloud_source
4546
i_cloud_source = i_cloud_target
4647
i_cloud_target = temp
47-
48+
4849
# conversion
4950
df_cloud_source_list = [df_cvt_bindings.cvt_rhcloud_2_dfcloud(i_cl_s) for i_cl_s in i_cloud_source]
5051
df_cloud_target_list = [df_cvt_bindings.cvt_rhcloud_2_dfcloud(i_cl_t) for i_cl_t in i_cloud_target]
@@ -56,7 +57,7 @@ def RunScript(self,
5657

5758

5859
if __name__ == "__main__":
59-
com = CloudToCloudDistance()
60+
com = CloudCloudDistance()
6061
o_distances, o_mse, o_max_deviation, o_min_deviation, o_std_deviation, o_results = com.RunScript(
6162
i_cloud_source,
6263
i_cloud_target,
File renamed without changes.

src/gh/components/DF_cloud_to_cloud_distance/metadata.json renamed to src/gh/components/DF_cloud_cloud_distance/metadata.json

File renamed without changes.

src/gh/components/DF_cloud_to_mesh_distance/code.py renamed to src/gh/components/DF_cloud_mesh_distance/code.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,30 @@
1616
from diffCheck.df_geometries import DFBeam
1717

1818

19-
class CloudToMeshDistance(component):
19+
class CloudMeshDistance(component):
2020
def RunScript(self,
2121
i_cloud_source: typing.List[rg.PointCloud],
2222
i_beam: typing.List[DFBeam],
2323
i_signed_flag: bool,
2424
i_swap: bool):
25+
2526
"""
2627
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.
2728
28-
:param i_cloud_source: source point cloud
29-
:param i_mesh_target: target point cloud to align to
29+
:param i_cloud_source: a list of point clouds
30+
:param i_beam: a list of DF beams
31+
:param i_signed_flag: calculate the sign of the distances
32+
:param i_swap: swap source and target
3033
3134
:return o_distances : list of calculated distances for each point
3235
:return o_mse: the average squared difference between corresponding points of source and target
33-
:return o_max_deviation: the max deviation between source and target (Hausdorff Distance)
36+
:return o_max_deviation: the max deviation between source and target
3437
:return o_min_deviation: the min deviation between source and target
38+
:returns o_resluts: the results of the comparison all in one object
3539
"""
3640
if i_cloud_source is None or i_beam is None:
3741
ghenv.Component.AddRuntimeMessage(RML.Warning, "Please provide an object of type point cloud and an object of type mesh to compare")
3842
return None
39-
4043

4144
# conversion
4245
df_cloud_source_list = [df_cvt_bindings.cvt_rhcloud_2_dfcloud(i_cl_s) for i_cl_s in i_cloud_source]
@@ -49,7 +52,7 @@ def RunScript(self,
4952

5053

5154
if __name__ == "__main__":
52-
com = CloudToMeshDistance()
55+
com = CloudMeshDistance()
5356
o_distances, o_mse, o_max_deviation, o_min_deviation, o_std_deviation, o_results = com.RunScript(
5457
i_cloud_source,
5558
i_beam,
File renamed without changes.

src/gh/components/DF_cloud_to_mesh_distance/metadata.json renamed to src/gh/components/DF_cloud_mesh_distance/metadata.json

File renamed without changes.

src/gh/components/DF_vizualization/code.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ def RunScript(self,
2020
i_results,
2121
i_viz_settings):
2222
"""
23-
Adds color to the mesh or point cloud and generates a corresponding legend and histogram
23+
Adds color to the mesh or point cloud
24+
and generates a corresponding legend and histogram
2425
"""
2526

2627
values, min_value, max_value = df_vizualization.filter_values_based_on_valuetype(i_results, i_viz_settings)

src/gh/components/DF_vizualization_settings/code.py

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

13-
import diffCheck
1413
from diffCheck import df_vizualization
1514

16-
import diffCheck.df_util
17-
18-
1915
class VisualizationSettings(component):
2016
def RunScript(self,
2117
i_value_type,
@@ -39,13 +35,13 @@ def RunScript(self,
3935
if i_histogram_scale_factor is None: i_histogram_scale_factor = 0.01
4036

4137
# pack settings
42-
o_viz_settings = df_vizualization.DFVizSettings(i_value_type,
43-
i_upper_threshold,
44-
i_lower_threshold,
45-
i_palette,
46-
i_legend_height,
47-
i_legend_width,
48-
i_legend_plane,
38+
o_viz_settings = df_vizualization.DFVizSettings(i_value_type,
39+
i_upper_threshold,
40+
i_lower_threshold,
41+
i_palette,
42+
i_legend_height,
43+
i_legend_width,
44+
i_legend_plane,
4945
i_histogram_scale_factor)
5046

5147
return o_viz_settings

src/gh/diffCheck/diffCheck/df_error_estimation.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,15 @@ def cloud_2_cloud_comparison(source_list, target_list):
1515
"""
1616
results = DFVizResults()
1717
for source, target in zip(source_list, target_list):
18-
distances = cloud_2_cloud_distance(source, target)
18+
distances = np.asarray(source.compute_distance(target))
1919
results.add(source, target, distances)
2020

2121
return results
2222

2323

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))
31-
32-
3324
def cloud_2_rhino_mesh_comparison(cloud_source_list, rhino_mesh_target_list, signed_flag, swap):
3425
"""
35-
Compute the Euclidean distance for every point of a source pcd to its
36-
closest point on a target pointcloud
26+
Computes distances between a pcd and a mesh
3727
"""
3828
results = DFVizResults()
3929

@@ -66,30 +56,48 @@ def cloud_2_rhino_mesh_comparison(cloud_source_list, rhino_mesh_target_list, sig
6656

6757
# return distances
6858

59+
6960
def rhino_mesh_2_cloud_distance(source, target, signed=False):
7061
"""
7162
Calculate the distance between every vertex of a Rhino Mesh to its closest point on a PCD
7263
"""
73-
#make a Df point cloud containing all the vertices of the source rhino mesh
64+
# make a Df point cloud containing all the vertices of the source rhino mesh
7465
df_pcd_from_mesh_vertices = diffcheck_bindings.dfb_geometry.DFPointCloud()
7566
df_pcd_from_mesh_vertices.points = [[pt.X, pt.Y, pt.Z] for pt in source.Vertices]
76-
#calculate the distances
67+
# calculate the distances
7768
distances = np.asarray(df_pcd_from_mesh_vertices.compute_distance(target))
7869

7970
if signed:
71+
# build an RTree containing all the points of the target
72+
tree = rg.RTree()
73+
for i, ver in enumerate(target.points):
74+
tree.Insert(rg.Point3d(ver[0], ver[1], ver[2]), i)
75+
8076
for idx, p in enumerate(source.Vertices):
8177

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)
78+
# find the index on the target that the vertex is closest to
79+
search_point = p
80+
sphere = rg.Sphere(search_point, distances[idx]*1.0001)
81+
found_indices = []
82+
83+
# what if we find 2 indices
84+
if len(found_indices) > 1:
85+
pass
86+
87+
def search_callback(sender, e):
88+
found_indices.append(e.Id)
89+
90+
tree.Search(sphere, search_callback)
91+
92+
df_closest_point = target.points[found_indices[0]]
93+
closest_point = rg.Point3d(df_closest_point[0], df_closest_point[1], df_closest_point[2])
8694
# Calculate the direction from target to source
87-
direction = rhp - closest_point
95+
direction = p - closest_point
8896
# Calculate the signed distance
89-
normal = source.NormalAt(closest_meshPoint)
97+
normal = source.Normals[idx]
9098
dot_product = direction * normal
9199
if dot_product < 0:
92-
distances[idx] = - distance
100+
distances[idx] = - distances[idx]
93101

94102
return np.asarray(distances)
95103

src/gh/diffCheck/diffCheck/df_vizualization.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from System.Drawing import Color
88
from diffCheck import df_vizualization
99

10+
1011
class DFVizSettings:
1112
"""
1213
This class compiles the settings for the vizualization into one object
@@ -66,6 +67,7 @@ def __init__(self, name):
6667
Color.FromArgb(248, 230, 33)
6768
]
6869

70+
6971
def interpolate_color(color1, color2, t):
7072
"""
7173
Interpolate between two colors.
@@ -74,6 +76,7 @@ def interpolate_color(color1, color2, t):
7476
r = int(color1.R + (color2.R - color1.R) * t)
7577
g = int(color1.G + (color2.G - color1.G) * t)
7678
b = int(color1.B + (color2.B - color1.B) * t)
79+
7780
return Color.FromArgb(r, g, b)
7881

7982

@@ -96,7 +99,7 @@ def value_to_color(value, min_value, max_value, palette):
9699
t = (value - min_value) / (max_value - min_value)
97100

98101
# Determine the segment in the colormap
99-
n = len(colormap)- 1
102+
n = len(colormap) - 1
100103
idx = int(t * n)
101104
if idx >= n:
102105
idx = n - 1
@@ -132,7 +135,7 @@ def color_mesh(mesh, values, min_value, max_value, palette):
132135
"""
133136

134137
mesh.VertexColors.Clear()
135-
138+
136139
for i, vertex in enumerate(mesh.Vertices):
137140
# check if values is a list
138141
if isinstance(values, list):
@@ -163,9 +166,9 @@ def create_legend(min_value, max_value, palette, steps=10, plane=rg.Plane.WorldX
163166
mesh = rg.Mesh()
164167
for pt in rect_pts:
165168
mesh.Vertices.Add(pt)
166-
# color mesh
169+
167170
mesh.Faces.AddFace(0, 1, 2, 3)
168-
171+
# color mesh
169172
mesh.VertexColors.Add(previous_color.R, previous_color.G, previous_color.B)
170173
mesh.VertexColors.Add(previous_color.R, previous_color.G, previous_color.B)
171174
mesh.VertexColors.Add(color.R, color.G, color.B)
@@ -200,7 +203,9 @@ def create_legend(min_value, max_value, palette, steps=10, plane=rg.Plane.WorldX
200203
return legend_geometry
201204

202205

203-
def create_histogram(values, min_value, max_value, steps=100, plane=rg.Plane.WorldXY, total_height=10, scaling_factor = 0.01, spacing=0):
206+
def create_histogram(values, min_value, max_value, steps=100,
207+
plane=rg.Plane.WorldXY, total_height=10,
208+
scaling_factor=0.01, spacing=0):
204209
"""
205210
Create a histogram in Rhino with a polyline representing value frequencies.
206211
"""
@@ -261,7 +266,7 @@ def filter_values_based_on_valuetype(results, settings):
261266
values = results.distances_mse
262267
min_value = min(values)
263268
max_value = max(values)
264-
269+
265270
elif settings.valueType == "MAX":
266271

267272
values = results.distances_max_deviation

0 commit comments

Comments
 (0)