-
Notifications
You must be signed in to change notification settings - Fork 152
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
Python bindings #206
Comments
Hey, |
Probably right here is the best place to discuss this for the time being. |
If you haven't seen this website: it is a good place to start. Have a look at the stack diagram on the front page. A language binding involves re-implementing the Scheme bindings and Standard library layers, at least. To view models, you can either export to STL and use a STL viewer or re-implement the Studio layer. The https://github.com/libfive/libfive/blob/master/libfive/include/libfive.h The Libfive Scheme bindings call functions from this API to implement primitives: https://github.com/libfive/libfive/blob/master/libfive/bind/libfive-guile.cpp The standard library builds upon these primitives to build shape, transforms, CSG operations, etc.: https://github.com/libfive/libfive/blob/master/libfive/bind/shapes.scm Libfive also uses sandboxing, which complicates things a little. For a simplified model viewer, there is Inspekt3d, written in Scheme, which could be ported to Python: https://github.com/sjm-tl-gh/inspekt3d Other ideas for model viewing with Python bindings: PyInventor: https://github.com/TheHubbit/PyInventor Currently, doing a Libfive language binding involves a lot of code reading. Libfive does not have a mailing list or wiki, as far as I know, so this Github issue tracker is the place to get help. |
Wow thanks a lot ! This for sure gives a clear view of how everything is structured. Your project is really cool. I think more advanced users will prefer using their own editor and view the model in a separate window. |
That's a great overview, thanks @sjm-tl-gh! Let me clarify a few details:
I've added a bunch of API docs in 59a7c99, which should help explain what functions in |
Hey guys, I've done a bit of work: https://gitlab.com/rcmz0/libfivepy I have a couple of questions:
|
@rcmz When I try https://gitlab.com/rcmz0/libfivepy, I get "An error occurred while loading commit signatures" at the top of the page in a red box. There is no source code shown. Re: your second question, for an infix expression language like Python, it might be more elegant to use infix as much as possible. Libfive uses F-rep, which is functional representation, and allows adding new functions. I may be wrong, but Python doesn't support adding infix operators as a language feature--but there are some hacks like: http://code.activestate.com/recipes/384122/. Unless you can come up with a method of generally extending infix notation, at some point users are going to see prefix function calls. That's an advantage of Lisp for the modeling language, which uses prefix notation uniformly. Of course, Python developers are used to looking at mixed expressions, so they might not be too confused. |
Also looking forward to python bindings to this project :) |
@sjm-tl-gh Sorry about the gitlab error it should be fixed now. The trick you showed for infix operators in python is pretty cool. It is quite hacky but it is an idea to keep in mind. |
@rcmz Your repository is now visible. Looks like you have a good start! Re: your previous question 1, at about: https://github.com/libfive/libfive/blob/master/libfive/bind/libfive-guile.cpp#L380 in Libfive, you can see where Matt has implemented generic arithmetic operations for shapes with function overloading. (Note that at this point, a lower level tree becomes a higher level When you get to adding vectors, the Libfive vector code also uses generic arithmetic. I'm not sure what Python has built-in for vector support, but I found this helpful: https://github.com/libfive/libfive/blob/master/libfive/bind/vec.scm when writing my Common Lisp binding to Libfive: https://common-lisp.net/viewvc/tovero/trunk/src/tovero/ I also factored out the generic arithmetic code for shapes into a separate file: https://common-lisp.net/viewvc/tovero/trunk/src/tovero/generic.lisp?view=markup I took the second approach @mkeeter mentioned earlier, using dynamic FFI rather than a C++ code extension library like Libfive Scheme. In general, though, I translated the Libfive binding code fairly closely, as it is well organized (and works!). |
@rcmz I'd recommend wrapping the math tree object ( Here's a very minimal example (that only overloads addition), with a sample interaction at the bottom. The only issue, as @sjm-tl-gh mentioned, is prefix operations (like
|
@mkeeter, your code for shape addition illustrates in Python what I was trying to say in my last post. However, you are overloading the built-in operators "inside" the class, rather than "externally" with generic functions like GOOPS/CLOS. Your code also illustrates the equivalent of It looks @rcmz has started doing it similarly, except with a I don't know what approach would be best for issues like with As for the @rcmz 's question:
I think you want to use Python for |
Oh yeah, it looks like @rcmz is already past the point of my example – I hadn't looked at their code before writing out my reply. I agree that you should use Python for basic arithmetic, only returning |
Thanks for your answers, I have renamed Tree to Shape and started the work to use libfive functions only when dealing with libfive objects. I also made sure that pointers where freed correctly (But their might probably be some memory leaks somewhere ). I added/changed quite a bit of stuff but the main one is that you can use transforms and cgs operations OOP style. So for example
|
Quick update: You can now use |
Personally I'd go for
Really |
I don't think it makes sense to overload arithmetic operators for CSG; because shapes are math expressions under the hood, those operators already have meaning as arithmetic. For example, |
Well python is a duck typed language. It should be pretty easy to have it subtract number as in your example, but subtract shapes as a CSG operation? While your CAD kernal is a lot more powerful then something like openscad, I really don't expect most of the people who use it from python to be using it like that, and I think it should be optimized for the most common use case. When you're doing an operation on a shape you're doing an operation on a shape. A shape is an abstraction for a math expression, they're not the math expression them self. We need to be talking about shapes or math, they are not the same level of abstraction. I'd recommend not mixing your level of abstraction on this, and that you treat shapes as shapes for the most part. Don't leak the math up to the easier to use abstraction, especially when there's a lovely lisp environment for the people who like math-based paradigms. |
but then what WOULD you recommend for an offset operation? That's one I use a lot, and I'd be expecting to think of it as addition to the distance field... I second |
I would recommend something like But, I mean, duck-typing. You can have it do different things for operations on numbers or on shapes. I guess my question is, if you want it to work like that, why not use the scheme bindings instead? It seems like the scheme bindings would better fit how you like to program, where as the python bindings should be pythonic. |
It's not number-vs-shape, it's "math expression that represents a shape" vs "math expression that represents a math expression", which is a distinction that's subtle-verging-on-nonexistent. For example, should You could potentially add a flag to the The most consistent behavior is to avoid that distinction altogether: have |
Alright, how would it work is the shapes weren't math expressions at all? If there were just platonic (heh) ideal shapes handed down from the gods, with the intent of matching people's intuition about what shapes are? |
If that's what people wanted, why would they even be using libfive? |
If folks want to treat shapes as purely abstract objects, then they can use If you want to do arithmetic on shapes, it makes sense to think about the underlying representation. It also makes it easier to build shapes using Python-like syntax, where you can say
(since the arithmetic operations are overloaded to do the same thing as Python's arithmetic, but producing math trees) |
I like the idea of shapes as objects but one of the great thing about libfive is that it enables you to use and understand shapes as functional representation, which is much more powerful. |
Because it's a lot easier for libraries to implement things like fillet unions, chamfers, pipes, shape-blending, etc. But my expectation is that most of the people using it for CAD aren't operating at that level, they're operating at a level closer to openscad. I'd expect libraries like the above operate at that lower-level. Meeting the expectations of the 90% of people who pick it up to use it like openscad is, in my opinion, more important then meeting the expectations of people who are going to dive into libfive in depth. I think that it should meet the expectations of low-skill users first, having a smooth learning curve for high-skill users. Ultimately I'd like to see it as part of the scientific python ecosystem, along side conda (on windows), numpy, scipy, etc. My hope is that this could enable truly reusable CAD modules, something openscad never managed to pull off, along side things like finite-element-analysis and geometric constraint solvers. This could allow the building of specialized CAD tools for things like architecture or circuit-board fabrication, as python libraries. |
See also: We need less powerful languages.
|
I tried earlier to create a Shape class with arrhythmic operator overloading. But if you really wanna try it I encourage you do so the project is open-source. |
I'm currently getting a segfault whenever I try to run |
Sorry this project is still really rough. |
It loads the library fine, but it segfaults. I haven't done a lot with ctypes before, so I'm not sure how to go about debugging that. |
I have committed the latest changes so I'm sure this build is working on my machine. |
My immediate thought is to provide two interfaces, a pythonic holds-your-hand interface that matches user expectations, and an Honestly there are much more important things then this, which is an ideological thing. It's not a point I'm going to fight very hard on until things are a fair bit more mature.
Yep, I've loaded the tutorial shape successfully. I am using archlinux, which means my libfive-studio is
|
Re: Libfive language design in Python For comparison, it might help to look at an example of a 3D modeling system already written in Python. Here's a model in CadQuery: It integrates into Juypter notebooks: https://mybinder.org/v2/gh/RustyVermeer/tryCQ/master At the Jupyter notebook level, there are GUI fields for model parameters which might appeal more to non-programmers. It becomes "declarative modeling". (It would be nice to have both Guile and Python versions of this for Libfive.) CadQuery apparently uses the "concatenate function calls" syntax like |
|
Thanks for the help. I've got libfive recompiled with the build_type=Debug flag set (I think). I just edited my distributions pkgbuild to include the I've added prints around line 103 of kernel.py, where the I'm not sure what
|
No nulls there, I'll see about getting it actually building as debug |
@traverseda Re: segfault, let's move this to an issue on https://gitlab.com/rcmz0/libfivepy if you are still having trouble. I deleted my posts because I think the debugging session is cluttering up the original issue here. Thanks. (Github really needs threading in issues, like we expect even in plain old email.) |
I used PyInventor to view the sample model from @rcmz pylibfive project: https://gitlab.com/rcmz0/libfivepy/issues/1 I'm looking converting the PyOpenGL GLUT shader example into a simple viewer like Inspekt3D. |
There seems to be a pretty big issue with |
Ok it has been fixed 🎉 It was: I thought those two expressions were equivalent but apparently no ! |
Here are two links that might help you with F-rep: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm |
If you open an libfivepy generated stl file with fstl and set it to auto-reload; every time you regenerate the stl (with libfivepy) fstl say it is corrupted. Which is strange because it display the stl fine and it doesn't occur when you load the file manually. This is probably a libfivepy issue but here is a post anyway. Link to the thread on libfivepy: https://gitlab.com/rcmz0/libfivepy/issues/4 |
Sorry for posting on such an old thread, but it seems like sorting out python arithmetic ops vs lib5 ops is a perfect use case for single-dispatch function |
Just posting a message here to let you know I started new Python bindings here: https://github.com/SemMulder/libfive-python. The main difference compared to Right now it only exposes the raw functionality of the libfive C API, but if you are familiar with F-rep that should be enough to get going! Let me know what you think! |
Python bindings are now part of core, although they're not documented yet. Closing this issue, that's some very exciting stuff! |
Noticed that there isn't currently a ticket for python bindings. I for one would find that useful.
The text was updated successfully, but these errors were encountered: