The most minimalistic approach would be to take a point on each BoundaryPath and verify if that is inside the other BoundaryPath's.
This method makes several assumptions:
- Any random point on a BoundaryPath will do
- Locally a number of boundary loops except one are inside other loops
- Boundary loops do not touch others
- Boundary loops do not intersect with others
- Boundary loops do not self-intersect
- ...
And in a way you need to verify all these conditions.
The QCAD resources have some methods to accomplish the minimalistic approach.
The second part of the code below is typically implemented as a function to determine the order of the BoundaryPath's nested nature.
Code: Select all
var hatchEntity; // A hatch entity queried from the document
var segmentLength; // Segment length to approximate curved line-art
// = = = = = = = = =
var loops = hatchEntity.getBoundaryAsPolylines(segmentLength);
var nestOrders = []
var iMax = loops.length;
if (iMax < 1) return undefined; // Failed, no boundary loops
if (iMax < 2) return [0]; // Single boundary loop
// Process all hatch boundary loops for their nested nature:
for (var i=0; i<iMax; i++) {
var loop = loops[i];
// Verify with other boundary loops:
var nested = 0;
var point = loop.getStartPoint();
for (var j=0; j<iMax; j++) {
if (i === j) continue; // Skip itself
var trial = loops[j];
// Verify if the boundary is nested inside the one on trial:
// A) Exclude boundaries that are not even close box based:
if (!trial.getBoundingBox().contains(loop.getBoundingBox())) {
continue; // Is not nested
}
// B) Verify if a random vertex is inside the trial boundary.
if (trial.contains(point, false, RS.PointTolerance)) { // NotOn poly with tolerance = 1e-9
nested++; // Is nested in loop
}
}
// Collect the order of the nested nature:
nestOrders.push(nested);
}
return nestOrders;
You are not out the woods yet.
Let's assume this returns
[0, 2, 1].
An even count is filled, an uneven not, loop 2 is inside loop 3 and all that is inside loop 1.
So far so good. Note that I index loops starting with 1, an array index is zero based.
With 4 loops this may return
[0, 2, 0, 1].
Loops 1 and 3 are not inside another loop, loop 2 is most likely inside 4 but it doesn't tell you if loop 4 is inside 1 or inside 3.
And even harder with this 5 loops example
[0, 2, 0, 1, 1] ... 4 and 5 may be both or not inside 1 or 3, 2 is inside 4 or 5.
Per definition it is thus not strictly pairwise as you described it.
Having the nesting order it is a question of further determination of what is inside what starting with the highest order(s).
I don't think this can be coded along with the code of the above routine there you can not predict the outcome of a yet untested nesting order.
Note that curved boundary shapes are approximated by short line segments, which simplifies the internal math.
This may be sufficient for most purposes ...

Too coarse it may return rubbish, way too fine the
contain algorithm may take forever.
Another method may rely on a point inside a certain area to fill or not.
Counting the times that a ray starting in this point intersects with the boundary loops.
Even or uneven intersections is then again related to hatched or not, intersecting or self-intersecting loops are accounted for.
The trouble here is that the number of intersections may vary according the tested orientation.
With even and uneven counts it is not uniquely defined if an enclosed area should be filled or not.
In these complex situations other rules need to be implemented.
Regards,
CVH