Highlighted

## JSFL: how to get separate bounding boxes for shapes in merge drawing mode

Explorer ,
Jul 15, 2019

Copy link to clipboard

Copied

I'm writing a script for hole-detection in geometries that also tells which geometry the hole is in. Once it recognizes a Contour as a hole, it scans all elements using bounding boxes to determine where the hole is. Everything is alright as long as I use object drawing mode (since it registers shapes as separate elements) but when the shapes are drawn in merge drawing mode they are all registered as one element, so I end up with just one huge bounding box containing all these shapes. Does anyone one know if and how the information about the bounding box of a single shape in merge mode can be retrieved? I believe that these information are stored somewhere (since the Free Transform Tool detects the bounding box of the geometry by selecting it for example).

EDIT: actually even if two or more shapes in merge mode are combined in one drawing object the resultant bounding box is the one containing them all. So the question would be: how can I get the bounding box of a single Contour object?

Participant
| Participant

Hi,

If I understand your question correctly, you need to detect the bounding box of each part of the "shape". In this case, you may to iterate through all contours, to detect all separate parts using the IDs of the vertices,  and then, for each detected closed bezier polygon, you may use one of the known algorithms. For example, De Casteljau's one:

`function getCurveBounds(ax, ay, bx, by, cx, cy, dx, dy){        var px, py, qx, qy, rx, ry, sx, sy, tx, ty,            tobx, toby, tocx, tocy, todx, tody, toqx, toqy,            torx, tory, totx, toty;        var x, y, minx, miny, maxx, maxy;        minx = miny = Number.POSITIVE_INFINITY;        maxx = maxy = Number.NEGATIVE_INFINITY;        tobx = bx - ax;  toby = by - ay;  // directions        tocx = cx - bx;  tocy = cy - by;        todx = dx - cx;  tody = dy - cy;        var step = 1/40;      // precision        for(var d=0; d<1.001; d+=step)        {            px = ax +d*tobx;  py = ay +d*toby;            qx = bx +d*tocx;  qy = by +d*tocy;            rx = cx +d*todx;  ry = cy +d*tody;            toqx = qx - px;      toqy = qy - py;            torx = rx - qx;      tory = ry - qy;            sx = px +d*toqx;  sy = py +d*toqy;            tx = qx +d*torx;  ty = qy +d*tory;            totx = tx - sx;   toty = ty - sy;            x = sx + d*totx;  y = sy + d*toty;                          minx = Math.min(minx, x); miny = Math.min(miny, y);            maxx = Math.max(maxx, x); maxy = Math.max(maxy, y);        }              return {x:minx, y:miny, width:maxx-minx, height:maxy-miny};}`

Views

231

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

## JSFL: how to get separate bounding boxes for shapes in merge drawing mode

Explorer ,
Jul 15, 2019

Copy link to clipboard

Copied

I'm writing a script for hole-detection in geometries that also tells which geometry the hole is in. Once it recognizes a Contour as a hole, it scans all elements using bounding boxes to determine where the hole is. Everything is alright as long as I use object drawing mode (since it registers shapes as separate elements) but when the shapes are drawn in merge drawing mode they are all registered as one element, so I end up with just one huge bounding box containing all these shapes. Does anyone one know if and how the information about the bounding box of a single shape in merge mode can be retrieved? I believe that these information are stored somewhere (since the Free Transform Tool detects the bounding box of the geometry by selecting it for example).

EDIT: actually even if two or more shapes in merge mode are combined in one drawing object the resultant bounding box is the one containing them all. So the question would be: how can I get the bounding box of a single Contour object?

Participant
| Participant

Hi,

If I understand your question correctly, you need to detect the bounding box of each part of the "shape". In this case, you may to iterate through all contours, to detect all separate parts using the IDs of the vertices,  and then, for each detected closed bezier polygon, you may use one of the known algorithms. For example, De Casteljau's one:

`function getCurveBounds(ax, ay, bx, by, cx, cy, dx, dy){        var px, py, qx, qy, rx, ry, sx, sy, tx, ty,            tobx, toby, tocx, tocy, todx, tody, toqx, toqy,            torx, tory, totx, toty;        var x, y, minx, miny, maxx, maxy;        minx = miny = Number.POSITIVE_INFINITY;        maxx = maxy = Number.NEGATIVE_INFINITY;        tobx = bx - ax;  toby = by - ay;  // directions        tocx = cx - bx;  tocy = cy - by;        todx = dx - cx;  tody = dy - cy;        var step = 1/40;      // precision        for(var d=0; d<1.001; d+=step)        {            px = ax +d*tobx;  py = ay +d*toby;            qx = bx +d*tocx;  qy = by +d*tocy;            rx = cx +d*todx;  ry = cy +d*tody;            toqx = qx - px;      toqy = qy - py;            torx = rx - qx;      tory = ry - qy;            sx = px +d*toqx;  sy = py +d*toqy;            tx = qx +d*torx;  ty = qy +d*tory;            totx = tx - sx;   toty = ty - sy;            x = sx + d*totx;  y = sy + d*toty;                          minx = Math.min(minx, x); miny = Math.min(miny, y);            maxx = Math.max(maxx, x); maxy = Math.max(maxy, y);        }              return {x:minx, y:miny, width:maxx-minx, height:maxy-miny};}`

