discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

How to get an outline of a 2D object?

T
Troberg
Sat, Nov 14, 2020 7:35 PM

I have a problem. I have 2D objects, which might be concave, and which has
holes in them. These objects are pretty complex, done in several stages, and
the holes are made in a pretty early part of the process, and the holes may
(or may not) also affect the shape of the outline.

What I want is to get just the outer contour of the object, without the
holes contained fully within, to create masks for other stages in the
production.

If I knew the objects were convex, it wouldn't be a problem, then hull()
would work, but I cannot rely on them to be convex (in fact, they most
certainly aren't).

If the objects were simple, I could do it by union() with some "cover
objects", but they aren't.

If I could do the holes last, it would (partly, but not guaranteed) help,
but I can't as I have other later stages which requires them to be there.

Likewise, bouncing an offset out and back won't work, as it'll affect
corners.

So, any idea on how one could do an outline() module?

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

I have a problem. I have 2D objects, which might be concave, and which has holes in them. These objects are pretty complex, done in several stages, and the holes are made in a pretty early part of the process, and the holes may (or may not) also affect the shape of the outline. What I want is to get just the outer contour of the object, without the holes contained fully within, to create masks for other stages in the production. If I knew the objects were convex, it wouldn't be a problem, then hull() would work, but I cannot rely on them to be convex (in fact, they most certainly aren't). If the objects were simple, I could do it by union() with some "cover objects", but they aren't. If I could do the holes last, it would (partly, but not guaranteed) help, but I can't as I have other later stages which requires them to be there. Likewise, bouncing an offset out and back won't work, as it'll affect corners. So, any idea on how one could do an outline() module? -- Sent from: http://forum.openscad.org/
WF
William F. Adams
Sat, Nov 14, 2020 7:49 PM

Position the object and then do projection()?
William

Position the object and then do projection()? William
T
Troberg
Sat, Nov 14, 2020 9:06 PM

Wouldn't projection() just give me the same 2D object as I had, with the same
holes in it?

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

Wouldn't projection() just give me the same 2D object as I had, with the same holes in it? -- Sent from: http://forum.openscad.org/
A
adrianv
Sat, Nov 14, 2020 9:14 PM

I don't know if this would be practical for your situation, but BOSL2 has
some functions for doing boolean operations on 2d objects expressed as point
lists.  I haven't really experimented with that code much, but I believe if
you were to construct your object with that code the final output would be
the outline you desire plus a list of (entirely internal and disjoint) holes
that need to be subtracted.

Simple example below shows some boolean operations to make a 2d object.
Full 2d object on the left, and then just the outline object on the right.

include<BOSL2/std.scad>

$fn=32;

obj1 = circle(5);
obj2 = apply(move([1,2]), circle(1));
obj3 = apply(move([2.5,-4]), square(3));
obj4 = apply(move([-3,-3.1]), circle(2));
obj5 = apply(move([-2,-2.5]), square(2));

obj = difference([ [obj1],[obj2], [obj3], [obj4], [obj5]]);

region(obj);      // Display compound object

right(12)
polygon(obj[0]);  // obj[0] is the desired outline

http://forum.openscad.org/file/t2477/geom.png

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

I don't know if this would be practical for your situation, but BOSL2 has some functions for doing boolean operations on 2d objects expressed as point lists. I haven't really experimented with that code much, but I believe if you were to construct your object with that code the final output would be the outline you desire plus a list of (entirely internal and disjoint) holes that need to be subtracted. Simple example below shows some boolean operations to make a 2d object. Full 2d object on the left, and then just the outline object on the right. include<BOSL2/std.scad> $fn=32; obj1 = circle(5); obj2 = apply(move([1,2]), circle(1)); obj3 = apply(move([2.5,-4]), square(3)); obj4 = apply(move([-3,-3.1]), circle(2)); obj5 = apply(move([-2,-2.5]), square(2)); obj = difference([ [obj1],[obj2], [obj3], [obj4], [obj5]]); region(obj); // Display compound object right(12) polygon(obj[0]); // obj[0] is the desired outline <http://forum.openscad.org/file/t2477/geom.png> -- Sent from: http://forum.openscad.org/
T
Troberg
Sat, Nov 14, 2020 10:22 PM

adrianv wrote

I don't know if this would be practical for your situation, but BOSL2 has
some functions for doing boolean operations on 2d objects expressed as
point
lists.

Sorry, wouldn't be practical, I use a lot of offsets and stuff to get
rounded shapes, so it would be hard to get a point list.

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

adrianv wrote > I don't know if this would be practical for your situation, but BOSL2 has > some functions for doing boolean operations on 2d objects expressed as > point > lists. Sorry, wouldn't be practical, I use a lot of offsets and stuff to get rounded shapes, so it would be hard to get a point list. -- Sent from: http://forum.openscad.org/
A
adrianv
Sat, Nov 14, 2020 10:40 PM

Not sure why this is a problem: an offset() function is available.  (There
are also other ways to make rounded shapes that are more direct and more
flexible than offset.)

include<BOSL2/std.scad>

$fn=32;

obj1 = circle(5);
obj2 = apply(move([1,2]), circle(1));
obj3 = offset(apply(move([2,-4]), square([2,3])), r=.5, closed=true);
obj4 = apply(move([-3,-3.1]), circle(2));
obj5 = offset(apply(move([-2,-2.5]), square(2)),r=.5,closed=true);

obj = difference([ [obj1],[obj2], [obj3], [obj4], [obj5]]);

region(obj);      // Display compound object

right(12)
polygon(obj[0]);  // obj[0] is the desired outline

http://forum.openscad.org/file/t2477/geom2.png

Troberg wrote

adrianv wrote

I don't know if this would be practical for your situation, but BOSL2 has
some functions for doing boolean operations on 2d objects expressed as
point
lists.

Sorry, wouldn't be practical, I use a lot of offsets and stuff to get
rounded shapes, so it would be hard to get a point list.

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


OpenSCAD mailing list

Discuss@.openscad

Not sure why this is a problem: an offset() function is available. (There are also other ways to make rounded shapes that are more direct and more flexible than offset.) include<BOSL2/std.scad> $fn=32; obj1 = circle(5); obj2 = apply(move([1,2]), circle(1)); obj3 = offset(apply(move([2,-4]), square([2,3])), r=.5, closed=true); obj4 = apply(move([-3,-3.1]), circle(2)); obj5 = offset(apply(move([-2,-2.5]), square(2)),r=.5,closed=true); obj = difference([ [obj1],[obj2], [obj3], [obj4], [obj5]]); region(obj); // Display compound object right(12) polygon(obj[0]); // obj[0] is the desired outline <http://forum.openscad.org/file/t2477/geom2.png> Troberg wrote > adrianv wrote >> I don't know if this would be practical for your situation, but BOSL2 has >> some functions for doing boolean operations on 2d objects expressed as >> point >> lists. > > Sorry, wouldn't be practical, I use a lot of offsets and stuff to get > rounded shapes, so it would be hard to get a point list. > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@.openscad > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org -- Sent from: http://forum.openscad.org/
S
shadowwynd
Sun, Nov 15, 2020 1:00 AM

Normally, when I have this problem, I open the file in Inkscape, Ctrl+Shift+K
to break paths apart, then just grab the outside shape.  But to do this in
OpenSCAD:

Here is a simple proof of concept using offset and no external libraries.

In this case there is an interplay between the $fn and the "interior"
variable; with $fn high (like 200) interior can be between 10 and 20 (on
this example) without the outline of the external shape varying.  If $fn was
low... for example $fn=40, then you would start getting artifacts on some of
the outer curves.  But this technique works well enough for certain shapes.


$fn=200;
interior = 20;

module shape()
{
// Make a Complex Shape
difference()
{
square (100);
translate ([50, 50, 0]) circle (10);
translate ([100, 100, 0]) circle (20);
translate ([30, 70, 0]) circle (20, $fn=3);
translate ([0, 0, 0]) circle (40);
translate ([80, -1, ]) square (20);
translate ([80, 80, 0]) circle (5)
translate ([85, 40, 0]) circle (10);
}
translate ([80,20,0]) circle (20);
}

//Create the Outline
color ("blue") offset(r=-interior) offset (r=interior) shape();

//Original Shape
color ("yellow") translate ([0, 0, 10]) shape();

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

Normally, when I have this problem, I open the file in Inkscape, Ctrl+Shift+K to break paths apart, then just grab the outside shape. But to do this in OpenSCAD: Here is a simple proof of concept using offset and no external libraries. In this case there is an interplay between the $fn and the "interior" variable; with $fn high (like 200) interior can be between 10 and 20 (on this example) without the outline of the external shape varying. If $fn was low... for example $fn=40, then you would start getting artifacts on some of the outer curves. But this technique works well enough for certain shapes. ------------------------ $fn=200; interior = 20; module shape() { // Make a Complex Shape difference() { square (100); translate ([50, 50, 0]) circle (10); translate ([100, 100, 0]) circle (20); translate ([30, 70, 0]) circle (20, $fn=3); translate ([0, 0, 0]) circle (40); translate ([80, -1, ]) square (20); translate ([80, 80, 0]) circle (5) translate ([85, 40, 0]) circle (10); } translate ([80,20,0]) circle (20); } //Create the Outline color ("blue") offset(r=-interior) offset (r=interior) shape(); //Original Shape color ("yellow") translate ([0, 0, 10]) shape(); -- Sent from: http://forum.openscad.org/
T
Troberg
Sun, Nov 15, 2020 7:31 AM

adrianv wrote

Not sure why this is a problem: an offset() function is available.
(There
are also other ways to make rounded shapes that are more direct and more
flexible than offset.)

Well, it's not just offset(), consider it a big heap of operations, applied
in a specific order. For the purpose of this discussion, the holes may just
as well be random in shape and position.

Also, even if I could duplicate all the functionality of the ordinary
OpenSCAD syntax, I'd prefer not to. It's a huge code library, I don't want
to rewrite it too much, I still want to be able to use all the helper
modules I've written, so I'd prefer to, if at all possible, to work with
OpenSCAD, rather than against it.

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

adrianv wrote > Not sure why this is a problem: an offset() function is available. > (There > are also other ways to make rounded shapes that are more direct and more > flexible than offset.) Well, it's not just offset(), consider it a big heap of operations, applied in a specific order. For the purpose of this discussion, the holes may just as well be random in shape and position. Also, even if I could duplicate all the functionality of the ordinary OpenSCAD syntax, I'd prefer not to. It's a huge code library, I don't want to rewrite it too much, I still want to be able to use all the helper modules I've written, so I'd prefer to, if at all possible, to work with OpenSCAD, rather than against it. -- Sent from: http://forum.openscad.org/
T
Troberg
Sun, Nov 15, 2020 7:52 AM

shadowwynd wrote

Normally, when I have this problem, I export the file as DXF/SVG, open the
file in Inkscape, Ctrl+Shift+K
to break paths apart, then just grab the outside shape.  But to do this in
OpenSCAD:

Here is a simple proof of concept using offset and no external libraries.

In this case there is an interplay between the $fn and the "interior"
variable; with $fn high (like 200) interior can be between 10 and 20 (on
this example) without the outline of the external shape varying.  If $fn
was
low... for example $fn=40, then you would start getting artifacts on some
of
the outer curves.  But this technique works well enough for certain
shapes.


$fn=200;
interior = 20;

module shape()
{
// Make a Complex Shape
difference()
{
square (100);
translate ([50, 50, 0]) circle (10);
translate ([100, 100, 0]) circle (20);
translate ([30, 70, 0]) circle (20, $fn=3);
translate ([0, 0, 0]) circle (40);
translate ([80, -1, ]) square (20);
translate ([80, 80, 0]) circle (5)
translate ([85, 40, 0]) circle (10);

             // Not perfect - uncomment the line below to break it
             //translate ([80, 40,0]) square ([40, 10]);
}
translate ([80,20,0]) circle (20);

}

//Create the Outline
color ("blue") offset(r=-interior) offset (r=interior) shape();

//Original Shape
color ("yellow") translate ([0, 0, 10]) shape();

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


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

Yep, that's about as close as I got to a generic solution, but, in my case,
I have "dents" and holes ranging from 400 mm down to 11 mm, of various
shapes, so it's hard to find a setting which works for all.

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

shadowwynd wrote > Normally, when I have this problem, I export the file as DXF/SVG, open the > file in Inkscape, Ctrl+Shift+K > to break paths apart, then just grab the outside shape. But to do this in > OpenSCAD: > > Here is a simple proof of concept using offset and no external libraries. > > In this case there is an interplay between the $fn and the "interior" > variable; with $fn high (like 200) interior can be between 10 and 20 (on > this example) without the outline of the external shape varying. If $fn > was > low... for example $fn=40, then you would start getting artifacts on some > of > the outer curves. But this technique works well enough for certain > shapes. > > ------------------------ > > $fn=200; > interior = 20; > > module shape() > { > // Make a Complex Shape > difference() > { > square (100); > translate ([50, 50, 0]) circle (10); > translate ([100, 100, 0]) circle (20); > translate ([30, 70, 0]) circle (20, $fn=3); > translate ([0, 0, 0]) circle (40); > translate ([80, -1, ]) square (20); > translate ([80, 80, 0]) circle (5) > translate ([85, 40, 0]) circle (10); > > // Not perfect - uncomment the line below to break it > //translate ([80, 40,0]) square ([40, 10]); > } > translate ([80,20,0]) circle (20); > } > > //Create the Outline > color ("blue") offset(r=-interior) offset (r=interior) shape(); > > //Original Shape > color ("yellow") translate ([0, 0, 10]) shape(); > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org Yep, that's about as close as I got to a generic solution, but, in my case, I have "dents" and holes ranging from 400 mm down to 11 mm, of various shapes, so it's hard to find a setting which works for all. -- Sent from: http://forum.openscad.org/
A
arnholm@arnholm.org
Sun, Nov 15, 2020 9:01 AM

On 2020-11-14 20:35, Troberg wrote:

I have a problem. I have 2D objects, which might be concave, and which
has
holes in them. These objects are pretty complex, done in several
stages, and
the holes are made in a pretty early part of the process, and the holes
may
(or may not) also affect the shape of the outline.

What I want is to get just the outer contour of the object, without the
holes contained fully within, to create masks for other stages in the
production.

I don't think there is an automatic way to do it in OpenSCAD, but
'fill2d' in AngelCAD does exactly this, it fills the holes in any 2d
shape.

https://arnholm.github.io/angelcad-docs/docs/classfill2d.html

Carsten Arnholm

On 2020-11-14 20:35, Troberg wrote: > I have a problem. I have 2D objects, which might be concave, and which > has > holes in them. These objects are pretty complex, done in several > stages, and > the holes are made in a pretty early part of the process, and the holes > may > (or may not) also affect the shape of the outline. > > What I want is to get just the outer contour of the object, without the > holes contained fully within, to create masks for other stages in the > production. I don't think there is an automatic way to do it in OpenSCAD, but 'fill2d' in AngelCAD does exactly this, it fills the holes in any 2d shape. https://arnholm.github.io/angelcad-docs/docs/classfill2d.html Carsten Arnholm