discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Adding a border of d thickness to a polygon

N
nigeljohnson73
Mon, Nov 21, 2016 12:05 PM

I'm not sure where to post this or how to get to the point, please bear with
me and feel free to point me in directions.

I have a function and module that will draw me a heart polygon of an exact
size:

function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) *
(sqrt(abs(cos(t)))/(sin(t)+1.6))));

module njHeart(xy=80, pad = 0) {

td = 1; // theta delta - the resolution of the curve

// Calculate x/y co-ords separetely so I can scale correctly later
xp = [ for (t = [0 : td : 360-td]) heartRadius(t) * cos(t) ]; // x

co-ordinates on the curve
yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // y
co-ordinates on the curve

xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected size
ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected size

// Generate a vector of points for the polygon to work
p = [ for (i = [0 : 360/td - 1]) [xsc*xp[i]+pad, ysc*yp[i]+pad] ];

// translate polygon so it is centralised at +/- xy/2	
translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)])

linear_extrude(height=0.01) polygon(p);
}

color("red") njHeart(xy=80);
color("white") njHeart(xy=78);

Originally, I thought this was going to be easy, do it in polar and then
just add 'pad' to the calculated 'r' and it'll all be good... nope.

I had already worked out that scaling is not the answer.

Then I thought about calculating normals to the gradient of the 2 sides of
the point... but then you get a hole at the top of the heart as it loops
back on itself. My most promising idea was to test if the normal (x,y) was
of the same sign in x as the current point, but that got really messy trying
to make the array work- and I never did.

I then wondered if I could find the 'true' center of the object whether the
scaling would work better, but I couldn't figure out how to do it.

The only other option I can think of is to draw the outline of the heart in
hull'd cylinders with a radius of "pad", then subtracting the solid from the
middle. After working out the math it was very clear that the computational
power required was going to make it unworkable.

I have now run out of ideas.

Any help much apprecaited.
Kind regards
Nigel

--
View this message in context: http://forum.openscad.org/Adding-a-border-of-d-thickness-to-a-polygon-tp19283.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

I'm not sure where to post this or how to get to the point, please bear with me and feel free to point me in directions. I have a function and module that will draw me a heart polygon of an exact size: function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) * (sqrt(abs(cos(t)))/(sin(t)+1.6)))); module njHeart(xy=80, pad = 0) { td = 1; // theta delta - the resolution of the curve // Calculate x/y co-ords separetely so I can scale correctly later xp = [ for (t = [0 : td : 360-td]) heartRadius(t) * cos(t) ]; // x co-ordinates on the curve yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // y co-ordinates on the curve xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected size ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected size // Generate a vector of points for the polygon to work p = [ for (i = [0 : 360/td - 1]) [xsc*xp[i]+pad, ysc*yp[i]+pad] ]; // translate polygon so it is centralised at +/- xy/2 translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)]) linear_extrude(height=0.01) polygon(p); } color("red") njHeart(xy=80); color("white") njHeart(xy=78); Originally, I thought this was going to be easy, do it in polar and then just add 'pad' to the calculated 'r' and it'll all be good... nope. I had already worked out that scaling is not the answer. Then I thought about calculating normals to the gradient of the 2 sides of the point... but then you get a hole at the top of the heart as it loops back on itself. My most promising idea was to test if the normal (x,y) was of the same sign in x as the current point, but that got really messy trying to make the array work- and I never did. I then wondered if I could find the 'true' center of the object whether the scaling would work better, but I couldn't figure out how to do it. The only other option I can think of is to draw the outline of the heart in hull'd cylinders with a radius of "pad", then subtracting the solid from the middle. After working out the math it was very clear that the computational power required was going to make it unworkable. I have now run out of ideas. Any help much apprecaited. Kind regards Nigel -- View this message in context: http://forum.openscad.org/Adding-a-border-of-d-thickness-to-a-polygon-tp19283.html Sent from the OpenSCAD mailing list archive at Nabble.com.
RP
Ronaldo Persiano
Mon, Nov 21, 2016 1:31 PM
Try offset <https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Transformations#offset>.
NH
nop head
Mon, Nov 21, 2016 1:36 PM

I think you just need to use offset() to expand the shape in 2D before
extruding it to 3D if I understand the question right.

On 21 November 2016 at 12:05, nigeljohnson73 nigel@nigeljohnson.net wrote:

I'm not sure where to post this or how to get to the point, please bear
with
me and feel free to point me in directions.

I have a function and module that will draw me a heart polygon of an exact
size:

function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) *
(sqrt(abs(cos(t)))/(sin(t)+1.6))));

module njHeart(xy=80, pad = 0) {

     td = 1; // theta delta - the resolution of the curve

     // Calculate x/y co-ords separetely so I can scale correctly later
     xp = [ for (t = [0 : td : 360-td]) heartRadius(t) * cos(t) ]; // x

co-ordinates on the curve
yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // y
co-ordinates on the curve

     xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected

size
ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected
size

     // Generate a vector of points for the polygon to work
     p = [ for (i = [0 : 360/td - 1]) [xsc*xp[i]+pad, ysc*yp[i]+pad] ];

