Script to replicate hull and minkoswki for CSG export/import into FreeCAD

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

Script to replicate hull and minkoswki for CSG export/import into FreeCAD

droftarts
Hi, long time OpenSCAD user, first time poster.

I want to export a model I've designed in OpenSCAD in a form that I can import into a more 'feature rich' CAD package, so I can do some nice renders of it. I've looked at Blender OpenSCAD import scripts, but these seem to be rather limited, and the only other apparent way to export the model, and retain geometry (rather than export as STL), seems to be to export as CSG, and import into FreeCAD - the only tool I've found that can cope with OpenSCAD CSG files.

FreeCAD's CSG import doesn't support OpenSCAD functions such as 'hull' and 'minkowski', which I've used to give my design nice rounded edges. Fortunately, most of my parts are 2D extrusions, as I plan to lasercut most of it, and it's relatively easy to reduce minkowski and hull functions to squares, circles and polygons.

However, FreeCAD (on Mac OS X at least) doesn't seem to like unions of lots of circles, squares and polygons, and drops geometry, creating holes from overlapping parts when I import them. Also, some shapes are difficult to translate into circles and squares alone. So I've come up a script that, to some extent, replicates 2D hull and minkowski with just circles and a polygon. With an input of the points of the shape, it draws a circle of a given radius at each point, then calculates the tangents that connect all the circles, and creates a polygon. With a linear extrusion, FreeCAD seems happy with this. Here's my code so far:

radius = 5;
shape = [ 10,10 , 0,40 , 40,80 , 100,80 , 50,0];

x1 = shape[0];
y1 = shape[1];
x2 = shape[2];
y2 = shape[3];
x3 = shape[4];
y3 = shape[5];
x4 = shape[6];
y4 = shape[7];
x5 = shape[8];
y5 = shape[9];

linear_extrude (height=5)
 
 union () {
    translate ([x1,y1]) circle (r=radius);
    translate ([x2,y2]) circle (r=radius);
    translate ([x3,y3]) circle (r=radius);
    translate ([x4,y4]) circle (r=radius);
    translate ([x5,y5]) circle (r=radius);

    polygon ([
        tangent_1 (x1,y1,x2,y2,radius),
        tangent_2 (x1,y1,x2,y2,radius),
        tangent_1 (x2,y2,x3,y3,radius),
        tangent_2 (x2,y2,x3,y3,radius),
        tangent_1 (x3,y3,x4,y4,radius),
        tangent_2 (x3,y3,x4,y4,radius),
        tangent_1 (x4,y4,x5,y5,radius),
        tangent_2 (x4,y4,x5,y5,radius),
        tangent_1 (x5,y5,x1,y1,radius),
        tangent_2 (x5,y5,x1,y1,radius),
        ]);
 }

function tangent_1 (x_1, y_1, x_2, y_2, rad) =
    let (
    x_delta = x_2-x_1,
    y_delta = y_2-y_1,
    theta = atan2(y_delta,x_delta)+360,
    xa = x_1+(cos(90+theta)*rad),
    ya = y_1+(sin(90+theta)*rad),
    xb = xa+x_delta,
    yb = ya+y_delta
    )

    [xa,ya];
   
function tangent_2 (x_1,y_1,x_2,y_2,rad) =
    let (
    x_delta = x_2-x_1,
    y_delta = y_2-y_1,
    theta = atan2(y_delta,x_delta),
    xa = x_1+(cos(90+theta)*rad),
    ya = y_1+(sin(90+theta)*rad),
    xb = xa+x_delta,
    yb = ya+y_delta
    )

    [xb,yb];

This seems to produce a valid CSG shape, that I can import into FreeCAD, displays correctly, and can be exported as a STEP file to bring into other CAD programs with better rendering engines (Blender/Fusion360 are the ones I've briefly tested).
   
I'm nearly at my limit of maths/programming, so I'm having difficulty with a few things:
1. I'd really like to be able to put as few (minimum 3) or as many points in for the shape (currently 5), but I can't work out the way of iterating the function through all the points, and then back to the first again.
2. Having a different radius for each point would be nice too (eg shape = [ [x1,y1,r1] , [x2,y2r2], ... ] ), but I think that needs some extra trig to calculate the tangents.
3. Finally, it's not a million miles away from another 'hull' requested feature (I've seen it asked about on the forum before); that of have a point outside the hull, to create an indent into the shape. If you change the shape to:

shape = [ 50,50 , 0,40 , 40,80 , 100,80 , 50,0];

