discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

How to get an outline of a 2D object?

CA
Carsten Arnholm
Wed, Nov 18, 2020 12:32 PM

On 18.11.2020 12:53, Parkinbot wrote:

A boundingbox function would probably return me the coordinates of the
diagonal and I could calculate the center and a translation, just like you
do it.

The center of a boundingbox is not guaranteed to be located within its
2d shape, although it will in most cases.

A general solution would be to find the different edge loops and discard
all but the one covering the largest area.

Carsten Arnholm

On 18.11.2020 12:53, Parkinbot wrote: > A boundingbox function would probably return me the coordinates of the > diagonal and I could calculate the center and a translation, just like you > do it. > The center of a boundingbox is not guaranteed to be located within its 2d shape, although it will in most cases. A general solution would be to find the different edge loops and discard all but the one covering the largest area. Carsten Arnholm >
RP
Ronaldo Persiano
Wed, Nov 18, 2020 2:30 PM

For convex outlines, hull() would be enough to get the outline.
It is not difficult to get an approximation of the bounding box center as a
very small square. But the hard issue is that the bounding box center will
not be a "visual center" in general (non-convex-cases). In some cases, the
outline has no visual center. Consider the following polygon for instance:

module polyg()

difference() {

square(20,center=true);

for(x=7*[-1,1], y=7*[-1,1])

   translate([x,y])

     circle(5);

   circle(3);

}

projection()

linear_extrude(height = 1, scale =0)

polyg();

We can relax the "visual center" condition. If P is a list of points such
that all vertices of the outline are visible by at least one point in P,
then fill_holes(P) will compute the correct outline:

module fill_holes2(P)

intersection_for(p=P)

translate(p) {

  projection()

    linear_extrude(1, scale=0.0001)

      translate( -p) children();

scale(.01) hull() children();

}

For example:

P = [ [10,0], [-10,0], [0,10], [0,-10], [0,0] ];

fill_holes2(P) polyg();

However, I can't see a simple way to find a list P like that.

Btw, linear_extrude with scale=0 will produce a non-manifold when the
polygon has holes.

Em qua., 18 de nov. de 2020 às 11:54, Parkinbot rudolf@digitaldocument.de
escreveu:

A boundingbox function would probably return me the coordinates of the
diagonal and I could calculate the center and a translation, just like you
do it.

Of course a boundingbox function can also be implemented to just return the
[dx, dy, dz] extents according to the three axes. But this would be the
worst way to implement it. Usually it is implemented to return a pair of
3D-points or a box object with an origin and the [dx, dy, dz] extents.

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


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

For convex outlines, hull() would be enough to get the outline. It is not difficult to get an approximation of the bounding box center as a very small square. But the hard issue is that the bounding box center will not be a "visual center" in general (non-convex-cases). In some cases, the outline has no visual center. Consider the following polygon for instance: module polyg() difference() { square(20,center=true); for(x=7*[-1,1], y=7*[-1,1]) translate([x,y]) circle(5); circle(3); } projection() linear_extrude(height = 1, scale =0) polyg(); We can relax the "visual center" condition. If P is a list of points such that all vertices of the outline are visible by at least one point in P, then fill_holes(P) will compute the correct outline: module fill_holes2(P) intersection_for(p=P) translate(p) { projection() linear_extrude(1, scale=0.0001) translate( -p) children(); scale(.01) hull() children(); } For example: P = [ [10,0], [-10,0], [0,10], [0,-10], [0,0] ]; fill_holes2(P) polyg(); However, I can't see a simple way to find a list P like that. Btw, linear_extrude with scale=0 will produce a non-manifold when the polygon has holes. Em qua., 18 de nov. de 2020 às 11:54, Parkinbot <rudolf@digitaldocument.de> escreveu: > A boundingbox function would probably return me the coordinates of the > diagonal and I could calculate the center and a translation, just like you > do it. > > Of course a boundingbox function can also be implemented to just return the > [dx, dy, dz] extents according to the three axes. But this would be the > worst way to implement it. Usually it is implemented to return a pair of > 3D-points or a box object with an origin and the [dx, dy, dz] extents. > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
T
Troberg
Wed, Nov 18, 2020 4:24 PM

Ronaldo wrote

Nice designs,

I guess that if you could collect all arc and circle center points in a
list P, fill_holes2(P) would give you the outline you want.

Thanks!

Well, I do the arcs by using offset() to get the rounded shapes, and I do it
in layers (small radius for outside corners, large for inside corners, then
I add some elements (such as the hinges) and put a small radius on the new
inside corners. All this on parametric designs.

While I suppose I could track all this, it's not a task I would enjoy...

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

Ronaldo wrote > Nice designs, > > I guess that if you could collect all arc and circle center points in a > list P, fill_holes2(P) would give you the outline you want. Thanks! Well, I do the arcs by using offset() to get the rounded shapes, and I do it in layers (small radius for outside corners, large for inside corners, then I add some elements (such as the hinges) and put a small radius on the new inside corners. All this on parametric designs. While I suppose I could track all this, it's not a task I would enjoy... -- Sent from: http://forum.openscad.org/
P
Parkinbot
Sat, Nov 21, 2020 10:03 PM

cacb wrote

The center of a boundingbox is not guaranteed to be located within its
2d shape, although it will in most cases.

Ups, yeah, of course you are right. Non-convexity is a mess.

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

cacb wrote > The center of a boundingbox is not guaranteed to be located within its > 2d shape, although it will in most cases. Ups, yeah, of course you are right. Non-convexity is a mess. -- Sent from: http://forum.openscad.org/
T
Troberg
Mon, Nov 23, 2020 11:12 AM

Another example where this would be nice, and where the inside geometry isn't
defined by me, so I can't "reverse engineer" my code to remove the holes. A
very typical laser cutter example:

Say that you are making a sign, with some text, and a baseline to hold the
characters together. So, basically, a union of a square and some text. Very
common laser cutting task.

You want to engrave the letters, but cut the outline of the object (with a
slight offset), but you don't want any holes in it.

I can't reverse engineer the font, a hull() would just make a mess of
everything, using offset to remove holes would destroy the outline as well.
The only way I can figure out to make it work is if there were some kind of
built-in outline() module.

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

Another example where this would be nice, and where the inside geometry isn't defined by me, so I can't "reverse engineer" my code to remove the holes. A very typical laser cutter example: Say that you are making a sign, with some text, and a baseline to hold the characters together. So, basically, a union of a square and some text. Very common laser cutting task. You want to engrave the letters, but cut the outline of the object (with a slight offset), but you don't want any holes in it. I can't reverse engineer the font, a hull() would just make a mess of everything, using offset to remove holes would destroy the outline as well. The only way I can figure out to make it work is if there were some kind of built-in outline() module. -- Sent from: http://forum.openscad.org/
NH
nop head
Mon, Nov 23, 2020 11:25 AM

Can't you just use Ronaldo's  fill_holes2(P) solution? All you have to do
is nominate some positions on the object that together can see all the
vertices of the perimeter. For the item you describe, that would seem not
to be many and they don't need great precision.

On Mon, 23 Nov 2020 at 11:13, Troberg troberg.anders@gmail.com wrote:

Another example where this would be nice, and where the inside geometry
isn't
defined by me, so I can't "reverse engineer" my code to remove the holes. A
very typical laser cutter example:

Say that you are making a sign, with some text, and a baseline to hold the
characters together. So, basically, a union of a square and some text. Very
common laser cutting task.

You want to engrave the letters, but cut the outline of the object (with a
slight offset), but you don't want any holes in it.

I can't reverse engineer the font, a hull() would just make a mess of
everything, using offset to remove holes would destroy the outline as well.
The only way I can figure out to make it work is if there were some kind of
built-in outline() module.

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


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

Can't you just use Ronaldo's fill_holes2(P) solution? All you have to do is nominate some positions on the object that together can see all the vertices of the perimeter. For the item you describe, that would seem not to be many and they don't need great precision. On Mon, 23 Nov 2020 at 11:13, Troberg <troberg.anders@gmail.com> wrote: > Another example where this would be nice, and where the inside geometry > isn't > defined by me, so I can't "reverse engineer" my code to remove the holes. A > very typical laser cutter example: > > Say that you are making a sign, with some text, and a baseline to hold the > characters together. So, basically, a union of a square and some text. Very > common laser cutting task. > > You want to engrave the letters, but cut the outline of the object (with a > slight offset), but you don't want any holes in it. > > I can't reverse engineer the font, a hull() would just make a mess of > everything, using offset to remove holes would destroy the outline as well. > The only way I can figure out to make it work is if there were some kind of > built-in outline() module. > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
RP
Ronaldo Persiano
Mon, Nov 23, 2020 12:37 PM

Unhappily that process fails miserably in some cases. The char "@" for
instance cannot be correctly processed by fill_holes2() with any set of
points. It is hard to distinguish channels from holes in the polygon. I
don't see any general solution with the tools at hand.

A segunda, 23/11/2020, 08:26, nop head nop.head@gmail.com escreveu:

Can't you just use Ronaldo's  fill_holes2(P) solution? All you have to do
is nominate some positions on the object that together can see all the
vertices of the perimeter. For the item you describe, that would seem not
to be many and they don't need great precision.

On Mon, 23 Nov 2020 at 11:13, Troberg troberg.anders@gmail.com wrote:

Another example where this would be nice, and where the inside geometry
isn't
defined by me, so I can't "reverse engineer" my code to remove the holes.
A
very typical laser cutter example:

Say that you are making a sign, with some text, and a baseline to hold the
characters together. So, basically, a union of a square and some text.
Very
common laser cutting task.

You want to engrave the letters, but cut the outline of the object (with a
slight offset), but you don't want any holes in it.

I can't reverse engineer the font, a hull() would just make a mess of
everything, using offset to remove holes would destroy the outline as
well.
The only way I can figure out to make it work is if there were some kind
of
built-in outline() module.

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


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

Unhappily that process fails miserably in some cases. The char "@" for instance cannot be correctly processed by fill_holes2() with any set of points. It is hard to distinguish channels from holes in the polygon. I don't see any general solution with the tools at hand. A segunda, 23/11/2020, 08:26, nop head <nop.head@gmail.com> escreveu: > Can't you just use Ronaldo's fill_holes2(P) solution? All you have to do > is nominate some positions on the object that together can see all the > vertices of the perimeter. For the item you describe, that would seem not > to be many and they don't need great precision. > > On Mon, 23 Nov 2020 at 11:13, Troberg <troberg.anders@gmail.com> wrote: > >> Another example where this would be nice, and where the inside geometry >> isn't >> defined by me, so I can't "reverse engineer" my code to remove the holes. >> A >> very typical laser cutter example: >> >> Say that you are making a sign, with some text, and a baseline to hold the >> characters together. So, basically, a union of a square and some text. >> Very >> common laser cutting task. >> >> You want to engrave the letters, but cut the outline of the object (with a >> slight offset), but you don't want any holes in it. >> >> I can't reverse engineer the font, a hull() would just make a mess of >> everything, using offset to remove holes would destroy the outline as >> well. >> The only way I can figure out to make it work is if there were some kind >> of >> built-in outline() module. >> >> >> >> -- >> Sent from: http://forum.openscad.org/ >> >> _______________________________________________ >> 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 >
CA
Carsten Arnholm
Mon, Nov 23, 2020 1:30 PM

On 23.11.2020 12:12, Troberg wrote:

Say that you are making a sign, with some text, and a baseline to hold the
characters together. So, basically, a union of a square and some text. Very
common laser cutting task.

You want to engrave the letters, but cut the outline of the object (with a
slight offset), but you don't want any holes in it.

I don't think you can solve it 100% in OpenSCAD, but let me show you a
work-around that starts and ends with OpenSCAD. Imagine this is your
code for a sign:

eclipse.scad

$fa=0.01;
difference() {
circle(r=100);
translate([0,-40])
circle(r=70);
translate([0,55])
scale(3)
text("eclipse"
,halign="center"
,valign="center");
}

It is a concave outline with some text engraved, and you want to remove
the "eclipse" text but keep the rest.

If this was your code you could just remove the text, but let us assume
it was someone else's code, or maybe a DXF or SVG file you got from
someone and imported, and you still wanted to remove the "eclipse" text
holes. Also assume it is too complex to fix manually, or that you have
many such cases and want an automatic process. In any case, you can fix
it using a couple of command line steps:

First, run OpenSCAD and create a DXF file from the model. The DXF will
be used for extracting the final outline:

$ openscad eclipse.scad --o=eclipse_outline.dxf

This DXF contains everything, including the holes.

Second, create a DXF with only the outline

Run AngelCADs "dxfread" and create a function from the DXF.
(the installation directory is here assumed to be in system PATH)

$ dxfread eclipse_outline.dxf -asfunc

This creates "eclipse_outline.as" containing a function called
"eclipse_outline_dxf()", returning a 2d shape with the complete DXF file
geometry, including the holes. Open the file in AngelCAD and add the
following somewhere in the file (outside of the function body):

void main()
{
shape2d@ outline = fill2d(eclipse_outline_dxf());
outline.write_xcsg(GetInputFullPath());
}

Notice the use of "fill2d", it is key. It removes the holes, but keeps
the outline. Now build the file (F6) (it is also possible from command
line). If dxf is selected as an output format, you get a new DXF file in
a subfolder:

xcsg/eclipse_outline.dxf

This contains the outline only.

Third, view the outline DXF in OpenSCAD

import("xcsg/eclipse_outline.dxf");

Carsten Arnholm

On 23.11.2020 12:12, Troberg wrote: > Say that you are making a sign, with some text, and a baseline to hold the > characters together. So, basically, a union of a square and some text. Very > common laser cutting task. > > You want to engrave the letters, but cut the outline of the object (with a > slight offset), but you don't want any holes in it. I don't think you can solve it 100% in OpenSCAD, but let me show you a work-around that starts and ends with OpenSCAD. Imagine this is your code for a sign: eclipse.scad ------------ $fa=0.01; difference() { circle(r=100); translate([0,-40]) circle(r=70); translate([0,55]) scale(3) text("eclipse" ,halign="center" ,valign="center"); } It is a concave outline with some text engraved, and you want to remove the "eclipse" text but keep the rest. If this was your code you could just remove the text, but let us assume it was someone else's code, or maybe a DXF or SVG file you got from someone and imported, and you still wanted to remove the "eclipse" text holes. Also assume it is too complex to fix manually, or that you have many such cases and want an automatic process. In any case, you can fix it using a couple of command line steps: First, run OpenSCAD and create a DXF file from the model. The DXF will be used for extracting the final outline: $ openscad eclipse.scad --o=eclipse_outline.dxf This DXF contains everything, including the holes. Second, create a DXF with only the outline ------------------------------------------ Run AngelCADs "dxfread" and create a function from the DXF. (the installation directory is here assumed to be in system PATH) $ dxfread eclipse_outline.dxf -asfunc This creates "eclipse_outline.as" containing a function called "eclipse_outline_dxf()", returning a 2d shape with the complete DXF file geometry, including the holes. Open the file in AngelCAD and add the following somewhere in the file (outside of the function body): void main() { shape2d@ outline = fill2d(eclipse_outline_dxf()); outline.write_xcsg(GetInputFullPath()); } Notice the use of "fill2d", it is key. It removes the holes, but keeps the outline. Now build the file (F6) (it is also possible from command line). If dxf is selected as an output format, you get a new DXF file in a subfolder: xcsg/eclipse_outline.dxf This contains the outline only. Third, view the outline DXF in OpenSCAD --------------------------------------- import("xcsg/eclipse_outline.dxf"); Carsten Arnholm
T
Troberg
Mon, Nov 23, 2020 1:47 PM

I'm thinking more like this:

module sign(){
text("Boobies!",100);
square([520,5]);
}

//engrave
color([0,0,0])
translate([0,0,1])
sign();

//cut, but without the holes
offset(10)
sign();

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

I'm thinking more like this: module sign(){ text("Boobies!",100); square([520,5]); } //engrave color([0,0,0]) translate([0,0,1]) sign(); //cut, but without the holes offset(10) sign(); -- Sent from: http://forum.openscad.org/
CA
Carsten Arnholm
Mon, Nov 23, 2020 2:09 PM

On 23.11.2020 14:47, Troberg wrote:

I'm thinking more like this:

module sign(){
text("Boobies!",100);
square([520,5]);
}

//engrave
color([0,0,0])
translate([0,0,1])
sign();

//cut, but without the holes
offset(10)
sign();

Sure, no problem.

Carsten Arnholm

On 23.11.2020 14:47, Troberg wrote: > I'm thinking more like this: > > module sign(){ > text("Boobies!",100); > square([520,5]); > } > > //engrave > color([0,0,0]) > translate([0,0,1]) > sign(); > > //cut, but without the holes > offset(10) > sign(); Sure, no problem. Carsten Arnholm