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?
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
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};
}
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