     // translate polygon so it is centralised at +/- xy/2
     translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)])

linear_extrude(height=0.01) polygon(p);
}

color("red") njHeart(xy=80);
color("white") njHeart(xy=78);

Originally, I thought this was going to be easy, do it in polar and then
just add 'pad' to the calculated 'r' and it'll all be good... nope.

I had already worked out that scaling is not the answer.

Then I thought about calculating normals to the gradient of the 2 sides of
the point... but then you get a hole at the top of the heart as it loops
back on itself. My most promising idea was to test if the normal (x,y) was
of the same sign in x as the current point, but that got really messy
trying
to make the array work- and I never did.

I then wondered if I could find the 'true' center of the object whether the
scaling would work better, but I couldn't figure out how to do it.

The only other option I can think of is to draw the outline of the heart in
hull'd cylinders with a radius of "pad", then subtracting the solid from
the
middle. After working out the math it was very clear that the computational
power required was going to make it unworkable.

I have now run out of ideas.

Any help much apprecaited.
Kind regards
Nigel

--
View this message in context: http://forum.openscad.org/
Adding-a-border-of-d-thickness-to-a-polygon-tp19283.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

I think you just need to use offset() to expand the shape in 2D before extruding it to 3D if I understand the question right. On 21 November 2016 at 12:05, nigeljohnson73 <nigel@nigeljohnson.net> wrote: > I'm not sure where to post this or how to get to the point, please bear > with > me and feel free to point me in directions. > > I have a function and module that will draw me a heart polygon of an exact > size: > > function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) * > (sqrt(abs(cos(t)))/(sin(t)+1.6)))); > > module njHeart(xy=80, pad = 0) { > > td = 1; // theta delta - the resolution of the curve > > // Calculate x/y co-ords separetely so I can scale correctly later > xp = [ for (t = [0 : td : 360-td]) heartRadius(t) * cos(t) ]; // x > co-ordinates on the curve > yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // y > co-ordinates on the curve > > xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected > size > ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected > size > > // Generate a vector of points for the polygon to work > p = [ for (i = [0 : 360/td - 1]) [xsc*xp[i]+pad, ysc*yp[i]+pad] ]; > > // translate polygon so it is centralised at +/- xy/2 > translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)]) > linear_extrude(height=0.01) polygon(p); > } > > color("red") njHeart(xy=80); > color("white") njHeart(xy=78); > > Originally, I thought this was going to be easy, do it in polar and then > just add 'pad' to the calculated 'r' and it'll all be good... nope. > > I had already worked out that scaling is not the answer. > > Then I thought about calculating normals to the gradient of the 2 sides of > the point... but then you get a hole at the top of the heart as it loops > back on itself. My most promising idea was to test if the normal (x,y) was > of the same sign in x as the current point, but that got really messy > trying > to make the array work- and I never did. > > I then wondered if I could find the 'true' center of the object whether the > scaling would work better, but I couldn't figure out how to do it. > > The only other option I can think of is to draw the outline of the heart in > hull'd cylinders with a radius of "pad", then subtracting the solid from > the > middle. After working out the math it was very clear that the computational > power required was going to make it unworkable. > > I have now run out of ideas. > > Any help much apprecaited. > Kind regards > Nigel > > > > -- > View this message in context: http://forum.openscad.org/ > Adding-a-border-of-d-thickness-to-a-polygon-tp19283.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
N
nigeljohnson73
Mon, Nov 21, 2016 7:49 PM

Thanks, that's what I was after. It doesn't like the sharp points though, so
a bit of tweaking was required.

--
View this message in context: http://forum.openscad.org/Adding-a-border-of-d-thickness-to-a-polygon-tp19283p19298.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Thanks, that's what I was after. It doesn't like the sharp points though, so a bit of tweaking was required. -- View this message in context: http://forum.openscad.org/Adding-a-border-of-d-thickness-to-a-polygon-tp19283p19298.html Sent from the OpenSCAD mailing list archive at Nabble.com.
MK
Marius Kintel
Mon, Nov 21, 2016 9:10 PM

On Nov 21, 2016, at 14:49, nigeljohnson73 nigel@nigeljohnson.net wrote:

Thanks, that's what I was after. It doesn't like the sharp points though, so
a bit of tweaking was required.

Nigel,

There are some parameters to offset() which can be used to control sharp corners, see:
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Transformations#offset

-Marius

> On Nov 21, 2016, at 14:49, nigeljohnson73 <nigel@nigeljohnson.net> wrote: > > Thanks, that's what I was after. It doesn't like the sharp points though, so > a bit of tweaking was required. > Nigel, There are some parameters to offset() which can be used to control sharp corners, see: https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Transformations#offset -Marius
N
nigeljohnson73
Tue, Nov 22, 2016 4:37 PM

Thanks Marius.

I should have been more specific though; with my heart shape, the delta -
which is what I wanted based on the images in the documentation - doesn't
like the top point, and with a bit of delta cuts the whole object in half.
The radius is also not the greatest here, but it works enough for my needs.

Cheers
Nigel

