Skip to content

get_at() does not reach distance when the requested value is infinitesimally larger than the last trajectory point #305

@gambon2010

Description

@gambon2010

Describe the bug
HitResult.get_at() raises ArithmeticError: Trajectory does not reach distance when the requested value is infinitesimally larger than the last trajectory point, rather than returning that last point.

To Reproduce

  1. Fire a trajectory with a maximum distance that produces a final trajectory point of 39370.07874015748 inches
  2. Call get_at("distance", value) where value is 39370.078740157485 (a floating point epsilon larger than the last point)
  3. See error: ArithmeticError: Trajectory does not reach distance

Expected behavior
get_at should return the last TrajectoryData point when the requested value is within floating point precision of the final trajectory point. The epsilon parameter is intended to handle this case, but is never reached because the forward search loop condition key_value <= next_val filters out any value greater than the last trajectory point before any epsilon comparison can occur, causing target_idx to remain -1 and the error to be raised unconditionally.

Root Cause
In the forward search loop:

for i in range(start_idx, n - 1):
    if (curr_val < key_value <= next_val) or (next_val <= key_value < curr_val):
        target_idx = i + 1
        break

When key_value is fractionally greater than the last point, no bracketing pair is found and target_idx stays -1. The fix would be to add an epsilon check against traj[-1] before raising:

if target_idx == -1:
    if abs(get_key_val(traj[-1]) - key_value) < epsilon:
        return traj[-1]
    raise ArithmeticError(f"Trajectory does not reach {key_attribute} = {value}")

Environment:

  • OS: [Linux]
  • Python3 version: [3.10]
  • Release [2.2.8]

Additional context
The difference between the last trajectory point and the requested value is ~4.9e-13 inches, which is a floating point precision artifact of unit conversion (meters → inches). Passing a larger epsilon to get_at does not work around this issue since the epsilon check is never reached — the only current workaround is to clamp the input value to the last trajectory point before calling get_at.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions