tscircuit / tscircuit/math-utils
pointToSegmentClosestPoint loses finite projections at extreme coordinate scales
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 11
- PR merge metrics
- No merged PRs in 30d
Description
pointToSegmentClosestPoint can return NaN or the wrong endpoint for finite, nonzero segments when the squared length overflows or underflows. This is independent of the final distance-norm issue in #51: the closest-point API does not compute a distance.
Reproduced on main 7b26935a5cccb6b68a3d889d5e5d03ba04dc9a1b (v0.0.38), Bun 1.4.2. For a horizontal segment (0,0) -> (4*s,0) and query (2*s,3*s), the exact closest point is (2*s,0):
| s | actual x/s | expected x/s |
|---|---|---|
| 1 | 2 | 2 |
| 1e160 | NaN | 2 |
| 1e-170 | 0 | 2 |
Reversing the small segment changes the wrong answer to x/s=4. All input coordinates and the expected result are finite and representable. These are extreme-scale robustness cases, not a claim that ordinary PCB coordinates fail.
Runnable regression (tests/projection-scales-repro.test.ts, bun test tests/projection-scales-repro.test.ts):
import { expect, test } from "bun:test"
import { pointToSegmentClosestPoint } from "../src"
for (const scale of [1, 1e160, 1e-170]) {
for (const reverse of [false, true]) {
test(`closest point at ${scale}, reverse=${reverse}`, () => {
const left = { x: 0, y: 0 }
const right = { x: 4 * scale, y: 0 }
const a = reverse ? right : left
const b = reverse ? left : right
for (const [x, expectedX] of [[2, 2], [-1, 0], [5, 4]]) {
const actual = pointToSegmentClosestPoint(
{ x: x * scale, y: 3 * scale }, a, b,
)
expect(actual.x / scale).toBe(expectedX)
expect(actual.y).toBe(0)
}
})
}
}
test("zero-length segment remains a point", () => {
const endpoint = { x: 2, y: 3 }
expect(pointToSegmentClosestPoint({ x: 4, y: 7 }, endpoint, endpoint)).toEqual(endpoint)
})
Observed: 3 tests pass, 4 fail; TypeScript check passes. In src/segment-distance.ts, dx_ab * dx_ab + dy_ab * dy_ab becomes Infinity or zero. The former makes the interior projection Infinity/Infinity; the latter incorrectly selects the degenerate-segment branch. A scale-aware projection should retain interior projection and endpoint clamping without treating a nonzero segment as a point. Other helpers repeat the squared-length formula and may need the same treatment; this reproduction isolates the closest-point API. #44 focuses on distance performance rather than this function.
Prepared with Codex (Astra) assistance and verified locally.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/segment-distance.ts at pointToSegmentClosestPoint and run bun test tests/projection-scales-repro.test.ts. Check the reported extreme-scale cases, including reversed and zero-length segments. Done means the regression passes, finite nonzero segments retain the expected closest point, and the zero-length case remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- bun, typescript
- Domain
- testing-qa, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100