• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

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

Explorer ,
Jul 15, 2019 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?

Views

686

Translate

Translate

Report

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

correct answers 1 Correct answer

Engaged , Jul 16, 2019 Jul 16, 2019

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, to

...

Votes

Translate

Translate
Engaged ,
Jul 16, 2019 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

Votes

Translate

Translate

Report

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

Copy link to clipboard

Copied

LATEST

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

Votes

Translate

Translate

Report

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