RW
Rogier Wolff
Wed, Dec 31, 2025 5:46 PM
Hi,
I am working on objects that are created like this:
m = 0.5;
cs = 50;
difference () {
translate ([0,0,cs/2+.001]) cube (cs, center=true);
linear_extrude (height=cs+.002, twist = 5*90, convexity=10) square ([100,m], center=true);
}
Put it on its side and 3D-print and you have a simple puzzle to put it
back together.
But the procedure is to click "split to objects" in the slicer and
orient the pieces before printing. This adds a step that needs to be
redone with an intelligent person behind the keyboard. I want to make
the prints reproducible by doing it in openscad before exporting.
This requires being able to separate the two resulting objects.
Does anybody have a way of doing this?
In this simplest-example,
difference () {
translate ([0,0,cs/2+.001]) cube (cs, center=true);
linear_extrude (height=cs+.002, twist = 5*90, convexity=10)
translate ([-50,0])square ([100,100]);
}
works to get one half. But my splitting shapes are quickly becoming
more complicated from here on out.
Roger.
--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 **
** Verl. Spiegelmakerstraat 37 2645 LZ Delfgauw, The Netherlands.
** KVK: 27239233 **
f equals m times a. When your f is steady, and your m is going down
your a** is going up. -- Chris Hadfield about flying up the space shuttle.
** 'a' for accelleration.
Hi,
I am working on objects that are created like this:
--------------
m = 0.5;
cs = 50;
difference () {
translate ([0,0,cs/2+.001]) cube (cs, center=true);
linear_extrude (height=cs+.002, twist = 5*90, convexity=10) square ([100,m], center=true);
}
--------------
Put it on its side and 3D-print and you have a simple puzzle to put it
back together.
But the procedure is to click "split to objects" in the slicer and
orient the pieces before printing. This adds a step that needs to be
redone with an intelligent person behind the keyboard. I want to make
the prints reproducible by doing it in openscad before exporting.
This requires being able to separate the two resulting objects.
Does anybody have a way of doing this?
In this simplest-example,
difference () {
translate ([0,0,cs/2+.001]) cube (cs, center=true);
linear_extrude (height=cs+.002, twist = 5*90, convexity=10)
translate ([-50,0])square ([100,100]);
}
works to get one half. But my splitting shapes are quickly becoming
more complicated from here on out.
Roger.
--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 **
** Verl. Spiegelmakerstraat 37 2645 LZ Delfgauw, The Netherlands.
** KVK: 27239233 **
f equals m times a. When your f is steady, and your m is going down
your a** is going up. -- Chris Hadfield about flying up the space shuttle.
** 'a' for accelleration.
JB
Jordan Brown
Wed, Dec 31, 2025 7:17 PM
If I understand your question correctly, it simplifies down to this:
difference() {
cube(20, center=true);
cube([1,30,30], center=true);
}
and you then want to operate on the two half-cubes independently.
No, there is no way to do that.
What you have to do is generate each side independently, something like so:
module split(side) {
big = 1000;
gap = 1;
intersection() {
children();
if (side == "left") {
translate([-big - gap/2, -big/2, -big/2])
cube(big);
} else {
assert(side == "right");
translate([gap/2, -big/2, -big/2])
cube(big);
}
}
}
module model() {
cube(20, center=true);
}
explode = 5;
translate([-explode, 0, 0]) split("left") model();
translate([explode, 0, 0]) split("right") model();
But you do have to do it by defining the boundaries of each "side",
rather than by defining the cut.
If I understand your question correctly, it simplifies down to this:
difference() {
cube(20, center=true);
cube([1,30,30], center=true);
}
and you then want to operate on the two half-cubes independently.
No, there is no way to do that.
What you have to do is generate each side independently, something like so:
module split(side) {
big = 1000;
gap = 1;
intersection() {
children();
if (side == "left") {
translate([-big - gap/2, -big/2, -big/2])
cube(big);
} else {
assert(side == "right");
translate([gap/2, -big/2, -big/2])
cube(big);
}
}
}
module model() {
cube(20, center=true);
}
explode = 5;
translate([-explode, 0, 0]) split("left") model();
translate([explode, 0, 0]) split("right") model();
But you do have to do it by defining the boundaries of each "side",
rather than by defining the cut.
CC
Cory Cross
Wed, Dec 31, 2025 9:34 PM
On 12/31/25 9:46 AM, Rogier Wolff via Discuss wrote:
I am working on objects that are created like this:
m = 0.5;
cs = 50;
difference () {
translate ([0,0,cs/2+.001]) cube (cs, center=true);
linear_extrude (height=cs+.002, twist = 5*90, convexity=10) square ([100,m], center=true);
}
For anyone looking for a summary, the above is defining the gap between
pieces and removing it from a cube.
But the procedure is to click "split to objects" in the slicer and
orient the pieces before printing. This adds a step that needs to be
redone with an intelligent person behind the keyboard. I want to make
the prints reproducible by doing it in openscad before exporting.
This requires being able to separate the two resulting objects.
Does anybody have a way of doing this?
Jordan's "geometry literals
https://github.com/openscad/openscad/pull/4478," when complete, could
allow iterating across distinct meshes. Something like:
g = {{ m = 0.5; cs = 50; difference () { ... } }};
num_meshs = g.num_meshes();
for(i=[1:num_meshes]) translate([i*60,0,0]) g.mesh(i);
That would space every non-overlapping mesh out along the X axis every
60 units.
On 12/31/25 9:46 AM, Rogier Wolff via Discuss wrote:
> I am working on objects that are created like this:
>
> --------------
> m = 0.5;
> cs = 50;
>
> difference () {
> translate ([0,0,cs/2+.001]) cube (cs, center=true);
> linear_extrude (height=cs+.002, twist = 5*90, convexity=10) square ([100,m], center=true);
> }
> --------------
For anyone looking for a summary, the above is defining the gap between
pieces and removing it from a cube.
> But the procedure is to click "split to objects" in the slicer and
> orient the pieces before printing. This adds a step that needs to be
> redone with an intelligent person behind the keyboard. I want to make
> the prints reproducible by doing it in openscad before exporting.
>
> This requires being able to separate the two resulting objects.
>
> Does anybody have a way of doing this?
Jordan's "geometry literals
<https://github.com/openscad/openscad/pull/4478>," when complete, could
allow iterating across distinct meshes. Something like:
g = {{ m = 0.5; cs = 50; difference () { ... } }};
num_meshs = g.num_meshes();
for(i=[1:num_meshes]) translate([i*60,0,0]) g.mesh(i);
That would space every non-overlapping mesh out along the X axis every
60 units.
- Cory
RW
Rogier Wolff
Wed, Dec 31, 2025 10:04 PM
On Wed, Dec 31, 2025 at 11:17:20AM -0800, Jordan Brown via Discuss wrote:
translate([-explode, 0, 0]) split("left") model();
translate([explode, 0, 0]) split("right") model();
But you do have to do it by defining the boundaries of each "side",
rather than by defining the cut.
The "cutting objects into parts" started with George Hart's screw
puzzles. (The STLs he published have OpenSCAD artefacts in them, so I
know how he made them!)
I'm now splitting a cube into 8 parts. So writing separate code for
each part becomes tedious.
Roger.
--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 **
** Verl. Spiegelmakerstraat 37 2645 LZ Delfgauw, The Netherlands.
** KVK: 27239233 **
f equals m times a. When your f is steady, and your m is going down
your a** is going up. -- Chris Hadfield about flying up the space shuttle.
** 'a' for accelleration.
On Wed, Dec 31, 2025 at 11:17:20AM -0800, Jordan Brown via Discuss wrote:
> translate([-explode, 0, 0]) split("left") model();
> translate([explode, 0, 0]) split("right") model();
>
> But you do have to do it by defining the boundaries of each "side",
> rather than by defining the cut.
The "cutting objects into parts" started with George Hart's screw
puzzles. (The STLs he published have OpenSCAD artefacts in them, so I
know how he made them!)
I'm now splitting a cube into 8 parts. So writing separate code for
each part becomes tedious.
Roger.
--
** R.E.Wolff@BitWizard.nl ** https://www.BitWizard.nl/ ** +31-15-2049110 **
** Verl. Spiegelmakerstraat 37 2645 LZ Delfgauw, The Netherlands.
** KVK: 27239233 **
f equals m times a. When your f is steady, and your m is going down
your a** is going up. -- Chris Hadfield about flying up the space shuttle.
** 'a' for accelleration.
GH
gene heskett
Thu, Jan 1, 2026 12:32 AM
On 12/31/25 12:47, Rogier Wolff via Discuss wrote:
Hi,
I am working on objects that are created like this:
m = 0.5;
cs = 50;
difference () {
translate ([0,0,cs/2+.001]) cube (cs, center=true);
linear_extrude (height=cs+.002, twist = 5*90, convexity=10) square ([100,m], center=true);
}
Put it on its side and 3D-print and you have a simple puzzle to put it
back together.
But the procedure is to click "split to objects" in the slicer and
orient the pieces before printing. This adds a step that needs to be
redone with an intelligent person behind the keyboard. I want to make
the prints reproducible by doing it in openscad before exporting.
This requires being able to separate the two resulting objects.
Does anybody have a way of doing this?
In this simplest-example,
difference () {
translate ([0,0,cs/2+.001]) cube (cs, center=true);
linear_extrude (height=cs+.002, twist = 5*90, convexity=10)
translate ([-50,0])square ([100,100]);
}
works to get one half. But my splitting shapes are quickly becoming
more complicated from here on out.
Roger.
I do it pretty simply. I print a complete hotend for a 3d printer in 5
pieces after I design it all to just fit, then translate and rotate the
individual parts to put them separated on the printers bed. Works a
treat for me.
Cheers, Gene Heskett, CET.
"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author, 1940)
If we desire respect for the law, we must first make the law respectable.
- Louis D. Brandeis
Don't poison our oceans, interdict drugs at the src.
On 12/31/25 12:47, Rogier Wolff via Discuss wrote:
> Hi,
>
> I am working on objects that are created like this:
>
> --------------
> m = 0.5;
> cs = 50;
>
> difference () {
> translate ([0,0,cs/2+.001]) cube (cs, center=true);
> linear_extrude (height=cs+.002, twist = 5*90, convexity=10) square ([100,m], center=true);
> }
> --------------
>
> Put it on its side and 3D-print and you have a simple puzzle to put it
> back together.
>
> But the procedure is to click "split to objects" in the slicer and
> orient the pieces before printing. This adds a step that needs to be
> redone with an intelligent person behind the keyboard. I want to make
> the prints reproducible by doing it in openscad before exporting.
>
> This requires being able to separate the two resulting objects.
>
> Does anybody have a way of doing this?
>
>
> In this simplest-example,
>
> difference () {
> translate ([0,0,cs/2+.001]) cube (cs, center=true);
> linear_extrude (height=cs+.002, twist = 5*90, convexity=10)
> translate ([-50,0])square ([100,100]);
> }
>
> works to get one half. But my splitting shapes are quickly becoming
> more complicated from here on out.
>
> Roger.
I do it pretty simply. I print a complete hotend for a 3d printer in 5
pieces after I design it all to just fit, then translate and rotate the
individual parts to put them separated on the printers bed. Works a
treat for me.
>
Cheers, Gene Heskett, CET.
--
"There are four boxes to be used in defense of liberty:
soap, ballot, jury, and ammo. Please use in that order."
-Ed Howdershelt (Author, 1940)
If we desire respect for the law, we must first make the law respectable.
- Louis D. Brandeis
Don't poison our oceans, interdict drugs at the src.
JB
Jordan Brown
Thu, Jan 1, 2026 2:06 AM
On 12/31/2025 1:34 PM, Cory Cross via Discuss wrote:
No, the data that I "currently" (which is to say, a year or two ago)
have access to is not broken up into distinct volumes. It is, in
essence, the same as the arguments to a single polyhedron() call: a
list of vertexes and a list of faces.
One could certainly post-process that to find sets of faces that were
disjoint, but in the current state of #4478 it does not do that processing.
But note: disjoint sets of faces do not necessarily represent disjoint
shapes, or at least not exactly: a shape with an interior void would
have disjoint faces but would not normally be considered to be two
disjoint shapes. I think that one could further post-process the data
to determine that a particular set of faces represent a void inside a
solid, rather than representing the outer boundary of a solid. Even
then, if there was a second shape inside that void, it would be still
a third disjoint set of faces. Whether you would want to separate that
interior shape would depend entirely on the situation.
But still another note: I am not aware of any current 3D printing
technology capable of creating a free-floating shape inside a void
inside another shape.
On 12/31/2025 1:34 PM, Cory Cross via Discuss wrote:
> Jordan's "geometry literals
> <https://github.com/openscad/openscad/pull/4478>," when complete,
> could allow iterating across distinct meshes.
No, the data that I "currently" (which is to say, a year or two ago)
have access to is not broken up into distinct volumes. It is, in
essence, the same as the arguments to a single polyhedron() call: a
list of vertexes and a list of faces.
One could certainly post-process that to find sets of faces that were
disjoint, but in the current state of #4478 it does not do that processing.
But note: disjoint sets of faces do not necessarily represent disjoint
shapes, or at least not exactly: a shape with an interior void would
have disjoint faces but would not normally be considered to be two
disjoint shapes. I *think* that one could further post-process the data
to determine that a particular set of faces represent a void inside a
solid, rather than representing the outer boundary of a solid. Even
then, if there was a second shape *inside* that void, it would be still
a third disjoint set of faces. Whether you would want to separate that
interior shape would depend entirely on the situation.
But still another note: I am not aware of any current 3D printing
technology capable of creating a free-floating shape inside a void
inside another shape.
MM
Michael Marx (spintel)
Thu, Jan 1, 2026 2:14 AM
Keep in mind that OpenSCAD is used to model things other than for 3D printing.
From: Jordan Brown via Discuss [mailto:discuss@lists.openscad.org]
Sent: Thursday, January 01, 2026 1:07 PM
To: OpenSCAD general discussion Mailing-list
Cc: Cory Cross; Jordan Brown
Subject: [OpenSCAD] Re: Separating objects.
On 12/31/2025 1:34 PM, Cory Cross via Discuss wrote:
Jordan's "geometry literals https://github.com/openscad/openscad/pull/4478 ," when complete, could allow iterating across distinct meshes.
No, the data that I "currently" (which is to say, a year or two ago) have access to is not broken up into distinct volumes. It is, in essence, the same as the arguments to a single polyhedron() call: a list of vertexes and a list of faces.
One could certainly post-process that to find sets of faces that were disjoint, but in the current state of #4478 it does not do that processing.
But note: disjoint sets of faces do not necessarily represent disjoint shapes, or at least not exactly: a shape with an interior void would have disjoint faces but would not normally be considered to be two disjoint shapes. I think that one could further post-process the data to determine that a particular set of faces represent a void inside a solid, rather than representing the outer boundary of a solid. Even then, if there was a second shape inside that void, it would be still a third disjoint set of faces. Whether you would want to separate that interior shape would depend entirely on the situation.
But still another note: I am not aware of any current 3D printing technology capable of creating a free-floating shape inside a void inside another shape.
Keep in mind that OpenSCAD is used to model things other than for 3D printing.
_____
From: Jordan Brown via Discuss [mailto:discuss@lists.openscad.org]
Sent: Thursday, January 01, 2026 1:07 PM
To: OpenSCAD general discussion Mailing-list
Cc: Cory Cross; Jordan Brown
Subject: [OpenSCAD] Re: Separating objects.
On 12/31/2025 1:34 PM, Cory Cross via Discuss wrote:
Jordan's "geometry literals <https://github.com/openscad/openscad/pull/4478> ," when complete, could allow iterating across distinct meshes.
No, the data that I "currently" (which is to say, a year or two ago) have access to is not broken up into distinct volumes. It is, in essence, the same as the arguments to a single polyhedron() call: a list of vertexes and a list of faces.
One could certainly post-process that to find sets of faces that were disjoint, but in the current state of #4478 it does not do that processing.
But note: disjoint sets of faces do not necessarily represent disjoint shapes, or at least not exactly: a shape with an interior void would have disjoint faces but would not normally be considered to be two disjoint shapes. I *think* that one could further post-process the data to determine that a particular set of faces represent a void inside a solid, rather than representing the outer boundary of a solid. Even then, if there was a second shape *inside* that void, it would be still a third disjoint set of faces. Whether you would want to separate that interior shape would depend entirely on the situation.
But still another note: I am not aware of any current 3D printing technology capable of creating a free-floating shape inside a void inside another shape.
JB
Jordan Brown
Thu, Jan 1, 2026 2:27 AM
On 12/31/2025 6:06 PM, Jordan Brown via Discuss wrote:
But note: disjoint sets of faces do not necessarily represent
disjoint shapes, or at least not exactly: a shape with an interior
void would have disjoint faces but would not normally be considered to
be two disjoint shapes. I think that one could further post-process
the data to determine that a particular set of faces represent a void
inside a solid, rather than representing the outer boundary of a solid.
I realized as I was writing a response to a GitHub comment on this topic
that this is incomplete.
Say you have a solid with faces ABCD and IJKL, and a void with faces EFGH.
I believe you could readily and relatively inexpensively determine that
ABCD and IJKL are solids, and that EFGH is a void - I believe that if
you calculated their volumes, ABCD and IJKL would have positive volumes
and EFGH would have a negative volume. (And I believe that calculation
is linear on the number of faces, or maybe on the number of vertexes.)
However, I don't believe that you could easily tell whether EFGH was
inside ABCD or inside IJKL. To do that would require, I think,
intersecting EFGH with the other two to determine which one it had a
non-empty overlap with.
I suspect that you would need to do something like N²/2 intersections
(where N is the number of distinct sets of faces) to be able to
topologically sort the various shapes into what contains what.
On 12/31/2025 6:06 PM, Jordan Brown via Discuss wrote:
> But note: disjoint sets of faces do not necessarily represent
> disjoint shapes, or at least not exactly: a shape with an interior
> void would have disjoint faces but would not normally be considered to
> be two disjoint shapes. I *think* that one could further post-process
> the data to determine that a particular set of faces represent a void
> inside a solid, rather than representing the outer boundary of a solid.
I realized as I was writing a response to a GitHub comment on this topic
that this is incomplete.
Say you have a solid with faces ABCD and IJKL, and a void with faces EFGH.
I believe you could readily and relatively inexpensively determine that
ABCD and IJKL are solids, and that EFGH is a void - I believe that if
you calculated their volumes, ABCD and IJKL would have positive volumes
and EFGH would have a negative volume. (And I believe that calculation
is linear on the number of faces, or maybe on the number of vertexes.)
However, I don't believe that you could easily tell whether EFGH was
inside ABCD or inside IJKL. To do that would require, I think,
intersecting EFGH with the other two to determine which one it had a
non-empty overlap with.
I suspect that you would need to do something like N²/2 intersections
(where N is the number of distinct sets of faces) to be able to
topologically sort the various shapes into what contains what.
JB
Jordan Brown
Thu, Jan 1, 2026 3:08 AM
On 12/31/2025 6:27 PM, Jordan Brown via Discuss wrote:
Say you have a solid with faces ABCD and IJKL, and a void with faces EFGH.
I believe you could readily and relatively inexpensively determine
that ABCD and IJKL are solids, and that EFGH is a void - I believe
that if you calculated their volumes, ABCD and IJKL would have
positive volumes and EFGH would have a negative volume. (And I
believe that calculation is linear on the number of faces, or maybe on
the number of vertexes.) However, I don't believe that you could
easily tell whether EFGH was inside ABCD or inside IJKL. To do that
would require, I think, intersecting EFGH with the other two to
determine which one it had a non-empty overlap with.
I suspect that you would need to do something like N²/2 intersections
(where N is the number of distinct sets of faces) to be able to
topologically sort the various shapes into what contains what.
And I realized as I was writing a subsequent GitHub comment that that
too is incomplete (or incorrect).
If your shapes are well-formed - no shapes crossing other shapes'
boundaries - then you don't have to do all of those intersections. You
need only test shape X against one vertex of shape Y; if the vertex is
inside shape X, then the entirely of Y is inside X.
I don't know how to do that enclosure test, but it is surely easier than
calculating an intersection.
On 12/31/2025 6:27 PM, Jordan Brown via Discuss wrote:
> Say you have a solid with faces ABCD and IJKL, and a void with faces EFGH.
>
> I believe you could readily and relatively inexpensively determine
> that ABCD and IJKL are solids, and that EFGH is a void - I believe
> that if you calculated their volumes, ABCD and IJKL would have
> positive volumes and EFGH would have a negative volume. (And I
> believe that calculation is linear on the number of faces, or maybe on
> the number of vertexes.) However, I don't believe that you could
> easily tell whether EFGH was inside ABCD or inside IJKL. To do that
> would require, I think, intersecting EFGH with the other two to
> determine which one it had a non-empty overlap with.
>
> I suspect that you would need to do something like N²/2 intersections
> (where N is the number of distinct sets of faces) to be able to
> topologically sort the various shapes into what contains what.
And I realized as I was writing a subsequent GitHub comment that that
too is incomplete (or incorrect).
If your shapes are well-formed - no shapes crossing other shapes'
boundaries - then you don't have to do all of those intersections. You
need only test shape X against one vertex of shape Y; if the vertex is
inside shape X, then the entirely of Y is inside X.
I don't know how to do that enclosure test, but it is surely easier than
calculating an intersection.
CC
Cory Cross
Thu, Jan 1, 2026 4:05 AM
On 12/31/2025 1:34 PM, Cory Cross via Discuss wrote:
No, the data that I "currently" (which is to say, a year or two ago)
have access to is not broken up into distinct volumes. It is, in
essence, the same as the arguments to a single polyhedron() call: a
list of vertexes and a list of faces.
All I meant was it was essentially a prerequisite to executing the code I shared, not that it could already do this. I apologize for not communicating clearly.
On December 31, 2025 6:06:43 PM PST, Jordan Brown via Discuss <discuss@lists.openscad.org> wrote:
>On 12/31/2025 1:34 PM, Cory Cross via Discuss wrote:
>> Jordan's "geometry literals
>> <https://github.com/openscad/openscad/pull/4478>," when complete,
>> could allow iterating across distinct meshes.
>
>No, the data that I "currently" (which is to say, a year or two ago)
>have access to is not broken up into distinct volumes. It is, in
>essence, the same as the arguments to a single polyhedron() call: a
>list of vertexes and a list of faces.
All I meant was it was essentially a prerequisite to executing the code I shared, not that it could already do this. I apologize for not communicating clearly.