workflow/approach request

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

workflow/approach request

OpenSCAD mailing list
I'm not a wizard at OpenSCAD, but enjoy using it for model creation. It
appeals to the logical side of my alleged mind. Unfortunately, the grey
matter is deteriorating too fast to encompass the massive power of coding
with OpenSCAD, so I'm asking for a bit of help.

I have been using  SolveSpace <http://solvespace.com/index.pl>   to create
quick-and-dirty drawings that also happen to have valuable parametric data.
As a result, my latest project allowed me to type out a list of 2D points on
a circle, ten in all, with semi-regular spacing. "Here's a hole, there's a
hole x mm away, then a hole y mm away, repeat five times."

I've attempted to understand the children() feature of OpenSCAD, with no
luck. Perhaps if children is/are the answer, I may understand it better in
the long run, but I'm not able to figure it out on my own.

If children isn't the best approach, what would be?

As it stands, the brute force method would be to create cylinders and
translate each one individually to the correct location. Is there a better
way?

19.5, 49.81
-19.5, 49.81

41.34, 33.94
-41.34, 33.94

53.4, -3.15
-53.4, -3.15

45.05, -28.83
-45.05, -28.83

13.5, -51.76
-13.5, -51.76

thanks
fred



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

nophead
Does this help?

image.png

points = [
    [19.5, 49.81],
    [-19.5, 49.81],

    [41.34, 33.94],
    [-41.34, 33.94],

    [53.4, -3.15],
    [-53.4, -3.15],

    [45.05, -28.83],
    [-45.05, -28.83],

    [13.5, -51.76],
    [-13.5, -51.76],
];

module translate_child_to_points(plist)
    for(p = plist)
        translate(p)
            children();

translate_child_to_points(points)
        sphere($fn = 32);
    

On Mon, 19 Aug 2019 at 18:40, fred_dot_u via Discuss <[hidden email]> wrote:
I'm not a wizard at OpenSCAD, but enjoy using it for model creation. It
appeals to the logical side of my alleged mind. Unfortunately, the grey
matter is deteriorating too fast to encompass the massive power of coding
with OpenSCAD, so I'm asking for a bit of help.

I have been using  SolveSpace <http://solvespace.com/index.pl>   to create
quick-and-dirty drawings that also happen to have valuable parametric data.
As a result, my latest project allowed me to type out a list of 2D points on
a circle, ten in all, with semi-regular spacing. "Here's a hole, there's a
hole x mm away, then a hole y mm away, repeat five times."

I've attempted to understand the children() feature of OpenSCAD, with no
luck. Perhaps if children is/are the answer, I may understand it better in
the long run, but I'm not able to figure it out on my own.

If children isn't the best approach, what would be?

As it stands, the brute force method would be to create cylinders and
translate each one individually to the correct location. Is there a better
way?

19.5, 49.81
-19.5, 49.81

41.34, 33.94
-41.34, 33.94

53.4, -3.15
-53.4, -3.15

45.05, -28.83
-45.05, -28.83

13.5, -51.76
-13.5, -51.76

thanks
fred



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

Mike Aubury
In reply to this post by OpenSCAD mailing list
for ?

points=10;
inc=360/points;

for (i=[0:inc:360]) {
    rotate([0,0,i]) translate([0,10,0]) sphere(r=1);
}

On Mon, 19 Aug 2019 at 18:42, fred_dot_u via Discuss <[hidden email]> wrote:
I'm not a wizard at OpenSCAD, but enjoy using it for model creation. It
appeals to the logical side of my alleged mind. Unfortunately, the grey
matter is deteriorating too fast to encompass the massive power of coding
with OpenSCAD, so I'm asking for a bit of help.

I have been using  SolveSpace <http://solvespace.com/index.pl>   to create
quick-and-dirty drawings that also happen to have valuable parametric data.
As a result, my latest project allowed me to type out a list of 2D points on
a circle, ten in all, with semi-regular spacing. "Here's a hole, there's a
hole x mm away, then a hole y mm away, repeat five times."

I've attempted to understand the children() feature of OpenSCAD, with no
luck. Perhaps if children is/are the answer, I may understand it better in
the long run, but I'm not able to figure it out on my own.

If children isn't the best approach, what would be?

As it stands, the brute force method would be to create cylinders and
translate each one individually to the correct location. Is there a better
way?

19.5, 49.81
-19.5, 49.81

41.34, 33.94
-41.34, 33.94

53.4, -3.15
-53.4, -3.15

45.05, -28.83
-45.05, -28.83

13.5, -51.76
-13.5, -51.76

thanks
fred



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

OpenSCAD mailing list
In reply to this post by nophead
That's exactly the layout/code I was hoping to find. I don't think I'd have
been able to generate it on my own. Other than cylinders at the points, it's
spot-on perfect for my requirements.