You can see it attempts to draw the indentation, but it gets the tangent wrong, because it needs to use inner tangent lines, rather than outer tangent lines. I think it would be possible to create a script that deals with these (the maths is here: http://www.ambrsoft.com/TrigoCalc/Circles2/Circles2Tangent_.htm ), and points outside the hull could be identified by using '-r', perhaps, then the '-r' circles differenced from the polygon shape, rather than unioned.  I could probably use conditional operators ( https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#Conditional_Operator ) or some kind of recursive function ( https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#Recursive_functions ). But then I'm really at the limits of my maths/programming!

Unless you know of any other way of getting a model out of OpenSCAD, while maintaining the geometry, any pointers/help with this script would be greatly appreciated!

Ian S.
Reply | Threaded
Open this post in threaded view
|

Re: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

alexgibson
Nice job so far Ian.  I am hoping to do similar for my printer parts, will read with interest...  

Tapped on my mobile phone.

> On 18 Mar 2016, at 10:13, droftarts <[hidden email]> wrote:
>
> Hi, long time OpenSCAD user, first time poster.
>
> I want to export a model I've designed in OpenSCAD in a form that I can
> import into a more 'feature rich' CAD package, so I can do some nice renders
> of it. I've looked at Blender OpenSCAD import scripts, but these seem to be
> rather limited, and the only other apparent way to export the model, and
> retain geometry (rather than export as STL), seems to be to export as CSG,
> and import into FreeCAD - the only tool I've found that can cope with
> OpenSCAD CSG files.
>
> FreeCAD's CSG import doesn't support OpenSCAD functions such as 'hull' and
> 'minkowski', which I've used to give my design nice rounded edges.
> Fortunately, most of my parts are 2D extrusions, as I plan to lasercut most
> of it, and it's relatively easy to reduce minkowski and hull functions to
> squares, circles and polygons.
>
> However, FreeCAD (on Mac OS X at least) doesn't seem to like unions of lots
> of circles, squares and polygons, and drops geometry, creating holes from
> overlapping parts when I import them. Also, some shapes are difficult to
> translate into circles and squares alone. So I've come up a script that, to
> some extent, replicates 2D hull and minkowski with just circles and a
> polygon. With an input of the points of the shape, it draws a circle of a
> given radius at each point, then calculates the tangents that connect all
> the circles, and creates a polygon. With a linear extrusion, FreeCAD seems
> happy with this. Here's my code so far:
>
> radius = 5;
> shape = [ 10,10 , 0,40 , 40,80 , 100,80 , 50,0];
>
> x1 = shape[0];
> y1 = shape[1];
> x2 = shape[2];
> y2 = shape[3];
> x3 = shape[4];
> y3 = shape[5];
> x4 = shape[6];
> y4 = shape[7];
> x5 = shape[8];
> y5 = shape[9];
>
> linear_extrude (height=5)
>
> union () {
>    translate ([x1,y1]) circle (r=radius);
>    translate ([x2,y2]) circle (r=radius);
>    translate ([x3,y3]) circle (r=radius);
>    translate ([x4,y4]) circle (r=radius);
>    translate ([x5,y5]) circle (r=radius);
>
>    polygon ([
>        tangent_1 (x1,y1,x2,y2,radius),
>        tangent_2 (x1,y1,x2,y2,radius),
>        tangent_1 (x2,y2,x3,y3,radius),
>        tangent_2 (x2,y2,x3,y3,radius),
>        tangent_1 (x3,y3,x4,y4,radius),
>        tangent_2 (x3,y3,x4,y4,radius),
>        tangent_1 (x4,y4,x5,y5,radius),
>        tangent_2 (x4,y4,x5,y5,radius),
>        tangent_1 (x5,y5,x1,y1,radius),
>        tangent_2 (x5,y5,x1,y1,radius),
>        ]);
> }
>
> function tangent_1 (x_1, y_1, x_2, y_2, rad) =
>    let (
>    x_delta = x_2-x_1,
>    y_delta = y_2-y_1,
>    theta = atan2(y_delta,x_delta)+360,
>    xa = x_1+(cos(90+theta)*rad),
>    ya = y_1+(sin(90+theta)*rad),
>    xb = xa+x_delta,
>    yb = ya+y_delta
>    )
>
>    [xa,ya];
>
> function tangent_2 (x_1,y_1,x_2,y_2,rad) =
>    let (
>    x_delta = x_2-x_1,
>    y_delta = y_2-y_1,
>    theta = atan2(y_delta,x_delta),
>    xa = x_1+(cos(90+theta)*rad),
>    ya = y_1+(sin(90+theta)*rad),
>    xb = xa+x_delta,
>    yb = ya+y_delta
>    )
>
>    [xb,yb];
>
> This seems to produce a valid CSG shape, that I can import into FreeCAD,
> displays correctly, and can be exported as a STEP file to bring into other
> CAD programs with better rendering engines (Blender/Fusion360 are the ones
> I've briefly tested).
>
> I'm nearly at my limit of maths/programming, so I'm having difficulty with a
> few things:
> 1. I'd really like to be able to put as few (minimum 3) or as many points in
> for the shape (currently 5), but I can't work out the way of iterating the
> function through all the points, and then back to the first again.
> 2. Having a different radius for each point would be nice too (eg shape = [
> [x1,y1,r1] , [x2,y2r2], ... ] ), but I think that needs some extra trig to
> calculate the tangents.
> 3. Finally, it's not a million miles away from another 'hull' requested
> feature (I've seen it asked about on the forum before); that of have a point
> outside the hull, to create an indent into the shape. If you change the
> shape to:
>
> shape = [ 50,50 , 0,40 , 40,80 , 100,80 , 50,0];
>
> You can see it attempts to draw the indentation, but it gets the tangent
> wrong, because it needs to use inner tangent lines, rather than outer
> tangent lines. I think it would be possible to create a script that deals
> with these (the maths is here:
> http://www.ambrsoft.com/TrigoCalc/Circles2/Circles2Tangent_.htm ), and
> points outside the hull could be identified by using '-r', perhaps, then the
> '-r' circles differenced from the polygon shape, rather than unioned.  I
> could probably use conditional operators (
> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#Conditional_Operator
> ) or some kind of recursive function (
> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#Recursive_functions
> ). But then I'm really at the limits of my maths/programming!
>
> Unless you know of any other way of getting a model out of OpenSCAD, while
> maintaining the geometry, any pointers/help with this script would be
> greatly appreciated!
>
> Ian S.
>
>
>
> --
> View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537.html
> Sent from the OpenSCAD mailing list archive at Nabble.com.
>
> _______________________________________________
> 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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

shadowwynd
In reply to this post by droftarts
Just a quick side note - especially for 2D extrusions, the double
offset() command can do an awesome job of rounding corners.

example:   offset (r=+5) offset (r=-5) square(20);

of course, offset isn't supported in FreeCAD either.


On 3/18/2016 6:13 AM, droftarts wrote:

> Hi, long time OpenSCAD user, first time poster.
>
> I want to export a model I've designed in OpenSCAD in a form that I can
> import into a more 'feature rich' CAD package, so I can do some nice renders
> of it. I've looked at Blender OpenSCAD import scripts, but these seem to be
> rather limited, and the only other apparent way to export the model, and
> retain geometry (rather than export as STL), seems to be to export as CSG,
> and import into FreeCAD - the only tool I've found that can cope with
> OpenSCAD CSG files.
>
> FreeCAD's CSG import doesn't support OpenSCAD functions such as 'hull' and
> 'minkowski', which I've used to give my design nice rounded edges.
> Fortunately, most of my parts are 2D extrusions, as I plan to lasercut most
> of it, and it's relatively easy to reduce minkowski and hull functions to
> squares, circles and polygons.
>
> However, FreeCAD (on Mac OS X at least) doesn't seem to like unions of lots
> of circles, squares and polygons, and drops geometry, creating holes from
> overlapping parts when I import them. Also, some shapes are difficult to
> translate into circles and squares alone. So I've come up a script that, to
> some extent, replicates 2D hull and minkowski with just circles and a
> polygon. With an input of the points of the shape, it draws a circle of a
> given radius at each point, then calculates the tangents that connect all
> the circles, and creates a polygon. With a linear extrusion, FreeCAD seems
> happy with this. Here's my code so far:
>
> radius = 5;
> shape = [ 10,10 , 0,40 , 40,80 , 100,80 , 50,0];
>
> x1 = shape[0];
> y1 = shape[1];
> x2 = shape[2];
> y2 = shape[3];
> x3 = shape[4];
> y3 = shape[5];
> x4 = shape[6];
> y4 = shape[7];
> x5 = shape[8];
> y5 = shape[9];
>
> linear_extrude (height=5)
>
>   union () {
>      translate ([x1,y1]) circle (r=radius);
>      translate ([x2,y2]) circle (r=radius);
>      translate ([x3,y3]) circle (r=radius);
>      translate ([x4,y4]) circle (r=radius);
>      translate ([x5,y5]) circle (r=radius);
>
>      polygon ([
>          tangent_1 (x1,y1,x2,y2,radius),
>          tangent_2 (x1,y1,x2,y2,radius),
>          tangent_1 (x2,y2,x3,y3,radius),
>          tangent_2 (x2,y2,x3,y3,radius),
>          tangent_1 (x3,y3,x4,y4,radius),
>          tangent_2 (x3,y3,x4,y4,radius),
>          tangent_1 (x4,y4,x5,y5,radius),
>          tangent_2 (x4,y4,x5,y5,radius),
>          tangent_1 (x5,y5,x1,y1,radius),
>          tangent_2 (x5,y5,x1,y1,radius),
>          ]);
>   }
>
> function tangent_1 (x_1, y_1, x_2, y_2, rad) =
>      let (
>      x_delta = x_2-x_1,
>      y_delta = y_2-y_1,
>      theta = atan2(y_delta,x_delta)+360,
>      xa = x_1+(cos(90+theta)*rad),
>      ya = y_1+(sin(90+theta)*rad),
>      xb = xa+x_delta,
>      yb = ya+y_delta
>      )
>
>      [xa,ya];
>
> function tangent_2 (x_1,y_1,x_2,y_2,rad) =
>      let (
>      x_delta = x_2-x_1,
>      y_delta = y_2-y_1,
>      theta = atan2(y_delta,x_delta),
>      xa = x_1+(cos(90+theta)*rad),
>      ya = y_1+(sin(90+theta)*rad),
>      xb = xa+x_delta,
>      yb = ya+y_delta
>      )
>
>      [xb,yb];
>
> This seems to produce a valid CSG shape, that I can import into FreeCAD,
> displays correctly, and can be exported as a STEP file to bring into other
> CAD programs with better rendering engines (Blender/Fusion360 are the ones
> I've briefly tested).
>
> I'm nearly at my limit of maths/programming, so I'm having difficulty with a
> few things:
> 1. I'd really like to be able to put as few (minimum 3) or as many points in
> for the shape (currently 5), but I can't work out the way of iterating the
> function through all the points, and then back to the first again.
> 2. Having a different radius for each point would be nice too (eg shape = [
> [x1,y1,r1] , [x2,y2r2], ... ] ), but I think that needs some extra trig to
> calculate the tangents.
> 3. Finally, it's not a million miles away from another 'hull' requested
> feature (I've seen it asked about on the forum before); that of have a point
> outside the hull, to create an indent into the shape. If you change the
> shape to:
>
> shape = [ 50,50 , 0,40 , 40,80 , 100,80 , 50,0];
>
> You can see it attempts to draw the indentation, but it gets the tangent
> wrong, because it needs to use inner tangent lines, rather than outer
> tangent lines. I think it would be possible to create a script that deals
> with these (the maths is here:
> http://www.ambrsoft.com/TrigoCalc/Circles2/Circles2Tangent_.htm ), and
> points outside the hull could be identified by using '-r', perhaps, then the
> '-r' circles differenced from the polygon shape, rather than unioned.  I
> could probably use conditional operators (
> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#Conditional_Operator
> ) or some kind of recursive function (
> https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#Recursive_functions
> ). But then I'm really at the limits of my maths/programming!
>
> Unless you know of any other way of getting a model out of OpenSCAD, while
> maintaining the geometry, any pointers/help with this script would be
> greatly appreciated!
>
> Ian S.
>
>
>
> --
> View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537.html
> Sent from the OpenSCAD mailing list archive at Nabble.com.
>
> _______________________________________________
> 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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

droftarts
In reply to this post by alexgibson
Thanks, Alex!

A note about the current script:
- The points need to be in a clockwise direction, or it draws the polygon on the wrong side of the circles, as it only calculates the tangent on one side of the circle (out of a possible four tangents)

I did try another approach, which was to draw a polygon from each point, draw a circle on each point, then draw a square of width r*2 between each point, but this caused problems in FreeCAD. As each element (polygon, circles, squares) is stored in the CSG, there were multiple overlapping elements, and FreeCAD seemed to randomly put holes in. A 2D (ie no linear_extrude) output of the above script still doesn't show correctly in FreeCAD (there are some parts that are not coloured in), but the 3D version does show correctly.

Ian
Reply | Threaded
Open this post in threaded view
|

Re: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

droftarts
In reply to this post by shadowwynd
Thanks shadowwynd, and I agree, offest is very useful. I'd tried that approach for this problem, too, before finding it didn't import into FreeCAD either!

Ian S
Reply | Threaded
Open this post in threaded view
|

Re: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
Hi Stuart,
  Here is a general version that takes a list of points and makes a rounded polygon.

radius = 5;
shape = [ [10,10] , [0,40] , [40,80] , [100,80] , [50,0] ];
linear_extrude (height=5) rounded_polygon(shape, radius);

function next(i) = (i + 1) % len(shape);

function tangents(i) = [tangent(shape[i], shape[next(i)],radius, 0),
                        tangent(shape[i], shape[next(i)],radius, 1)];

function flatten(list) = [for(p = list) for(x = p) x];

module rounded_polygon(points, radius)
    union () {
        for(point = shape)
            translate(point)
                circle (r = radius);

        polygon(flatten([for(i  = [0 : len(shape) - 1]) tangents(i)]));
    }


function tangent(p1, p2, rad, side) =
    let (
    x_delta = p2.x - p1.x,
    y_delta = p2.y - p1.y,
    theta = atan2(y_delta, x_delta),
    xa = p1.x +(cos(90 + theta) * rad),
    ya = p1.y +(sin(90 + theta) * rad),
    xb = xa + x_delta,
    yb = ya + y_delta
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 10:51, droftarts <[hidden email]> wrote:
Thanks shadowwynd, and I agree, offest is very useful. I'd tried that
approach for this problem, too, before finding it didn't import into FreeCAD
either!

Ian S



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16542.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
Here's a simpler one:

radius = 5;
shape = [ [10,10] , [0,40] , [40,80] , [100,80] , [50,0] ];
linear_extrude (height=5) rounded_polygon(shape, radius);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)],radius, side);

module rounded_polygon(points, radius)
    union () {
        for(point = shape)
            translate(point)
                circle (r = radius);

        polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
    }

function tangent(p1, p2, rad, side) =
    let (
    x_delta = p2.x - p1.x,
    y_delta = p2.y - p1.y,
    theta = atan2(y_delta, x_delta),
    xa = p1.x +(cos(90 + theta) * rad),
    ya = p1.y +(sin(90 + theta) * rad),
    xb = xa + x_delta,
    yb = ya + y_delta
    )

    side ? [xb, yb] : [xa, ya];


On 18 March 2016 at 11:29, nop head <[hidden email]> wrote:
Hi Stuart,
  Here is a general version that takes a list of points and makes a rounded polygon.

radius = 5;
shape = [ [10,10] , [0,40] , [40,80] , [100,80] , [50,0] ];
linear_extrude (height=5) rounded_polygon(shape, radius);

function next(i) = (i + 1) % len(shape);

function tangents(i) = [tangent(shape[i], shape[next(i)],radius, 0),
                        tangent(shape[i], shape[next(i)],radius, 1)];

function flatten(list) = [for(p = list) for(x = p) x];

module rounded_polygon(points, radius)
    union () {
        for(point = shape)
            translate(point)
                circle (r = radius);

        polygon(flatten([for(i  = [0 : len(shape) - 1]) tangents(i)]));
    }


function tangent(p1, p2, rad, side) =
    let (
    x_delta = p2.x - p1.x,
    y_delta = p2.y - p1.y,
    theta = atan2(y_delta, x_delta),
    xa = p1.x +(cos(90 + theta) * rad),
    ya = p1.y +(sin(90 + theta) * rad),
    xb = xa + x_delta,
    yb = ya + y_delta
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 10:51, droftarts <[hidden email]> wrote:
Thanks shadowwynd, and I agree, offest is very useful. I'd tried that
approach for this problem, too, before finding it didn't import into FreeCAD
either!

Ian S



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16542.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

droftarts
Hi nophead

Wow! Thanks for the reply, that solves what I need at the moment. I knew there had to be a way to iterate this, but just couldn't see it. That gives me plenty to wrap my head around; I'd perhaps like to extend it to allow for different radii.

I've been spending some time with your Mendel90 OpenSCAD files recently, and have learnt a huge amount from that!

Ian S

P.S. Who's Stuart?!
Reply | Threaded
Open this post in threaded view
|

Re: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
>P.S. Who's Stuart?!

No idea, sorry Ian.

I am attempting the different radii case at the moment. No quite right yet.

On 18 March 2016 at 12:26, droftarts <[hidden email]> wrote:
Hi nophead

Wow! Thanks for the reply, that solves what I need at the moment. I knew
there had to be a way to iterate this, but just couldn't see it. That gives
me plenty to wrap my head around; I'd perhaps like to extend it to allow for
different radii.

I've been spending some time with your Mendel90 OpenSCAD files recently, and
have learnt a huge amount from that!

Ian S

P.S. Who's Stuart?!



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16545.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
Here is a multi radii version. It looks right but somebody might want to check my maths as it is much simpler than the link you provided.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 80, 5], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    union () {
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                #circle(shape[i][2]);

        polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 12:35, nop head <[hidden email]> wrote:
>P.S. Who's Stuart?!

No idea, sorry Ian.

I am attempting the different radii case at the moment. No quite right yet.

On 18 March 2016 at 12:26, droftarts <[hidden email]> wrote:
Hi nophead

Wow! Thanks for the reply, that solves what I need at the moment. I knew
there had to be a way to iterate this, but just couldn't see it. That gives
me plenty to wrap my head around; I'd perhaps like to extend it to allow for
different radii.

I've been spending some time with your Mendel90 OpenSCAD files recently, and
have learnt a huge amount from that!

Ian S

P.S. Who's Stuart?!



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16545.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
This version seems to handle the negative radii case:

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 13:01, nop head <[hidden email]> wrote:
Here is a multi radii version. It looks right but somebody might want to check my maths as it is much simpler than the link you provided.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 80, 5], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    union () {
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                #circle(shape[i][2]);

        polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 12:35, nop head <[hidden email]> wrote:
>P.S. Who's Stuart?!

No idea, sorry Ian.

I am attempting the different radii case at the moment. No quite right yet.

On 18 March 2016 at 12:26, droftarts <[hidden email]> wrote:
Hi nophead

Wow! Thanks for the reply, that solves what I need at the moment. I knew
there had to be a way to iterate this, but just couldn't see it. That gives
me plenty to wrap my head around; I'd perhaps like to extend it to allow for
different radii.

I've been spending some time with your Mendel90 OpenSCAD files recently, and
have learnt a huge amount from that!

Ian S

P.S. Who's Stuart?!



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16545.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
Slightly more efficient version that only calls tangent once per corner.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i)[side]]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
     }

function tangent(p1, p2) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )[ [xa, ya], [xb, yb] ];



On 18 March 2016 at 13:08, nop head <[hidden email]> wrote:
This version seems to handle the negative radii case:

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 13:01, nop head <[hidden email]> wrote:
Here is a multi radii version. It looks right but somebody might want to check my maths as it is much simpler than the link you provided.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 80, 5], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    union () {
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                #circle(shape[i][2]);

        polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 12:35, nop head <[hidden email]> wrote:
>P.S. Who's Stuart?!

No idea, sorry Ian.

I am attempting the different radii case at the moment. No quite right yet.

On 18 March 2016 at 12:26, droftarts <[hidden email]> wrote:
Hi nophead

Wow! Thanks for the reply, that solves what I need at the moment. I knew
there had to be a way to iterate this, but just couldn't see it. That gives
me plenty to wrap my head around; I'd perhaps like to extend it to allow for
different radii.

I've been spending some time with your Mendel90 OpenSCAD files recently, and
have learnt a huge amount from that!

Ian S

P.S. Who's Stuart?!



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16545.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
Actually that still called tangent twice, this version calls it once.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1])
                let(ends = tangents(i))
                    for(end = [0, 1])
                        ends[end]]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
     }

