-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
[p5.js 2.0 RFC Proposal]: New API for vertex functions #6766
Comments
Thanks for the writeup @GregStanton! I'm in favor of the consistency we'd get from an API like this, as well as the readability (any time a function has a bunch of positional arguments, I find myself having to write comments between arguments to remind myself which is which.) For curveVertex texture coordinates, I think the same pattern we're suggesting for bezier vertices will also apply. When getting a position along a Catmull-Rom curve in between two control points, the interpolated position is a weighted sum of the curve's control points. I think we can do the same weighting for texture coordinates if we have one texture coordinate per control point, similar to position. |
I do really like the overall simplicity and flexibility this can potentially give. One thing I would like to illustrate this proposal a bit more would be some more complete code examples, maybe even a before and after versions to make the use case clearer. I'll probably share this with my colleagues teaching with p5.js to get their thoughts as well. |
@limzykenneth Thanks! Code examples are a great idea. Here's a list of examples that illustrates some key differences: Example 1Current syntax:
Proposed Syntax:
Example 2Current syntax (the Bézier case isn't actually supported, but a user might expect this to work):
Proposed syntax (contours are used to specify separate pieces of different orders):
Example 3Current syntax (the first one will cause an error because it's not supported, due to an inconsistency):
Proposed syntax:
Example 4Current syntax (this will produce an error because higher-order Bézier curves aren't currently supported):
Proposed syntax (this assumes we want to support higher-order Bézier curves):
Example 5Current syntax (this is how a user might try to create a Bézier triangle, but that's not currently supported):
Proposed syntax:
Special casesShape built from multiple béziersOne issue with having a single Composite shapesCurrently, composite shapes aren't supported, but #6560 would address this, and it provides more examples of that type in the current syntax. TODO / Invitation for contributions
|
I want to also invite @peilingjiang who created the p5.bezier addon library to have a look at this. Seeing that your library also deals with Bezier curves and also support higher order Bezier curves, it would be great to hear your thoughts, we can even look at the implementation you have in p5.bezier as a starting point for this too. |
Thanks for the invite! Looking at the example code comparisons, I think this would be a very nice update, syntax-wise (I don't know how differently the updated functions will be implemented, so I'll only share some thoughts on the proposed syntax)! The vertex-related syntax would be unified, and having consistent, separate functions with a manageable number of arguments, instead of a crazy list of 9 or 15 arguments, would greatly improve the code readability. For the implementation, I hope my implementation for the higher-order Bézier curves would be helpful to serve as a starting point for the new native support. Moreover, I wonder if you would consider having an array of arrays of vertices, e.g., beginShape();
bezierVertices([
[x0, y0, z0, u0, v0],
[x1, y1, z1, u1, v1],
[x2, y2, z2, u2, v2],
[x3, y3, z3, u3, v3]
])
endShape(); I did something similar for the addon for the usability of the API, as managing items in an array (e.g., when adding or removing vertices) would be easier than modifying separate function calls. Moreover, the users may already maintain the positions somewhere else using nested arrays. This would be a further departure from the native Canvas API, but that might not be a bad thing - we could keep the old APIs for a few more minor version updates, mark them as deprecated, and introduce new ones like |
Thanks for your feedback @peilingjiang! Your library looks really cool, by the way. I think it'd be great to flesh out the pros and cons of your API idea, for the sake of discussion. I've already written up a partial list, but that gave me a new idea that I want to think about a bit more. I'll share what I have as soon as I'm able to think it over a bit more. |
Okay, @peilingjiang! I have some initial feedback to share regarding the API you proposed. ProsThe
ConsThe
Questions for the community
Edit: Added first point under cons, about features of the |
Thanks so much @davepagurek! This is a great discussion. Disambiguating primitivesI'm glad you raised the issue about using Having
Implicit start verticesYep! The current refactoring plan handles Note: These are initial thoughts. It will be good to confirm the details when time permits. |
I think I think as a matter of opinion, I'm still unsure that the extra code required to surround each segment by
The con for me is really just:
At least in my own experience, I've rarely felt the need to go higher than a cubic Bezier, and SVG/CanvasRenderingContext2D APIs don't natively support them either. I'd still love to support them, but I'm personally OK going with a more complex API for those since I see them as a very special case. Meanwhile, most shapes I'd want to draw (imagine drawing text glyphs as a motivating example) are composed of connected lines and curves, often with many connected cubic segments. Since a single text glyph can have upwards of 20 segments in it, and each segment would now need a duplicate vertex to remain connected, this adds a lot of overhead, which gives me pause. As an alternative, I think if we break each control point into their own call but don't try to support multi-order bezier and don't try to surround segments with other functions, we'd still check the other boxes we wanted. That's just an opinion based on my own experience though! I want to hear if other people's experience is similar to that too. As a final aside, I think if we keep separate methods for the different bezier orders, maybe it's worth aliasing |
Thanks @davepagurek! I'll reply to your points about using Considerations for
|
I think the issue I was thinking of is that, if there isn't an implicit
Here we've got all four in the segment. I guess the point I'm unclear on is whether or not that's a special case for just the first segment? e.g. would the following also be valid? beginShape();
vertex(x0, y0, z0);
beginPrimitive();
bezierVertex(x1, y1, z1);
bezierVertex(x2, y2, z2);
bezierVertex(x3, y3, z3);
endPrimitive();
endShape(); If it is, then does that mean that within the first primitive, bezier segments will always have one fewer point than in the later ones?
For context, what is the special case you're referring to here? |
Thanks for bringing up these points @davepagurek! This is all helpful for filling in the details. Bézier curves are a special case?Yeah, I probably could've worded that more clearly. What I meant was that So, I really meant that Implied
|
Thanks for explaining! I think my confusion about the special casing is because I saw a different pattern in vertex/quadraticVertex/bezierVertex: all can be used to chain multiple segments, but each segment has an increasing number of control points (1, 2, then 3) from the last point. In fact, vertex() can be seen as a linear bezier, which is just a line segment, needing no control point in the middle. In that sense, adding multiple vertices isn't different from cubic beziers, since each straight line is a segment, not the whole polyline. (That's also why curveVertex felt like the odd one out to me, where all the points make up one segment. For what it's worth, the curveVertex workflow feels pretty separate from the rest, which are shared in other vector software. A possibly simplifying mental model would just be to treat curve vertices as a shortcut to bezier segments rather than a "real" primitive?) One of the things that still feels inconsistent in the variable-order proposal is that multiple vertices adds more segments, but multiple of arc or bezier vertices increases the order of the same segment. To me it feels that to be consistent, more vertices in a row would do a line of beat fit through them rather than a polyline. I think the heart of what I'm suggesting is to always add more segments as the standard behavior. The shift I was initially imagining was from grouping all control points of a segment extension into a single function call, to putting each control point into its own call., and the difference between segment extension types would be the interval at which a whole segment is complete. So vertex() calls, needing only one control point, add a new segment each time, quadratic points add a new segment every other point, cubic every three, and one could add quartic and quintic in the future that add a segment every four and five. (One could maybe add a generic version where you pass in the order into the first parameter.) Of course, this is all from a frame of mind where chaining is key. I still think this in my own work this is the case that is most common, where paths are composed of many segments. I ideally want the freedom that vertex() has in your proposal, where you can keep chaining more of them without boilerplate, for bezier curves too, since I think in your proposal right now every cubic segment would need to be bounded by begin/endPrimitive. Do you think there's anything we can do in the API proposal to make that use case a bit easier? |
Another thought: if we do go the route of having chains of vertices be all one segment like you're suggesting, maybe curve vertices don't have to be a separate thing, but just an interpolation strategy for those vertices?
So for an API, that would mean quadratic and cubic vertices continue to chain the same way normal vertices do, but you could surround vertices in Sorry if I'm derailing a bit haha, just wanted to share some thoughts that might combine both models! |
This is getting very interesting @davepagurek! I'm going to think about this some more. As if we didn't already have enough to think about, here are some papers that your recent comments inspired me to discover: I've only barely glanced through them, but the first of these seems to provide an interesting framework for a whole class of splines, which includes Bézier splines and elliptical splines (splines made from elliptical arcs) as special cases. They're distinguished by choosing different interpolation functions. The second article seems to develop an approach that's specific to splines made up of elliptical arcs. I need to think through everything again in light of all this discussion, so I'm not sure if these will be relevant yet, but I figured I'd share them in case they inspire ideas from others. |
Good morning again, just adding a summary comment about some of the discussion so far so it's easier to follow!
|
Thanks so much for the summary @davepagurek! I'll add a few thoughts about the existing options and propose a new one. A chaining-only APIOne option is to keep the original proposal, with a few changes.
In this case, we would sacrifice extensibility (e.g. higher-order Bézier curves); in other words, we wouldn't try to solve Problem 8 of the original proposal.1 We’d also lose the simplicity of being able to call any vertex function an unlimited amount of times. Separate APIs for chaining and aggregatingHere I'll add some issues to consider in relation to the idea you recently proposed.
Combined API for chaining and aggregatingBelow, I'll describe one approach that seems to do everything we want in a simple way. It's a variation of the API proposed by @peilingjiang. I'm not sure about it yet, but it seems really nice. The idea is to have four vertex functions:
As in the current version of p5.js, each function call creates a new segment (when the default shape kind is being used), and multiple calls will chain segments. There are two main differences from the current API:
As an initial example, here's how we could create a cubic Bézier segment:
This would be a slight departure from typical p5.js usage, which has users passing coordinates directly into functions, but it's similar to how we already allow users to pass a If we don't immediately see any major problems with this overall approach, I can work out more of the details (e.g. I can redo this list of examples in the new API). Footnotes
|
Thanks @GregStanton! Here are a few thoughts on the different ideas you mentioned.
|
@davepagurek I have some initial impressions but haven't had the opportunity to teach this part of API yet. I'll share some thoughts soon. @tabreturn you know much more about teaching curves than I do. What do you think about the proposal? |
I'll need to make some time to study this properly -- but it looks interesting! |
The 2.0 advisory committee was looking at all the proposals, and the feedback on this one is that the most important goal here is to increase simplicity and predictability, and the larger departures from the existing API end up complicating things too much to be worth it. So I think to move forward with this one, the best approach would be to narrow the focus and pick out the bits that offer incremental improvements to just the current p5 shape functions. In this case, I think that means going back to the chaining-only API described above. To summarize, from the current API:
This compromises the original proposal's side goal of allowing higher order Beziers and different interpolation schemes. I think if we want, we can extend the above to cover some of those other points by adding a |
@davepagurek Thanks so much for sharing the feedback! After reading it, I had a new idea that I'm excited about. I think it's consistent with the feedback, in spirit: it preserves the simplicity and predictability of the original API proposal, with few changes to the current API. It also happens to be very extensible. Actually, it solves all ten of the original problems, and it addresses the main flaw in the original proposal. I’d like to make more code examples to vet the idea further, but I’m hoping to get some initial feedback first. The API is indicated below, along with a code example, and some additional context. API
Example
Detailed benefitsThis API
It also solves an additional problem not identified in the original proposal's list of ten problems:
The term "spline" is more specific, while also being general enough to allow other types of splines in the future, e.g. via a function such as Note on
|
I'm a fan of that proposal! In your example, do you think that you can start with a |
Yay! Also, you've identified the exact issue that's been on my mind. It seems to be the only remaining detail to sort out (famous last words haha). For anyone who is following along, I'll describe it below, and I'll discuss a few ways we might proceed. Explicit-first-vertex issueIn the version of the API under discussion, Bézier curves of the same order can require different numbers of function calls. For example, when a Bézier segment of order ExplanationThis issue arises because a Bézier curve of order A few options for dealing with the explicit-first-vertex issueI'll describe the options presented so far, along with one new option. I'll also indicate costs and benefits of each option. 1. No changeIt'd be nice if a Bézier curve of order Also, this pattern for reusing vertices is precisely consistent with existing vertex features (triangle fans, triangle strips, and quad strips use the same pattern). For example, when using the 2. Use
|
I'm still thinking about what other options there might be, but in the mean time, one comment on this bit:
I'm imagining that each type of shape drawing function continues off of the last point, using its parameters to define how that continuation happens. The native drawing context
It's a little different for spline vertices because they could be used without continuing on from something else, which is the current inconsistency. Here's how that currently renders (the curve vertex points drawn in red for illustration):
If we were to make it consistent and require you to add a regular
|
@davepagurek: Thanks so much for fleshing that out! It seems like you're moving toward making splines work more like polylines, which would be great for usability. It also makes sense, since polylines really are linear interpolating splines. This got me digging into some different options, and it seems like we could maybe take this a step further. I need to develop this idea more, but I'll share what I'm thinking so far. Making splines as intuitive as polylinesAs an illustration of what I have in mind, you can try tinkering with this online demo. Try setting "Curve ends" to "Show," delete the default curve, and start adding control points one by one. You can leave the interpolation function on hybrid mode. The interface takes a little getting used to since points are added in random places, and you need to hover over the canvas to reveal the control points, but anyway... The cool thing is that this demo allows the user to specify a smooth spline with just two vertices or more, and they're all rendered (as long as "Curve ends" is set to "Show"). With this kind of approach, making splines would be about as intuitive as making polylines! This would be simpler than the interpolated-start-and-end option in your last diagram, since that would still require the user to supply four vertices, and I think it'd be less clear why we need four vertices. Note: This is a JavaScript and WebGL implementation of a new class of C^2 interpolating splines with some very nice properties; I'd be happy to share what I've learned about it (the researcher behind this is also an expert and seems available, e.g. via X). We may want to consider this new class for our implementation, but it may also be possible to come up with something similar without changing p5's implementation much. ModesWhile it may be nice to render all control vertices by default, the user would have less control if that were the only option. Perhaps we could support several modes, to be specified with a
These would correspond to "show," "hide," and "loop" in the online demo. However, there are some possible problems with this:
|
I think that paper makes for a good curve mode, as maybe would Hobby curves. I think all of them have pros and cons, so having a
I'm imagining users won't need to specify four vertices to use Catmull-Rom if we want to modify it to always go through endpoints, since the duplication would happen under the hood. This would look something like this to end users (click to add points): https://editor.p5js.org/davepagurek/sketches/kVff25GyA In this way I think it would be interchangeable with the C^2 spline algorithm or Hobby curves. I think the endpoint modes make sense! If using the For joining: definitely a little weird that there's a separate Also, here's a little implementation of how loop-closing Catmull-Rom with interpolated endpoints would look: https://editor.p5js.org/davepagurek/sketches/36Ro7HpR- Both this and Hobby curves are still cubic beziers under the hood, so it's maybe helpful for implementation that these strategies could both be implemented as translations or generators for a bezier path. (Edit for a little more context: other interpolation methods that aren't translatable to cubic bezier are still doable, it maybe would maybe just require us to convert it to a polyline for 2D mode to render it there. We'd be doing that anyway for WebGL mode so that's not a huge downside.) |
Anyway before getting too much more in the weeds with |
Thanks @davepagurek! I went ahead and incorporated all the important updates into the original proposal. I included a section at the end to indicate which updates were made. I agree that gathering more feedback would be a good next step! Also, your diagrams and sketches are all really helpful. I think that makes sense about Catmull-Rom not requiring four vertices if we're interpolating the control points at the beginning and end; thanks for the clarification. Your comments did give me some extra ideas about splines, which I've shared below. Also, especially now that I've summarized the latest proposal, I have a couple extra points on the overall API that I'm curious to get your feedback on. I'll start with those, since they seem more fundamental. Overall API: Predictability and Simplicity
SplinesI'll reply to a few points about splines as well, in case it helps us make progress. Type modesYeah, I was thinking we could potentially have a End modesI wanted to reply quickly, so hopefully my reasoning makes sense in this section. If I'm thinking incorrectly, please let me know! Hidden
|
SHOW |
HIDE |
---|---|
But, in SHOW
mode, it seems like we'd want the following instead:
P.S. It seems like the JOIN
case will take some more time to think through. I'm looking forward to working on that when I get a chance.
Starting vertexI'm ok with the idea that some things don't need to always start with a vertex, like the strip modes, and also splines. I think the consistent rule I'm imagining is that each new segment is responsible for transitioning from the last drawn point (not control point), if it exists, and that still holds for splines if they don't start with a I think my concern for bezier segments is that it's pretty rare to just have one Bezier segment compared to a chain of many of them. In that case, the concern that it's hard to tell segments apart in the code becomes the primary issue. I worry that if there isn't consistency (n calls always adds a new segment) then splitting a segment into multiple control points becomes too confusing, and that's the primary change that I personally am hoping to get out of the refactor. Forcing it to start with a vertex still keeps that rule above consistent: the difference between it and a spline is that splines can support arbitrarily many points in them, whereas non-splines always have a fixed amount (so I'd imagine SplinesSlight aside, but I think spline ends only apply to some splines, like Catmull-Rom or something like B splines, so if we do add something like C^2 interpolating curves or Hobby curves, the Anyway here's how I was imagining the end modes would work, keeping consistent that rule above:
|
Thanks for all the examples @davepagurek! Starting vertexIn my last reply, I think I could've been clearer when I tried to answer your original question:
I'm totally empathetic to your position! I originally had the same concern. But, based on all the considerations so far, I'm actually proposing the former option... For the record, I'll try to clarify my current reasoning with an example. 1 Example
ReasoningWith strips and fans, we've already accepted that the first piece of a shape will require more vertices than the remaining pieces. If we can accept that for strips and fans, then I think we could accept it for curves. This has several benefits:
We do lose the simplicity of always calling SplinesI was actually thinking about whether the end modes would only apply to some types of splines. Thanks for putting that on record. I have an initial idea of how we could handle that, but it's not ideal. I was thinking we could hash that out once the basics are in place. I do think end modes would apply to the Real-time discussions?For the rest of the issues around splines (names for the modes, etc.), maybe it'd make sense to set up one or more video calls at some point? In order to keep my GitHub replies from being super verbose, I've ended up omitting ideas or not communicating them clearly enough. Also, this discussion is getting long :) I usually prefer total transparency for anyone following along, but it might actually be easier for everyone if we just post summaries of real-time discussions? Footnotes
|
Hi @nickmcintyre and @tabreturn! The last time you were pinged on this issue, we were in the midst of a fairly complicated discussion. Since then, we've ironed out the main issues, and I've updated the original proposal to summarize the key points. I'm hoping it's easier to digest now. If you have any feedback, that'd be amazing! Also, @peilingjiang, the proposal now includes a function |
Thanks @GregStanton! @shiffman @stalgiag @outofambit, if any of you are interested and have the time, the issue description at the top has been updated with a new proposal. Since the last time you read it, we've reduced the scope of the changes, and they now mainly affect bezier and curve vertices, described in the "What's the solution?" section. |
Just wanted to add an update about this footnote in the issue description! Greg and I took a look at our shape drawing APIs, and as he mentioned, by looking at the number of arguments, we can distinguish between 1.x's
I'll be implementing it in one of those two spots at least, so we only need to decide whether the old API should remain a core feature or not. We also did some checks to see how much would be affected by our breaking changes. We found:
|
Sounds amazing! @davepagurek thank you for being so thoughtful about checking the Nature of Code examples ❤️ ❤️ ❤️ |
This feels like a big step in the right direction! The examples @GregStanton shared seem like they'd be much easier to teach -- maybe draw the curve, then draw a @davepagurek the 1.x compatibility addon seems perfect for making the old API available for awhile. |
Thanks so much for taking a look @nickmcintyre! That's a good observation about (Eventually, we might even consider making |
Quoting this comment from @golanlevin below, for the record. Here, an add-on library author acknowledges possible breaking changes and writes that the new API "is great" :)
|
Hi all, just chiming in to say that the vertex-functions proposal looks very thoughtfully conceived overall — and I look forward to adjusting my new SVG-exporting addon library, https://github.com/golanlevin/p5.plotSvg, as appropriate, in due time. I'm glad to learn of the 1.x compatibility addon for lots of reasons, this is thoughtful. But relative to p5.plotSvg, my library is quite new and it doesn't yet have a large user base. When 2.x comes out I'll probably just shrink-wrap a 1.x-compatible version of p5.plotSvg and start a new branch. |
A new Also, @davepagurek and I continued the discussion about the explicit-first-vertex issue, and we settled on leaving the proposal as it currently stands. Specifically, Béziers start with |
Before we lock in the names of the modes for ProblemAs @davepagurek pointed out, the names Solution?Dave previously suggested Less appealing alternativesI haven't come up with anything better. I don't think Future
|
I like |
This will be in 2.0 as of #7373! @GregStanton do you think I should keep this issue open for a bit for more discussion + any follow up work? |
Thanks @davepagurek! Yeah, I do think it'd be good to keep this open in case we can get a bit more feedback on the latest changes. I just read over all the discussion again, and I think the key points that remain are below. This issueThere are two points that would be nice to discuss further.
|
+1 for It'd be helpful to see a few quick examples of As for @GregStanton @davepagurek FWIW I appreciate the master class you two led while working on this part of the API 🙏🏽 Can't wait to use it! |
Thanks so much for the thoughtful reply and kind words @nickmcintyre! That's a great point about continuing the discussion of A revised API for spline settingsBelow, I've included some examples of what user code could look like, for a sample of spline types, and two possible APIs. In either case, vertices would be specified with For now, I'm using
Beginner-friendliness:
|
Increasing access
Implementing this proposal would
As a result, p5.js would be more accessible to beginners, while offering others access to a wider feature set.
Which types of changes would be made?
Most appropriate sub-area of p5.js?
What's the problem?
Short version
The current API for vertex functions contains complexities, inconsistencies, and hard-to-extend features. It's included below for easier comparison with the proposed API.
Long version
Eleven distinct problems arise from the current API for vertex functions. Below, each problem is listed and tagged with a problem type. (In case we want to modify the proposed solution, we can check the new version against this list.)
vertex()
but not toquadraticVertex()
,curveVertex()
, orbezierVertex()
, as noted in #5722. Under the current API, specifying texture coordinates would require up to fifteen parameters in a single function call, with the following syntax:bezierVertex(x2, y2, z2, u2, v2, x3, y3, z3, u3, v3, x4, y4, z4, u4, v4)
. [Inconsistency/Inflexibility]quadraticVertex()
andbezierVertex()
really do start withx2, y2
/x2, y2, z2
. That's because the first set of parametersx1, y1
/x1, y1, z1
must be specified separately, and we need a way to distinguish the second, third, and fourth points since they're grouped together in the same function call. [Complexity]x1, y1
/x1, y1, z1
gets passed tovertex()
. But that's just for Bézier curves. If we want to make a Catmull-Rom spline, the first point and all successive points get specified directly tocurveVertex()
. In other words, the current API allows the user to callvertex()
to start and continue a polyline, and to callcurveVertex()
to start and continue a Catmull-Rom spline; however, to start a shape with a quadratic or cubic Bézier curve, the user needs to mix commands. [Inconsistency]bezierVertex()
is named after a single vertex, but it accepts coordinates for three points. We may try to reconcile this by identifying the first two of those points as "control points" and the last point as a "vertex," but this is an uncommon distinction, and it doesn't hold up: we cannot reconcile it with the meaning of "vertex" incurveVertex()
. [Inconsistency]bezierVertex(x2, y2, x3, y3, x4, y4)
andbezierVertex(x2, y2, z2, x3, y3, z3, x4, y4, z4)
. Each of these signatures looks rather complicated by itself. [Complexity]bezierVertex()
andbezier()
are supported, andcurveVertex()
andcurve()
are supported. We also havequadraticVertex()
, butquadratic()
is not supported. (I've proposed separately that we should introduce a new functionarcVertex()
to address a similar inconsistency.) [Inconsistency]quadraticVertex()
is confusing for multiple reasons. BothquadraticVertex()
andbezierVertex()
produce Bézier curves, but only one of them contains the name "Bézier"; in other words, one function is named after the type of curve while the other is named after the order of the curve. Also, many p5 users are students who will have recently learned in algebra that "the vertex of a quadratic" (a parabola) corresponds to its lowest or highest point; that's not generally true of a vertex specified withquadraticVertex()
. [Inconsistency]vertex()
and specify the next four withquadraticVertex()
, we only have five vertices. We could potentially usevertex()
to specify the sixth vertex at the end, but this is inconsistent with howvertex()
is used everywhere else, and it still requires us to mix command types to create a single primitive. [Inflexibility]curveVertex()
uses a general term for a special shape, which leads to inconsistencies. For example, in the p5 reference, “Curves” is used as a general section heading that includes Béziers, whilecurve()
specifically creates Catmull-Rom splines only. This may lead to confusion. For instance, if we introduce a function such ascurveType()
for different spline implementations, it will be hard to guess whether it applies to all curves or only curves made withcurveVertex()
. [Inconsistency]What's the solution?
The main idea is to pass only one vertex into each vertex function.
Proposed API
The proposed API is indicated below.1
Amazingly, this simple API solves all eleven problems listed above 🤯The basic design was inspired by this comment from @davepagurek.
Notes:
bezierOrder()
eliminates the need forquadraticVertex()
arcVertex()
is based on the latest iteration of #6459splineVertex()
replacescurveVertex()
2Code examples
Example 1: Consistency across all types of curves
Note: Conceptually, polylines can be viewed as linear splines or as chained first-order Béziers.
Example 2: Clear function names, readable parameter lists, and flexible design
Note: Chaining quadratic and cubic Bézier curves does not currently work in p5, but issue #6560 aims to address this.
Example 3: Consistency across all chained shapes (curves, triangles, and quads)
Note: Bézier control points are rendered below as a visual aid, but the code for that is not shown.
Pros (updated based on community comments)
arcVertex()
, rather thanvertex()
. Same for other curve types.Cons (updated based on community comments)
Proposal status
Under review
Updates
This proposal has been updated to reflect some small adjustments, based on the discussion in the comments section:
bezierOrder()
was added to the API so that chained segments of different orders can be distinguishedarcVertex()
was added based on the current consensus in #6459curveVertex()
was replaced withsplineVertex()
based on Problem 11, which was added to the problem listsplineEnds()
was added to the proposed API to allow interpolated and non-interpolated endpointsAdditional code examples have also been included.
Footnotes
We may also want to support texture coordinates when a
z
-coordinate is not passed. This is currently supported byvertex()
(see the last example fortexture()
in the reference); however, it requires a separate signature forvertex()
that is not documented on its reference page (i.e.vertex(x, y, [u], [v])
). We'd need to discuss whether the benefits justify the extra complexity (namely, documenting and supporting an extra signature for every type of vertex function). ↩For consistency, we could also rename
curve()
asspline()
. ↩We can distinguish new and old usage of
bezierVertex()
by detecting the number of arguments, and we can deprecate the old usage. We could deprecatequadraticVertex()
andcurveVertex()
entirely with the @deprecated tag in the inline documentation. ↩The text was updated successfully, but these errors were encountered: