Skip to content

query.face_p4: wire GetLoopCrossings in SmFace::ClassifyLoops - #717

Merged
bherbruck merged 4 commits into
tangency-labs:mainfrom
brett19:fix/query-face-p4-get-loop-crossings
Oct 24, 2026
Merged

bherbruck merged 4 commits into
tangency-labs:mainfrom
brett19:fix/query-face-p4-get-loop-crossings

Conversation

@brett19

@brett19 brett19 commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Replaces the stale UNPORTED(intersect.curve_class_p4): SmCurveClassification::GetLoopCrossings stub in query/face/p4.rs (SmFace::ClassifyLoops, bisector branch) with the real call. It passes what upstream passes: the target loops, the face props and the bisector classification. The status stays ignored, and InvalidInput / NotFound (upstream undefined behaviour) and Unported propagate.

The query.face_p4 runner now exports the face props the bisector and GetLoopCrossings read (zone tolerance, no-vertex poles, pole points, missing seam direction). Without them, 32 of the newly compared cases disagreed.

On main this stub blocked about 410 deferred cases (query.face_p4 90, topology.brep_p10 153, heal.heal_data_p1 109, topology.brep_p7 26, heal.heal_data_p3 19, topology.brep_p1 12, heal.face_props 1).

Difftest, main (CI run 40061276652) → this branch (local)

query.face_p4      500 cases: 395 pass, 105 deferred                → 481 pass, 0 failed, 17 deferred, 2 known mismatches (454 compare values, 27 both-errored as before)
heal.heal_data_p3  478 cases: 458 pass, 20 deferred                 → 477 pass, 0 failed, 1 deferred
topology.brep_p7   348 cases: 289 pass, 59 deferred                 → 315 pass, 0 failed, 33 deferred
heal.heal_data_p1  495 cases: 367 pass, 128 deferred                → 450 pass, 0 failed, 19 deferred, 26 known mismatches
topology.brep_p1   2627 cases: 2461 pass, 150 deferred              → 2465 pass, 0 failed, 138 deferred, 8 known mismatches
topology.brep_p10  1404 cases: 1156 pass, 231 deferred              → 1282 pass, 0 failed, 99 deferred, 6 known mismatches
heal.face_props    1528 cases: 1439 pass, 89 deferred               → 1440 pass, 0 failed, 88 deferred
query.face_p3      unchanged (1087 pass, 112 deferred)

Cases still deferred now mostly stop at SmFace::FindVertexSector (topology.face_p4). The others stop at SmEdge::GetTolerance / GetCurve (topology.edge), SmFace::PointClassify (query.face_p2) and the trimmed-surface-cache tolerance growth (surface.surface_p2).

