Skip to content

Fix/plane detection and joint detection - #182

Open
DamienGilliard wants to merge 10 commits into
release/2.0.0from
fix/plane_detection_and_joint_detection
Open

Fix/plane detection and joint detection#182
DamienGilliard wants to merge 10 commits into
release/2.0.0from
fix/plane_detection_and_joint_detection

Conversation

@DamienGilliard

@DamienGilliard DamienGilliard commented Mar 8, 2026

Copy link
Copy Markdown
Collaborator

various fixes needed for the big eval:

  • JointDetector allows curved joint faces and is more robust when loops in brepface convert to "complex Nurbs" (not straight lines)
  • Pose detection respects DFBeam vector directions
  • C++ point association a bit simplified
  • Added exposition of detected pose at CAD segmentation, and possibility to use that pose estimation in the pose estimation component:
image

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved critical and moderate correctness issues can invalidate geometry, poses, and segment association.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Improves joint detection, beam pose orientation, Brep loop handling, and point-cloud association.

Changes:

  • Adds optional curved joint-face detection.
  • Revises beam pose and oriented bounding-box calculations.
  • Updates NURBS loop conversion and segment-center association.
File summaries
File Review
src/gh/diffCheck/diffCheck/df_util.py Adds Brep OBB computation; critical: rank-deficient curved geometry may fail.
src/gh/diffCheck/diffCheck/df_poses.py Revises pose axes; moderate: Y-axis selection can choose Z based on input order.
src/gh/diffCheck/diffCheck/df_joint_detector.py Adds curved-face candidates; moderate: adjacency still rejects curved faces.
src/gh/diffCheck/diffCheck/df_geometries.py Updates loop conversion and beam planes; critical: filtering NURBS control points can produce invalid boundaries.
src/gh/components/DF_pose_estimation/code.py Corrects axis ordering; moderate: the documented segmentation-pose handoff remains unavailable.
src/gh/components/DF_build_assembly/metadata.json Defines the curved-face option.
src/gh/components/DF_build_assembly/code.py Passes the curved-face option into beam construction.
src/diffCheck/segmentation/DFSegmentation.cc Uses bounding-box centers; moderate: the midpoint may not lie in the plane. Nit: bounds are redundantly computed twice.
Review details

Suppressed comments (2)

src/diffCheck/segmentation/DFSegmentation.cc:266

  • GetAxixAlignedBoundingBox() converts the entire segment and computes its bounds, but it is called twice here inside the face-by-cluster loop. Cache the two returned bounds so this change does not double that O(n) work and allocation for every candidate association.
                    segmentCenter = segment->GetAxixAlignedBoundingBox()[0] + (segment->GetAxixAlignedBoundingBox()[1] - segment->GetAxixAlignedBoundingBox()[0])/2.0;

src/gh/diffCheck/diffCheck/df_poses.py:141

  • The selected X normal remains eligible as Y. When only one usable face normal remains, or all normals are parallel, projecting this candidate onto the plane perpendicular to X yields a zero vector; Unitize() then fails and pose estimation can construct an invalid plane. Filter out collinear candidates and handle the no-candidate case explicitly.
        sorted_vectors_by_perpendicularity = sorted(vectors, key=lambda v: abs(compute_dot_product(v, previous_xDirection)))
        new_yDirection = sorted_vectors_by_perpendicularity[0] - compute_dot_product(sorted_vectors_by_perpendicularity[0], new_xDirection) * new_xDirection
  • Files reviewed: 8/8 changed files
  • Comments generated: 6
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +189 to +190
if distance < 10 * Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance:
vertex = DFVertex(l_v.X, l_v.Y, l_v.Z)
Comment on lines +203 to +206
for face in largest_faces:
for v in face.ToBrep().Vertices:
bb_vertices.append(Rhino.Geometry.Point3d(v.Location.X, v.Location.Y, v.Location.Z))
df_cloud.points = [np.array([vertex.X, vertex.Y, vertex.Z]).reshape(3, 1) for vertex in bb_vertices]
DIFFCHECK_WARN("Empty segment. Skipping the segment.");
continue;
}
segmentCenter = segment->GetAxixAlignedBoundingBox()[0] + (segment->GetAxixAlignedBoundingBox()[1] - segment->GetAxixAlignedBoundingBox()[0])/2.0;

new_xDirection, new_yDirection = df_poses.select_vectors(rh_face_normals, i_assembly.beams[i].plane.XAxis, i_assembly.beams[i].plane.YAxis)
rh_tentative_plane = Rhino.Geometry.Plane(rh_tentative_bb_centroid, new_yDirection, new_xDirection)
rh_tentative_plane = Rhino.Geometry.Plane(rh_tentative_bb_centroid, new_xDirection, new_yDirection)
Comment on lines +167 to 168
faces = self._find_joint_faces(bounding_geometry, allow_curved_joint_faces)
adjacency_of_faces = self._compute_adjacency_of_faces(faces)
Comment on lines +140 to 141
sorted_vectors_by_perpendicularity = sorted(vectors, key=lambda v: abs(compute_dot_product(v, previous_xDirection)))
new_yDirection = sorted_vectors_by_perpendicularity[0] - compute_dot_product(sorted_vectors_by_perpendicularity[0], new_xDirection) * new_xDirection
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants