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

Building paths with arcs #260

Open
derekdreery opened this issue Apr 3, 2023 · 5 comments
Open

Building paths with arcs #260

derekdreery opened this issue Apr 3, 2023 · 5 comments
Labels
question Further information is requested

Comments

@derekdreery
Copy link
Collaborator

derekdreery commented Apr 3, 2023

In CAD it's quite common to draw with circular arcs (elliptic arcs as well, but less often, and most commonly after transforming a circular arc with a non-uniform scale). To make the arc easy to work with within a path, an arc section is often specified as start and end points, plus a 'bulge' parameter. This parameter specifies how much the arc should deviate from a straight line, with 0 representing a straight line from start to end, and the sign representing which side the bulge should be on. A more precise definition is given in https://www.afralisp.net/archive/lisp/Bulges1.htm, along with some nice drawings.

It would be great if there was a way to build paths that included arcs in kurbo (defined with the bulge as above). However I'm not sure that you would just add another variant to BezPath. These curves are tools for designers, and would be converted to Beziers before rendering. So perhaps there is room for another path type in kurbo? Or perhaps multiple path types (inside a submodule called something like paths), so that other path types based on e.g. NURBS or Euler spirals could also be added?

I'm interested to hear other people's thoughts on this.

@derekdreery derekdreery added the question Further information is requested label Apr 3, 2023
@raphlinus
Copy link
Contributor

Here are some thoughts on this, though I think it deserves a deeper discussion.

First, I think BezPath itself should not change. One of its great strengths is that it can be consumed and manipulated while only dealing with a small number of cases. It is something of a universal representation for paths, as any reasonably smooth curve can be lowered to it with O(n^6) accuracy scaling. The recent work adding cubic Bézier curve fitting cements that, as it makes it practical to achieve that, from any curve representation.

That said, there is a role to support other curve types. Though BezPath is universal in that it can represent any curve to any desired degree of accuracy, it is not a suitable "source of truth" for all applications. As observed, it cannot losslessly represent arcs as in SVG paths.

The traits, including the ParamCurve family and Shape, are designed to accommodate more curve types, and are open-ended, giving a number of operations "for free" as soon as those traits are implemented. But it's possible some should actually make it into kurbo.

One strong candidate is rational Béziers, as that can exactly represent conic sections, at least some NURBS inputs (I haven't researched this extensively), and also has the advantage of being closed under perspective transform.

I'm mixed on whether Euler spirals should qualify. Obviously they have some very desirable properties, including being able to exactly represent circular arcs, but they have some other challenges, including not being closed under affine transformation. I have been considering them for other applications, but am generally coming to the conclusion that staying in cubic space is better.

For any given "source of truth" path representation (including those that contain additional metadata for the purpose of interactive editing), it should be possible to implement Shape, and also the ParamCurve traits on individual segments. I'm very interested in feedback on this topic: Is it practical to implement those traits? Are the benefits worth it? Is there potentially a better way kurbo could support extension along these lines?

I'm also very much interested in other thoughts.

@derekdreery
Copy link
Collaborator Author

derekdreery commented Apr 5, 2023

I'm going to experiment making my own path type out-of-tree, using the kurbo traits. Will report back how it goes.

@rsheeter
Copy link
Collaborator

rsheeter commented Apr 5, 2023

It would be quite handy if kurbo supported a path type that losslessly converts to/from svg path representation. To be fair, perhaps that makes more sense in an independent crate that depends on kurbo.

@derekdreery
Copy link
Collaborator Author

Totally agree with @rsheeter now that a path equivalent to the SVG path is the way to go. They handle elliptic arcs in paths in the best way I think possible.

@ZhennanWu
Copy link

ZhennanWu commented Oct 21, 2023

Agree there should be an elliptic arc primitive in PathEl.

The problem with arc being lowered into bezier curves is that tolerance will be violated with a scaling transform. For scientific purposes, it is quite counterintuitive to consider circles and ellipses would be distorted under scaling and requires re-lowering every frame, like other fitted curves.

(E.g.: In a GUI app which caches vello::SceneFragment for certain framework components, the author would have to be very careful to avoid vello::SceneFragment caching behavior if any child component is supposed to accurately render circle shapes. Say, a SVG renderer.)

The problem of SVG's elliptic arcs not being closed under affine transforms can be circumvented by picking other degrees of freedom, although I have not looked into the numerical stability side of the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants