How to get an outline of a 2D object?

classic Classic list List threaded Threaded
35 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

cacb
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


>


_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

Ronaldo
In reply to this post by Parkinbot
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 <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

Troberg
In reply to this post by Ronaldo
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

Parkinbot
In reply to this post by cacb
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

Troberg
In reply to this post by Troberg
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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

nophead
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 <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

Ronaldo
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 <[hidden email]> 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 <[hidden email]> 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
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

cacb
In reply to this post by Troberg
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
















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

eclipse.scad (282 bytes) Download Attachment
eclipse_outline.as (33K) Download Attachment
eclipse_outline.scad (282 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

Troberg
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/

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

cacb
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

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

outline.dxf (9K) Download Attachment
outline.scad (32 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

rickan
In reply to this post by Troberg
Close enough?

Maybe the curves (vs corners) added by the negative offset are unwanted?
Might be suited to a milling machine or router but maybe sharp corners are
wanted to show off very narrow kerf cutter.


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

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

//Fill the holes
module fill(){
  offset(20)
  sign();
}

//Cut
offset(-10) fill();



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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

rickan
If this is close enough, now the problem is finding the minimum offset for
fill().

Setting os=9.5 below does not work.

os=10;

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

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

//Fill the holes
module fill(){
  offset(10 + os)
  sign();
}

//Cut
offset(-os) fill();



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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
tp3
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

tp3
In reply to this post by Ronaldo
On 23.11.20 13:37, Ronaldo Persiano wrote:
> The char "@" for instance cannot be correctly processed

That's a good example. What would a built-in outline() function
do exactly? Using just the outer most polygon would fill only
the inner hole but still leave the tail.

ciao,
  Torsten.



_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
-- Torsten
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

rickan
In reply to this post by Troberg
I have just written a quick and dirty PostScript (PS) program which will
remove the inner paths in a text string. (But the procedures used are not
allowed for all fonts, and there are probably strange fonts for which my
algorithm won't work because it relies on the characters' outer path being
drawn first followed by the inner paths and the bounding boxes of the inner
paths being inside the bounding boxes of the outer paths.)

I converted the result to SVG using ps2svg and imported it into OpenSCAD.

Using this with OpenSCAD text() is not straight forward because PS and
OpenSCAD scale fonts differently, i.e. you can specify the exact same font
in GhostScript and OpenSCAD (at least on my system) and scale them to the
same size and they do not match because PS scales them for line spacing and
OpenSCAD scales them omitting the descenders so that capital letters come
out close to the size specified.  But I have posted a program on this forum
which will calculate a good approximation of the OpenSCAD scale factor in PS
and scale the font in PS accordingly.
<http://forum.openscad.org/3D-keychains-and-cutting-out-the-whitespace-of-text-tp30493p30505.html>  

<http://forum.openscad.org/file/t1112/filtext.png>

The PS file to remove inner paths from a text string, filtext.ps, follows:

/Helvetica findfont 1 scalefont setfont

/cbbox[0 0 0 0]def

/bbinside{ % [bounding box] -- true if inside cbbox
  aload pop
  cbbox 3 get lt{
    cbbox 2 get lt{
      cbbox 1 get gt{
        cbbox 0 get gt{
          true
        }{
          false
        }ifelse
      }{
        pop
        false
      }ifelse
    }{
      pop pop
      false
    }ifelse
  }{
    pop pop pop
    false
  }ifelse
}def

/pathclosed true def
/pathstarted false def
/outerpath[]def

/startpath{
  pathstarted{
    (Warning! redundant moveto encountered.\n)print
  }{
    [3 1 roll
  }ifelse
  /moveto load
  /pathclosed false def
  /pathstarted true def
}def

/extendpath{
  /lineto load
}def

/nocurves{
  (Warning! There should be no curvto ops. use flattenpath.\n)print
}def

/checkpath{
  /closepath load]
  /testpath exch def
  gsave %{
    newpath
    testpath cvx exec /testbox[pathbbox]def testbox bbinside not{
      /outerpath [outerpath aload pop testpath aload pop]def
      /cbbox testbox def
    }if
  grestore %}
  /pathclosed true def
  /pathstarted false def
}def

/fillstring{
  false charpath flattenpath
  {startpath}{extendpath}{nocurves}{checkpath}pathforall
  cleartomark
  newpath
}def

100 dup scale % change to suit. This is 100 72/inch units
1 11 2 div translate % Comment this line to put the text at the origin
.005 setlinewidth
0 0 moveto
(Boobies!) fillstring
outerpath cvx exec
stroke




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

_______________________________________________
OpenSCAD mailing list
[hidden email]
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org
Reply | Threaded
Open this post in threaded view
|

Re: How to get an outline of a 2D object?

mondo
In reply to this post by Troberg
Just my two penn'orth - the result depends on the style of font, and the
characters used. In most cases you will need to make some manual
adjustment, in particular for punctuation, lower case letters such as 
i, j, and any language with accents. If it is a question of making
signs, and you are leaving the backing in place, then no need for the
base-line (square) and If there is the base line, then no need for the
backing.

You could try it with  more 'difficult letters', adjust the size of the
binding line, etc., and view from afar, say -

module sign(){
     text("rnmg@jie423s!ILl71PBRFCG=-_:;",100);
     square([2050,9]);
}

Best wishes,

Ray

On 23/11/2020 11:12, Troberg 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
> [hidden email]
> http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

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