It does seem like cheating, since I can copy and paste your work into my
final code, rather than to type it in piecemeal.

thanks very much for the assist.



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

nophead
The children can be cylinders to drill holes and later fasteners to fill them, etc. This is how express nearly all of my positions. I.e. with a module that translates its children.

On Mon, 19 Aug 2019 at 20:53, fred_dot_u via Discuss <[hidden email]> wrote:
That's exactly the layout/code I was hoping to find. I don't think I'd have
been able to generate it on my own. Other than cylinders at the points, it's
spot-on perfect for my requirements.

It does seem like cheating, since I can copy and paste your work into my
final code, rather than to type it in piecemeal.

thanks very much for the assist.



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

Troberg
In reply to this post by OpenSCAD mailing list
I find it easiest to think of children() as a function pointer. Whenever it
is used, it calls everything you pass to your module.

So, if I have this (all very simplified, and not necessarily exactly how I'd
do it):

module screw(){
...
}

module nut(){
...
}

module washer(){
...
}

module screwassembly(){
    screw();
    washer();
    translate([0,0,-20])
    washer();
    nut();
}

module placesstuff(){
    for(some logic to get some coordinates){
        translate(coord)
        children();
    }
}

placestuff()
screwassembly();

In this case, each time children() is called, all the code in the other
modules will be run, creating a new screwassembly.



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

OpenSCAD mailing list
Unfortunately (or fortunately), I took nophead's code verbatim and changed
only sphere to cylinder. It may be due to my personal density of a neutron
star, but I am yet lacking a comfortable understanding of the use of
children().

The code you've provided escapes me as well. Even though that is the current
situation, my resulting program is going well and merely needs to be printed
and test fit to determine final adjustments.



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

cgriffith
This post was updated on .
@discuss

Maybe this would help you...

First, recognize that your openscad scripts, in order to draw something,
construct a tree of operations.

                                                                 rotate([90, 0, 0])
                                                                           |
                                                                           |
                                                                translate([20, 20, 0])
                                                                           |
                                                                           |
                                                                      union()
                                                                        /   \
                                                                       /     \
                                           cube(size = [5, 5, 5])    cube(size = [10, 3, 5], center = false)

Next recognize in Openscad there are two types of operations; modules and
functions.

Functions only return values.  These can be used to calculate some value,
iterate over a list of values and do something with them, or whatever else
you can dream up so long as the result is one or more values.  The return
values are expressed as either a number, a list of numbers, or a matrix of
numbers.

Modules on the other hand do not return anything, but rather either act on,
or draw shapes.  The "cube" operation obviously draws a shape.  The "union",
"translate", and "rotate" operations act on a shape.  Which shape?  Their
children in the operation tree.  So these modules are coded to do stuff to
"children()".

The next time you go to craft a module, ask yourself is the module going to
draw something, or manipulate something that is already drawn.  If the
latter, you'll need to use "children()".



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

OpenSCAD mailing list
cgriffith, your information may indeed be helpful. When I write to build a
model, I attempt to create modules for construction of components, as your
note references. I've yet to write a function.

I'm not sure if I've used a module to perform manipulation on a construction
module as yet, other than the code provided by nophead. That bit confused me
slightly as well, as there were no curly braces after the module call, but
copy/paste worked anyway.

With your information in mind, I've opened a few reference web pages to
study when I return from my errands, in hopes that I'll understand more with
the new viewpoint.



--
Sent from: http://forum.openscad.org/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

Ronaldo
Em qua, 21 de ago de 2019 às 13:35, fred_dot_u via Discuss <[hidden email]> escreveu:
That bit confused me
slightly as well, as there were no curly braces after the module call, but
copy/paste worked anyway.

You don't need curly braces to translate a single object:

translate([10,0,0]) sphere(10);

The same happens with modules and it children(). 

Note that translate() is itself an operator module that could be pseudocoded by:

module translate(v=[0,0,0]) 
  rebuild children() adding v to each of its vertices;

I interpret children as the argument name of a module that operates on an object. OpenSCAD language does not allow that objects (models) be passed as parameter to functions and modules. So, children replaces the role a parameter for modules that operates on objects. So, instead of :

module rotranlate(ang, vec, object) {
   rotate(ang)
      translate(vec)
        object;
}

rotranslate( 30, [10,0,0], cube(10) );

which is forbidden, we may write:

module rotranslate(ang, vec) {
  rotate(ang)
    translate(vec)
      children();
}

rotranslate( 30, [10,0,0] ) cube(10);

or, equivalently:

rotranslate( 30, [10,0,0] ) { cube(10); }

When your operator needs more than one object to operate, you need to index children to identify each object:
module hullDifference() {
  difference() {
    hull() children(0);
    hull() children(1);
  }
}

