feat(g.Curve): add isLine() and use it in getSubdivisions() - #3504
Open
kumilingus wants to merge 1 commit into
Open
kumilingus wants to merge 1 commit into
kumilingus wants to merge 1 commit into
Conversation
`isLine()` is true when both control points lie on the start-end chord. The cross product is compared against a scale-relative tolerance (1e-9 of the squared chord length) instead of exact zero, so straight curves built by `Curve.throughPoints()` - which carry floating point noise in their control points - are recognized. Point-like curves and loops (start equal to end) are not lines. `getSubdivisions()` previously inlined an exact-zero version of this check for its "straight-line curve" special case. That check missed ~96% of straight curves produced by `throughPoints()` (falling back to 4 subdivisions instead of the intended 2^(2*precision)) and matched any loop whose start equals its end. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the
@jointjs-devboard card "g: addg.Curve.isLinemethod".g.Curve#isLine()—truewhen both control points lie on thestart–endchord (the curve traces a straight line, possibly overshooting the chord). Point-like curves and loops (startequal toend) returnfalse.1e-9 × chord²rather than exact zero. Sincecross = chord length × distance of the control point from the chord, this is a scale-independent "distance below 1e-9 × chord length" test. Motivation: the exact-zero check misses 1913 / 2000 straight curves produced byCurve.throughPoints([a, b])— the library's own straight-curve constructor — because of the(2·P0 + P3) / 3arithmetic. With the tolerance: 0 / 5000 missed.getSubdivisions()now callsisLine()for its "straight-line curve" special case (forces2 × precisioniterations, because the observed-length convergence test cannot distinguish iterations on a straight curve). Effects:throughPoints()get the intended 64 subdivisions (precision 3) instead of 4 → finert↔ length mapping for unevenly spaced control points;startequalsendno longer trigger the special case (they were matched by the exact check becausecross(start, end)is trivially 0 whenstart === end).isPoint()alias (the card's suggestion); it would be!isDifferentiable()and no other shape has one.Changesets:
minorfor the new method,patchfor thegetSubdivisions()behaviour change.Test plan
karma:geometry— 353/353; newisLine()module (evenly/unevenly spaced, control points equal to endpoints, overshooting, diagonal; curved, one control point off, point, loop; 100 randomthroughPoints()curves, tiny coordinates, visible deviation rejected). Watched failing first (isLine is not a function). ExistinggetSubdivisions()assertions (64 for straight, 4 for curved) unchanged.karma:joint— 2113/2113grunt test:ts🤖 Generated with Claude Code