Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for elliptical arcs #478

Open
awhitty opened this issue Dec 15, 2020 · 1 comment
Open

Support for elliptical arcs #478

awhitty opened this issue Dec 15, 2020 · 1 comment

Comments

@awhitty
Copy link

awhitty commented Dec 15, 2020

Hi there! Thanks for making a useful library!

I've been working on parsing SVG files (not just path data, but the whole file -- warts and all), and I noticed maker.js does not have "true" support for elliptical arcs.

The models.EllipticArc constructor is definitely handy and works in a pinch, but the internal representation looks to be many circular arcs approximating a set of bézier curves which approximate the arc. I can't help but imagine we're losing some precision along the way!


I've had a lot of coffee today, so I have a couple questions while I'm at it:

Is there a historical reason why this choice to use circular arcs was made? Elliptical arcs can accurately represent circular arcs, so I'd imagine it would be more useful to use elliptical arcs internally and not the other way around.

I'm also curious about the choice to approximate béziers using arcs in the data model. I recognize that that has performance implications for tasks like measuring path length and extents, so I imagine a reason would be to optimize for that use case. Do mutating operations like scale or rotate operate on the original curve on or on the approximation? If the latter, it seems we'd lose some precision along the way?

Perhaps I'm fretting about precision when in reality the differences wouldn't matter for practical purposes. I'm totally open to that rationale if that's the case. I'm still learning what's normal in CAD.

@danmarshall
Copy link
Contributor

Hi @awhitty, thanks for the feedback. The primary reason for this decision back in the beginning was to match with the DXF file format. Beziers were added later due to community request. The secondary reason is to limit the API surface, and have as few primitives as possible. The third reason is to make the math code as easy as possible, especially with regard to intersections. Since ellipses can be expressed with a series of Bezier Curves, we almost got them for free.

I totally understand your concerns about precision. In most cases, the circular arcs representations are not used when exporting to SVG, and the underlying Bezier info is used. The circular arcs get used when a Bezier has been clipped, such as in a Boolean operation with the combine() function. You may want to dig into the docs and peruse comments in the code for specifics.

Representing a circle (or ellipse) with a Bezier is also not mathematically perfectly exact, but its extremely close. I've studied https://pomax.github.io/bezierinfo/#circles_cubic and implemented ideas from there. We also use arc segments no greater than 45 degrees to get even better accuracy. Pomax's stuff is a great resource, but it took me a while to even understand some of the basics.

And yes we hope to get some performance perks by pre-computing Bezier curves into arcs so we don't need to iterate so much when computing intersections.

I have been planning to introduce a new primitive, a "mild Bezier curve". See 57b5657 and the mild-bezier branch. The idea is to have a subsegment of a Bezier which is guaranteed monotonic in 2 dimensions, like a circular arc. I just haven't had time to finish all permutations of the code for all of the API. And, some of the math is still a little perplexing.

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

No branches or pull requests

2 participants