function tangent(p1, p2) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )[ [xa, ya], [xb, yb] ];


On 18 March 2016 at 13:47, nop head <[hidden email]> wrote:
Slightly more efficient version that only calls tangent once per corner.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i)[side]]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
     }

function tangent(p1, p2) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )[ [xa, ya], [xb, yb] ];



On 18 March 2016 at 13:08, nop head <[hidden email]> wrote:
This version seems to handle the negative radii case:

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 13:01, nop head <[hidden email]> wrote:
Here is a multi radii version. It looks right but somebody might want to check my maths as it is much simpler than the link you provided.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 80, 5], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    union () {
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                #circle(shape[i][2]);

        polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 12:35, nop head <[hidden email]> wrote:
>P.S. Who's Stuart?!

No idea, sorry Ian.

I am attempting the different radii case at the moment. No quite right yet.

On 18 March 2016 at 12:26, droftarts <[hidden email]> wrote:
Hi nophead

Wow! Thanks for the reply, that solves what I need at the moment. I knew
there had to be a way to iterate this, but just couldn't see it. That gives
me plenty to wrap my head around; I'd perhaps like to extend it to allow for
different radii.

I've been spending some time with your Mendel90 OpenSCAD files recently, and
have learnt a huge amount from that!

Ian S

P.S. Who's Stuart?!



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16545.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
Fixed all the references to shape instead of points and removed single use functions.

$fn = 100;

shape1 = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape1);

