Skip to content

pointsinside(): take distance sign from natcpp winding number - #529

Merged
jefferis merged 3 commits into
masterfrom
feature/pointsinside-winding-distance
Sep 29, 2026
Merged

jefferis merged 3 commits into
masterfrom
feature/pointsinside-winding-distance

Conversation

@jefferis

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #528. When natcpp (>= 0.3.2, Enhances) is available, pointsinside(rval="distance") and rval="mesh3d" now combine:

  • the unsigned closest-point distance from Rvcg::vcgClostKD(sign=FALSE) (purely geometric), with
  • the sign from natcpp's generalised winding-number test.

Rvcg derives the sign from the normal of a single closest face, which is unreliable near edges, vertices and thin features. On kcs20 vs MB_CA_L, 73 points ~36 µm outside the calyx (all outside its bounding box — the "red points in the vertical lobe" in the example) were previously reported as inside. distance >= 0 now agrees exactly with rval="logical"; distance magnitudes are unchanged. Cost is ~20% extra for rval="distance".

All natcpp use is behind the internal inside_winding() helper, which returns NULL unless use_natcpp(version='0.3.2'), so the pure Rvcg path is used when natcpp is absent or options(nat.use_natcpp=FALSE).

Changes

  • R/hxsurf.R, man/pointsinside.Rd, NEWS.md: implementation and docs (also tempers the face-orientation robustness claim: winding numbers handle globally inverted meshes, not mixed orientation).
  • Tests: new with_and_without_natcpp() helper runs pointsinside() tests on both paths; natcpp-specific tests check sign/logical agreement, bbox consistency, unsigned magnitude, and an inverted tetrahedron.
  • CI: new ubuntu release job without natcpp (asserts it is absent) to exercise the fallback paths in tests/examples/vignettes.

Test plan

  • test-hxsurf.R passes locally with natcpp
  • CI including the new no-natcpp job

🤖 Generated with Claude Code

When natcpp (>= 0.3.2, Enhances) is available, rval="distance" and
rval="mesh3d" now combine the unsigned closest-point distance from
Rvcg::vcgClostKD with the sign from natcpp's generalised winding-number test.
Rvcg's sign comes from the normal of a single closest face, which gives wrong
results near edges, vertices and thin features (e.g. 73 kcs20 points ~36um
outside MB_CA_L were reported as inside). distance >= 0 now agrees exactly with
rval="logical".

All natcpp use goes through the internal inside_winding() helper, which returns
NULL unless use_natcpp(version='0.3.2') so callers fall back to pure Rvcg.
Add with_and_without_natcpp() test helper, which runs a block on the pure
R/Rvcg path (options(nat.use_natcpp=FALSE)) and again on the natcpp path when
it is available. Use it for the existing pointsinside() tests and new
path-agnostic checks on an analytic tetrahedron and the kcs20/MB_CA_L data.
natcpp-specific tests check that the distance sign matches rval='logical',
the magnitude matches unsigned Rvcg, and that inverted faces are handled.
@jefferis
jefferis force-pushed the feature/pointsinside-winding-distance branch from 7b3b335 to f09540c Compare September 28, 2026 18:42
natcpp is only in Enhances, so add an ubuntu release job that removes it after
dependency installation and asserts it is absent. This exercises the pure
R/Rvcg fallback paths in tests, examples and vignettes, and catches any
natcpp:: calls not guarded by use_natcpp().
@jefferis
jefferis force-pushed the feature/pointsinside-winding-distance branch from f09540c to e48afd3 Compare September 28, 2026 18:53
@jefferis
jefferis merged commit 7d6bae3 into master Sep 29, 2026
9 checks passed
@jefferis
jefferis deleted the feature/pointsinside-winding-distance branch September 29, 2026 23:47
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.

1 participant