Views

232

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Jul 15, 2019 0
2 Replies 2
Participant ,
Jul 16, 2019

Copy link to clipboard

Copied

Hi,

If I understand your question correctly, you need to detect the bounding box of each part of the "shape". In this case, you may to iterate through all contours, to detect all separate parts using the IDs of the vertices,  and then, for each detected closed bezier polygon, you may use one of the known algorithms. For example, De Casteljau's one:

`function getCurveBounds(ax, ay, bx, by, cx, cy, dx, dy){        var px, py, qx, qy, rx, ry, sx, sy, tx, ty,            tobx, toby, tocx, tocy, todx, tody, toqx, toqy,            torx, tory, totx, toty;        var x, y, minx, miny, maxx, maxy;        minx = miny = Number.POSITIVE_INFINITY;        maxx = maxy = Number.NEGATIVE_INFINITY;        tobx = bx - ax;  toby = by - ay;  // directions        tocx = cx - bx;  tocy = cy - by;        todx = dx - cx;  tody = dy - cy;        var step = 1/40;      // precision        for(var d=0; d<1.001; d+=step)        {            px = ax +d*tobx;  py = ay +d*toby;            qx = bx +d*tocx;  qy = by +d*tocy;            rx = cx +d*todx;  ry = cy +d*tody;            toqx = qx - px;      toqy = qy - py;            torx = rx - qx;      tory = ry - qy;            sx = px +d*toqx;  sy = py +d*toqy;            tx = qx +d*torx;  ty = qy +d*tory;            totx = tx - sx;   toty = ty - sy;            x = sx + d*totx;  y = sy + d*toty;                          minx = Math.min(minx, x); miny = Math.min(miny, y);            maxx = Math.max(maxx, x); maxy = Math.max(maxy, y);        }              return {x:minx, y:miny, width:maxx-minx, height:maxy-miny};}`
- Vlad: UX and graphic design, Flash user since 1998
Member of Flanimate Power Tools team - extensions for character animation

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Jul 16, 2019 3
LATEST
Explorer ,
Jul 17, 2019

Copy link to clipboard

Copied

THANK YOU. This is so cool! Yesterday I found a temporary solution using the edges' control points of the contour: the array of these points gives enough information to obtain a quite good approximation of the bounding box, but adding de Casteljau's gives a real boost on the accuracy! I mixed the codes using the best of the two solutions, this is what came out:

`for each(shape in fl.getDocumentDOM().getTimeline().layers[0].frames[0].elements) {     var contourArray = shape.contours;     var index = 0;     for (i = 0; i < contourArray.length; i++) {          if (contourArray.interior) { //check if contour is a closed path               var contour = contourArray;               var he = contour.getHalfEdge();               var iStart = he.id;               var id = 0;               left = top = Number.POSITIVE_INFINITY;               right = bottom = Number.NEGATIVE_INFINITY;               while (id != iStart) {                    e = he.getEdge();                    edgeAnalysis(e);                    he = he.getNext();                    id = he.id;               }               fl.getDocumentDOM().addNewPrimitiveRectangle({left:left,top:top,right:right,bottom:bottom}, 0, true, false); //visualize the bounding box               index++;          }     }}function edgeAnalysis(edge) {     step = 1/40;     p0x = edge.getControl(0).x     p0y = edge.getControl(0).y     p1x = edge.getControl(1).x     p1y = edge.getControl(1).y     p2x = edge.getControl(2).x     p2y = edge.getControl(2).y     for(d = 0; d<1.001; d+=step) {          left = Math.min(left, quadBez(p0x, p1x, p2x, d));          top = Math.min(top, quadBez(p0y, p1y, p2y, d));            right = Math.max(right, quadBez(p0x, p1x, p2x, d));          bottom = Math.max(bottom, quadBez(p0y, p1y, p2y, d));     }}function quadBez(p0, p1, p2, t) {     return Math.pow((1.0 - t), 2) * p0 + 2 * t * (1.0 - t) * p1 + Math.pow(t, 2) * p2;}`

since each edge object is a quadratic bezier, the math is even simpler!

Again, thank you for the help

Likes

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Jul 17, 2019 2