module rounded_polygon(points, radius)
    difference() {
        len = len(points);
        union () {
            for(i = [0 : len - 1])
                translate([points[i].x, points[i].y])
                    if(points[i][2] > 0)
                        circle(points[i][2]);

            polygon([for(i  = [0 : len - 1])
                let(ends = tangent(points[i], points[(i + 1) % len(points)]))
                    for(end = [0, 1])
                        ends[end]]);
        }
        for(i = [0 : len - 1])
            translate([points[i].x, points[i].y])
                if(points[i][2] < 0)
                    circle(-points[i][2]);
     }

function tangent(p1, p2) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )[ [xa, ya], [xb, yb] ];



On 18 March 2016 at 13:53, nop head <[hidden email]> wrote:
Actually that still called tangent twice, this version calls it once.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1])
                let(ends = tangents(i))
                    for(end = [0, 1])
                        ends[end]]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
     }

function tangent(p1, p2) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )[ [xa, ya], [xb, yb] ];


On 18 March 2016 at 13:47, nop head <[hidden email]> wrote:
Slightly more efficient version that only calls tangent once per corner.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i)[side]]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
     }

function tangent(p1, p2) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )[ [xa, ya], [xb, yb] ];



On 18 March 2016 at 13:08, nop head <[hidden email]> wrote:
This version seems to handle the negative radii case:

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    difference() {
        union () {
            for(i = [0 : len(shape) - 1])
                translate([shape[i].x, shape[i].y])
                    if(shape[i][2] > 0)
                        circle(shape[i][2]);

            polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
        }
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                if(shape[i][2] < 0)
                    circle(-shape[i][2]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 13:01, nop head <[hidden email]> wrote:
Here is a multi radii version. It looks right but somebody might want to check my maths as it is much simpler than the link you provided.

$fn = 100;

shape = [ [10, 10, 8], [0, 40, 3], [40, 80, 5], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape);

function next(i) = (i + 1) % len(shape);

function tangents(i, side) = tangent(shape[i], shape[next(i)], side);

module rounded_polygon(points, radius)
    union () {
        for(i = [0 : len(shape) - 1])
            translate([shape[i].x, shape[i].y])
                #circle(shape[i][2]);

        polygon([for(i  = [0 : len(shape) - 1]) for(side = [0, 1]) tangents(i, side)]);
    }


function tangent(p1, p2, side) =
    let (
    r1 = p1[2],
    r2 = p2[2],
    dx = p2.x - p1.x,
    dy = p2.y - p1.y,
    d = sqrt(dx * dx + dy * dy),
    theta = atan2(dy, dx) + acos((r1 - r2) / d),
    xa = p1.x +(cos(theta) * r1),
    ya = p1.y +(sin(theta) * r1),
    xb = p2.x +(cos(theta) * r2),
    yb = p2.y +(sin(theta) * r2)
    )

    side ? [xb, yb] : [xa, ya];



On 18 March 2016 at 12:35, nop head <[hidden email]> wrote:
>P.S. Who's Stuart?!

No idea, sorry Ian.

I am attempting the different radii case at the moment. No quite right yet.

On 18 March 2016 at 12:26, droftarts <[hidden email]> wrote:
Hi nophead

Wow! Thanks for the reply, that solves what I need at the moment. I knew
there had to be a way to iterate this, but just couldn't see it. That gives
me plenty to wrap my head around; I'd perhaps like to extend it to allow for
different radii.

I've been spending some time with your Mendel90 OpenSCAD files recently, and
have learnt a huge amount from that!

Ian S

P.S. Who's Stuart?!



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16545.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

droftarts
Thanks nophead, awesome stuff! I hope you find it useful too. But, dammit, you're not giving me a chance to use my brain...!

I'll have a sit down over the weekend and see how you've coded this, so I can understand it. One quick question: you use a '%' sign here:

...
let(ends = tangent(points[i], points[(i + 1) % len(points)]))
...

What does that do? I can see it's a 'scalar arithmetical operator'  ( https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Mathematical_Operators ) for modulo (so finds the remainder after division of one number by another), but I'm not clear why!

Ian S

P.S. re 'Stuart', you addressed me as Stuart in your first post!
Reply | Threaded
Open this post in threaded view
|

Re: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
It calculates the remainder after dividing by the length. That causes the wrap round to zero to close the loop when i+1 equals the length.

On 18 March 2016 at 15:10, droftarts <[hidden email]> wrote:
Thanks nophead, awesome stuff! I hope you find it useful too. But, dammit,
you're not giving me a chance to use my brain...!

I'll have a sit down over the weekend and see how you've coded this, so I
can understand it. One quick question: you use a '%' sign here:

...
let(ends = tangent(points[i], points[(i + 1) % len(points)]))
...

What does that do? I can see it's a 'scalar arithmetical operator'  (
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Mathematical_Operators )
for modulo (so finds the remainder after division of one number by another),
but I'm not clear why!

Ian S

P.S. re 'Stuart', you addressed me as Stuart in your first post!



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16553.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

droftarts
In reply to this post by droftarts
And just to confirm, this exports as a CSG file, and imports nicely into FreeCAD as :



Which exports happily as a STEP file, which Fusion 360 can import and render:



Thanks! I'll try it with some more complex geometry, and see if it still copes.

Ian S
Reply | Threaded
Open this post in threaded view
|

Re: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
In reply to this post by nophead
Cleaned up the generated csg by moving the circle translates inside the if and replaced a call of len(points) with len.

$fn = 100;

shape1 = [ [10, 10, 8], [0, 40, 3], [40, 50, -10], [100, 80, 10], [50, 0, 20] ];

linear_extrude (height = 5) rounded_polygon(shape1);

module rounded_polygon(points)
    difference() {
        len = len(points);
        union() {
            for(i = [0 : len - 1])
                if(points[i][2] > 0)
                    translate([points[i].x, points[i].y])
                        circle(points[i][2]);

            polygon([for(i  = [0 : len - 1])
                        let(ends = tangent(points[i], points[(i + 1) % len]))
                            for(end = [0, 1])
                                ends[end]]);
        }
        for(i = [0 : len - 1])
            if(points[i][2] < 0)
                translate([points[i].x, points[i].y])
                    circle(-points[i][2]);
     }

function tangent(p1, p2) =
    let(
        r1 = p1[2],
        r2 = p2[2],
        dx = p2.x - p1.x,
        dy = p2.y - p1.y,
        d = sqrt(dx * dx + dy * dy),
        theta = atan2(dy, dx) + acos((r1 - r2) / d),
        xa = p1.x +(cos(theta) * r1),
        ya = p1.y +(sin(theta) * r1),
        xb = p2.x +(cos(theta) * r2),
        yb = p2.y +(sin(theta) * r2)
    )[ [xa, ya], [xb, yb] ];


On 18 March 2016 at 15:20, nop head <[hidden email]> wrote:
It calculates the remainder after dividing by the length. That causes the wrap round to zero to close the loop when i+1 equals the length.

On 18 March 2016 at 15:10, droftarts <[hidden email]> wrote:
Thanks nophead, awesome stuff! I hope you find it useful too. But, dammit,
you're not giving me a chance to use my brain...!

I'll have a sit down over the weekend and see how you've coded this, so I
can understand it. One quick question: you use a '%' sign here:

...
let(ends = tangent(points[i], points[(i + 1) % len(points)]))
...

What does that do? I can see it's a 'scalar arithmetical operator'  (
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Mathematical_Operators )
for modulo (so finds the remainder after division of one number by another),
but I'm not clear why!

