Suppose you want to add a lamp holder to a panel. The holder has a positive
shape: the usual notion of a holder, but it also has a void shape: going
along with the lamp holder is the associated hole in the panel so the user
can see the light. Often, we apply a set of transforms to a part: scales,
translations, rotations. It is convenient so you can encapsulate those
transformations in the part's module. For convenience, we give that module
a parameter to select either the positive shape or the negative shape.
Then, when we want to use that as part of a larger assembly we can say:
difference(){
union(){
partA(positive=true);
partB(positive=true);
…
}
partA(positive=false);
partB(positive=false);
}
and all of the transforms that are built into partA will be reused for both
its positive component and its void component. (Including necessary
clearances.)
On Thu, Feb 3, 2022 at 11:17 AM Raymond West raywest@raywest.com wrote:
I'm not sure of what you are trying to explain. I see it as you have a
clip, which you want to place in a hole (which is a smaller diameter
than the OD of the clip by eps ). The hole is associated with the case,
and needs to be long enough to penetrate the case wall, but since you
have chosen a curved side for the hole, then it needs to be longer than
if it were a flat side. The hole is part of the case, not part of the
clip, at least that's how I see it. I use openscad to simulate what and
how I would build whatever in practice, so the case would have the hole.
There is no point in designing something that I can not build.
Best wishes,
Ray
On 03/02/2022 17:22, Torsten Paul wrote:
On 03.02.22 17:57, Carsten Fuchs wrote:
You don't believe it's feasible?
I'm not sure. It might be, maybe it needs some sort of
clear rules to work.
Example:
Have a 5mm LED clip thingy, e.g. a tube with outer
diameter of 10mm and inner diameter of about 5mm
and some clips to grip the LED.
Now I want to put that into the wall of a box.
$fa = 4; $fs = 0.4;
eps = 0.01;
module clip() {
rotate([0, -90, 0])
if ($positive) {
// some tube with outer dia of 10mm
linear_extrude(10, center = true)
difference() { circle(10); circle(5.2); }
} else {
// cut hole of slightly less than 10mm
// how to decide the value for h?
// if too small, it will not cut enough, if too
// big it might interfere with other geometry
// h = 12 -> too small
// h = 20 -> awesome!
// h = 200 -> oops
#cylinder(h = 200, r = 10 - eps, center = true);
}
}
module case() {
translate([-23, 0, 0])
linear_extrude(30, center = true, convexity = 3)
difference() { circle(30); circle(25); }
}
module design() {
difference() {
case();
clip($positive = false);
}
clip($positive = true);
}
design();
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
On 03/02/2022 19:17, Raymond West wrote:
I'm not sure of what you are trying to explain. I see it as you have a
clip, which you want to place in a hole (which is a smaller diameter
than the OD of the clip by eps ). The hole is associated with the
case, and needs to be long enough to penetrate the case wall, but
since you have chosen a curved side for the hole, then it needs to be
longer than if it were a flat side. The hole is part of the case, not
part of the clip, at least that's how I see it. I use openscad to
simulate what and how I would build whatever in practice, so the case
would have the hole. There is no point in designing something that I
can not build.
Best wishes,
Ray
/////like this
$fa = 4; $fs = 0.4;
eps = 0.01;
lc= 10; //clip length
module clip() {
rotate([0, -90, 0])
// some tube with outer dia of 10mm
linear_extrude(lc, center = true)
difference() { circle(10); circle(5.2); }
}
module case() {
translate([-23, 0, 0])
difference(){
linear_extrude(30, center = true, convexity = 3)
difference() {
circle(30);
circle(25);
}
translate([25,0,0]) //hole for clip
rotate([0, -90, 0])
#cylinder(h = lc, r = 10 - eps, center = true);
}
}
module design() {
case();
clip();
}
design();
On 03/02/2022 17:22, Torsten Paul wrote:
On 03.02.22 17:57, Carsten Fuchs wrote:
You don't believe it's feasible?
I'm not sure. It might be, maybe it needs some sort of
clear rules to work.Example:
Have a 5mm LED clip thingy, e.g. a tube with outer
diameter of 10mm and inner diameter of about 5mm
and some clips to grip the LED.Now I want to put that into the wall of a box.
$fa = 4; $fs = 0.4;
eps = 0.01;
module clip() {
rotate([0, -90, 0])
if ($positive) {
// some tube with outer dia of 10mm
linear_extrude(10, center = true)
difference() { circle(10); circle(5.2); }
} else {
// cut hole of slightly less than 10mm
// how to decide the value for h?
// if too small, it will not cut enough, if too
// big it might interfere with other geometry
// h = 12 -> too small
// h = 20 -> awesome!
// h = 200 -> oops
#cylinder(h = 200, r = 10 - eps, center = true);
}
}module case() {
translate([-23, 0, 0])
linear_extrude(30, center = true, convexity = 3)
difference() { circle(30); circle(25); }
}module design() {
difference() {
case();
clip($positive = false);
}
clip($positive = true);
}design();
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
On 03/02/2022 19:33, David Phillip Oster wrote:
Suppose you want to add a lamp holder to a panel. The holder has a
positive shape: the usual notion of a holder, but it also has a void
shape: going along with the lamp holder is the associated hole in the
panel so the user can see the light. Often, we apply a set of
transforms to a part: scales, translations, rotations. It is
convenient so you can encapsulate those transformations in the part's
module. For convenience, we give that module a parameter to select
either the positive shape or the negative shape. Then, when we want
to use that as part of a larger assembly we can say:
difference(){
union(){
partA(positive=true);
partB(positive=true);
…
}
partA(positive=false);
partB(positive=false);
}
and all of the transforms that are built into partA will be reused for
both its positive component and its void component. (Including
necessary clearances.)
I would treat it as separate 'parts' - copy and paste is fine. Never
have to think about if it is positive or negative that I want, whatever,
simply lamp holder and associated hole in panel in your example. I would
normally comment out the parts that I did not want. It may make for
lengthier code, but the editor can 'compress' the modules. But each to
his own, I guess, but so far I've managed to design things in a very
simple method, by replicating how it would be made in practice, which
may be a bit tedious in some instances, but generally the method rarely
fails.
Of course it depends on how you look at things, is there just one hole
associated with the lamp? There may be four fixing screws, so four
tapped fixing holes associated with the lamp, but I only fit two on the
panel, or i decide to drill bigger holes and use nuts and bolts. The
holes are associated with the lamp but they are part of the panel. It's
a bit like the English breakfast, the hen was involved in it, but the
pig was committed to it.
When it comes to clearances, that also depends on the materials being
used, and method of manufacture, as does tolerances. I understand what
you are saying, but for what i do, it is not my preferred approach.
Best wishes,
Ray
On Thu, Feb 3, 2022 at 11:17 AM Raymond West raywest@raywest.com wrote:
I'm not sure of what you are trying to explain. I see it as you
have a
clip, which you want to place in a hole (which is a smaller diameter
than the OD of the clip by eps ). The hole is associated with the
case,
and needs to be long enough to penetrate the case wall, but since you
have chosen a curved side for the hole, then it needs to be longer
than
if it were a flat side. The hole is part of the case, not part of the
clip, at least that's how I see it. I use openscad to simulate
what and
how I would build whatever in practice, so the case would have the
hole.
There is no point in designing something that I can not build.
Best wishes,
Ray
On 03/02/2022 17:22, Torsten Paul wrote:
On 03.02.22 17:57, Carsten Fuchs wrote:
You don't believe it's feasible?
I'm not sure. It might be, maybe it needs some sort of
clear rules to work.
Example:
Have a 5mm LED clip thingy, e.g. a tube with outer
diameter of 10mm and inner diameter of about 5mm
and some clips to grip the LED.
Now I want to put that into the wall of a box.
$fa = 4; $fs = 0.4;
eps = 0.01;
module clip() {
rotate([0, -90, 0])
if ($positive) {
// some tube with outer dia of 10mm
linear_extrude(10, center = true)
difference() { circle(10); circle(5.2); }
} else {
// cut hole of slightly less than 10mm
// how to decide the value for h?
// if too small, it will not cut enough, if too
// big it might interfere with other geometry
// h = 12 -> too small
// h = 20 -> awesome!
// h = 200 -> oops
#cylinder(h = 200, r = 10 - eps, center = true);
}
}
module case() {
translate([-23, 0, 0])
linear_extrude(30, center = true, convexity = 3)
difference() { circle(30); circle(25); }
}
module design() {
difference() {
case();
clip($positive = false);
}
clip($positive = true);
}
design();
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
_______________________________________________
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
OpenSCAD mailing list
To unsubscribe send an email todiscuss-leave@lists.openscad.org
Perhaps the following will show what I'm on about.
/ door
//dimensions in inches
// scale 7mm/foot = * 7/12
// 1 to 25.4 scale = no scale since in inches
door_height=77;
door_width= 30; // actual size of opening door, add frame to fit hole
door_panel_thick = 1.3;
door_drip =2.5;
door_panels =3; // number of panels 1,2,3,4 0 for no stiles - flush door
door_frame_width= 2;
door_frame_thick=4; //thickness of both sides and wall
stile_width =6;
stile_thick= 2.5;
frame_clear=0.2; // clearance between frame and door (before scaling)
inset=.7;// distance of face of door to face of frame
planked = true; // if planked door, then following
hinged_left =false; // sets struts, based on rear view
num_planks =6; // number of planks on door front
//----------------------------------------------------
module plank(w,h){
cube ([w,door_panel_thick0.6,h],true);
cube([w0.8,door_panel_thick,h],true);
}
module pan(){ // does main door panel
translate([0,0,door_height/2])
cube([door_width,door_panel_thick,door_height],true);
}
module strutt(l){
translate([0,door_panel_thick/2,door_width/(2*num_planks)])
# cube([l,door_panel_thick,door_width/num_planks],true);
}
module planked_pan(){
if (planked==true){
plank_width= door_width/num_planks;
translate ([ - (door_width/2)-plank_width/2,0,door_height/2])
for (j=[1:num_planks])
translate ([j*plank_width,0,0])
plank(plank_width,door_height);
//now do strutts
translate([0,0,door_height0.1])
strutt(door_width);
translate([0,0,door_height0.8])
strutt(door_width);
translate([0,0,door_height0.1+((door_height0.8)-
(door_height*0.1))/2])
strutt(door_width);
}
}
module frame(){ // does frame
// offset frame
dins = (door_panels==0)? door_panel_thick : stile_thick;
translate([0,(door_frame_thick-dins)/2-inset,0]){
inside_width= door_width+2frame_clear;
height=door_height+2frame_clear;
translate([0,0,door_height/2])
difference(){
cube([inside_width+2door_frame_width,door_frame_thick,height+2door_frame_width],true);
cube([inside_width,2door_frame_thick,height],true);
translate([0,0,-height/2-2door_frame_thick])
cube([inside_width2, 4door_frame_thick,4*door_frame_thick],true);
}
}
}
module stiles(){
translate([0,0,door_height/2]){
if (door_panels>=1){
translate([-(door_width-stile_width)/2,0,0])
cube([stile_width,stile_thick,door_height],true);
translate([(door_width-stile_width)/2,0,0])
cube([stile_width,stile_thick,door_height],true);
translate([0,0,(door_height-stile_width)/2])
cube([door_width,stile_thick,stile_width],true);
translate([0,0,-(door_height-stile_width)/2])
cube([door_width,stile_thick,stile_width],true);
}
if (door_panels>=2){
translate([0,0,+stile_width/2]) // off set for lock rail
cube([door_width,stile_thick,stile_width],true);
}
if (door_panels==3){
// translate([0,0,-door_height*.2])
translate([0,0,-((door_height+stile_width)/2)/2+stile_width/2])
cube([stile_width*.8,stile_thick,(door_height+stile_width)/2],true);
//mullion thinner than stiles
}
if (door_panels>=4){
cube([stile_width*.8,stile_thick,door_height],true); //mullion thinner
than stiles
}
}
}
module rain(){
translate([0,-stile_thick/2,door_drip/2])
difference(){
cube([door_width,door_drip,door_drip],true);
translate([0,-door_drip,door_drip])
rotate([45,0,0])
cube([door_width2,door_drip2.8,door_drip*2.8],true);
}
}
module get_strutts(bot_x,bot_z,ang,mid_z,strutt_len){
if (hinged_left ==true){
// now diagonals
translate([-bot_x,0,bot_z])
rotate([0,ang,0])
strutt(strutt_len);
translate([-bot_x,0,mid_z])
rotate([0,ang,0])
strutt(strutt_len);
}
if (hinged_left==false){
translate([bot_x,0,bot_z])
rotate([0,-ang,0])
strutt(strutt_len);
translate([bot_x,0,mid_z])
rotate([0,-ang,0])
strutt(strutt_len);
}
}
/*
// planked door
scale(7/12){
frame();
planked_pan();
// get_strutts (bot_x,bot_z,ang,mid_z,strutt_len)
get_strutts (2,22,45, 49,door_width*1.2); // needs fiddling for door
size if outside my designed range
rain();
}
*/
//panelled door
scale(7/12){
rain();
frame();
pan();
rain();
}
//// code ends
If I want a planked door, then I can comment out the panelled door lines
at the bottom. The two frame dimensions - door_height and door_width,
-are all that are needed for any wall that has a door., and of course
the type of wall determines if the rain drip is needed and possibly the
door_frame-thick value too. It is all straightforward, if I don't want
the the rain drip or other parts, I just just comment them out. I can
readily separate any part, and if printing an stl the door can be
hinged in the frame, (if frame_clear is larger) by stopping the print,
insert some tape and carry on. The parts were 'designed' in a similar
manner to which a door would be constructed, panels thinner than frames,
and for a planked door the horizontal struts first then diagonals
(although no need to mitre the corners 😉), but manually positioned.
Works for me, even if the code is not very pretty..
Best wishes,
Ray
On 03/02/2022 20:18, Raymond West wrote:
On 03/02/2022 19:33, David Phillip Oster wrote:
Suppose you want to add a lamp holder to a panel. The holder has a
positive shape: the usual notion of a holder, but it also has a void
shape: going along with the lamp holder is the associated hole in the
panel so the user can see the light. Often, we apply a set of
transforms to a part: scales, translations, rotations. It is
convenient so you can encapsulate those transformations in the part's
module. For convenience, we give that module a parameter to select
either the positive shape or the negative shape. Then, when we want
to use that as part of a larger assembly we can say:difference(){
union(){
partA(positive=true);
partB(positive=true);
…
}
partA(positive=false);
partB(positive=false);
}and all of the transforms that are built into partA will be reused
for both its positive component and its void component. (Including
necessary clearances.)
To unsubscribe send an email to discuss-leave@lists.openscad.org
It is a little bit unclear to me if your problems can be addressed
with the tagging mechanism in BOSL2, but you might want to take a
look. Maybe it's similar to what Craig West mentions, but in BOSL2
you can have a difference operation and you can tag children to be
subtracted and also you can tag children to be unioned back in. The
tags are inherited by children through the $tags variable. I
honestly have only scratched the surface of what you can do with this
feature, so I'm not really sure if it can help with your situation.
https://github.com/revarbat/BOSL2/wiki/Tutorial-Attachments#tagged-operations
On Thu, Feb 3, 2022 at 10:29 AM Carsten Fuchs carsten.fuchs@cafu.de wrote:
The example with the box was in fact only an example. I experience this problem frequently in more general and more complicated cases, both with self-made submodels or with the occassional library import.
After another iteration thinking about this, maybe it would be ideal if we had a union() variant that:
a) unioned all solids in all children,
b) unioned all subtracted objects in all children (and grandchildren)
c) computed a - b
Pre-cutting holes using a hull (with offsets as needed) and then inserting the actual submodule into the cleared space is (similar to) what I do now. It works, but if there was a boolean operator like the modified union() described above, things would be a lot simpler.
Thanks for your kind help!
Best regards,
Carsten
Am 03.02.22 um 10:18 schrieb nop head:
It would work if the submodule was written in the same style but not in the general case if it had holes in it that were not positioned with a module or function that it exposed.
Perhaps you can use a projection() to get the shape of the bottom of the box including its holes. Your baseplate could then have the hull of the projection offset inwards slightly subtracted from it and a linear extrusion of the projection added to it.
On Thu, 3 Feb 2022 at 09:09, Carsten Fuchs <carsten.fuchs@cafu.de mailto:carsten.fuchs@cafu.de> wrote:
Many thanks for your quick reply! I did indeed not think of modules that can have children. However, this only works if you are the maker of the submodule, does it? If I used something complicated from someone else, where I have not easy access to the subtracted parts, it doesn't work? An example would be an open, empty box, e.g. a housing for a circuit board, that is to be embedded into something else, e.g. a base plate that is not flush to the bottom of the box, but at the half height of it. A normal union would make the base plate visible inside the box and so we have to figure out something to remove it from there, which can be a very difficult problem. (With this thought, I'd modify my original question a bit: Is there a way to have a union() that unions its children but keeps (applies) all their nested subtractions?) Best regards, Carsten Am 03.02.22 um 09:44 schrieb nop head: > No, but you never need to repeat anything in OpenSCAD. You can make the complicated transformation into a module that has a child and use it multiple times. For example I have modules to translate a child to the screw positions of lots of my objects. That is used to make the screw hole in the object, the matching clearance hole in the panel it gets screwed to and also places the screws. > > On Thu, 3 Feb 2022 at 08:38, Carsten Fuchs <carsten.fuchs@cafu.de <mailto:carsten.fuchs@cafu.de> <mailto:carsten.fuchs@cafu.de <mailto:carsten.fuchs@cafu.de>>> wrote: > > Dear group, > > is there a way to mark solids for „absolute subtraction“, that is, for subtraction also from all parent nodes upwards in the hierarchy? > > I'm relatively frequently faced with the challenge of creating submodules that use difference() for clearing a part of the submodule. Sometimes such cleared space is supposed to kept clear even if the submodule is unioned with other modules, that is, it should be subtracted there as well. If however the submodule is transformed in a complicated way before it is combined with the parent nodes, it is necessary but very difficult to repeat the transform for subtracting a remake of the cutting solid from the parent directly. > > Best regards, > Carsten
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org
On 03.02.22 20:43, Raymond West wrote:
/////like this
The question was if there's some way to automate this positive/
negative module idea. And the example just something specific
to start with.
Yes, it can be done in a different way, but that's not the
point and totally off-topic for the question.
This +/- parts topic comes up now and then and it would be
useful to give it some sort of conclusion. I don't care much
either way. If we find out, it's not possible, then we can
point to this discussion later. If we find out there's a way
to generalize, that's the input for a good feature request.
ciao,
Torsten.
I think every once in a while about the "negative parts" model, and the
notion that union(A, -B) should be, like the relationship between
addition and subtraction, equivalent to difference(A, B).
The problem that I keep coming back to is that you don't really want to
have "negative parts" that survive all the way to the top of the model.
You want to be able to drill a hole for screws, sure. So far so good.
But now you want to put screws into the hole... and the hole, in its
infinite negative-ness, eats the screws.
You want the negative object to be negative up to a certain level, and
then above that (or in siblings) you want to be able to put stuff into
the hole.
But, hmm. I've been thinking about multi-material /multi-color support,
where
union() {
material(A) objA();
material(B) objB();
}
would internally turn into
material(A) difference() { objA(); objB(); }
material(B) objB();
and so on up the tree, so that the result of the union is that the parts
that are just objA are material A, and the rest (the common parts and
the objB parts) are material B. (This is based on the paint model,
where the last paint stroke wins.)
Such a scheme might adapt well to a "negative material" model, and
perhaps there would be another operator that would strip out any
negative material at a desired level.
Am 04.02.22 um 01:49 schrieb Torsten Paul:
On 03.02.22 20:43, Raymond West wrote:
/////like this
The question was if there's some way to automate this positive/
negative module idea. And the example just something specific
to start with.
Yes, it can be done in a different way, but that's not the
point and totally off-topic for the question.
Just for clarity, here is a simple example for the problem I'm facing:
module case() {
difference() {
cube(30);
// Make the box empty.
translate([2, 2, 4.1])
cube(26);
}
}
module panel() {
cube([100, 100, 2], center=true);
}
union() {
#panel();
// Module `case()` created an empty box, but when sunk into the panel
// the panel is also inside the box.
// Thus, desired is a method that subtracts the cutting `cube(26)` also
// in the scope of this union (but not necessarily further up!).
rotate([10, -12, 0])
translate([0, 0, -20])
case();
}
Am 03.02.22 um 22:53 schrieb Adrian Mariano:
Thanks for the link! It looks very interesting, but also complicated, and I'm not sure if it works with modules made outside of BOSL2, i.e. ones that don't come with attachments?
Best regards,
Carsten
Changed the code to work with BOSL2 and seems to work:
include <BOSL2/std.scad>;
module case() {
cuboid(30)
position(TOP)
up(0.01)
cuboid(26, $tags="hole", anchor=TOP);
}
module panel() {
cuboid([100, 100, 2]) {
children();
}
}
union() {
diff("hole")
panel()
attach(CENTER, BOTTOM)
// Module case() created an empty box, but when sunk into the panel
// the panel is also inside the box.
// Thus, desired is a method that subtracts the cutting cube(26) also
// in the scope of this union (but not necessarily further up!).
rotate([10, -12, 0])
translate([0, 0, -20])
case();
}
non-BOSL objects can be tagged with the tags() module:
https://github.com/revarbat/BOSL2/wiki/attachments.scad#module-tags.
Problem with the example above is that case doesn't look like it was
supposed to, you can apply the diff operation only once on a certain tag as
far as I can figure it out.
Victor Buciuc
On Fri, Feb 4, 2022 at 10:02 AM Carsten Fuchs carsten.fuchs@cafu.de wrote:
Am 03.02.22 um 22:53 schrieb Adrian Mariano:
https://github.com/revarbat/BOSL2/wiki/Tutorial-Attachments#tagged-operations
Thanks for the link! It looks very interesting, but also complicated, and
I'm not sure if it works with modules made outside of BOSL2, i.e. ones that
don't come with attachments?
Best regards,
Carsten
OpenSCAD mailing list
To unsubscribe send an email to discuss-leave@lists.openscad.org