Skip to content

BUG: fix NaN in ND linear interpolation outside convex hull#969

Open
YuriCastroDev wants to merge 2 commits into
RocketPy-Team:developfrom
YuriCastroDev:fix/nd-function-linear-interpolation-nan
Open

BUG: fix NaN in ND linear interpolation outside convex hull#969
YuriCastroDev wants to merge 2 commits into
RocketPy-Team:developfrom
YuriCastroDev:fix/nd-function-linear-interpolation-nan

Conversation

@YuriCastroDev

Copy link
Copy Markdown

Pull request type

  • Code changes (bugfix, features)
  • Code maintenance (refactoring, formatting, tests)

Checklist

  • Tests for the changes have been added (if needed)
  • Lint (black rocketpy/ tests/) has passed locally
  • All tests (pytest tests -m slow --runslow) have passed locally
  • CHANGELOG.md has been updated (if relevant)

Current behavior

Closes #926.

When using Function(..., interpolation="linear") with N-D data,
querying a point inside the axis-aligned bounding box but outside
the convex hull silently returns nan with no warning.

data = [
    [0.0, 0.0, 0.000],
    [0.0, 0.1, 0.100],
    [0.0, 0.4, 0.400],
    [0.3, 0.2, 0.150],
]
f = Function(data, interpolation="linear")
print(f(0.3, 0.3))  # nan

New behavior

f(0.3, 0.3) no longer returns nan. Points outside the convex
hull are correctly identified and routed to the extrapolation method.

Breaking change

  • Yes
  • No

Additional information

__get_value_opt_nd used per-axis min/max (bounding box) to decide
between interpolation and extrapolation. LinearNDInterpolator
operates on the Delaunay triangulation (convex hull), not the
bounding box — points in the gap between the two were silently
sent to the interpolator and came back as nan.

Fix: compute Delaunay(self._domain) once at setup, pass it to
LinearNDInterpolator (reuses the triangulation at no extra cost),
and store it as self._nd_triangulation. In __get_value_opt_nd,
replace the bounding box check with find_simplex(args) < 0.
Shepard, RBF and other ND interpolators are unaffected.

Use Delaunay.find_simplex() instead of bounding box check in
__get_value_opt_nd to correctly detect out-of-domain points.

Closes RocketPy-Team#926
Use Delaunay.find_simplex() instead of bounding box check in
__get_value_opt_nd to correctly detect out-of-domain points.

Closes RocketPy-Team#926
@YuriCastroDev YuriCastroDev requested a review from a team as a code owner June 15, 2026 18:52
@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.12%. Comparing base (9cf3dd4) to head (1cb0bc7).
⚠️ Report is 74 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #969      +/-   ##
===========================================
+ Coverage    80.27%   81.12%   +0.85%     
===========================================
  Files          104      113       +9     
  Lines        12769    14560    +1791     
===========================================
+ Hits         10250    11812    +1562     
- Misses        2519     2748     +229     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Gui-FernandesBR Gui-FernandesBR requested a review from Copilot June 16, 2026 01:32

@Gui-FernandesBR Gui-FernandesBR left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug in rocketpy.mathutils.Function where N-D interpolation="linear" could return NaN for query points that are inside the axis-aligned bounding box but outside the Delaunay convex hull, by using the triangulation to correctly route those points to extrapolation.

Changes:

  • Build and cache a scipy.spatial.Delaunay triangulation for N-D linear interpolation and reuse it for convex-hull membership checks.
  • Update N-D fast evaluation to detect “outside hull” points via find_simplex(...) < 0 instead of bounding-box checks.
  • Add a regression unit test for the NaN case and document the fix in the changelog.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
rocketpy/mathutils/function.py Cache Delaunay triangulation for N-D linear interpolation and use it to decide interpolation vs extrapolation.
tests/unit/mathutils/test_function.py Adds regression test ensuring no NaN is returned for bounding-box-but-outside-hull queries.
CHANGELOG.md Notes the bug fix under Unreleased/Fixed.

Comment on lines +833 to +837
if hasattr(self, "_nd_triangulation"):
extrap = self._nd_triangulation.find_simplex(args) < 0
else:
lower, upper = args < min_domain, args > max_domain
extrap = np.logical_or(lower.any(axis=1), upper.any(axis=1))
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