discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Polygon Offset Function

N
Neon22
Sat, Apr 30, 2016 11:16 PM

In my experience:

  • you move the vertices along the calculated normal,
  • monitoring adjacent edge lengths,
  • as they approach zero (or change direction indicating reversal) you remove
    them.

In the more general case (where these two edge lists may want to maintain
connectivity),

  • this implies existence of a lofting operator that can connect verts in two
    edgelists which don't have the same number of vertices.
    Something that has to be done by examining how close vertices are to each
    other (rather than just counting) and finding points of correspondance to
    connect.
    But we'd only need that if we were going to have lofting in the future.

--
View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17261.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

In my experience: - you move the vertices along the calculated normal, - monitoring adjacent edge lengths, - as they approach zero (or change direction indicating reversal) you remove them. In the more general case (where these two edge lists may want to maintain connectivity), - this implies existence of a lofting operator that can connect verts in two edgelists which don't have the same number of vertices. Something that has to be done by examining how close vertices are to each other (rather than just counting) and finding points of correspondance to connect. But we'd only need that if we were going to have lofting in the future. -- View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17261.html Sent from the OpenSCAD mailing list archive at Nabble.com.
J
Jamie_K
Sun, May 1, 2016 4:05 AM

After some false starts, I found a method that is similar in spirit to what
Neon22 had mentioned which also ties in to the angle bisectors.  For my
purposes, because I intend to apply offsets to polygons that are not derived
from functions, I'm constraining myself and not assuming a differentiable
function.

Each vertex, as it is offset, moves along the angle bisector between the
adjacent edges.  Each edge then shrinks or expands and there exists an
offset (positive or negative) at which the edge vanishes to a point.  Beyond
that offset, the edge would be flipped, and needs to be removed with the two
adjacent edges connected to each other.

This can be accomplished by calculating for each edge an 'offset limit'
which is the offset (positive or negative) at which the edge will vanish.
For edges where adjacent edges are parallel (and angle bisectors are
parallel) the offset limit is nan, which is okay as long as we handle it
properly.

Then for a given offset value, we can remove those edges that would be
flipped.  To fill in the gaps this program transforms edges into linear
equations and then reconstructs the vertices by solving the intersections.

One application of this operation might not be complete because removing an
edge will change the angle bisectors and potential offset limit for segments
that are adjacent to the removed segments, meaning that some edges may be
deemed "okay" (within offset limit) but after removing the flipped edges,
the previously okay edges can produce self-intersections.

For this reason the removal of edges is applied repeatedly until the number
of edges stops decreasing.

Technically I think it would be more correct to incrementally remove the
edges in order of increasing offset limit, because the opposite could
happen: an edge could be removed even though removing an adjacent edge would
change the angles and prevent flipping.  But for most cases I think this is
not needed.

Below is the code (also requires code from previous post) and the results.
Also I should emphasize, if it's not already clear, this does not clean up
self intersections in general, it only cleans up self intersections that
result from high 'curvature' which causes edges to flip.  An hourglass shape
for example will self-intersect when offset and this approach will do
nothing to fix it.

-Jamie

http://forum.openscad.org/file/n17263/airfoil_offset_clean.png

--
View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17263.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

After some false starts, I found a method that is similar in spirit to what Neon22 had mentioned which also ties in to the angle bisectors. For my purposes, because I intend to apply offsets to polygons that are not derived from functions, I'm constraining myself and not assuming a differentiable function. Each vertex, as it is offset, moves along the angle bisector between the adjacent edges. Each edge then shrinks or expands and there exists an offset (positive or negative) at which the edge vanishes to a point. Beyond that offset, the edge would be flipped, and needs to be removed with the two adjacent edges connected to each other. This can be accomplished by calculating for each edge an 'offset limit' which is the offset (positive or negative) at which the edge will vanish. For edges where adjacent edges are parallel (and angle bisectors are parallel) the offset limit is nan, which is okay as long as we handle it properly. Then for a given offset value, we can remove those edges that would be flipped. To fill in the gaps this program transforms edges into linear equations and then reconstructs the vertices by solving the intersections. One application of this operation might not be complete because removing an edge will change the angle bisectors and potential offset limit for segments that are adjacent to the removed segments, meaning that some edges may be deemed "okay" (within offset limit) but after removing the flipped edges, the previously okay edges can produce self-intersections. For this reason the removal of edges is applied repeatedly until the number of edges stops decreasing. Technically I think it would be more correct to incrementally remove the edges in order of increasing offset limit, because the opposite could happen: an edge could be removed even though removing an adjacent edge would change the angles and prevent flipping. But for most cases I think this is not needed. Below is the code (also requires code from previous post) and the results. Also I should emphasize, if it's not already clear, this does not clean up self intersections in general, it only cleans up self intersections that result from high 'curvature' which causes edges to flip. An hourglass shape for example will self-intersect when offset and this approach will do nothing to fix it. -Jamie <http://forum.openscad.org/file/n17263/airfoil_offset_clean.png> -- View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17263.html Sent from the OpenSCAD mailing list archive at Nabble.com.
P
Parkinbot
Sun, May 1, 2016 11:03 PM

Nice, but O(n²) as expected.

--
View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17268.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

Nice, but O(n²) as expected. -- View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17268.html Sent from the OpenSCAD mailing list archive at Nabble.com.
R
Ronaldo
Mon, May 2, 2016 12:39 AM

@Jamie K. Your approach is nice for convex polygons but it seems to fail at
sharp concave vertices.

// spiral
N=0.98;
p = [ for(a=[0:10:360*N]) [cos(a), sin(a)]*a/20 ];
polygon(p);
color("red") translate([0, 0, 0.1])
polygon(offset_poly_clean(p, -0.5));

// star
q = [ for(a=[0:d:359]) 10*[cos(a), sin(a)] * (a%12 ==0 ? 1: 0.5) ];
translate([30,0,0]) {
polygon(q);
color("red") translate([0, 0, 0.1])
polygon(offset_poly_clean(q, -0.5));
}

http://forum.openscad.org/file/n17270/Offset.png

--
View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17270.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

@Jamie K. Your approach is nice for convex polygons but it seems to fail at sharp concave vertices. > // spiral > N=0.98; > p = [ for(a=[0:10:360*N]) [cos(a), sin(a)]*a/20 ]; > polygon(p); > color("red") translate([0, 0, 0.1]) > polygon(offset_poly_clean(p, -0.5)); > > // star > q = [ for(a=[0:d:359]) 10*[cos(a), sin(a)] * (a%12 ==0 ? 1: 0.5) ]; > translate([30,0,0]) { > polygon(q); > color("red") translate([0, 0, 0.1]) > polygon(offset_poly_clean(q, -0.5)); > } <http://forum.openscad.org/file/n17270/Offset.png> -- View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17270.html Sent from the OpenSCAD mailing list archive at Nabble.com.
P
Parkinbot
Mon, May 2, 2016 1:03 AM

You mean this one?

// spiral
N=1.1;
p = [ for(a=[20:1:360*N]) [cos(a), sin(a)]*a/20 ];
polygon(p);
color("red") translate([0, 0, 0.1])
polygon(offset_poly_clean(p, -0.5));
http://forum.openscad.org/file/n17272/neu.png

--
View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17272.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

You mean this one? // spiral N=1.1; p = [ for(a=[20:1:360*N]) [cos(a), sin(a)]*a/20 ]; polygon(p); color("red") translate([0, 0, 0.1]) polygon(offset_poly_clean(p, -0.5)); <http://forum.openscad.org/file/n17272/neu.png> -- View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17272.html Sent from the OpenSCAD mailing list archive at Nabble.com.
RP
Ronaldo Persiano
Mon, May 2, 2016 11:54 AM

Not exactly. The negative offset curves should be rounded at concave
vertices and positive offset curves should be rounded at convex vertices.
So, even for convex polygons the method is incorrect with positive offsets
although it may be valuable as an approximation to some applications.

2016-05-01 22:03 GMT-03:00 Parkinbot rudolf@parkinbot.com:

You mean this one?

// spiral
N=1.1;
p = [ for(a=[20:1:360*N]) [cos(a), sin(a)]*a/20 ];
polygon(p);
color("red") translate([0, 0, 0.1])
polygon(offset_poly_clean(p, -0.5));
http://forum.openscad.org/file/n17272/neu.png

--
View this message in context:
http://forum.openscad.org/Polygon-Offset-Function-tp17186p17272.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

Not exactly. The negative offset curves should be rounded at concave vertices and positive offset curves should be rounded at convex vertices. So, even for convex polygons the method is incorrect with positive offsets although it may be valuable as an approximation to some applications. 2016-05-01 22:03 GMT-03:00 Parkinbot <rudolf@parkinbot.com>: > You mean this one? > > // spiral > N=1.1; > p = [ for(a=[20:1:360*N]) [cos(a), sin(a)]*a/20 ]; > polygon(p); > color("red") translate([0, 0, 0.1]) > polygon(offset_poly_clean(p, -0.5)); > <http://forum.openscad.org/file/n17272/neu.png> > > > > -- > View this message in context: > http://forum.openscad.org/Polygon-Offset-Function-tp17186p17272.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 >
P
Parkinbot
Mon, May 2, 2016 1:30 PM

There is no 'natural' semantics for it. This one is a first and well done
step to implement stuff like that. Look at  offset
https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Transformations#offset
.
It always depends what you want to do. I guess it is not very difficult to
add an extra cycle cutting down or even rounding spiky corners. In this case
you have to deal with granularity. Another theme would be: how to do an
offset keeping the vertex count unchanged. And for an organic sweep using an
interpolation scheme the code has to be fast. The more general an algorithm
gets, the slower it is.

But isn't it too much code (and time) already spent for the problem of the
theme starter? Especially as he is not willing to post any code himself. The
next questions will be: But how can I control wall thickness locally? And:
How to inset a 3D shape (of course with local control)?

Again: OpenSCAD is not a language to implement sophisticated algorithms
doing look-ahead and look-aside and all that stuff. The one and only
important feature request would be an API allowing for function callout.

In my eyes it doesn't make much sense to print a hollow airfoil with spars
and ribs anyway. Z-layers tend to break apart and that is the best way to
FDM print it. And why use ribs and spars then if you can use infill?

--
View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17277.html
Sent from the OpenSCAD mailing list archive at Nabble.com.

There is no 'natural' semantics for it. This one is a first and well done step to implement stuff like that. Look at offset <https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Transformations#offset> . It always depends what you want to do. I guess it is not very difficult to add an extra cycle cutting down or even rounding spiky corners. In this case you have to deal with granularity. Another theme would be: how to do an offset keeping the vertex count unchanged. And for an organic sweep using an interpolation scheme the code has to be fast. The more general an algorithm gets, the slower it is. But isn't it too much code (and time) already spent for the problem of the theme starter? Especially as he is not willing to post any code himself. The next questions will be: But how can I control wall thickness locally? And: How to inset a 3D shape (of course with local control)? Again: OpenSCAD is not a language to implement sophisticated algorithms doing look-ahead and look-aside and all that stuff. The one and only important feature request would be an API allowing for function callout. In my eyes it doesn't make much sense to print a hollow airfoil with spars and ribs anyway. Z-layers tend to break apart and that is the best way to FDM print it. And why use ribs and spars then if you can use infill? -- View this message in context: http://forum.openscad.org/Polygon-Offset-Function-tp17186p17277.html Sent from the OpenSCAD mailing list archive at Nabble.com.