--
View this message in context: http://forum.openscad.org/Adding-a-border-of-d-thickness-to-a-polygon-tp19283p19321.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Thanks Marius. I should have been more specific though; with my heart shape, the delta - which is what I wanted based on the images in the documentation - doesn't like the top point, and with a bit of delta cuts the whole object in half. The radius is also not the greatest here, but it works enough for my needs. Cheers Nigel -- View this message in context: http://forum.openscad.org/Adding-a-border-of-d-thickness-to-a-polygon-tp19283p19321.html Sent from the OpenSCAD mailing list archive at Nabble.com.
FV
Frank van der Hulst
Tue, Nov 22, 2016 5:37 PM

Check out http://www.thingiverse.com/thing:8483 (this tells you how to make
a heart using Bezier curves) and http://www.thingiverse.com/thing:186660
(tells you how to extrude along a path).

Combine the two to extrude a square or rectangle along a heart-shaped path
and you should have what you're after?

Frank

On Wed, Nov 23, 2016 at 5:37 AM, nigeljohnson73 nigel@nigeljohnson.net
wrote:

Thanks Marius.

I should have been more specific though; with my heart shape, the delta -
which is what I wanted based on the images in the documentation - doesn't
like the top point, and with a bit of delta cuts the whole object in half.
The radius is also not the greatest here, but it works enough for my needs.

Cheers
Nigel

--
View this message in context: http://forum.openscad.org/
Adding-a-border-of-d-thickness-to-a-polygon-tp19283p19321.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Check out http://www.thingiverse.com/thing:8483 (this tells you how to make a heart using Bezier curves) and http://www.thingiverse.com/thing:186660 (tells you how to extrude along a path). Combine the two to extrude a square or rectangle along a heart-shaped path and you should have what you're after? Frank On Wed, Nov 23, 2016 at 5:37 AM, nigeljohnson73 <nigel@nigeljohnson.net> wrote: > Thanks Marius. > > I should have been more specific though; with my heart shape, the delta - > which is what I wanted based on the images in the documentation - doesn't > like the top point, and with a bit of delta cuts the whole object in half. > The radius is also not the greatest here, but it works enough for my needs. > > Cheers > Nigel > > > > -- > View this message in context: http://forum.openscad.org/ > Adding-a-border-of-d-thickness-to-a-polygon-tp19283p19321.html > Sent from the OpenSCAD mailing list archive at Nabble.com. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
K
kintel
Tue, Nov 22, 2016 5:40 PM

You have a very sharp angle in your heart, which makes it hard to offset. We
have a chamfer flag for this purpose, but that doesn't look too good in this
case.
Another option is to get rid of sharp angles by offsetting the original a
small amount:

difference() {
color("red") offset(delta=2) offset(delta=0.5) njHeart(xy=80);
color("white") offset(delta=0.5) njHeart(xy=80);
}

-Marius

--
View this message in context: http://forum.openscad.org/Adding-a-border-of-d-thickness-to-a-polygon-tp19283p19323.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

You have a very sharp angle in your heart, which makes it hard to offset. We have a chamfer flag for this purpose, but that doesn't look too good in this case. Another option is to get rid of sharp angles by offsetting the original a small amount: difference() { color("red") offset(delta=2) offset(delta=0.5) njHeart(xy=80); color("white") offset(delta=0.5) njHeart(xy=80); } -Marius -- View this message in context: http://forum.openscad.org/Adding-a-border-of-d-thickness-to-a-polygon-tp19283p19323.html Sent from the OpenSCAD mailing list archive at Nabble.com.
O
otto
Wed, Nov 23, 2016 2:41 PM

Another way to achieve this is with the 2-D minkowski which is
moderately efficient.

function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) *
(sqrt(abs(cos(t)))/(sin(t)+1.6))));
$fn=23;

module pHeart(xy,off=0) {

td = 1; // theta delta - the resolution of the curve

// Calculate x/y co-ords separetely so I can scale correctly later
xp = [ for (t = [0: td : 360-td]) heartRadius(t) * cos(t) ]; // xco-ordinates on the curve
yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // yco-ordinates on the curve

xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected size
ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected size

// Generate a vector of points for the polygon to work
p = [ for (i = [0 : 360/td-1]) [xsc*xp[i], ysc*yp[i]] ];

// translate polygon so it is centralised at +/- xy/2	
translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)])
if(off)
{    
minkowski(){ polygon(p); circle(off); }
}
else polygon(p);

}

difference()
{
linear_extrude(5) pHeart(xy=78,off=2);
translate([0,0,-.5]) linear_extrude(6) pHeart(xy=78, off=.4);
}

On Mon, 21 Nov 2016 13:36:36 +0000
nop head nop.head@gmail.com wrote:

I think you just need to use offset() to expand the shape in 2D before
extruding it to 3D if I understand the question right.

On 21 November 2016 at 12:05, nigeljohnson73 nigel@nigeljohnson.net
wrote:

I'm not sure where to post this or how to get to the point, please
bear with
me and feel free to point me in directions.

I have a function and module that will draw me a heart polygon of
an exact size:

function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) *
(sqrt(abs(cos(t)))/(sin(t)+1.6))));

module njHeart(xy=80, pad = 0) {

     td = 1; // theta delta - the resolution of the curve

     // Calculate x/y co-ords separetely so I can scale

correctly later xp = [ for (t = [0 : td : 360-td]) heartRadius(t) *
cos(t) ]; // x co-ordinates on the curve
yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t)
]; // y co-ordinates on the curve

     xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit

expected size
ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit
expected size

     // Generate a vector of points for the polygon to work
     p = [ for (i = [0 : 360/td - 1]) [xsc*xp[i]+pad,

ysc*yp[i]+pad] ];

     // translate polygon so it is centralised at +/- xy/2
     translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)])

linear_extrude(height=0.01) polygon(p);
}

color("red") njHeart(xy=80);
color("white") njHeart(xy=78);

Originally, I thought this was going to be easy, do it in polar and
then just add 'pad' to the calculated 'r' and it'll all be good...
nope.

I had already worked out that scaling is not the answer.

Then I thought about calculating normals to the gradient of the 2
sides of the point... but then you get a hole at the top of the
heart as it loops back on itself. My most promising idea was to
test if the normal (x,y) was of the same sign in x as the current
point, but that got really messy trying
to make the array work- and I never did.

I then wondered if I could find the 'true' center of the object
whether the scaling would work better, but I couldn't figure out
how to do it.

The only other option I can think of is to draw the outline of the
heart in hull'd cylinders with a radius of "pad", then subtracting
the solid from the
middle. After working out the math it was very clear that the
computational power required was going to make it unworkable.

I have now run out of ideas.

Any help much apprecaited.
Kind regards
Nigel

--
View this message in context: http://forum.openscad.org/
Adding-a-border-of-d-thickness-to-a-polygon-tp19283.html
Sent from the OpenSCAD mailing list archive at Nabble.com.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Another way to achieve this is with the 2-D minkowski which is moderately efficient. function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) * (sqrt(abs(cos(t)))/(sin(t)+1.6)))); $fn=23; module pHeart(xy,off=0) { td = 1; // theta delta - the resolution of the curve // Calculate x/y co-ords separetely so I can scale correctly later xp = [ for (t = [0: td : 360-td]) heartRadius(t) * cos(t) ]; // xco-ordinates on the curve yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // yco-ordinates on the curve xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected size ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected size // Generate a vector of points for the polygon to work p = [ for (i = [0 : 360/td-1]) [xsc*xp[i], ysc*yp[i]] ]; // translate polygon so it is centralised at +/- xy/2 translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)]) if(off) { minkowski(){ polygon(p); circle(off); } } else polygon(p); } difference() { linear_extrude(5) pHeart(xy=78,off=2); translate([0,0,-.5]) linear_extrude(6) pHeart(xy=78, off=.4); } On Mon, 21 Nov 2016 13:36:36 +0000 nop head <nop.head@gmail.com> wrote: > I think you just need to use offset() to expand the shape in 2D before > extruding it to 3D if I understand the question right. > > On 21 November 2016 at 12:05, nigeljohnson73 <nigel@nigeljohnson.net> > wrote: > > > I'm not sure where to post this or how to get to the point, please > > bear with > > me and feel free to point me in directions. > > > > I have a function and module that will draw me a heart polygon of > > an exact size: > > > > function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) * > > (sqrt(abs(cos(t)))/(sin(t)+1.6)))); > > > > module njHeart(xy=80, pad = 0) { > > > > td = 1; // theta delta - the resolution of the curve > > > > // Calculate x/y co-ords separetely so I can scale > > correctly later xp = [ for (t = [0 : td : 360-td]) heartRadius(t) * > > cos(t) ]; // x co-ordinates on the curve > > yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) > > ]; // y co-ordinates on the curve > > > > xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit > > expected size > > ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit > > expected size > > > > // Generate a vector of points for the polygon to work > > p = [ for (i = [0 : 360/td - 1]) [xsc*xp[i]+pad, > > ysc*yp[i]+pad] ]; > > > > // translate polygon so it is centralised at +/- xy/2 > > translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)]) > > linear_extrude(height=0.01) polygon(p); > > } > > > > color("red") njHeart(xy=80); > > color("white") njHeart(xy=78); > > > > Originally, I thought this was going to be easy, do it in polar and > > then just add 'pad' to the calculated 'r' and it'll all be good... > > nope. > > > > I had already worked out that scaling is not the answer. > > > > Then I thought about calculating normals to the gradient of the 2 > > sides of the point... but then you get a hole at the top of the > > heart as it loops back on itself. My most promising idea was to > > test if the normal (x,y) was of the same sign in x as the current > > point, but that got really messy trying > > to make the array work- and I never did. > > > > I then wondered if I could find the 'true' center of the object > > whether the scaling would work better, but I couldn't figure out > > how to do it. > > > > The only other option I can think of is to draw the outline of the > > heart in hull'd cylinders with a radius of "pad", then subtracting > > the solid from the > > middle. After working out the math it was very clear that the > > computational power required was going to make it unworkable. > > > > I have now run out of ideas. > > > > Any help much apprecaited. > > Kind regards > > Nigel > > > > > > > > -- > > View this message in context: http://forum.openscad.org/ > > Adding-a-border-of-d-thickness-to-a-polygon-tp19283.html > > Sent from the OpenSCAD mailing list archive at Nabble.com. > > > > _______________________________________________ > > OpenSCAD mailing list > > Discuss@lists.openscad.org > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >
MK
Marius Kintel
Thu, Nov 24, 2016 1:38 AM

On Nov 23, 2016, at 09:41, otto otto@123phase.com wrote:

Another way to achieve this is with the 2-D minkowski which is
moderately efficient.

Note that 2D minkowski is equivalent to 2D offset with a radius, but 2D offset should be considerably faster.

-Marius

> On Nov 23, 2016, at 09:41, otto <otto@123phase.com> wrote: > > Another way to achieve this is with the 2-D minkowski which is > moderately efficient. Note that 2D minkowski is equivalent to 2D offset with a radius, but 2D offset should be considerably faster. -Marius
O
otto
Thu, Nov 24, 2016 8:29 PM

On Wed, 23 Nov 2016 20:38:02 -0500
Marius Kintel marius@kintel.net wrote:

On Nov 23, 2016, at 09:41, otto otto@123phase.com wrote:

Another way to achieve this is with the 2-D minkowski which is
moderately efficient.

Note that 2D minkowski is equivalent to 2D offset with a radius, but
2D offset should be considerably faster.

-Marius

Testing the code shows no difference in speed.  The test code is
below.  Make sure to clear the cache!  div should be a power of 2.
Incidentally, as div gets large both versions show they same failure
artifacts.  I think that the offset module is simply a wrapper around
the minkowski.  In this program they seem to behave
identically to the agree that they have the same identical timed speed
and with the same identical artifacts.  Is there a known algorithm that
can calculate the offset faster than a minkowski algorithm or
that doesn't use the minkowski or some equivalent?

Regards
Otto

function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) *
(sqrt(abs(cos(t)))/(sin(t)+1.6))));
$fn=23;
div=512;  //ONLY USE POWERS OF 2

module pHeart(xy,off=0) {

td = 1/div; // theta delta - the resolution of the curve

// Calculate x/y co-ords separetely so I can scale correctly later
xp = [ for (t = [0: td : 360-td]) heartRadius(t) * cos(t) ]; // xco-ordinates on the curve
yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // yco-ordinates on the curve

xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected size
ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected size

// Generate a vector of points for the polygon to work
p = [ for (i = [0 : 360/td-1]) [xsc*xp[i], ysc*yp[i]] ];

// translate polygon so it is centralised at +/- xy/2	
translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)])

//// UNCOMMENT LINE TO TEST
//// CLEAR THE CACHE FIRST

///////////////////////  MINKOWSKY
//if(off){minkowski(){polygon(p);circle(off);}}else polygon(p);
///////////////////////  OFFSET
//offset(r=off) polygon(p);

}

difference()
{
linear_extrude(5) pHeart(xy=78,off=2);
translate([0,0,-.5]) linear_extrude(6) pHeart(xy=78, off=.4);
}

On Wed, 23 Nov 2016 20:38:02 -0500 Marius Kintel <marius@kintel.net> wrote: > > On Nov 23, 2016, at 09:41, otto <otto@123phase.com> wrote: > > > > Another way to achieve this is with the 2-D minkowski which is > > moderately efficient. > > Note that 2D minkowski is equivalent to 2D offset with a radius, but > 2D offset should be considerably faster. > > -Marius Testing the code shows no difference in speed. The test code is below. Make sure to clear the cache! div should be a power of 2. Incidentally, as div gets large both versions show they same failure artifacts. I think that the offset module is simply a wrapper around the minkowski. In this program they seem to behave identically to the agree that they have the same identical timed speed and with the same identical artifacts. Is there a known algorithm that can calculate the offset faster than a minkowski algorithm or that doesn't use the minkowski or some equivalent? Regards Otto function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) * (sqrt(abs(cos(t)))/(sin(t)+1.6)))); $fn=23; div=512; //ONLY USE POWERS OF 2 module pHeart(xy,off=0) { td = 1/div; // theta delta - the resolution of the curve // Calculate x/y co-ords separetely so I can scale correctly later xp = [ for (t = [0: td : 360-td]) heartRadius(t) * cos(t) ]; // xco-ordinates on the curve yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // yco-ordinates on the curve xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected size ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected size // Generate a vector of points for the polygon to work p = [ for (i = [0 : 360/td-1]) [xsc*xp[i], ysc*yp[i]] ]; // translate polygon so it is centralised at +/- xy/2 translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)]) //// UNCOMMENT LINE TO TEST //// CLEAR THE CACHE FIRST /////////////////////// MINKOWSKY //if(off){minkowski(){polygon(p);circle(off);}}else polygon(p); /////////////////////// OFFSET //offset(r=off) polygon(p); } difference() { linear_extrude(5) pHeart(xy=78,off=2); translate([0,0,-.5]) linear_extrude(6) pHeart(xy=78, off=.4); } > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
NH
nop head
Fri, Nov 25, 2016 10:53 AM

I might be wrong but I think OpenSCAD uses the clipper library for offset
and presumably CGAL for 2D Minkowski.

The artefacts from low div values come from the polygon generation, not the
offsetting, so it is no surprise they look identical. Provided clipper
obeys $fn they should produce the same results as they are mathematically
identical operations. There is no ambiguity where each vertex should be, so
any differences should only be down to the different number representations.

I am surprised there is little difference in speed but both are very fast
until you get to tens of thousands of vertices.

BTW rather than linear extruding twice and subtracting 3D shapes I think it
is more efficient to subtract the 2D shapes and extrude that.

linear_extrude(5, convexity = 2)
difference() {
pHeart(xy = 78, off = 2);
pHeart(xy = 78, off = 0.4);
}

On 24 November 2016 at 20:29, otto otto@123phase.com wrote:

On Wed, 23 Nov 2016 20:38:02 -0500
Marius Kintel marius@kintel.net wrote:

On Nov 23, 2016, at 09:41, otto otto@123phase.com wrote:

Another way to achieve this is with the 2-D minkowski which is
moderately efficient.

Note that 2D minkowski is equivalent to 2D offset with a radius, but
2D offset should be considerably faster.

-Marius

Testing the code shows no difference in speed.  The test code is
below.  Make sure to clear the cache!  div should be a power of 2.
Incidentally, as div gets large both versions show they same failure
artifacts.  I think that the offset module is simply a wrapper around
the minkowski.  In this program they seem to behave
identically to the agree that they have the same identical timed speed
and with the same identical artifacts.  Is there a known algorithm that
can calculate the offset faster than a minkowski algorithm or
that doesn't use the minkowski or some equivalent?

Regards
Otto

function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) *
(sqrt(abs(cos(t)))/(sin(t)+1.6))));
$fn=23;
div=512;  //ONLY USE POWERS OF 2

module pHeart(xy,off=0) {

     td = 1/div; // theta delta - the resolution of the curve

     // Calculate x/y co-ords separetely so I can scale correctly later
     xp = [ for (t = [0: td : 360-td]) heartRadius(t) * cos(t) ]; //

xco-ordinates on the curve
yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; //
yco-ordinates on the curve

     xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected

size
ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected
size

     // Generate a vector of points for the polygon to work
     p = [ for (i = [0 : 360/td-1]) [xsc*xp[i], ysc*yp[i]] ];

     // translate polygon so it is centralised at +/- xy/2
     translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)])

 //// UNCOMMENT LINE TO TEST
 //// CLEAR THE CACHE FIRST

 ///////////////////////  MINKOWSKY
 //if(off){minkowski(){polygon(p);circle(off);}}else polygon(p);
 ///////////////////////  OFFSET
 //offset(r=off) polygon(p);

}

difference()
{
linear_extrude(5) pHeart(xy=78,off=2);
translate([0,0,-.5]) linear_extrude(6) pHeart(xy=78, off=.4);
}

I might be wrong but I think OpenSCAD uses the clipper library for offset and presumably CGAL for 2D Minkowski. The artefacts from low div values come from the polygon generation, not the offsetting, so it is no surprise they look identical. Provided clipper obeys $fn they should produce the same results as they are mathematically identical operations. There is no ambiguity where each vertex should be, so any differences should only be down to the different number representations. I am surprised there is little difference in speed but both are very fast until you get to tens of thousands of vertices. BTW rather than linear extruding twice and subtracting 3D shapes I think it is more efficient to subtract the 2D shapes and extrude that. linear_extrude(5, convexity = 2) difference() { pHeart(xy = 78, off = 2); pHeart(xy = 78, off = 0.4); } On 24 November 2016 at 20:29, otto <otto@123phase.com> wrote: > > > > > > On Wed, 23 Nov 2016 20:38:02 -0500 > Marius Kintel <marius@kintel.net> wrote: > > > > On Nov 23, 2016, at 09:41, otto <otto@123phase.com> wrote: > > > > > > Another way to achieve this is with the 2-D minkowski which is > > > moderately efficient. > > > > Note that 2D minkowski is equivalent to 2D offset with a radius, but > > 2D offset should be considerably faster. > > > > -Marius > > Testing the code shows no difference in speed. The test code is > below. Make sure to clear the cache! div should be a power of 2. > Incidentally, as div gets large both versions show they same failure > artifacts. I think that the offset module is simply a wrapper around > the minkowski. In this program they seem to behave > identically to the agree that they have the same identical timed speed > and with the same identical artifacts. Is there a known algorithm that > can calculate the offset faster than a minkowski algorithm or > that doesn't use the minkowski or some equivalent? > > Regards > Otto > > function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) * > (sqrt(abs(cos(t)))/(sin(t)+1.6)))); > $fn=23; > div=512; //ONLY USE POWERS OF 2 > > module pHeart(xy,off=0) { > > td = 1/div; // theta delta - the resolution of the curve > > // Calculate x/y co-ords separetely so I can scale correctly later > xp = [ for (t = [0: td : 360-td]) heartRadius(t) * cos(t) ]; // > xco-ordinates on the curve > yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) ]; // > yco-ordinates on the curve > > xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit expected > size > ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit expected > size > > // Generate a vector of points for the polygon to work > p = [ for (i = [0 : 360/td-1]) [xsc*xp[i], ysc*yp[i]] ]; > > // translate polygon so it is centralised at +/- xy/2 > translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)]) > > //// UNCOMMENT LINE TO TEST > //// CLEAR THE CACHE FIRST > > /////////////////////// MINKOWSKY > //if(off){minkowski(){polygon(p);circle(off);}}else polygon(p); > /////////////////////// OFFSET > //offset(r=off) polygon(p); > > } > > difference() > { > linear_extrude(5) pHeart(xy=78,off=2); > translate([0,0,-.5]) linear_extrude(6) pHeart(xy=78, off=.4); > } > > > > > > > > _______________________________________________ > > OpenSCAD mailing list > > Discuss@lists.openscad.org > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
MK
Marius Kintel
Fri, Nov 25, 2016 3:07 PM

On Nov 25, 2016, at 05:53, nop head nop.head@gmail.com wrote:

I might be wrong but I think OpenSCAD uses the clipper library for offset and presumably CGAL for 2D Minkowski.

We use the clipper library for both offset and 2D minkowski. Perhaps they implement offset using minkowski internally?

-Marius

> On Nov 25, 2016, at 05:53, nop head <nop.head@gmail.com> wrote: > > I might be wrong but I think OpenSCAD uses the clipper library for offset and presumably CGAL for 2D Minkowski. > We use the clipper library for both offset and 2D minkowski. Perhaps they implement offset using minkowski internally? -Marius
NH
nop head
Fri, Nov 25, 2016 3:30 PM

I didn't realise clipper did Minkowski. A quick look at the code reveals
they don't use Minkowski for offset. Minkowski is just the union of a
polygon shifted by each point in a path. Offset is a lot more complex.

On 25 November 2016 at 15:07, Marius Kintel marius@kintel.net wrote:

On Nov 25, 2016, at 05:53, nop head nop.head@gmail.com wrote:

I might be wrong but I think OpenSCAD uses the clipper library for

offset and presumably CGAL for 2D Minkowski.

We use the clipper library for both offset and 2D minkowski. Perhaps they
implement offset using minkowski internally?

-Marius


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

I didn't realise clipper did Minkowski. A quick look at the code reveals they don't use Minkowski for offset. Minkowski is just the union of a polygon shifted by each point in a path. Offset is a lot more complex. On 25 November 2016 at 15:07, Marius Kintel <marius@kintel.net> wrote: > > On Nov 25, 2016, at 05:53, nop head <nop.head@gmail.com> wrote: > > > > I might be wrong but I think OpenSCAD uses the clipper library for > offset and presumably CGAL for 2D Minkowski. > > > We use the clipper library for both offset and 2D minkowski. Perhaps they > implement offset using minkowski internally? > > -Marius > > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
O
otto
Fri, Nov 25, 2016 6:11 PM

I agree.

Otto

On Fri, 25 Nov 2016 10:53:27 +0000
nop head nop.head@gmail.com wrote:

I might be wrong but I think OpenSCAD uses the clipper library for
offset and presumably CGAL for 2D Minkowski.

The artefacts from low div values come from the polygon generation,
not the offsetting, so it is no surprise they look identical.
Provided clipper obeys $fn they should produce the same results as
they are mathematically identical operations. There is no ambiguity
where each vertex should be, so any differences should only be down
to the different number representations.

I am surprised there is little difference in speed but both are very
fast until you get to tens of thousands of vertices.

BTW rather than linear extruding twice and subtracting 3D shapes I
think it is more efficient to subtract the 2D shapes and extrude that.

linear_extrude(5, convexity = 2)
difference() {
pHeart(xy = 78, off = 2);
pHeart(xy = 78, off = 0.4);
}

On 24 November 2016 at 20:29, otto otto@123phase.com wrote:

On Wed, 23 Nov 2016 20:38:02 -0500
Marius Kintel marius@kintel.net wrote:

On Nov 23, 2016, at 09:41, otto otto@123phase.com wrote:

Another way to achieve this is with the 2-D minkowski which is
moderately efficient.

Note that 2D minkowski is equivalent to 2D offset with a radius,
but 2D offset should be considerably faster.

-Marius

Testing the code shows no difference in speed.  The test code is
below.  Make sure to clear the cache!  div should be a power of 2.
Incidentally, as div gets large both versions show they same failure
artifacts.  I think that the offset module is simply a wrapper
around the minkowski.  In this program they seem to behave
identically to the agree that they have the same identical timed
speed and with the same identical artifacts.  Is there a known
algorithm that can calculate the offset faster than a minkowski
algorithm or that doesn't use the minkowski or some equivalent?

Regards
Otto

function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) *
(sqrt(abs(cos(t)))/(sin(t)+1.6))));
$fn=23;
div=512;  //ONLY USE POWERS OF 2

