Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dd62996
feat: bump up version from 1.3.0 to 1.3.1 in manifest.yml
DamienGilliard Jul 10, 2025
efa2582
Update manifest.yml
DamienGilliard Jul 10, 2025
227504f
Merge pull request #156 from diffCheckOrg/DamienGilliard-patch-2
DamienGilliard Jul 10, 2025
21f34f2
Update manifest.yml
DamienGilliard Jul 10, 2025
efdca84
Update manifest.yml
DamienGilliard Jul 10, 2025
b985813
ACTION_BOT: Sync version for release (#158)
github-actions[bot] Jul 10, 2025
8f668b1
Merge pull request #157 from diffCheckOrg/DamienGilliard-patch-2
eleniv3d Jul 11, 2025
e2dead4
feat-wip: creation of pose comparison component
DamienGilliard Aug 7, 2025
cdef3ba
fix: remove unneeded markdown file
DamienGilliard Aug 7, 2025
9475b6e
feat: add a plane property to beams, automatically computed and with …
DamienGilliard Oct 28, 2025
7348919
feat: bump up version from 1.3.0 to 1.3.1 in manifest.yml
DamienGilliard Jul 10, 2025
f15c055
Update manifest.yml
DamienGilliard Jul 10, 2025
0c3835d
ACTION_BOT: Sync version for release (#158)
github-actions[bot] Jul 10, 2025
3d1be89
Update manifest.yml
DamienGilliard Jul 10, 2025
63feaf7
Update manifest.yml
DamienGilliard Jul 10, 2025
eb0b20d
feat-wip: creation of pose comparison component
DamienGilliard Aug 7, 2025
b2a10b3
fix: remove unneeded markdown file
DamienGilliard Aug 7, 2025
af989eb
feat: add a plane property to beams, automatically computed and with …
DamienGilliard Oct 28, 2025
28d6bb2
feat-wip: use assembly instead of explicit list of planes
DamienGilliard Oct 28, 2025
b97e8c6
rebasing to release/2.0.0 so the pose comparison component has the la…
DamienGilliard Oct 28, 2025
c1f2c86
feat: remove unneeded message about evaluation during assembly of aft…
DamienGilliard Oct 28, 2025
b466cd1
fix: rebase variable name mixup
DamienGilliard Oct 28, 2025
32d9456
feat: update metadata of pose comparison conponent
DamienGilliard Oct 28, 2025
0500f54
feat: adapt pose comparison component so it also works with the full …
DamienGilliard Oct 30, 2025
12bd9e3
feat: remove type hint for i_measured_poses so it takes datatree as well
DamienGilliard Oct 30, 2025
5683c05
fix: use plane instead of pose
DamienGilliard Oct 30, 2025
6660ecb
fix: use consistent naming between pose estimation and pose comparison
DamienGilliard Oct 30, 2025
e0e314c
feat-fix: pose comparison takes (or converts to) data tree as input a…
DamienGilliard Oct 30, 2025
5beaaaf
fix: more robust check for validity of poses that are used in the pos…
DamienGilliard Jan 7, 2026
8c54bc5
fix: create DFBeam base plane with coherent orientation with plane de…
DamienGilliard Jan 8, 2026
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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.16.)
project(diffCheck VERSION 1.3.0 LANGUAGES CXX C)
project(diffCheck VERSION 1.3.1 LANGUAGES CXX C)
set(CMAKE_CXX_STANDARD 17)

list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
Expand Down
2 changes: 1 addition & 1 deletion deps/eigen
Submodule eigen updated from 81044e to 954e21
2 changes: 1 addition & 1 deletion manifest.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: diffCheck
version: 1.3.0
version: 1.3.1
authors:
- Andrea Settimi
- Damien Gilliard
Expand Down
73 changes: 73 additions & 0 deletions src/gh/components/DF_pose_comparison/code.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""Compares CAD poses with measured poses to compute errors."""
#! python3

import Rhino
import Grasshopper
from ghpythonlib.componentbase import executingcomponent as component
import ghpythonlib.treehelpers as th

import diffCheck.df_geometries
import numpy

def compute_comparison(measured_pose, cad_pose):
cad_origin = cad_pose.Origin
measured_origin = measured_pose.Origin
distance = cad_origin.DistanceTo(measured_origin)

# Compare the orientations using the formula: $$ \theta = \arccos\left(\frac{\text{trace}(R_{\text{pred}}^T R_{\text{meas}}) - 1}{2}\right) $$
transform_o_to_cad = Rhino.Geometry.Transform.PlaneToPlane(Rhino.Geometry.Plane.WorldXY, cad_pose)
transform_o_to_measured = Rhino.Geometry.Transform.PlaneToPlane(Rhino.Geometry.Plane.WorldXY, measured_pose)
np_transform_o_to_cad = numpy.array(transform_o_to_cad.ToDoubleArray(rowDominant=True)).reshape((4, 4))
np_transform_o_to_measured = numpy.array(transform_o_to_measured.ToDoubleArray(rowDominant=True)).reshape((4, 4))

R_cad = np_transform_o_to_cad[:3, :3]
R_measured = np_transform_o_to_measured[:3, :3]
R_rel = numpy.dot(R_cad.T, R_measured)
theta = numpy.arccos(numpy.clip((numpy.trace(R_rel) - 1) / 2, -1.0, 1.0))

# Compute the transformation matrix between the CAD pose and the measured pose
transform_cad_to_measured = Rhino.Geometry.Transform.PlaneToPlane(cad_pose, measured_pose)
return distance, theta, transform_cad_to_measured

class DFPoseComparison(component):
def RunScript(self, i_assembly: diffCheck.df_geometries.DFAssembly, i_measured_planes: Grasshopper.DataTree[object]):

CAD_poses = [beam.plane for beam in i_assembly.beams]

o_distances = []
o_angles = []
o_transforms_cad_to_measured = []
# Compare the origins
# measure the distance between the origins of the CAD pose and the measured pose and output this in the component

bc = i_measured_planes.BranchCount
if bc > 1:
poses_per_beam = i_measured_planes.Branches
for beam_id, poses in enumerate(poses_per_beam):
o_distances.append(bc * [])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably the bc is not needed here.. bc * [ ] = [ ] Not a problem just confusing :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If bc > 1, it means the full history has been given to compare with, so each of the N beam we have N poses to compare with. It sems to me we need the bc * []

o_angles.append(bc * [])
o_transforms_cad_to_measured.append(bc * [])
for pose in poses:
if not pose or not pose.IsValid:
o_distances[beam_id].append(None)
o_angles[beam_id].append(None)
o_transforms_cad_to_measured[beam_id].append(None)
else:
dist, angle, transform_cad_to_measured = compute_comparison(pose, CAD_poses[beam_id])
o_distances[beam_id].append(dist)
o_angles[beam_id].append(angle)
o_transforms_cad_to_measured[beam_id].append(transform_cad_to_measured)
else:
i_measured_planes.Flatten()
measured_plane_list = th.tree_to_list(i_measured_planes)
print(measured_plane_list)
for i, plane in enumerate(measured_plane_list):
dist, angle, transform_cad_to_measured = compute_comparison(plane, CAD_poses[i])
o_distances.append(dist)
o_angles.append(angle)
o_transforms_cad_to_measured.append(transform_cad_to_measured)

if bc == 1:
return o_distances, o_angles, o_transforms_cad_to_measured
else:
return th.list_to_tree(o_distances), th.list_to_tree(o_angles), th.list_to_tree(o_transforms_cad_to_measured)
Binary file added src/gh/components/DF_pose_comparison/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions src/gh/components/DF_pose_comparison/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"name": "DFPoseComparison",
"nickname": "DFPoseComparison",
"category": "diffCheck",
"subcategory": "Analysis",
"description": "Compares CAD poses with measured poses to compute errors.",
"exposure": 4,
"instanceGuid": "13d76641-6f4f-4e78-a7dd-e64e176ffb2a",
"ghpython": {
"hideOutput": true,
"hideInput": true,
"isAdvancedMode": true,
"marshalOutGuids": true,
"iconDisplay": 2,
"inputParameters": [
{
"name": "i_assembly",
"nickname": "i_assembly",
"description": "The DFAssembly of the structure.",
"optional": false,
"allowTreeAccess": true,
"showTypeHints": true,
"scriptParamAccess": "item",
"wireDisplay": "default",
"sourceCount": 0,
"typeHintID": "ghdoc"
},
{
"name": "i_measured_planes",
"nickname": "i_measured_planes",
"description": "The measured planes (aka poses) to compare against the CAD planes.",
"optional": false,
"allowTreeAccess": true,
"showTypeHints": true,
"scriptParamAccess": "tree",
"wireDisplay": "default",
"sourceCount": 0
}
],
"outputParameters": [
{
"name": "o_distances",
"nickname": "o_distances",
"description": "The distances between the CAD pose origins and measured pose origins.",
"optional": false,
"sourceCount": 0,
"graft": false
},
{
"name": "o_angles",
"nickname": "o_angles",
"description": "The angles between the CAD pose orientations and measured pose orientations.",
"optional": false,
"sourceCount": 0,
"graft": false
},
{
"name": "o_transforms_cad_to_measured",
"nickname": "o_transforms_cad_to_measured",
"description": "The transformation matrices from CAD poses to measured poses.",
"optional": false,
"sourceCount": 0,
"graft": false
}
]
}
}
4 changes: 2 additions & 2 deletions src/gh/components/DF_pose_estimation/metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@
],
"outputParameters": [
{
"name": "o_planes",
"nickname": "o_planes",
"name": "o_measured_planes",
"nickname": "o_measured_planes",
"description": "The resulting planes of the pose estimation in the last iteration.",
"optional": false,
"sourceCount": 0,
Expand Down
2 changes: 1 addition & 1 deletion src/gh/diffCheck/diffCheck/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os

__version__ = "1.3.0"
__version__ = "1.3.1"

# make the dlls available to the python interpreter
PATH_TO_DLL = "dlls"
Expand Down
30 changes: 14 additions & 16 deletions src/gh/diffCheck/diffCheck/df_geometries.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ def __post_init__(self):

self._center: rg.Point3d = None
self._axis: rg.Line = self.compute_axis()
self.plane: rg.Plane = self.compute_plane()
self._plane: rg.Plane = self.compute_plane()
self._length: float = self._axis.Length

self.__uuid = uuid.uuid4().int
Expand Down Expand Up @@ -516,25 +516,18 @@ def compute_axis(self, is_unitized: bool = True) -> rg.Line:

def compute_plane(self) -> rg.Plane:
"""
This function computes the plane of the beam based on its axis and the first joint's center.
The plane is oriented along the beam's axis.
This is an utility function that computes the plane of the beam.
The plane is calculated using the beam's axis and the world Z axis.

:return plane: The plane of the beam
"""
if not self.joints:
raise ValueError("The beam has no joints to compute a plane")
beam_direction = self.axis.Direction
df_faces = [face for face in self.faces]
sorted_df_faces = sorted(df_faces, key=lambda face: Rhino.Geometry.AreaMassProperties.Compute(face._rh_brepface).Area if face._rh_brepface else 0, reverse=True)
largest_side_face_normal = sorted_df_faces[0].normal
rh_largest_side_face_normal = rg.Vector3d(largest_side_face_normal[0], largest_side_face_normal[1], largest_side_face_normal[2])

#main axis as defined above
main_direction = self.compute_axis().Direction

#secondary axis as normal to the largest face of the beam
largest_face = max(self.faces, key=lambda f: f.area)
secondary_axis = largest_face.normal
secondary_vector = rg.Vector3d(secondary_axis[0], secondary_axis[1], secondary_axis[2])
first_vector = rg.Vector3d.CrossProduct(main_direction, secondary_vector)
origin = self.center

return rg.Plane(origin, first_vector, secondary_vector)
return rg.Plane(self.center, rg.Vector3d.CrossProduct(beam_direction, rh_largest_side_face_normal), rh_largest_side_face_normal)

def compute_joint_distances_to_midpoint(self) -> typing.List[float]:
"""
Expand Down Expand Up @@ -696,6 +689,11 @@ def axis(self):
self._axis = self.compute_axis()
return self._axis

@property
def plane(self):
self._plane = self.compute_plane()
return self._plane

@property
def length(self):
self._length = self._axis.Length
Expand Down
2 changes: 1 addition & 1 deletion src/gh/diffCheck/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

setup(
name="diffCheck",
version="1.3.0",
version="1.3.1",
packages=find_packages(),
install_requires=[
"numpy",
Expand Down
Loading