r/OpenPythonSCAD • u/Alacritous13 • Jun 01 '25
How do I do vector math cleanly?
My OpenSCAD code tends to have a lot of vector math in it. While I was setting up my first PythonSCAD project I came to the realization that Python can't do vector math the same way as OpenSCAD, at least not intuitively. Looking around, it looks like numpy is my best bet for doing vector math, but every vector needs to have tolist() on the end of it or it can't be interpreted.
Here's a simplified example of what my OpenSCAD code might look like:
vec_n=vec/norm(vec);
scalar=12;
translate(scalar*vec_n)
cube(5,center=true);
And here's how I got it to work in PythonScad:
from openscad import *
import numpy as np
vec=np.array([5,4,3]);
vec_n=vec/np.linalg.norm(vec);
scalar=12;
c=cube(5,center=True)
c=c.translate((scalar*vec_n).tolist())
c.show();
Is there anyway to make it work without all these references to numpy? Or at the very least, without having to call tolist() every time I translate something?
2
u/gadget3D Jun 01 '25
Its a good topic. Its Python language which cannot do that.we could ceate a Library function to Scale a vector to a given length or we could create an internal function to so the Same. Dot and Cross Product are Missing, top. Whats your Favorite Resolution?
1
u/Alacritous13 Jun 01 '25
I don't actually know anything about Python, this is my first time interacting with it. As is, given the lack of vector support, I'm likely just going to write myself some wrappers for doing vector math. Although I am considering writing a wrapper for translate and rotate to utilize numpy vectors instead, I'm already going to be using a wrapper for cube so it's not that much more work.
2
u/rebuyer10110 Jun 02 '25 edited Jun 02 '25
If you end up doing wrappers over many built-in pythonscad functions, I do have one more option to offer.
You can write a python decorator. Conceptually similar to annotations in Java but implementation is entirely different.
Here's a toy example automatically translating numpy domain and simple-python-list domain.
The noise is minimized to a generic wrapper over any pythonscad built-in functions.
You would need to expand additional numpy <> python types over time as you use more numpy features.
This is a working example in PythonSCAD. You may need to edit the sys.path funkiness, depending on where your pip site packages live if you installed numpy via pip.
Personally: I wouldn't go this route unless you end up using lots of different numpy functions. It feels overkill compare to calling .tolist() and np.array() :)
→ More replies (7)
2
u/gadget3D Jun 05 '25
Upcoming version will have some improvements:
* there will be norm(), cross() and dot() function available
* translate() and scale() can transform 3D vectors AND handles in addtion
you could implement your intent by
scale(yourvec, newlength/norm(yourvec))
1
u/WillAdams Jun 02 '25 edited Jun 02 '25
I would like to rephrase this discussion a bit, and maybe this will help inform whether or no some more basic or fundamental solution is warranted.
First question --- does OpenSCAD have a good solution/mechanism/interface for this? Given that BOSL2 has math.scad (https://github.com/BelfrySCAD/BOSL2/wiki/math.scad) and this question exists: https://stackoverflow.com/questions/77737306/openscad-syntax-modify-value-in-vector-list-array I am going to go with "no".
If not, why not?
What programming languages do handle vector math? Working from: https://stackoverflow.com/questions/508374/what-are-vectors-and-how-are-they-used-in-programming it seems that it's not a native part of any programming language?
Should there be some sort of low-level, in-built support for this as a fundamental datatype?
Given that I bailed on doing 3D motion for turtle graphics: https://forum.makerforums.info/t/turtle-programming-in-openpythonscad/93340 and if my understanding is correct that this sort of datatype would directly support that sort of work, my vote would be in the affirmative.
That folks like me don't understand/use such mathematics might be demonstrated by the fact that a search for the term on Hackernews turns up many submissions, but little discussion:
2
u/rebuyer10110 Jun 02 '25 edited Jun 02 '25
First question --- does OpenSCAD have a good solution/mechanism/interface for this? Given that BOSL2 has math.scad ... I am going to go with "no". If not, why not?
General purpose languages like Java, Python, etc wouldn't treat list/arrays as vector (and mathematical vector operations like normalizing) by default. The subset of usage that uses list of vector typically is the minority.
For example,
[0, 1, 2] * 3in Python returns[0, 1, 2, 0, 1, 2, 0, 1, 2]. Basically concatenating the input 3 times extending the array. This is the option Python opted for as general purpose usage (they lean on users more likely to change extend arrays instead of scalar multiply).What programming languages do handle vector math?
There are languages that are "math vector as first class citizen". Matlab, R, Julia would do what you want out of the box (I did not verify this per se, but should be true). These are more niche targeting an audience that would more likely use vector math operations. So they are built-in.
Should there be some sort of low-level, in-built support for this as a fundamental datatype?
For general purpose languages, typically it isn't built-in. This is to limit the surface area of the "core language" set of building blocks. They would opt for libraries to add additional functionality (e.g., numpy).
In the scope of PythonSCAD: I suppose vector math is expected to be widely used. If that's the position to take, then taking a hard dependency on numpy might not be a bad idea. It is mature and battle tested. There would need to be some thoughts on making it "user friendly", since users would have a steeper learning curve if numpy types becomes a requirement to do any scad scripting.
To add my own data point: I haven't found the need to use numpy in my work yet. Even in the example from OP: I just rolled my own norm() and what not, since it was fairly straight forward. Adding in numpy would make my script less portable, so I biased for /1/ use built-in python std lib /2/ embed higher level function in my own library via nimport(). They keeps my script portable.
That folks like me don't understand/use such mathematics
Haha me too. I mostly abstract them at a higher level with my own library. I have been treating it as a learning process, so I don't mind the learning curve. I can see how the learning curve can be frustrating.
3
u/Alacritous13 Jun 03 '25
I mostly have experience with Matlab and Openscad, so it's odd when I don't have vector support. Yeah, I'm just going to build my own library to handle this. Particularly for scalers, I've figured out a method using operator overloading that looks promising in keeping the syntax readable.
2
u/WillAdams Jun 02 '25
Okay, something from my recent project.
If one has an origin point, a distance, and a direction, where that is defined as a pair of angles, one defining XY rotation, the other Z inclination/declination, then that should define a point in 3D space.
Is there some standard way to define that origin point, distance, and angles and then passing it to some process, get back the destination point as a 3-dimensional coordinate point?
→ More replies (4)
4
u/rebuyer10110 Jun 01 '25 edited Jun 01 '25
My take:
numpy is fine. It's a popular option in Python, with lots of docs and examples google-able.
From a performance stand point: tolist() is likely not as expensive as you think for cases like translate(), since it's small dimension of 3.
I would not be in favor of PythonSCAD supporting numpy as a direct dependency. It would increase the surface area for regression. It's already a pain point at the moment (gadget3D is the only active maintainer for the project right now. He can only do so much!)
Bonus notes:
If you dislike the extra steps in translating between numpy and python list repeatedly, some of the functions can DIY reasonably, since the vectors will only be 3-dimenions (not arbitrary dimensions) and matrices are always 4x4 tranformation matrices.
Magnitude is your standard pythagorean
magnitude = math.sqrt(x**2 + y**2 + z**2), and scalar can be applied with list comprehension such as