Open petaflot opened 5 months ago
Hi Petaflot, yes i like the idea of specifying a vector of 3 bools for center in a primitive instead of a single primitive. But before implementing your proposal, I feel we should even do more. My idea is that for each coordinate we should have even have 3 anchor points. So e.g. for the x coordinate min, mid, max would mean left, centered, right. I am just not sure if it would make sense to use False, None and True (and number) as "Tribool" Ultimately for a sphere and a cylinder this would mean that the reference point could be outside of the object Not mandatory to specify a number, but if so, the number could represent a percentage between left and right.
This would safe a lot of translate functions in the code and when displacements of two primitives are not automatically combined, code becomes much clearer.
I am just not sure, how to best solve the tribool issue.
yes.. but no? the problem I see is "it is relative" or "is it absolute". pretty much every part I design is a functional part (no companion cube or the like)
one idea is that if it is an int, is is absolute ; if it is a string (that ends with %
) then it is relative
IMHO having such control (relative/absolute on each axis) would really be cool and make for clean code
No need to stick with strings only
from openscad import * # yields constans OMIN, OMID, OMAX
cube(1) # Cube with origin on xmin, ymin, zmin cube(1, center=True) # cube with origin on xmid, ymid, zmid cube(1,center=[False, True, False] ) # cube with origin on xmin, ymid, zmin cube(1,center=[OMAX, OMAX, OMID]) # cube with origin on xmax, ymax, zmid] cube(1,center=[0.5, OMID, OMID] ) # cube with origin on 75% of X, ymid, zmid
just a proposal
c
so.. OMIN, OMID,OMAX would be "dynamic" constants?
cube(1,center=[0.5, OMID, OMID] ) # cube with origin on 75% of X, ymid, zmid
I really don't like the 0.5
value being 75%. TBH, I even set my printer's bed center to be at 0,0 because otherwise I thought it was so annoying. [0,0,0]
should IMHO be the grav center of the volume
.. or I somewhat misunderstood. grav center on spheres, cylinders and cubes is pretty straight forward. for more complicated shapes we might want a vertice as a reference : but then, what is relative positioning?
@gsohler I'd really like to share with you some code I've been working on for a few years ; ideally though I need to get a patent on some stuff because TBH I can barely eat, and getting health care is a whole different story
Yes OMIN, OMAX ,OMID would be dynamic constants and would change with the cube size e..g my previously suggested mapping was would be -1: total left -0.5: half left 0 center 0.5 half right (75% away from left side) 1 total right
but of course everything to be discussed(names, nomiclatures,etc) once everything makes sense, we implement
BTW feel free to send me secret data to my email, promise to keep it secret unless otherwise told
k I'll do that tomorrow
@gsohler it's taking me more time than expected, meanwhile I've had ideas that expand the whole thing and I'm pretty sure you'd have good input about this.
maybe you could start reading this https://github.com/openscad/openscad/issues/5120#issuecomment-2095285764 and preferably we'll meet on IRC so we can have a proper discussion about this and that and I could send you specific files as the discussion goes, answering any questions you might have.
I have this rather obsolete documentation on my project but unfortunately I cannot update it because of issues with gohugo ; meanwhile I've been able to generate and print some pretty interesting parts (examples attached).
this work was heavily inspired by openscad (I really like the concept of writing code to design parts), but it takes a totally different approach that does not compete with openscad, rather it's complimentary to it. FIY, I started it way before python for openscad, its origins date back to 2015-2016. it was started to offer a lot more control on the generation of gcode, and as it turns out it can be used efficiently for other purposes (one example is an automatic soldering machine I'm working on with a friend).
are you writing your own slicer in python ? if yes , what's its latest state ?
I am regularly checking #openscad and #pyopenscad
are you writing your own slicer in python ?
it's more than a slicer... because I program toolpaths, I can include gcode commands at specific points... but basically yes
latest state is working, I can export AND import gcode, made a number of successful prints with it, there still are a lot of features missing but I'm pretty happy with the way it works. and it's really fast too
oh and I still have to adjust the projection in quaternion space in order to make good use of the slerp() function
I was always excited about quaternions, but I never really understood, how they are working, but i presume, these influence the "tool path" of the 3d printer nozzle ? Can you give some examples, why your slicer is different and where are its advantages over others ?
objects (Polytopes) are basically a "string", made of a number of successive (in time ans space) vertices. This "string" could then be bent and folded along a chord, and printed with ie. a 6-axis robot, bent into knots (see knot theory for possible extensions and applications). Since a segment between two vertices is a (very simple) Polytope, one can define a sub-Polytope to replace that segment, and recursively, allowing for very intricate patterns and geometries.
My program (I don't like to call it a a slicer, because really it's very different from that) allows to have different layer thicknesses within objects (see second example image above), allows setting any number of properties to a Polytope (such as color, temperature, extrusion ratio, toolhead orientation...) for each vertices that can be either inherited from the Polytope or set individually for a point.
Since the order of the vertices and each of their individual properties can be defined at "drawing" time, this makes it most useful to control various machines that need to go around objects to do operation such as placing and soldering of electronic components. As a side-note, I also wrote a urwid-based program to send gcode to machine and that is specifically designed to get a number of machines work collaboratively : it is not finished and still has a few issues that need to be addressed (such as performance) but it looks very promising and can do stuff like gcode injection (and soon gcode interlacing.)
In my paradigm and to make it simple, a Polytope is basically a 4+D object that gets projected into 3D space based on a set of parameters that are all treated as rotating vectors (I actually started using pairs of complex numbers, like you do when using complex numbers to compute solutions in electricity
Below, a few more images of the things I've had to define in order to have consistency and not mix myself up in this quite complicated paradigm, and problems that still need to be solved.
Yet another example of a quite complicated object (based on a portion of the hilbert curve)
second image above, I just realized the title should not be Segment()
but Polytope()
; also, it is missing a dimension normal to the pseudo-plane.
Couldn't help adding this one too ;-) (some vertices are randomized for a better view)
Above (Skirt and convergent fill computation), it must be noted that the the normals to the plane through each point are not necessarily aligned (if we add a point D that is not on the plane, it is obvious that the normal though C will not be parallel to that through B ; the "plane" along the entire path is actually a mathematical strip (similar to a Moebius strip of infinite width.
I just realized in the "Skirt and convergent fill computation" image above that with proper use of quaternions and SLERP this problem may pretty much go away on its own..
[...] actually a mathematical strip [...]
In essence, a Polytope is the sequence of points that form the edge of a strip ; in a Moebius strip, that edge runs parallel to itself ; if a strip has a length l
, the edge has a length 2*l
: this makes a lot of sense when one thinks in terms of 2*Pi
for a full turn or single rotation.
The shortest path "between" those two halves of the edge form the strip ; the "unused" component (it really is meshed with all XYZ coordinates in the quaternion space) defines the local curvature of that path (normal to the edge)
- quaternions allow to avoid the singularities when doing rotations
objects (Polytopes) are basically a "string", made of a number of successive (in time ans space) vertices. This "string" could then be bent and folded along a chord, and printed with ie. a 6-axis robot, bent into knots (see knot theory for possible extensions and applications). Since a segment between two vertices is a (very simple) Polytope, one can define a sub-Polytope to replace that segment, and recursively, allowing for very intricate patterns and geometries.
- quaternions have 4 components, that can be mapped arbitrarily to XYZ space (with pretty much any arithmetic, as long as we can do the forward and reverse operation). This leaves us with an extra "trash" (or redundant) component that can be used efficiently to specify ie. the "twist" of that segment.
- quaternions can be interpolated with the SLERP function, computationally very effective and that has the side effect of making transitions very smooth and "organic" : drawing pipes that go through space becomes almost too easy.
My program (I don't like to call it a a slicer, because really it's very different from that) allows to have different layer thicknesses within objects (see second example image above), allows setting any number of properties to a Polytope (such as color, temperature, extrusion ratio, toolhead orientation...) for each vertices that can be either inherited from the Polytope or set individually for a point.
Since the order of the vertices and each of their individual properties can be defined at "drawing" time, this makes it most useful to control various machines that need to go around objects to do operation such as placing and soldering of electronic components. As a side-note, I also wrote a urwid-based program to send gcode to machine and that is specifically designed to get a number of machines work collaboratively : it is not finished and still has a few issues that need to be addressed (such as performance) but it looks very promising and can do stuff like gcode injection (and soon gcode interlacing.)
In my paradigm and to make it simple, a Polytope is basically a 4+D object that gets projected into 3D space based on a set of parameters that are all treated as rotating vectors (I actually started using pairs of complex numbers, like you do when using complex numbers to compute solutions in electricity
Below, a few more images of the things I've had to define in order to have consistency and not mix myself up in this quite complicated paradigm, and problems that still need to be solved.
Yet another example of a quite complicated object (based on a portion of the hilbert curve)
now I understand quaternions. its basically same concept like with quadcopters. there is pitch, yaw and roll. I am just not completely sure, if your software is a slicer or rather an aid to describe detailled movements in a clever way. Using your "tool path calculation as a slicer will have additional restrictions:
as for defining slicing properties in the openscad source, i don' t see that happen because
rather there are quite straght forward solutions viable with python like so:
solid1 = cube(10) | cylidner(r=5,h=10)
props_3mf = {"shell_thickness": 3, "bottom_layers: 3 ]
solid1.props_3mf = props_3mf export(solid1,"solid.3mf")
====== during exporting 3mf I could watch for keyword "props_3mf" and literally copy all available properties onto 3mf file Part using the 3MF set-property-on-part function.
now I understand quaternions. its basically same concept like with quadcopters. there is pitch, yaw and roll.
not really, but close. if you're interested, see geometrical transforms in the plane with complex numbers. quaternions are basically a pair of complex numbers
solid1 = cube(10) | cylidner(r=5,h=10) props_3mf = {"shell_thickness": 3, "bottom_layers: 3 ] solid1.props_3mf = props_3mf export(solid1,"solid.3mf")
====== during exporting 3mf I could watch for keyword "props_3mf" and literally copy all available properties onto 3mf file Part using the 3MF set-property-on-part function.
this looks very clean to me. I don't like comment parsing either...
I came up with this code now:
Any example code on how to use SetObjectLevelProperty ?
void Export3mfInfo::writePropsFloat(void pobj, const char name, float f) const { Lib3MF::PMeshObject obj = (Lib3MF::PMeshObject ) pobj; printf("Writing %s: %f\n",name, f); //void SetObjectLevelProperty(const Lib3MF_uint32 nUniqueResourceID, const Lib3MF_uint32 nPropertyID); }
in standard openscad
this can make placement of objects quite awkward ; in fact many years ago I wrote this library for openscad that makes this behaviour a little more uniform. see the prism() module here: https://github.com/petaflot/scadlib/blob/b5dedf222b124ac132a624b5d943df110fe6f9d6/scadlib.scad#L118
in particular, the center boolean true/false is replaced by an array with a boolean for each axis ; by default all prism objects are centered like a cylinder, and I have aliases (included from another file) such as
ttf=[true,true,false]
,tft=[true,false,true
etc. this has saved me a lot of time hassle and I would really like to see this type of behavior when using python in openscad.