Repository navigation
Conversation
A MAPPED_ITEM in a shape representation the traversal visits now queues its mapped_representation at mat * target * origin^-1, so tessellation, instance copies, colours and unit scaling reuse the existing path for both triangulate() and tessellate_step_bytes(). Presentation-only mapped items (draughting models, views) are still never reached. - origin/target: AXIS2_PLACEMENT_3D or CARTESIAN_TRANSFORMATION_OPERATOR_3D (ISO 10303-42 base_axis, uniform scale); anything else warns and skips. - Scaled instances keep unit normals; mirrored ones reverse winding. - Cycles through mapped items are detected per path and reported. - The mesh-every-solid-at-identity fallback no longer fires once mapped items were found, so mapped-only models are not stacked at the origin. - SHAPE_REPRESENTATION_RELATIONSHIPs to representations that hold only MAPPED_ITEMs are now followed. ENG-4019 Amp-Thread-ID: https://ampcode.com/threads/T-01a13904-410c-738a-9919-3b52df6a9383 Co-authored-by: Amp <amp@ampcode.com>
- Identity fallback: leave out only solids instanced by MAPPED_ITEMs whose placement could not be read, instead of disabling the fallback whenever any MAPPED_ITEM was seen (mapped wireframes emptied the mesh). - CARTESIAN_TRANSFORMATION_OPERATOR_3D without axis2 completes a right-handed frame, as OpenCascade does, rather than mirroring (axis3 = -z) or failing (axis3 = x). - Scaled instances: mesh shared geometry to tolerance / largest scale. - Relationships between two MAPPED_ITEM-only representations are oriented from the product's representation, or warned about when ambiguous. - Test: check the coloured mesh's vertex count before comparing positions. ENG-4019 Amp-Thread-ID: https://ampcode.com/threads/T-01a13904-410c-738a-9919-3b52df6a9383 Co-authored-by: Amp <amp@ampcode.com>
- A MAPPED_ITEM placement may omit its axis (ISO 10303-42 default +Z); previously the instance was dropped and its solid left out of the fallback, emptying meshes master drew at identity. - first_proj_axis treats directions within round-off of ±X as X, so printed noise no longer flips an operator's frame by 180 degrees. - Do not link a product's MAPPED_ITEM-only representation from another of its product representations; it is already traversed directly. ENG-4019 Amp-Thread-ID: https://ampcode.com/threads/T-01a13904-410c-738a-9919-3b52df6a9383 Co-authored-by: Amp <amp@ampcode.com>
- An AXIS2_PLACEMENT_3D along X without ref_direction no longer collapses (axis2_placement_3d's (1,0,0) default made x = z, y = 0): mapping placements now take their reference direction from first_proj_axis, and a reference parallel to the axis is an error instead of a singular frame. - Treat axes within 1e-6 rad of X as along X when choosing the default reference, covering single-precision exporter noise. ENG-4019 Amp-Thread-ID: https://ampcode.com/threads/T-01a13904-410c-738a-9919-3b52df6a9383 Co-authored-by: Amp <amp@ampcode.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 1146432. Configure here.
| r1.0, r2.0 | ||
| ); | ||
| continue; | ||
| } |
There was a problem hiding this comment.
Mapped-item relationship chains dropped
Medium Severity
A SHAPE_REPRESENTATION_RELATIONSHIP between two representations that contain only MAPPED_ITEMs is dropped when neither end is a product representation. A product can still reach the first representation, but the next mapped-item representation in the chain is never queued, so its solids are not instanced.
Reviewed by Cursor Bugbot for commit 1146432. Configure here.
| fn instance_scale(mat: &DMat4) -> f64 { | ||
| let scale = glm::mat4_to_mat3(mat).determinant().abs().cbrt(); | ||
| if (scale - 1.0).abs() > 1e-5 { scale } else { 1.0 } | ||
| } |
There was a problem hiding this comment.
Singular instances yield non-finite normals
Low Severity
instance_handedness divides by instance_scale for every instance matrix, and that scale is |det|^(1/3). A singular linear part has determinant 0, so the scale is 0 and every transformed normal is multiplied by infinity, producing Inf or NaN normals.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 1146432. Configure here.


Expands geometric
MAPPED_ITEMs into transformed instances (ENG-4019). Before this, they were silently ignored: mixed files lost their mapped bodies, and models whose bodies were all mapped had every part stacked at the origin by the identity fallback.Behaviour
MAPPED_ITEMin a visitedSHAPE_REPRESENTATION/ADVANCED_BREP_SHAPE_REPRESENTATION/MANIFOLD_SURFACE_SHAPE_REPRESENTATIONqueues itsmapped_representationatmat * target * origin^-1. Tessellation, instance copies, colours and unit scaling reuse the existing path, so bothtriangulate()andtessellate_step_bytes()get it. This includes representations reached throughSHAPE_REPRESENTATION_RELATIONSHIPand nested mapped items.MAPPED_ITEMs in presentation models (DRAUGHTING_MODEL,PRESENTATION_VIEW,PRESENTATION_AREA) are never reached, so they stay ignored.AXIS2_PLACEMENT_3DorCARTESIAN_TRANSFORMATION_OPERATOR_3D.build_axes: an omitted axis is +Z, and an axis along X without a reference direction uses +Y.axis2is omitted they complete a right-handed frame, as OpenCascade does. An explicitaxis2can still mirror.MAPPED_ITEMs is now followed. If both ends belong to products it is not followed, so nothing is instanced twice. Relationships into representations that hold bodies are unchanged.Testing
cargo test --release -p triangulate -p step -p nurbs -p cdt: all pass. Four new integration tests intriangulate/tests/examples.rs, built by editingcuboid.step/cube_hole.step:master.Notes
target * origin^-1. OpenCascade uses the operator alone in that case; the two differ only when the origin isn't identity.axis2_placement_3d, which is still used for assembly placements, still collapses an axis along X that has no reference direction. That is unchanged frommaster.https://ampcode.com/threads/T-01a13904-410c-738a-9919-3b52df6a9383
Note
Medium Risk
Changes core STEP placement traversal and mesh instancing; wrong transforms or relationship direction would misplace geometry, though behavior is heavily covered by new integration tests.
Overview
STEP triangulation now expands geometric
MAPPED_ITEMs in shape representations into extra instances attarget × origin⁻¹, instead of ignoring them or leaving mapped-only models stacked at the origin via the identity fallback.Traversal follows nested maps and
SHAPE_REPRESENTATION_RELATIONSHIPedges ranked by content (solids vs map-only reps), with cycle detection and skipping of solids reachable only through unresolved placements. Placements use ISO-styleAXIS2_PLACEMENT_3D(default +Z,first_proj_axis) andCARTESIAN_TRANSFORMATION_OPERATOR_3D(uniform scale, right-handed frame whenaxis2is omitted).Instance copying now handles mirrors (swap triangle winding) and scales (renormalize normals, tighten mesh tolerance for the largest scaled copy). Integration tests in
examples.rscover nested/scaled maps, relationship wiring, presentation-only maps, and fallback behavior.Reviewed by Cursor Bugbot for commit 1146432. Bugbot is set up for automated code reviews on this repo. Configure here.