module pHeart(xy,off=0) {

     td = 1/div; // theta delta - the resolution of the curve

     // Calculate x/y co-ords separetely so I can scale

correctly later xp = [ for (t = [0: td : 360-td]) heartRadius(t) *
cos(t) ]; // xco-ordinates on the curve
yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t)
]; // yco-ordinates on the curve

     xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit

expected size
ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit
expected size

     // Generate a vector of points for the polygon to work
     p = [ for (i = [0 : 360/td-1]) [xsc*xp[i], ysc*yp[i]] ];

     // translate polygon so it is centralised at +/- xy/2
     translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)])

 //// UNCOMMENT LINE TO TEST
 //// CLEAR THE CACHE FIRST

 ///////////////////////  MINKOWSKY
 //if(off){minkowski(){polygon(p);circle(off);}}else polygon(p);
 ///////////////////////  OFFSET
 //offset(r=off) polygon(p);

}

difference()
{
linear_extrude(5) pHeart(xy=78,off=2);
translate([0,0,-.5]) linear_extrude(6) pHeart(xy=78, off=.4);
}

I agree. Otto On Fri, 25 Nov 2016 10:53:27 +0000 nop head <nop.head@gmail.com> wrote: > I might be wrong but I think OpenSCAD uses the clipper library for > offset and presumably CGAL for 2D Minkowski. > > The artefacts from low div values come from the polygon generation, > not the offsetting, so it is no surprise they look identical. > Provided clipper obeys $fn they should produce the same results as > they are mathematically identical operations. There is no ambiguity > where each vertex should be, so any differences should only be down > to the different number representations. > > I am surprised there is little difference in speed but both are very > fast until you get to tens of thousands of vertices. > > BTW rather than linear extruding twice and subtracting 3D shapes I > think it is more efficient to subtract the 2D shapes and extrude that. > > linear_extrude(5, convexity = 2) > difference() { > pHeart(xy = 78, off = 2); > pHeart(xy = 78, off = 0.4); > } > > > On 24 November 2016 at 20:29, otto <otto@123phase.com> wrote: > > > > > > > > > > > > > On Wed, 23 Nov 2016 20:38:02 -0500 > > Marius Kintel <marius@kintel.net> wrote: > > > > > > On Nov 23, 2016, at 09:41, otto <otto@123phase.com> wrote: > > > > > > > > Another way to achieve this is with the 2-D minkowski which is > > > > moderately efficient. > > > > > > Note that 2D minkowski is equivalent to 2D offset with a radius, > > > but 2D offset should be considerably faster. > > > > > > -Marius > > > > Testing the code shows no difference in speed. The test code is > > below. Make sure to clear the cache! div should be a power of 2. > > Incidentally, as div gets large both versions show they same failure > > artifacts. I think that the offset module is simply a wrapper > > around the minkowski. In this program they seem to behave > > identically to the agree that they have the same identical timed > > speed and with the same identical artifacts. Is there a known > > algorithm that can calculate the offset faster than a minkowski > > algorithm or that doesn't use the minkowski or some equivalent? > > > > Regards > > Otto > > > > function heartRadius(t) = (1.5 - 1.5* sin(t) + (sin(t) * > > (sqrt(abs(cos(t)))/(sin(t)+1.6)))); > > $fn=23; > > div=512; //ONLY USE POWERS OF 2 > > > > module pHeart(xy,off=0) { > > > > td = 1/div; // theta delta - the resolution of the curve > > > > // Calculate x/y co-ords separetely so I can scale > > correctly later xp = [ for (t = [0: td : 360-td]) heartRadius(t) * > > cos(t) ]; // xco-ordinates on the curve > > yp = [ for (t = [0 : td : 360-td]) heartRadius(t) * sin(t) > > ]; // yco-ordinates on the curve > > > > xsc = xy/(max(xp) - min(xp)); // x scaler to get to fit > > expected size > > ysc = xy/(max(yp) - min(yp)); // y scaler to get to fit > > expected size > > > > // Generate a vector of points for the polygon to work > > p = [ for (i = [0 : 360/td-1]) [xsc*xp[i], ysc*yp[i]] ]; > > > > // translate polygon so it is centralised at +/- xy/2 > > translate([0,ysc*(-max(yp)+(max(yp)-min(yp))/2)]) > > > > //// UNCOMMENT LINE TO TEST > > //// CLEAR THE CACHE FIRST > > > > /////////////////////// MINKOWSKY > > //if(off){minkowski(){polygon(p);circle(off);}}else polygon(p); > > /////////////////////// OFFSET > > //offset(r=off) polygon(p); > > > > } > > > > difference() > > { > > linear_extrude(5) pHeart(xy=78,off=2); > > translate([0,0,-.5]) linear_extrude(6) pHeart(xy=78, off=.4); > > } > > > > > > > > > > > > > > _______________________________________________ > > > OpenSCAD mailing list > > > Discuss@lists.openscad.org > > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > > > > > > _______________________________________________ > > OpenSCAD mailing list > > Discuss@lists.openscad.org > > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org > >