Sometimes I want to use a vector's normalized form in an equation, but I don't want to mutate my original vector. In these cases it would be nice to have a static version of .normalize().
For example:
// current method
const normalizedVector = myVector.copy().normalize()
// proposed method
const normalizedVector = p5.Vector.normalize(myVector)
This would follow the pattern of .mag(), .add(), and other existing vector functions that have both a mutative prototype version and a static version.
I'd be happy to submit a PR implementing this enhancement, with tests and docs, if you think this would be a valuable addition.
Welcome! 馃憢 Thanks for opening your first issue here! And to ensure the community is able to respond to your issue, be sure to follow the issue template if you haven't already.
This sounds like a good addition to me, and I think there is a solid case to make for them. Having to use the copy() function like you did looks confusing and feels unintuitive. I think that a user would reasonably assume that if they could do p5.Vector.mag(v) they should also be able to do p5.Vector.normalize(v).
There are already a number of static vector math functions available. My guess is that a few of them were just overlooked. For instance, we're also missing one for p5.Vector.magSq().
You can see the static versions of these functions here
I personally don't mind this addition but I do wonder how this fit into the accessibility requirement for adding new features.
I think that this could fit into the accessibility requirement in that it makes the library more predictable and uniform for people new to programming / creative coding / vector math. The current scattershot state of vector math with half of the functions containing static versions, and half that don't feels to me like static functions were just added sporadically as different contributors needed to use them.
Perhaps it's out of scope for this issue but if we decide not to add these functions, I wonder if the errors / warnings could be more helpful if you tried to use a non-existing static function. Currently if you try to use p5.Vector.normalize() FES will tell you that p5.Vector.normalize doesn't exist, which is sort of true, but confusing since it does exist in the non-static form.
I went through to take an inventory of the existing static functions, and the missing ones and there's actually quite a lot missing. There are some functions where it doesn't makes sense to have a non-static version (random2D / random3D and fromAngle / fromAngles ) so keep that in mind as well.
| Function | Non-static | Static |
|-------------- |------------ |-------- |
| Copy |x | |
| Add | x | x |
| Rem | x | x |
| Sub | x | x |
| Mult | x | x |
| Div | x | x |
| Mag | x | x |
| MagSq | x | |
| Dot | x | x |
| Cross | x | x |
| Dist | x | x |
| Normalize | x | |
| Limit | x | |
| SetMag | x | |
| Heading | x | |
| Rotate | x | |
| AngleBetween | x | |
| Lerp | x | x |
| Reflect | x | |
| FromAngle | | x |
| FromAngles | | x |
| ToString | x | |
| Array | x | |
| Equals | x | |
| Random2d | | x |
| Random3d | | x |
Thanks for compiling that table @aferriss, that's really useful!
The basis in which a function has a static version or not is based on whether the equivalent function in Processing has static version or not (what Processing based it on though I have no idea), so this is mostly decision made almost at the very beginning.
I think the argument made about making the library more uniform and predictable does resonate with me though not as often with p5.js but rather with native String functions, I'm still constantly having to look up documentation to see if a function is static, functional, or modifies the callee. Same thing could be said to apply here.
I'm for adding static versions of functions to the vector methods where possible. If we get another sign off, I'd say we can go ahead with the implementation. @lmccart @stalgiag @outofambit @montoyamoraga or anyone else want to have a look at this proposal?
This issue was a joy to read. Thanks for the clear writing and thorough research everyone.
It may be more of a philosophical discussion but I think that predictability falls under the umbrella of accessibility. I too find myself 'having to look up documentation to see if a function is static, functional, or modifies the callee'. An argument could be made that the mutative prototype version encourages a better understanding of how objects are modified but I don't think that lesson is made unavailable by the existence of a static version. Also, it isn't as if this is currently consistent in only having prototype methods and never having static functions as illustrated by @aferriss 's table.
I support adding static versions of functions to the vector methods where possible.
hey thanks @limzykenneth , i like what @aferriss proposes about making the "library more predictable and uniform"
i agree with @stalgiag and support adding the static versions ~
Cool, barring any objections I'll put together a PR for this.
Since it will be my first contribution here I'm thinking I'll start with .normalize(), get some eyeballs on that first commit, and once I've got confirmation that I haven't missed anything (docs, tests, etc) I'll proceed to add the rest to that same branch. Sounds good?
@weslord that sounds like a great plan! Thanks for the input everyone :D
Heyy @weslord would you mind, if I can also assist you in this issue. I am also new contributing here
Before working on any function. I may ask or inform you prior working on function, so that we don't end up writing the code for the same function.
For instance, I would like to start with MagSq function. Thanks :)
thanks everyone, this sounds like a good plan! I wanted to point out that we have a pattern of adding readme files to each folder, to help explain the files inside and the key ideas/notes for the code. here is an example of the src/ and the src/core/ folders. this is a very in progress thing as you can see from the lack of readmes in most folders. however, it might be nice to take this opportunity to start a readme file for the src/math folder and document this static pattern decision.
@weslord I've assigned the issue to you. @covalentbond Do coordinate with @weslord if you wish to help out with this issue. Thanks all.
I would like to take a shot at this issue. @weslord @covalentbond Can you let me know which functions are you working on? I am planning to work on the rotate() function. Thanks!
I have curated a list of vector functions (table provided by @aferriss) that needs a static counterpart. This is my perspective, and I would love to hear your thoughts about this before diving into the implementation. @lmccart @limzykenneth @aferriss @montoyamoraga
| Function | Static version needed? | Reasoning |
|---|---|---|
| Normalize | Needed | The non-static versions of these functions changes the value of the vector supplied as argument. |
| Rotate | ||
| Reflect | ||
| Copy | Not sure | The non-static versions these function does not change the value of vector supplied as argument. As discussed above we could implement this for uniformity of p5.js. Is it fine to have two functions performing the same operation? | MagSq | Heading | AngleBetween | ToString | Array | Equals |
| Limit | Not sure | These functions are required to modify the vector supplied as argument. Hence, the static versions of these functions will perform the same operations performed by non static versions. |
| SetMag |
Thank you!! @aferriss for providing the vector functions table :)
Thanks for the help on rotate(), @siv2r! I'd prefer to work on the rest of the functions myself, if you don't mind.
Between proposing this issue and being assigned it, I've become much more busy, but I am still working on this and I expect I'll have time to finish it off over the next few weeks.
If there's still no progress from me after the 17th, please re-assign this.
Sure go ahead!! Do let me know if we could possibly coordinate to get this done faster.
Most helpful comment
thanks everyone, this sounds like a good plan! I wanted to point out that we have a pattern of adding readme files to each folder, to help explain the files inside and the key ideas/notes for the code. here is an example of the src/ and the src/core/ folders. this is a very in progress thing as you can see from the lack of readmes in most folders. however, it might be nice to take this opportunity to start a readme file for the
src/mathfolder and document this static pattern decision.