Hi All,
I'm a very new OpenSCAD user. I'm having a practical (and apparently
a conceptual...) problem and hope all y'all can set me straight.
I'd like to build of a library of modules, like the doohickey below
that create things like tabs and clips and ....
Some of the features (like doohickey) carve bits out of one part of
space and add bits to another.
I'd like to "drop" them onto a board and have the feature from the
doohickey take precedence over the feature in the base object. If
something's carved out by the doohickey then it's carved out in the
result. If somethings added by the doohickey, then it's added in the
result. If there's nothing in the doohickey, then the base object
expresses itself.
I'd like the example below to do something like this:
+-----------+
| |
| +-+
| |
| +-+
| |
| +--+
| |
| |
| +--+
| |
| |
+-----------+
I haven't been able to figure out a way to composite them. union
doesn't work, it fills in the hole in the C. intersection doesn't
work, it drops off the dingus.
// A little C shaped thingy with a dingus hanging off the top.
module doohickey () {
/* the C shaped bit */
difference() {
translate([-4, -3, 0]) cube([4, 6, 1]);
translate([-3, -1, 0]) cube([3,2,1]);
}
/* the dingus */
translate([0,3,0]) cube([2,1,1]);
}
cube([10, 20, 1]);
translate([10,10,0]) doohickey();
What's the right OpenSCAD approach to this?
Thanks,
g.
If I understand what you want correctly, one way to do what you want is to
fill the 'free' area for each component instead of leaving it open. Then
when you intersect things you get the stuff you want.
Another possibility is to make a 'positive' by subtracting the base from
your component, and a 'negative' by subtracting the component from from the
base. Then you can modify the base by adding the positive and subtracting
the negative.
--
Sent from: http://forum.openscad.org/
NateTG writes:
If I understand what you want correctly, one way to do what you want is to
fill the 'free' area for each component instead of leaving it open. Then
when you intersect things you get the stuff you want.
I'm not quite sure that I get what you're suggesting here, but it
might be related to my "riff" below.
Another possibility is to make a 'positive' by subtracting the base from
your component, and a 'negative' by subtracting the component from from the
base. Then you can modify the base by adding the positive and subtracting
the negative.
After thinking about this a bit, I think that's it's basically what's
happening in the lasercut library.
Here's an example that pulls the def'n of clipTab (your "positive",
above) and clipInner (your "negative", above) and sticks them onto a
flat plate:
module clipTab(angle, x, y, thickness)
{
translate([x,y,0]) rotate([0,0,angle]) union()
{
// make off-center
translate([-thickness/2-1,0,0])
{
difference()
{
translate([0,thickness/2,thickness/2]) cube([thickness+1,thickness,thickness], center=true);
translate([(1+thickness)/2+1,-thickness*8,0]) linear_extrude(height = thickness*3, center = true) polygon(points=[[0,0],[0,9*thickness],[-(thickness-1), 9*thickness]]);
}
translate([-thickness,thickness,0]) linear_extrude(height = thickness) polygon(points=[[0,0],[thickness+1,0],[thickness,thickness-1],[1,thickness-1]]);
}
translate([0.5,0,0]) cube([thickness,thickness,thickness]);
* cube([thickness*2+1,thickness,thickness], center=true);
}
}
module clipInner(angle, x, y, thickness)
{
translate([x,y,0]) rotate([0,0,angle]) union()
{
translate([-thickness/2-1,0,0])
{
translate([-(1+thickness)/2,-thickness*10,-thickness]) cube([1, thickness*11, thickness*3]);
translate([(1+thickness)/2+1,-thickness*8,0]) linear_extrude(height = thickness*3, center = true) polygon(points=[[0,0],[0,9*thickness],[-(thickness-1), 9*thickness]]);
translate([(1+thickness)/2+1-thickness+1,thickness-1,-thickness]) cube([thickness/2, thickness, thickness*3]);
translate([-thickness*3/2,0,-thickness]) cube([thickness, thickness, thickness*3]);
}
}
}
difference () {
union() {
translate([-10, -40, 0]) cube([20, 40, 3]);
clipTab(0, 0, 0, 3);
}
clipInner(0, 0, 0, 3);
}
It doesn't seem like a very general approach.
As a riff on what I think you're suggesting, I guess that I could
write a pair of modules, one of which defines a bounding box for a
doohickey and one of which defines the doohickey itself. I could
delete the bounding box (basically making a "slot") and then add the
doohickey into the resulting emptiness.
I feel like this has to be well trod ground and would appreciate
points to how other libraries/designs have approached it.
THANKS!,
g.
--
Sent from: http://forum.openscad.org/
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Hi George, how about this solution?
// A little C shaped thingy with a dingus hanging off the top.
module doohickey () {
/* the C shaped bit */
if ($negative) {
translate([-4, -3, 0]) cube([4, 6, 1]);
translate([-3, -1, 0]) cube([3,2,1]);
} else {
/* the dingus */
translate([0,3,0]) cube([2,1,1]);
}
}
// applies positive and negative features to the first child from all
subsequent children
module apply_features() {
union() {
difference() {
children(0);
for (i = [1:$children-1]) let($negative = true) {
children(i);
}
}
for (i = [1:$children-1]) let($negative = false) {
children(i);
}
}
}
apply_features() {
cube([10, 20, 1]);
translate([10,10,0]) doohickey();
}
On Fri, Feb 2, 2018 at 7:07 PM, George Hartzell hartzell@alerce.com wrote:
NateTG writes:
If I understand what you want correctly, one way to do what you want is to
fill the 'free' area for each component instead of leaving it open. Then
when you intersect things you get the stuff you want.
I'm not quite sure that I get what you're suggesting here, but it
might be related to my "riff" below.
Another possibility is to make a 'positive' by subtracting the base from
your component, and a 'negative' by subtracting the component from from the
base. Then you can modify the base by adding the positive and subtracting
the negative.
After thinking about this a bit, I think that's it's basically what's
happening in the lasercut library.
Here's an example that pulls the def'n of clipTab (your "positive",
above) and clipInner (your "negative", above) and sticks them onto a
flat plate:
module clipTab(angle, x, y, thickness)
{
translate([x,y,0]) rotate([0,0,angle]) union()
{
// make off-center
translate([-thickness/2-1,0,0])
{
difference()
{
translate([0,thickness/2,thickness/2]) cube([thickness+1,thickness,thickness], center=true);
translate([(1+thickness)/2+1,-thickness*8,0]) linear_extrude(height = thickness*3, center = true) polygon(points=[[0,0],[0,9*thickness],[-(thickness-1), 9*thickness]]);
}
translate([-thickness,thickness,0]) linear_extrude(height = thickness) polygon(points=[[0,0],[thickness+1,0],[thickness,thickness-1],[1,thickness-1]]);
}
translate([0.5,0,0]) cube([thickness,thickness,thickness]);
* cube([thickness*2+1,thickness,thickness], center=true);
}
}
module clipInner(angle, x, y, thickness)
{
translate([x,y,0]) rotate([0,0,angle]) union()
{
translate([-thickness/2-1,0,0])
{
translate([-(1+thickness)/2,-thickness*10,-thickness]) cube([1, thickness*11, thickness*3]);
translate([(1+thickness)/2+1,-thickness*8,0]) linear_extrude(height = thickness*3, center = true) polygon(points=[[0,0],[0,9*thickness],[-(thickness-1), 9*thickness]]);
translate([(1+thickness)/2+1-thickness+1,thickness-1,-thickness]) cube([thickness/2, thickness, thickness*3]);
translate([-thickness*3/2,0,-thickness]) cube([thickness, thickness, thickness*3]);
}
}
}
difference () {
union() {
translate([-10, -40, 0]) cube([20, 40, 3]);
clipTab(0, 0, 0, 3);
}
clipInner(0, 0, 0, 3);
}
It doesn't seem like a very general approach.
As a riff on what I think you're suggesting, I guess that I could
write a pair of modules, one of which defines a bounding box for a
doohickey and one of which defines the doohickey itself. I could
delete the bounding box (basically making a "slot") and then add the
doohickey into the resulting emptiness.
I feel like this has to be well trod ground and would appreciate
points to how other libraries/designs have approached it.
THANKS!,
g.
--
Sent from: http://forum.openscad.org/
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Hans L writes:
Hi George, how about this solution?
[... elegant solution elided ...]
That's quite nice. I was just playing around with deleting a bounding
cube explicitly then merging and it works. This is a nice way to do
that programmatically. I like the use of let and the
apply_features method.
It's too bad that I have to calculate the bounding cube "by hand", but
I've read through a couple of threads that make it sounds as if it's
not reasonably do-able in OpenSCAD at the moment.
I have a vague memory about being careful about butting two objects up
against each other, that OpenSCAD might get confused about their
edges. I can't find it now that I'm looking at it. Is that a
concern?
THANKS!
g.
It is possible to generate a the bounding box of a geometry, but minkowski
stuff is typically slow.
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Tips_and_Tricks#Computing_a_bounding_box
--
Sent from: http://forum.openscad.org/
This bounding box computation is pretty fast because minkowsky is applied
to just three cubes.
2018-02-03 1:53 GMT-02:00 NateTG nate-openscadforum@pedantic.org:
It is possible to generate a the bounding box of a geometry, but minkowski
stuff is typically slow.
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Tips_and_
Tricks#Computing_a_bounding_box
--
Sent from: http://forum.openscad.org/
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Is this supposed to actually work in OpenSCAD? I get a compiler error
at $negative but I am not using the latest OpenSCAD.
On 2/2/2018 9:26 PM, Hans L wrote:
Hi George, how about this solution?
// A little C shaped thingy with a dingus hanging off the top.
module doohickey () {
/* the C shaped bit */
if ($negative) {
translate([-4, -3, 0]) cube([4, 6, 1]);
translate([-3, -1, 0]) cube([3,2,1]);
} else {
/* the dingus */
translate([0,3,0]) cube([2,1,1]);
}
}
// applies positive and negative features to the first child from all
subsequent children
module apply_features() {
union() {
difference() {
children(0);
for (i = [1:$children-1]) let($negative = true) {
children(i);
}
}
for (i = [1:$children-1]) let($negative = false) {
children(i);
}
}
}
apply_features() {
cube([10, 20, 1]);
translate([10,10,0]) doohickey();
}
It does not work in version version 2015.03-3, which is the stable
version installed via Homebrew Cask.
It does work in the dev release that I manually downloaded,
2017.12.23 (git 39823be1).
This usage seems to be a variant of the list comprehension form, it's
documented here without any caveats about what
release it will work in, although the top of that list comprehension
section states that it (list comprehensions in general?) requires
"2015.03".
There's a comment in this thread from 2016 that states
that let is only available in the dev releases. It also states that
"the wiki" has been fixed.
Is there a doc bug in the User Manual?
g.
Hans L writes:
Hi George, how about this solution?
// A little C shaped thingy with a dingus hanging off the top.
module doohickey () {
/* the C shaped bit */
if ($negative) {
translate([-4, -3, 0]) cube([4, 6, 1]);
translate([-3, -1, 0]) cube([3,2,1]);
} else {
/* the dingus */
translate([0,3,0]) cube([2,1,1]);
}
}
[...]
One other comment about this solution.
The doohickey that my original code draws in isolation looks something
like this:
+---+
| |
+------------+---+
| |
| +--------+
| |
| |
| |
| +--------+
| |
+------------+
My intent was that it would be glued into a bigger whole like so:
+--------------+
| |
| +---+
| |
| +---+
| |
| +--------+
| |
| |
| |
| +--------+
| |
| |
+--------------+
In Hans' solution:
$negative is true it carves out negative space for each of
$negative is false it draws all
I had originally thought of simplifying this so that the negative step
carved out a bounding cube in one simple step and the positive step
filled it as it deemed appropriate. The advantage of this is that
code for the negative case is simpler.
If I were to take this approach then I would need to modify my
original positive step to fill in the area above the "C" shape,
otherwise it would be open space in the result.
On the other hand, with that simplification there's no way to position
the top of the "C" along the top edge of a base feature and have the
little dingus hang off into space. Hans' solution allows this, at the
cost of a slightly more complicated "negative" step.
On the gripping hand, there's the approach from the lasercut
library, where each object has a method that adds it's
positive bits and another method that carves out its negative space
and it's up to the end user to call them appropriately.
Horses for courses, I suppose. I'll screw around with it and see if I
have a preference. My end goal is to be able to output a
drawing for a lasercut boxes, e.g. clip-box.
g.