hullDifference()  { translate([10,0,0]) cylinder(h=20,r=10);
  rotate(30) translate([0,0,-0.5]) cube(21);
}

Note that here the curly braces are necessary to embrace the two children in the hullDifference() call. Try to eliminate the braces and see what happens.




_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: workflow/approach request

JordanBrown
In reply to this post by OpenSCAD mailing list
[ Sorry, sent the first copy from the wrong e-mail address. ]

On 8/21/2019 5:38 AM, fred_dot_u via Discuss wrote:
That bit confused me slightly as well, as there were no curly braces after the module call, [...]

Like most languages with sort-of-C-derived structure, you only need braces if you want to enclose more than one statement.  Also, line breaks are not important.

Thus these are equivalent:
translate(...) rotate(...) scale(...) cube(...);
translate(...)
    rotate(...)
        scale(...)
            cube(...);
translate(...) {
    rotate(...) {
        scale(...) {
            cube(...);
        }
    }
}

As for children( ), the way that I think of it is that modules can have arguments that are values - the ones in the parentheses, like the 10 in sphere(10) - and they can have arguments that are objects.  When you say "rotate(...) cube(...);" the cube is an argument to the rotate.

children( ) is how the module accesses those object-arguments.

For instance, here's a really simple module that replicates an object:
module twin(dist)
{
    children();            // First copy of the object

    translate([dist,0,0])
        children();        // Second copy of the object
}

Thus you could say

twin(10) cube(5);
Or, equivalently
twin(10) {
	cube(5);
}

Here's a more elaborate example.  Suppose I want to design a door, in a generic way, and I want to be able to put any number of different doorknobs on it.

I'm going to invoke it like this:
door(30) round_knob();	// make a 30" door with a round knob
door(36) handle();	// make a 36" door with a handle
The door module knows how to make a door.  In particular, it knows where the doorknob gets attached.
// Make a door of the specified width, with a knob supplied
// by the caller.
//
// Rules for the knob:
// * Its [0,0,0] is at the center of the mounting hole,
//   on the face of the door.
// * -X is towards the hinges; +X is towards the latch.
// * -Y is out of the door toward the user.
module door(width)
{
    // dimensions in inches
    height = 80;
    thick = 1.5;
    knob_inset = 2.5;
    knob_height = 36;
    
    cube([width, thick, height]);
    translate([width - knob_inset, 0, knob_height])
        children();
}

Now, here's a round doorknob:
module round_knob() {
    translate([0,-2,0])
        sphere(d=2);
    rotate([90,0,0])
        cylinder(d=1, h=2);
}
and here's a handle:
module handle() {
    rotate([90,0,0])
        cylinder(d=1, h=2);
    translate([0,-2,0]) {
        rotate([0,-90,0])
            cylinder(d=1, h=4);
        sphere(d=1);
    }
}
Note that, just like in the physical world, the door and the knob are separately designed.  You can put any knob onto any door, as long as they both follow the rules.

But wait.  That door only has a knob on one side.
// Make a door of the specified width, with a knob supplied
// by the caller on each side.
//
// Rules for the knob:
// * Its [0,0,0] is at the center of the mounting hole,
//   on the face of the door.
// * -X is towards the hinges; +X is towards the latch.
// * -Y is out of the door toward the user.
module door(width)
{
    // dimensions in inches
    height = 80;
    thick = 1.5;
    knob_inset = 2.5;
    knob_height = 36;
    
    cube([width, thick, height]);
    translate([width - knob_inset, 0, knob_height])
        children();
    translate([width - knob_inset, thick, knob_height])
        mirror([0,1,0]) children();
}

Now it has a knob on each side.  (Technical nit:  mirroring might not really be the right technique, but it works for the example.)  Note that the knob knows only its "local" coordinate system; it doesn't know nor care that it gets mirrored and translated to get put onto the back of the door.

But but... what if you sometimes have a round knob on one side and a handle on the other side?

// Make a door of the specified width, with a knob supplied
// by the caller on each side.
//
// Rules for the knob:
// * Its [0,0,0] is at the center of the mounting hole,
//   on the face of the door.
// * -X is towards the hinges; +X is towards the latch.
// * -Y is out of the door toward the user.
//
// With one child, put it on both sides.
// With two children, put the first child on the front
// and the second child on the back.
module door(width)
{
    // dimensions in inches
    height = 80;
    thick = 1.5;
    knob_inset = 2.5;
    knob_height = 36;
    
    cube([width, thick, height]);
    translate([width - knob_inset, 0, knob_height])
        children(0);
    translate([width - knob_inset, thick, knob_height])
        mirror([0,1,0]) children($children > 1 ? 1 : 0);
}
and you can invoke it as
door(30) {
    handle();
    round_knob();
}

With$fs=0.2 to make nicer curves, here's what we get:


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org