Parked so this can land

  • 40 heal-path cases (heal.heal_data_p1 26, topology.brep_p1 8, topology.brep_p10 6) are known mismatches. Upstream's loop bisector edits the real B-rep: CurveOnClassify → IntersectTSBound → SmVertexuse::ComputeUVPoint(uv) with bOKToMakeUVTrimCurve=TRUE builds missing UV trim curves. SetUVTrimCurve then resets the vertex/face gaps (SmEdgeuse.cpp:4537). The port runs the bisector on the b.clone() copy in query/face/p3.rs, so those edits are lost.
  • A follow-up that threads &mut Brep through ClassifyLoops comes right after this PR. It is coordinated separately because it overlaps the planned bisector work and the heal/face_props.rs changes in Propagate remaining topology and healing failures (follow-up #521) #700.
  • 2 query.face_p4 cases (gen0157, gen0300, cylinders at scale 1e-3) are known mismatches. The importer's approximation of the analytic edge curves moves the bisector's UV line by 1.6e-8 relative, across a loop. An exactness-based exclusion could not separate these two from about 85 cases that agree, so those cases are compared.
  • Both causes are recorded in plan/findings.md.

🤖 Generated with Claude Code

brett19 and others added 2 commits October 23, 2026 21:47
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…yLoops

SmFace::ClassifyLoops still returned Unported for a target loop that crosses
no seam, although SmCurveClassification::GetLoopCrossings is ported. Call it
with the target loops, the face props and the bisector's classification, as
upstream does; its status stays ignored.

The query.face_p4 runner now also exports the face props the bisector and
GetLoopCrossings read (zone tolerance, no-vertex poles, pole points, missing
seam direction). Faces whose surface or loop edge curves the importer cannot
reproduce exactly report inexact_geometry on both sides when ClassifyLoops
may evaluate them, decided from the export as unit query.face_p3 does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brett19

brett19 commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

@erlis, a heads-up, since this lands on site 2 from your #681 list (find_and_classify_loop_bisector_into, with LoopObjectCurves<'b, O> holding &'b Brep).

Wiring GetLoopCrossings here lets about 410 cases get past the stub: query.face_p4 goes green, topology.brep_p7 gains 26 and heal.heal_data_p3 gains 19. But 40 newly compared heal-path cases disagree with C++, and we're parking them as known mismatches in this PR so the rest can land:

  • heal.heal_data_p1: 26
  • topology.brep_p1: 8
  • topology.brep_p10: 6

Cause: upstream's bisector runs sms_FindAndClassifyLoopBisector → CurveOnClassify → IntersectTSBound → SmVertexuse::ComputeUVPoint (default bOKToMakeUVTrimCurve=TRUE) on the real B-rep. That builds missing UV trims, and SetUVTrimCurve then resets the vertex-use/face gap caches (SmEdgeuse.cpp:4537). The port runs the bisector on the b.clone() copy in query/face/p3.rs, so those edits are lost. Example: on plane_square, C++ ends with one vertex use's gap set to UNDEF, while Rust keeps 0.

The fix: &mut Brep through ClassifyLoops → the bisector / CurveOnClassify boundary views → set_props_stage3 → HealData::cache_face_props_stage3. That's your site 2 plus the heal chain you described as mechanical. It also touches heal/face_props.rs, which #700 edits.

So these 40 entries are waiting on that conversion. Are you still planning to take site 2? If so, the 40 entries can come off in your PR. If you'd rather we did it, tell us and we'll pick it up straight after this lands.

🤖 Generated with Claude Code

brett19 and others added 2 commits October 23, 2026 23:10
…p-edit mismatches

Drop the runner's inexact_geometry exclusion. Most faces the loop bisector reaches have
edge curves the importer only approximates, and every one of those cases agrees except
two scale-1e-3 cylinders (gen0157, gen0300). The rule could not separate those two from
the rest using the inputs alone, so they become known mismatches and the rest are
compared again.

Now that GetLoopCrossings runs, 40 heal-path cases (heal.heal_data_p1 26,
topology.brep_p1 8, topology.brep_p10 6) disagree. Upstream's bisector builds missing
UV trim curves on the real B-rep: CurveOnClassify -> IntersectTSBound ->
ComputeUVPoint with bOKToMakeUVTrimCurve=TRUE, after which SetUVTrimCurve resets the
vertex/face gaps. The port runs that on a private copy, so the edits are lost. These
cases are listed as known mismatches with a findings entry until a follow-up threads
&mut Brep through ClassifyLoops.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-loop-crossings

# Conflicts:
#	crates/difftest/known_mismatches.toml
@brett19
brett19 marked this pull request as ready for review October 24, 2026 06:34
@bherbruck
bherbruck added this pull request to the merge queue Oct 24, 2026
Merged via the queue into tangency-labs:main with commit 6ff9886 Oct 24, 2026
7 checks passed
@erlis

erlis commented Oct 24, 2026

Copy link
Copy Markdown
Contributor

@brett19 thanks for the heads-up and the plane_square trace. Yes, I'll take site 2 and the heal chain, and take the 40 entries off in that PR.

One overlap: your chain goes CurveOnClassify → IntersectTSBound → ComputeUVPoint. On our side that reaches the intersect_ts_bound snapshot in query::face::p2::curve_on_classify_cached, which is site 1 and goes with #697. To get those 40 bit-identical, the bisector has to reach the real B-rep through that path too. Which do you prefer?

Either way, the first step is making LoopObjectCurves stop holding &'b Brep, so the bisector can take &mut. I'll check with @fkirill on #700 before touching heal/face_props.rs.

🤖 Generated with Claude Code

@brett19

brett19 commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator Author

@erlis thanks, and sorry for the slow reply. (b) is already done: #697 merged earlier today (merge d2944e9), with the intersect_ts_bound cached branch. curve_on_classify_cached's snapshot can now take a caller's &mut Brep through CurveOnClassifyCache (described in #697's body). So please build on main as it is, and take whatever you need from site 1 along with site 2.

One update on the count: #718 (FindVertexSector) parked 9 more cases under the same reason, so it's now 49 in known_mismatches.toml (heal_data_p1 28, brep_p1 9, brep_p10 12). For three of the brep_p10 ones (read_Fillet_cyl_cyl_shell, read_Fillet_bottle, read_Fillet_fillet0227), #718's findings note a possible second source: HasSeamProblem → EvaluateNormalAtSingularity returns InvalidInput on the Rust side, and the port ignores it as upstream does. So those three may not all clear with the &mut change alone.

We won't touch LoopObjectCurves, ClassifyLoops, the bisector or the heal chain while you're on it.

🤖 Generated with Claude Code

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.

3 participants