/** * This takes a complicated expression assumed to contain multiple instances of leafA and returns * the equivalent CSG expression involving just leafA. * * @param leafA * @return equivalent CSG expression involving just leafA */ private RrCSG categorise(RrCSG leafA) { RrHalfPlane a = leafA.plane(); Rr2Point an = a.normal(); Rr2Point x = Rr2Point.add(a.pLine().origin(), an); if (value(x) <= 0) return leafA.complement(); else return leafA; }
/** * This takes a complicated expression assumed to contain multiple instances of leafA and leafB * and returns the equivalent CSG expression involving at most leafA and leafB once (except for * non-manifold shapes). * * @param leafA * @param leafB * @return equivalent CSG expression involving at most leafA and leafB once */ private RrCSG crossCategorise(RrCSG leafA, RrCSG leafB) { RrHalfPlane a = leafA.plane(); RrHalfPlane b = leafB.plane(); Rr2Point an = a.normal(); Rr2Point bn = b.normal(); Rr2Point v02 = Rr2Point.add(an, bn); Rr2Point v31 = Rr2Point.sub(bn, an); Rr2Point x, x0, x1, x2, x3; int category = 0; try { x = a.cross_point(b); v02 = v02.norm(); v31 = v31.norm(); x2 = Rr2Point.add(x, v02); x0 = Rr2Point.sub(x, v02); x1 = Rr2Point.add(x, v31); x3 = Rr2Point.sub(x, v31); if (value(x0) <= 0) category |= 1; if (value(x1) <= 0) category |= 2; if (value(x2) <= 0) category |= 4; if (value(x3) <= 0) category |= 8; switch (category) { case 0: return nothing(); case 1: return intersection(leafA, leafB); case 2: return intersection(leafA, leafB.complement()); case 3: return leafA; case 4: return intersection(leafA.complement(), leafB.complement()); case 5: Debug.e("RrCSG crossCategorise: non-manifold shape (case 0101)!"); return union( intersection(leafA, leafB), intersection(leafA.complement(), leafB.complement())); case 6: return leafB.complement(); case 7: return union(leafA, leafB.complement()); case 8: return intersection(leafA.complement(), leafB); case 9: return leafB; case 10: Debug.e("RrCSG crossCategorise: non-manifold shape (case 1010)!"); return union( RrCSG.intersection(leafA.complement(), leafB), intersection(leafA, leafB.complement())); case 11: return union(leafA, leafB); case 12: return leafA.complement(); case 13: return union(leafA.complement(), leafB); case 14: return union(leafA.complement(), leafB.complement()); case 15: return universe(); default: Debug.e("RrCSG crossCategorise: bitwise | doesn't seem to work..."); return this; } } catch (Exception e) { // leafA and leafB are parallel x0 = Rr2Point.mul(Rr2Point.add(a.pLine().origin(), b.pLine().origin()), 0.5); x1 = Rr2Point.mul(Rr2Point.sub(a.pLine().origin(), b.pLine().origin()), 3); x2 = Rr2Point.add(x0, x1); x1 = Rr2Point.sub(x0, x1); if (value(x0) <= 0) category |= 1; if (value(x1) <= 0) category |= 2; if (value(x2) <= 0) category |= 4; if (leafA.value(x0) <= 0) leafA = leafA.complement(); if (leafB.value(x0) <= 0) leafB = leafB.complement(); switch (category) { case 0: return nothing(); case 1: return intersection(leafA.complement(), leafB.complement()); case 2: return leafB; case 3: return leafA.complement(); case 4: return leafA; case 5: return union(leafA, leafB); case 6: return leafB.complement(); case 7: return universe(); default: Debug.e("RrCSG crossCategorise: bitwise | doesn't seem to work..."); return this; } } }