Ian S

P.S. re 'Stuart', you addressed me as Stuart in your first post!



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16553.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

nophead
In reply to this post by droftarts
Looks nice in wood.

I suspect you could export the STL to Blender and give it a wood texture and then render it. That would have the advantage of working with anything OpenScad can produce. The Mendel90 printed

parts are rendered in Blender for the manual.

Inline images 2

They are not very pretty but that is just down to the blender template used. I think it adds some random noise to make it look like a photo. I am sure it could texture it with wood and give a photo realistic view. I am not a blender user though, somebody else contributed it.

On 18 March 2016 at 15:30, droftarts <[hidden email]> wrote:
And just to confirm, this exports as a CSG file, and imports nicely into
FreeCAD as :

<http://forum.openscad.org/file/n16555/FreeCAD.png>

Which exports happily as a STEP file, which Fusion 360 can import and
render:

<http://forum.openscad.org/file/n16555/Fusion_360.png>

Thanks! I'll try it with some more complex geometry, and see if it still
copes.

Ian S



--
View this message in context: http://forum.openscad.org/Script-to-replicate-hull-and-minkoswki-for-CSG-export-import-into-FreeCAD-tp16537p16555.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

_______________________________________________
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: Script to replicate hull and minkoswki for CSG export/import into FreeCAD

cacb
In reply to this post by droftarts
On 18. mars 2016 16:30, droftarts wrote:

> And just to confirm, this exports as a CSG file, and imports nicely into
> FreeCAD as :
>
> <http://forum.openscad.org/file/n16555/FreeCAD.png>
>
> Which exports happily as a STEP file, which Fusion 360 can import and
> render:
>
> <http://forum.openscad.org/file/n16555/Fusion_360.png>
>
> Thanks! I'll try it with some more complex geometry, and see if it still
> copes.

Does FreeCAD understand the polyhedron command? If so, OpenSCAD could
have an option to save the final body as a polyhedron to .csg, and you
could then use it in FreeCAD even if you had used Hull and Minkowski.

Carsten Arnholm


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