@jgphilpott/polytree 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -1
- package/package.json +14 -6
- package/polytree.bundle.browser.js +3453 -0
- package/polytree.bundle.browser.min.js +1 -0
- package/polytree.bundle.js +835 -789
- package/polytree.bundle.min.js +1 -0
package/polytree.bundle.js
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
1
|
// Generated by CoffeeScript 2.7.0
|
|
2
|
-
var
|
|
2
|
+
var Box3, BufferAttribute, BufferGeometry, DoubleSide, Matrix3, Mesh, Ray, Raycaster, Triangle, Vector2, Vector3;
|
|
3
3
|
|
|
4
|
-
({Vector2, Vector3,
|
|
4
|
+
({Vector2, Vector3, Mesh, Triangle, Box3, Matrix3, DoubleSide, Ray, Raycaster, BufferGeometry, BufferAttribute} = require("three"));
|
|
5
|
+
// Generated by CoffeeScript 2.7.0
|
|
6
|
+
var BACK, COPLANAR, CSG_Rules, EPSILON, FRONT, Plane, Polygon, Polytree, RAY_EPSILON, SPANNING, Vertex, _asyncUnionArrayID, _asyncUnionID, _matrix3, _normal1, _polygonID, _wP, _wP_EPS_ARR, _wP_EPS_ARR_COUNT, _wV1, _wV2, _wV3, calcWindingNumber_buffer, disposePolytree, edge1, edge2, h, handleIntersectingPolytrees, handleObjectForOp, handleObjectForOp_async, isUniqueTriangle, isValidTriangle, nbuf2, nbuf3, pointRounding, polyInside_WindingNumber_buffer, prepareTriangleBuffer, q, rayIntersectsTriangle, raycastIntersectAscSort, returnXYZ, s, splitPolygonArr, splitPolygonByPlane, tempBox3, tempRay, tempRayDirection, tempRaycaster, tempVector1, tempVector2, tmpm3, triangleVertex0, triangleVertex1, ttvv0, wNPI;
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
tempVector1 = new Vector3();
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
tempVector2 = new Vector3();
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
tempBox3 = new Box3();
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
triangleVertex0 = new Vector3();
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
triangleVertex1 = new Vector3();
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
tempRaycaster = new Raycaster();
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
tempRay = new Ray();
|
|
19
21
|
|
|
20
|
-
|
|
22
|
+
tempRayDirection = new Vector3(0, 0, 1);
|
|
21
23
|
|
|
22
24
|
EPSILON = 1e-5;
|
|
23
25
|
|
|
@@ -31,7 +33,7 @@ SPANNING = 3;
|
|
|
31
33
|
|
|
32
34
|
_polygonID = 0;
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
Polytree = class Polytree {
|
|
35
37
|
constructor(box, parent) {
|
|
36
38
|
this.polygons = [];
|
|
37
39
|
this.replacedPolygons = [];
|
|
@@ -42,7 +44,7 @@ OctreeCSG = class OctreeCSG {
|
|
|
42
44
|
this.parent = parent;
|
|
43
45
|
this.level = 0;
|
|
44
46
|
this.polygonArrays = void 0;
|
|
45
|
-
// @
|
|
47
|
+
// @isPolytree = true
|
|
46
48
|
this.addPolygonsArrayToRoot(this.polygons);
|
|
47
49
|
}
|
|
48
50
|
|
|
@@ -133,33 +135,33 @@ OctreeCSG = class OctreeCSG {
|
|
|
133
135
|
return this;
|
|
134
136
|
}
|
|
135
137
|
|
|
136
|
-
|
|
138
|
+
newPolytree(box, parent) {
|
|
137
139
|
return new this.constructor(box, parent);
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
split(level) {
|
|
141
|
-
var box, found, halfsize, i,
|
|
143
|
+
var box, found, halfsize, i, k, l, len, m, n, o, polygon, ref, ref1, subTrees, vectorPosition, x, y, z;
|
|
142
144
|
if (!this.box) {
|
|
143
145
|
return;
|
|
144
146
|
}
|
|
145
147
|
subTrees = [];
|
|
146
|
-
halfsize =
|
|
148
|
+
halfsize = tempVector2.copy(this.box.max).sub(this.box.min).multiplyScalar(0.5);
|
|
147
149
|
for (x = k = 0; k <= 1; x = ++k) {
|
|
148
150
|
for (y = l = 0; l <= 1; y = ++l) {
|
|
149
151
|
for (z = m = 0; m <= 1; z = ++m) {
|
|
150
152
|
box = new Box3();
|
|
151
|
-
|
|
152
|
-
box.min.copy(this.box.min).add(
|
|
153
|
+
vectorPosition = tempVector1.set(x, y, z);
|
|
154
|
+
box.min.copy(this.box.min).add(vectorPosition.multiply(halfsize));
|
|
153
155
|
box.max.copy(box.min).add(halfsize);
|
|
154
156
|
box.expandByScalar(EPSILON);
|
|
155
|
-
subTrees.push(this.
|
|
157
|
+
subTrees.push(this.newPolytree(box, this));
|
|
156
158
|
}
|
|
157
159
|
}
|
|
158
160
|
}
|
|
159
161
|
polygon = void 0;
|
|
160
162
|
while (polygon = this.polygons.pop()) {
|
|
161
163
|
found = false;
|
|
162
|
-
for (i =
|
|
164
|
+
for (i = n = 0, ref = subTrees.length; (0 <= ref ? n < ref : n > ref); i = 0 <= ref ? ++n : --n) {
|
|
163
165
|
if (subTrees[i].box.containsPoint(polygon.getMidpoint())) {
|
|
164
166
|
subTrees[i].polygons.push(polygon);
|
|
165
167
|
found = true;
|
|
@@ -170,15 +172,16 @@ OctreeCSG = class OctreeCSG {
|
|
|
170
172
|
throw new Error(`Unable to find subtree for triangle at level ${level}`);
|
|
171
173
|
}
|
|
172
174
|
}
|
|
173
|
-
for (i =
|
|
175
|
+
for (i = o = 0, ref1 = subTrees.length; (0 <= ref1 ? o < ref1 : o > ref1); i = 0 <= ref1 ? ++o : --o) {
|
|
174
176
|
subTrees[i].level = level + 1;
|
|
175
177
|
len = subTrees[i].polygons.length;
|
|
176
178
|
// if (len !== 0) {
|
|
177
|
-
if (len >
|
|
179
|
+
if (len > Polytree.polygonsPerTree && level < Polytree.maxLevel) {
|
|
178
180
|
subTrees[i].split(level + 1);
|
|
179
181
|
}
|
|
180
182
|
this.subTrees.push(subTrees[i]);
|
|
181
183
|
}
|
|
184
|
+
// }
|
|
182
185
|
return this;
|
|
183
186
|
}
|
|
184
187
|
|
|
@@ -192,7 +195,7 @@ OctreeCSG = class OctreeCSG {
|
|
|
192
195
|
processTree() {
|
|
193
196
|
var i, k, l, ref, ref1, results1;
|
|
194
197
|
if (!this.isEmpty()) {
|
|
195
|
-
|
|
198
|
+
tempBox3.copy(this.box);
|
|
196
199
|
for (i = k = 0, ref = this.polygons.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
197
200
|
this.box.expandByPoint(this.polygons[i].triangle.a);
|
|
198
201
|
this.box.expandByPoint(this.polygons[i].triangle.b);
|
|
@@ -273,23 +276,23 @@ OctreeCSG = class OctreeCSG {
|
|
|
273
276
|
polygons = this.getRayPolygons(ray);
|
|
274
277
|
for (i = k = 0, ref = polygons.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
275
278
|
result = void 0;
|
|
276
|
-
if (
|
|
277
|
-
result = ray.intersectTriangle(polygons[i].triangle.a, polygons[i].triangle.b, polygons[i].triangle.c, false,
|
|
279
|
+
if (Polytree.rayIntersectTriangleType === "regular") {
|
|
280
|
+
result = ray.intersectTriangle(polygons[i].triangle.a, polygons[i].triangle.b, polygons[i].triangle.c, false, tempVector1);
|
|
278
281
|
if (result) {
|
|
279
|
-
|
|
280
|
-
distance =
|
|
282
|
+
tempVector1.applyMatrix4(matrixWorld);
|
|
283
|
+
distance = tempVector1.distanceTo(ray.origin);
|
|
281
284
|
if (distance < 0 || distance > 2e308) {
|
|
282
285
|
console.warn("[rayIntersect] Failed ray distance check", ray);
|
|
283
286
|
} else {
|
|
284
287
|
intersects.push({
|
|
285
288
|
distance: distance,
|
|
286
289
|
polygon: polygons[i],
|
|
287
|
-
position:
|
|
290
|
+
position: tempVector1.clone()
|
|
288
291
|
});
|
|
289
292
|
}
|
|
290
293
|
}
|
|
291
294
|
} else {
|
|
292
|
-
result = rayIntersectsTriangle(ray, polygons[i].triangle,
|
|
295
|
+
result = rayIntersectsTriangle(ray, polygons[i].triangle, tempVector1);
|
|
293
296
|
if (result) {
|
|
294
297
|
newdistance = result.clone().sub(ray.origin).length();
|
|
295
298
|
if (distance > newdistance) {
|
|
@@ -570,11 +573,11 @@ OctreeCSG = class OctreeCSG {
|
|
|
570
573
|
return true;
|
|
571
574
|
}
|
|
572
575
|
|
|
573
|
-
markIntesectingPolygons(
|
|
576
|
+
markIntesectingPolygons(targetPolytree) {
|
|
574
577
|
return this.polygonArrays.forEach(function(polygonsArray) {
|
|
575
578
|
if (polygonsArray.length) {
|
|
576
579
|
return polygonsArray.forEach(function(polygon) {
|
|
577
|
-
return polygon.intersects =
|
|
580
|
+
return polygon.intersects = targetPolytree.isPolygonIntersecting(polygon);
|
|
578
581
|
});
|
|
579
582
|
}
|
|
580
583
|
});
|
|
@@ -582,9 +585,9 @@ OctreeCSG = class OctreeCSG {
|
|
|
582
585
|
|
|
583
586
|
// if @polygons.length > 0
|
|
584
587
|
// @polygons.forEach (polygon) ->
|
|
585
|
-
// polygon.intersects =
|
|
588
|
+
// polygon.intersects = targetPolytree.isPolygonIntersecting(polygon)
|
|
586
589
|
// for i in [0...@subTrees.length]
|
|
587
|
-
// @subTrees[i].markIntesectingPolygons(
|
|
590
|
+
// @subTrees[i].markIntesectingPolygons(targetPolytree)
|
|
588
591
|
resetPolygons(resetOriginal = true) {
|
|
589
592
|
return this.polygonArrays.forEach(function(polygonsArray) {
|
|
590
593
|
if (polygonsArray.length) {
|
|
@@ -600,8 +603,8 @@ OctreeCSG = class OctreeCSG {
|
|
|
600
603
|
// polygon.reset(resetOriginal)
|
|
601
604
|
// for i in [0...@subTrees.length]
|
|
602
605
|
// @subTrees[i].resetPolygons(resetOriginal)
|
|
603
|
-
handleIntersectingPolygons(
|
|
604
|
-
var currentPolygon, i,
|
|
606
|
+
handleIntersectingPolygons(targetPolytree, targetPolytreeBuffer) {
|
|
607
|
+
var currentPolygon, i, inside, intersects, j, k, l, m, n, o, point, polygon, polygonStack, ref, ref1, ref2, ref3, ref4, results1, splitResults, target, targetPolygons;
|
|
605
608
|
// if @polygons.length > 0
|
|
606
609
|
// polygonStack = @polygons.filter (polygon) -> (polygon.valid == true) and (polygon.intersects == true) and (polygon.state == "undecided")
|
|
607
610
|
// currentPolygon = polygonStack.pop()
|
|
@@ -610,7 +613,7 @@ OctreeCSG = class OctreeCSG {
|
|
|
610
613
|
// continue
|
|
611
614
|
// unless currentPolygon.valid
|
|
612
615
|
// continue
|
|
613
|
-
// targetPolygons =
|
|
616
|
+
// targetPolygons = targetPolytree.getPolygonsIntersectingPolygon(currentPolygon)
|
|
614
617
|
// if targetPolygons.length > 0
|
|
615
618
|
// for j in [0...targetPolygons.length]
|
|
616
619
|
// target = targetPolygons[j]
|
|
@@ -642,42 +645,42 @@ OctreeCSG = class OctreeCSG {
|
|
|
642
645
|
// unless currentPolygon.valid
|
|
643
646
|
// continue
|
|
644
647
|
// inside = false
|
|
645
|
-
// if
|
|
646
|
-
// if
|
|
647
|
-
// inside = polyInside_WindingNumber_buffer(
|
|
648
|
+
// if targetPolytree.box.containsPoint(currentPolygon.getMidpoint())
|
|
649
|
+
// if Polytree.useWindingNumber is true
|
|
650
|
+
// inside = polyInside_WindingNumber_buffer(targetPolytreeBuffer, currentPolygon.getMidpoint(), currentPolygon.coplanar)
|
|
648
651
|
// else
|
|
649
|
-
// point = pointRounding(
|
|
650
|
-
// if
|
|
651
|
-
//
|
|
652
|
-
//
|
|
653
|
-
// intersects =
|
|
652
|
+
// point = pointRounding(tempVector2.copy(currentPolygon.getMidpoint()))
|
|
653
|
+
// if Polytree.usePolytreeRay isnt true and targetPolytree.mesh
|
|
654
|
+
// tempRayDirection.copy(currentPolygon.plane.normal)
|
|
655
|
+
// tempRaycaster.set(point, tempRayDirection)
|
|
656
|
+
// intersects = tempRaycaster.intersectObject(targetPolytree.mesh)
|
|
654
657
|
// if intersects.length
|
|
655
|
-
// if
|
|
658
|
+
// if tempRayDirection.dot(intersects[0].face.normal) > 0
|
|
656
659
|
// inside = true
|
|
657
660
|
// unless inside or not currentPolygon.coplanar
|
|
658
661
|
// for j in [0..._wP_EPS_ARR_COUNT]
|
|
659
|
-
//
|
|
660
|
-
// intersects =
|
|
662
|
+
// tempRaycaster.ray.origin.copy(point).add(_wP_EPS_ARR[j])
|
|
663
|
+
// intersects = tempRaycaster.intersectObject(targetPolytree.mesh)
|
|
661
664
|
// if intersects.length
|
|
662
|
-
// if
|
|
665
|
+
// if tempRayDirection.dot(intersects[0].face.normal) > 0
|
|
663
666
|
// inside = true
|
|
664
667
|
// break
|
|
665
668
|
// else
|
|
666
|
-
//
|
|
667
|
-
//
|
|
668
|
-
//
|
|
669
|
-
// intersects =
|
|
669
|
+
// tempRay.origin.copy(point)
|
|
670
|
+
// tempRayDirection.copy(currentPolygon.plane.normal)
|
|
671
|
+
// tempRay.direction.copy(currentPolygon.plane.normal)
|
|
672
|
+
// intersects = targetPolytree.rayIntersect(tempRay, targetPolytree.originalMatrixWorld)
|
|
670
673
|
// if intersects.length
|
|
671
|
-
// if
|
|
674
|
+
// if tempRayDirection.dot(intersects[0].polygon.plane.normal) > 0
|
|
672
675
|
// inside = true
|
|
673
676
|
// unless inside or not currentPolygon.coplanar
|
|
674
677
|
// for j in [0..._wP_EPS_ARR_COUNT]
|
|
675
|
-
//
|
|
676
|
-
//
|
|
677
|
-
//
|
|
678
|
-
// intersects =
|
|
678
|
+
// tempRay.origin.copy(point).add(_wP_EPS_ARR[j])
|
|
679
|
+
// tempRayDirection.copy(currentPolygon.plane.normal)
|
|
680
|
+
// tempRay.direction.copy(currentPolygon.plane.normal)
|
|
681
|
+
// intersects = targetPolytree.rayIntersect(tempRay, targetPolytree.originalMatrixWorld)
|
|
679
682
|
// if intersects.length
|
|
680
|
-
// if
|
|
683
|
+
// if tempRayDirection.dot(intersects[0].polygon.plane.normal) > 0
|
|
681
684
|
// inside = true
|
|
682
685
|
// break
|
|
683
686
|
// if inside is true
|
|
@@ -686,7 +689,7 @@ OctreeCSG = class OctreeCSG {
|
|
|
686
689
|
// currentPolygon.setState("outside")
|
|
687
690
|
// currentPolygon = polygonStack.pop()
|
|
688
691
|
// for i in [0...@subTrees.length]
|
|
689
|
-
// @subTrees[i].handleIntersectingPolygons(
|
|
692
|
+
// @subTrees[i].handleIntersectingPolygons(targetPolytree, targetPolytreeBuffer)
|
|
690
693
|
if (this.polygons.length > 0) {
|
|
691
694
|
polygonStack = this.polygons.filter(function(polygon) {
|
|
692
695
|
return (polygon.valid === true) && (polygon.intersects === true) && (polygon.state === "undecided");
|
|
@@ -699,7 +702,7 @@ OctreeCSG = class OctreeCSG {
|
|
|
699
702
|
if (!currentPolygon.valid) {
|
|
700
703
|
continue;
|
|
701
704
|
}
|
|
702
|
-
targetPolygons =
|
|
705
|
+
targetPolygons = targetPolytree.getPolygonsIntersectingPolygon(currentPolygon);
|
|
703
706
|
if (targetPolygons.length > 0) {
|
|
704
707
|
for (j = k = 0, ref = targetPolygons.length; (0 <= ref ? k < ref : k > ref); j = 0 <= ref ? ++k : --k) {
|
|
705
708
|
target = targetPolygons[j];
|
|
@@ -743,26 +746,26 @@ OctreeCSG = class OctreeCSG {
|
|
|
743
746
|
continue;
|
|
744
747
|
}
|
|
745
748
|
inside = false;
|
|
746
|
-
if (
|
|
747
|
-
if (
|
|
748
|
-
inside = polyInside_WindingNumber_buffer(
|
|
749
|
+
if (targetPolytree.box.containsPoint(currentPolygon.getMidpoint())) {
|
|
750
|
+
if (Polytree.useWindingNumber === true) {
|
|
751
|
+
inside = polyInside_WindingNumber_buffer(targetPolytreeBuffer, currentPolygon.getMidpoint(), currentPolygon.coplanar);
|
|
749
752
|
} else {
|
|
750
|
-
point = pointRounding(
|
|
751
|
-
if (
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
intersects =
|
|
753
|
+
point = pointRounding(tempVector2.copy(currentPolygon.getMidpoint()));
|
|
754
|
+
if (Polytree.usePolytreeRay !== true && targetPolytree.mesh) {
|
|
755
|
+
tempRayDirection.copy(currentPolygon.plane.normal);
|
|
756
|
+
tempRaycaster.set(point, tempRayDirection);
|
|
757
|
+
intersects = tempRaycaster.intersectObject(targetPolytree.mesh);
|
|
755
758
|
if (intersects.length) {
|
|
756
|
-
if (
|
|
759
|
+
if (tempRayDirection.dot(intersects[0].face.normal) > 0) {
|
|
757
760
|
inside = true;
|
|
758
761
|
}
|
|
759
762
|
}
|
|
760
763
|
if (!(inside || !currentPolygon.coplanar)) {
|
|
761
764
|
for (j = m = 0, ref2 = _wP_EPS_ARR_COUNT; (0 <= ref2 ? m < ref2 : m > ref2); j = 0 <= ref2 ? ++m : --m) {
|
|
762
|
-
|
|
763
|
-
intersects =
|
|
765
|
+
tempRaycaster.ray.origin.copy(point).add(_wP_EPS_ARR[j]);
|
|
766
|
+
intersects = tempRaycaster.intersectObject(targetPolytree.mesh);
|
|
764
767
|
if (intersects.length) {
|
|
765
|
-
if (
|
|
768
|
+
if (tempRayDirection.dot(intersects[0].face.normal) > 0) {
|
|
766
769
|
inside = true;
|
|
767
770
|
break;
|
|
768
771
|
}
|
|
@@ -770,23 +773,23 @@ OctreeCSG = class OctreeCSG {
|
|
|
770
773
|
}
|
|
771
774
|
}
|
|
772
775
|
} else {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
intersects =
|
|
776
|
+
tempRay.origin.copy(point);
|
|
777
|
+
tempRayDirection.copy(currentPolygon.plane.normal);
|
|
778
|
+
tempRay.direction.copy(currentPolygon.plane.normal);
|
|
779
|
+
intersects = targetPolytree.rayIntersect(tempRay, targetPolytree.originalMatrixWorld);
|
|
777
780
|
if (intersects.length) {
|
|
778
|
-
if (
|
|
781
|
+
if (tempRayDirection.dot(intersects[0].polygon.plane.normal) > 0) {
|
|
779
782
|
inside = true;
|
|
780
783
|
}
|
|
781
784
|
}
|
|
782
785
|
if (!(inside || !currentPolygon.coplanar)) {
|
|
783
|
-
for (j =
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
intersects =
|
|
786
|
+
for (j = n = 0, ref3 = _wP_EPS_ARR_COUNT; (0 <= ref3 ? n < ref3 : n > ref3); j = 0 <= ref3 ? ++n : --n) {
|
|
787
|
+
tempRay.origin.copy(point).add(_wP_EPS_ARR[j]);
|
|
788
|
+
tempRayDirection.copy(currentPolygon.plane.normal);
|
|
789
|
+
tempRay.direction.copy(currentPolygon.plane.normal);
|
|
790
|
+
intersects = targetPolytree.rayIntersect(tempRay, targetPolytree.originalMatrixWorld);
|
|
788
791
|
if (intersects.length) {
|
|
789
|
-
if (
|
|
792
|
+
if (tempRayDirection.dot(intersects[0].polygon.plane.normal) > 0) {
|
|
790
793
|
inside = true;
|
|
791
794
|
break;
|
|
792
795
|
}
|
|
@@ -805,8 +808,8 @@ OctreeCSG = class OctreeCSG {
|
|
|
805
808
|
}
|
|
806
809
|
}
|
|
807
810
|
results1 = [];
|
|
808
|
-
for (i =
|
|
809
|
-
results1.push(this.subTrees[i].handleIntersectingPolygons(
|
|
811
|
+
for (i = o = 0, ref4 = this.subTrees.length; (0 <= ref4 ? o < ref4 : o > ref4); i = 0 <= ref4 ? ++o : --o) {
|
|
812
|
+
results1.push(this.subTrees[i].handleIntersectingPolygons(targetPolytree, targetPolytreeBuffer));
|
|
810
813
|
}
|
|
811
814
|
return results1;
|
|
812
815
|
}
|
|
@@ -939,7 +942,7 @@ OctreeCSG = class OctreeCSG {
|
|
|
939
942
|
// @polygons.forEach (p) -> p.shared = index
|
|
940
943
|
// for i in [0...@subTrees.length]
|
|
941
944
|
// @subTrees[i].setPolygonIndex(index)
|
|
942
|
-
|
|
945
|
+
Polytree.prototype.isPolytree = true;
|
|
943
946
|
|
|
944
947
|
raycastIntersectAscSort = function(a, b) {
|
|
945
948
|
return a.distance - b.distance;
|
|
@@ -953,7 +956,7 @@ pointRounding = function(point, num = 15) {
|
|
|
953
956
|
};
|
|
954
957
|
|
|
955
958
|
splitPolygonByPlane = function(polygon, plane, result = []) {
|
|
956
|
-
var
|
|
959
|
+
var backVertices, currentType, currentVertex, distanceToPlane, frontVertices, i, intersectionParameter, k, l, m, n, newPolygons, nextIndex, nextType, nextVertex, polygonIndex, polygonType, ref, ref1, ref2, ref3, returnPolygon, type, types, vertexParameter;
|
|
957
960
|
returnPolygon = {
|
|
958
961
|
polygon: polygon,
|
|
959
962
|
type: "undecided"
|
|
@@ -961,8 +964,8 @@ splitPolygonByPlane = function(polygon, plane, result = []) {
|
|
|
961
964
|
polygonType = 0;
|
|
962
965
|
types = [];
|
|
963
966
|
for (i = k = 0, ref = polygon.vertices.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
964
|
-
|
|
965
|
-
type =
|
|
967
|
+
distanceToPlane = plane.normal.dot(polygon.vertices[i].pos) - plane.w;
|
|
968
|
+
type = distanceToPlane < -EPSILON ? BACK : distanceToPlane > EPSILON ? FRONT : COPLANAR;
|
|
966
969
|
polygonType |= type;
|
|
967
970
|
types.push(type);
|
|
968
971
|
}
|
|
@@ -980,55 +983,55 @@ splitPolygonByPlane = function(polygon, plane, result = []) {
|
|
|
980
983
|
result.push(returnPolygon);
|
|
981
984
|
break;
|
|
982
985
|
case SPANNING:
|
|
983
|
-
|
|
984
|
-
|
|
986
|
+
frontVertices = [];
|
|
987
|
+
backVertices = [];
|
|
985
988
|
for (i = l = 0, ref1 = polygon.vertices.length; (0 <= ref1 ? l < ref1 : l > ref1); i = 0 <= ref1 ? ++l : --l) {
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
if (
|
|
992
|
-
|
|
989
|
+
nextIndex = (i + 1) % polygon.vertices.length;
|
|
990
|
+
currentType = types[i];
|
|
991
|
+
nextType = types[nextIndex];
|
|
992
|
+
currentVertex = polygon.vertices[i];
|
|
993
|
+
nextVertex = polygon.vertices[nextIndex];
|
|
994
|
+
if (currentType !== BACK) {
|
|
995
|
+
frontVertices.push(currentVertex);
|
|
993
996
|
}
|
|
994
|
-
if (
|
|
995
|
-
|
|
997
|
+
if (currentType !== FRONT) {
|
|
998
|
+
backVertices.push(currentType !== BACK ? currentVertex.clone() : currentVertex);
|
|
996
999
|
}
|
|
997
|
-
if ((
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1000
|
+
if ((currentType | nextType) === SPANNING) {
|
|
1001
|
+
intersectionParameter = (plane.w - plane.normal.dot(currentVertex.pos)) / plane.normal.dot(triangleVertex0.copy(nextVertex.pos).sub(currentVertex.pos));
|
|
1002
|
+
vertexParameter = currentVertex.interpolate(nextVertex, intersectionParameter);
|
|
1003
|
+
frontVertices.push(vertexParameter);
|
|
1004
|
+
backVertices.push(vertexParameter.clone());
|
|
1002
1005
|
}
|
|
1003
1006
|
}
|
|
1004
|
-
if (
|
|
1005
|
-
if (
|
|
1006
|
-
|
|
1007
|
-
for (
|
|
1007
|
+
if (frontVertices.length >= 3) {
|
|
1008
|
+
if (frontVertices.length > 3) {
|
|
1009
|
+
newPolygons = splitPolygonArr(frontVertices);
|
|
1010
|
+
for (polygonIndex = m = 0, ref2 = newPolygons.length; (0 <= ref2 ? m < ref2 : m > ref2); polygonIndex = 0 <= ref2 ? ++m : --m) {
|
|
1008
1011
|
result.push({
|
|
1009
|
-
polygon: new Polygon(
|
|
1012
|
+
polygon: new Polygon(newPolygons[polygonIndex], polygon.shared),
|
|
1010
1013
|
type: "front"
|
|
1011
1014
|
});
|
|
1012
1015
|
}
|
|
1013
1016
|
} else {
|
|
1014
1017
|
result.push({
|
|
1015
|
-
polygon: new Polygon(
|
|
1018
|
+
polygon: new Polygon(frontVertices, polygon.shared),
|
|
1016
1019
|
type: "front"
|
|
1017
1020
|
});
|
|
1018
1021
|
}
|
|
1019
1022
|
}
|
|
1020
|
-
if (
|
|
1021
|
-
if (
|
|
1022
|
-
|
|
1023
|
-
for (
|
|
1023
|
+
if (backVertices.length >= 3) {
|
|
1024
|
+
if (backVertices.length > 3) {
|
|
1025
|
+
newPolygons = splitPolygonArr(backVertices);
|
|
1026
|
+
for (polygonIndex = n = 0, ref3 = newPolygons.length; (0 <= ref3 ? n < ref3 : n > ref3); polygonIndex = 0 <= ref3 ? ++n : --n) {
|
|
1024
1027
|
result.push({
|
|
1025
|
-
polygon: new Polygon(
|
|
1028
|
+
polygon: new Polygon(newPolygons[polygonIndex], polygon.shared),
|
|
1026
1029
|
type: "back"
|
|
1027
1030
|
});
|
|
1028
1031
|
}
|
|
1029
1032
|
} else {
|
|
1030
1033
|
result.push({
|
|
1031
|
-
polygon: new Polygon(
|
|
1034
|
+
polygon: new Polygon(backVertices, polygon.shared),
|
|
1032
1035
|
type: "back"
|
|
1033
1036
|
});
|
|
1034
1037
|
}
|
|
@@ -1183,7 +1186,7 @@ CSG_Rules = {
|
|
|
1183
1186
|
}
|
|
1184
1187
|
};
|
|
1185
1188
|
|
|
1186
|
-
// class
|
|
1189
|
+
// class Polytree { };
|
|
1187
1190
|
/*
|
|
1188
1191
|
Union:
|
|
1189
1192
|
- Combine all polygons from A and B, except:
|
|
@@ -1209,132 +1212,134 @@ Intersect:
|
|
|
1209
1212
|
d. outside and coplanar-back
|
|
1210
1213
|
e. outside
|
|
1211
1214
|
*/
|
|
1212
|
-
|
|
1213
|
-
var currentMeshSideA, currentMeshSideB,
|
|
1214
|
-
|
|
1215
|
+
Polytree.union = function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1216
|
+
var currentMeshSideA, currentMeshSideB, polytree, trianglesSet;
|
|
1217
|
+
polytree = new Polytree();
|
|
1215
1218
|
trianglesSet = new Set();
|
|
1216
|
-
if (
|
|
1219
|
+
if (polytreeA.box.intersectsBox(polytreeB.box)) {
|
|
1217
1220
|
currentMeshSideA = void 0;
|
|
1218
1221
|
currentMeshSideB = void 0;
|
|
1219
|
-
if (
|
|
1220
|
-
currentMeshSideA =
|
|
1221
|
-
|
|
1222
|
-
}
|
|
1223
|
-
if (
|
|
1224
|
-
currentMeshSideB =
|
|
1225
|
-
|
|
1226
|
-
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
if (
|
|
1239
|
-
|
|
1240
|
-
}
|
|
1241
|
-
if (
|
|
1242
|
-
|
|
1222
|
+
if (polytreeA.mesh) {
|
|
1223
|
+
currentMeshSideA = polytreeA.mesh.material.side;
|
|
1224
|
+
polytreeA.mesh.material.side = DoubleSide;
|
|
1225
|
+
}
|
|
1226
|
+
if (polytreeB.mesh) {
|
|
1227
|
+
currentMeshSideB = polytreeB.mesh.material.side;
|
|
1228
|
+
polytreeB.mesh.material.side = DoubleSide;
|
|
1229
|
+
}
|
|
1230
|
+
polytreeA.resetPolygons(false);
|
|
1231
|
+
polytreeB.resetPolygons(false);
|
|
1232
|
+
polytreeA.markIntesectingPolygons(polytreeB);
|
|
1233
|
+
polytreeB.markIntesectingPolygons(polytreeA);
|
|
1234
|
+
handleIntersectingPolytrees(polytreeA, polytreeB);
|
|
1235
|
+
polytreeA.deleteReplacedPolygons();
|
|
1236
|
+
polytreeB.deleteReplacedPolygons();
|
|
1237
|
+
polytreeA.deletePolygonsByStateRules(CSG_Rules.union.a);
|
|
1238
|
+
polytreeB.deletePolygonsByStateRules(CSG_Rules.union.b);
|
|
1239
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1240
|
+
polytreeB.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1241
|
+
if (polytreeA.mesh && polytreeA.mesh.material.side !== currentMeshSideA) {
|
|
1242
|
+
polytreeA.mesh.material.side = currentMeshSideA;
|
|
1243
|
+
}
|
|
1244
|
+
if (polytreeB.mesh && polytreeB.mesh.material.side !== currentMeshSideB) {
|
|
1245
|
+
polytreeB.mesh.material.side = currentMeshSideB;
|
|
1243
1246
|
}
|
|
1244
1247
|
} else {
|
|
1245
|
-
|
|
1246
|
-
|
|
1248
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1249
|
+
polytreeB.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1247
1250
|
}
|
|
1248
1251
|
trianglesSet.clear();
|
|
1249
1252
|
trianglesSet = void 0;
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
return
|
|
1253
|
+
polytree.markPolygonsAsOriginal();
|
|
1254
|
+
buildTargetPolytree && polytree.buildTree();
|
|
1255
|
+
return polytree;
|
|
1253
1256
|
};
|
|
1254
1257
|
|
|
1255
|
-
|
|
1256
|
-
var currentMeshSideA, currentMeshSideB,
|
|
1257
|
-
|
|
1258
|
+
Polytree.subtract = function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1259
|
+
var currentMeshSideA, currentMeshSideB, polytree, trianglesSet;
|
|
1260
|
+
polytree = new Polytree();
|
|
1258
1261
|
trianglesSet = new Set();
|
|
1259
|
-
if (
|
|
1262
|
+
if (polytreeA.box.intersectsBox(polytreeB.box)) {
|
|
1260
1263
|
currentMeshSideA = void 0;
|
|
1261
1264
|
currentMeshSideB = void 0;
|
|
1262
|
-
if (
|
|
1263
|
-
currentMeshSideA =
|
|
1264
|
-
|
|
1265
|
-
}
|
|
1266
|
-
if (
|
|
1267
|
-
currentMeshSideB =
|
|
1268
|
-
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
if (
|
|
1284
|
-
|
|
1285
|
-
}
|
|
1286
|
-
if (
|
|
1287
|
-
|
|
1265
|
+
if (polytreeA.mesh) {
|
|
1266
|
+
currentMeshSideA = polytreeA.mesh.material.side;
|
|
1267
|
+
polytreeA.mesh.material.side = DoubleSide;
|
|
1268
|
+
}
|
|
1269
|
+
if (polytreeB.mesh) {
|
|
1270
|
+
currentMeshSideB = polytreeB.mesh.material.side;
|
|
1271
|
+
polytreeB.mesh.material.side = DoubleSide;
|
|
1272
|
+
}
|
|
1273
|
+
polytreeA.resetPolygons(false);
|
|
1274
|
+
polytreeB.resetPolygons(false);
|
|
1275
|
+
polytreeA.markIntesectingPolygons(polytreeB);
|
|
1276
|
+
polytreeB.markIntesectingPolygons(polytreeA);
|
|
1277
|
+
handleIntersectingPolytrees(polytreeA, polytreeB);
|
|
1278
|
+
polytreeA.deleteReplacedPolygons();
|
|
1279
|
+
polytreeB.deleteReplacedPolygons();
|
|
1280
|
+
polytreeA.deletePolygonsByStateRules(CSG_Rules.subtract.a);
|
|
1281
|
+
polytreeB.deletePolygonsByStateRules(CSG_Rules.subtract.b);
|
|
1282
|
+
polytreeB.deletePolygonsByIntersection(false);
|
|
1283
|
+
polytreeB.invert();
|
|
1284
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1285
|
+
polytreeB.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1286
|
+
if (polytreeA.mesh && polytreeA.mesh.material.side !== currentMeshSideA) {
|
|
1287
|
+
polytreeA.mesh.material.side = currentMeshSideA;
|
|
1288
|
+
}
|
|
1289
|
+
if (polytreeB.mesh && polytreeB.mesh.material.side !== currentMeshSideB) {
|
|
1290
|
+
polytreeB.mesh.material.side = currentMeshSideB;
|
|
1288
1291
|
}
|
|
1289
1292
|
} else {
|
|
1290
|
-
|
|
1293
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1291
1294
|
}
|
|
1292
1295
|
trianglesSet.clear();
|
|
1293
1296
|
trianglesSet = void 0;
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
//
|
|
1297
|
-
return
|
|
1297
|
+
polytree.markPolygonsAsOriginal();
|
|
1298
|
+
buildTargetPolytree && polytree.buildTree();
|
|
1299
|
+
// polytree.invert()
|
|
1300
|
+
return polytree;
|
|
1298
1301
|
};
|
|
1299
1302
|
|
|
1300
|
-
|
|
1301
|
-
var currentMeshSideA, currentMeshSideB,
|
|
1302
|
-
|
|
1303
|
+
Polytree.intersect = function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1304
|
+
var currentMeshSideA, currentMeshSideB, polytree, trianglesSet;
|
|
1305
|
+
polytree = new Polytree();
|
|
1303
1306
|
trianglesSet = new Set();
|
|
1304
|
-
if (
|
|
1307
|
+
if (polytreeA.box.intersectsBox(polytreeB.box)) {
|
|
1305
1308
|
currentMeshSideA = void 0;
|
|
1306
1309
|
currentMeshSideB = void 0;
|
|
1307
|
-
if (
|
|
1308
|
-
currentMeshSideA =
|
|
1309
|
-
|
|
1310
|
-
}
|
|
1311
|
-
if (
|
|
1312
|
-
currentMeshSideB =
|
|
1313
|
-
|
|
1314
|
-
}
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
if (
|
|
1329
|
-
|
|
1330
|
-
}
|
|
1331
|
-
if (
|
|
1332
|
-
|
|
1310
|
+
if (polytreeA.mesh) {
|
|
1311
|
+
currentMeshSideA = polytreeA.mesh.material.side;
|
|
1312
|
+
polytreeA.mesh.material.side = DoubleSide;
|
|
1313
|
+
}
|
|
1314
|
+
if (polytreeB.mesh) {
|
|
1315
|
+
currentMeshSideB = polytreeB.mesh.material.side;
|
|
1316
|
+
polytreeB.mesh.material.side = DoubleSide;
|
|
1317
|
+
}
|
|
1318
|
+
polytreeA.resetPolygons(false);
|
|
1319
|
+
polytreeB.resetPolygons(false);
|
|
1320
|
+
polytreeA.markIntesectingPolygons(polytreeB);
|
|
1321
|
+
polytreeB.markIntesectingPolygons(polytreeA);
|
|
1322
|
+
handleIntersectingPolytrees(polytreeA, polytreeB);
|
|
1323
|
+
polytreeA.deleteReplacedPolygons();
|
|
1324
|
+
polytreeB.deleteReplacedPolygons();
|
|
1325
|
+
polytreeA.deletePolygonsByStateRules(CSG_Rules.intersect.a);
|
|
1326
|
+
polytreeB.deletePolygonsByStateRules(CSG_Rules.intersect.b);
|
|
1327
|
+
polytreeA.deletePolygonsByIntersection(false);
|
|
1328
|
+
polytreeB.deletePolygonsByIntersection(false);
|
|
1329
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1330
|
+
polytreeB.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1331
|
+
if (polytreeA.mesh && polytreeA.mesh.material.side !== currentMeshSideA) {
|
|
1332
|
+
polytreeA.mesh.material.side = currentMeshSideA;
|
|
1333
|
+
}
|
|
1334
|
+
if (polytreeB.mesh && polytreeB.mesh.material.side !== currentMeshSideB) {
|
|
1335
|
+
polytreeB.mesh.material.side = currentMeshSideB;
|
|
1333
1336
|
}
|
|
1334
1337
|
}
|
|
1335
1338
|
trianglesSet.clear();
|
|
1336
1339
|
trianglesSet = void 0;
|
|
1337
|
-
|
|
1340
|
+
polytree.markPolygonsAsOriginal();
|
|
1341
|
+
buildTargetPolytree && polytree.buildTree();
|
|
1342
|
+
return polytree;
|
|
1338
1343
|
};
|
|
1339
1344
|
|
|
1340
1345
|
CSG_Rules = {
|
|
@@ -1457,7 +1462,7 @@ CSG_Rules = {
|
|
|
1457
1462
|
}
|
|
1458
1463
|
};
|
|
1459
1464
|
|
|
1460
|
-
// class
|
|
1465
|
+
// class Polytree { };
|
|
1461
1466
|
/*
|
|
1462
1467
|
Union:
|
|
1463
1468
|
- Combine all polygons from A and B, except:
|
|
@@ -1483,205 +1488,205 @@ Intersect:
|
|
|
1483
1488
|
d. outside and coplanar-back
|
|
1484
1489
|
e. outside
|
|
1485
1490
|
*/
|
|
1486
|
-
|
|
1487
|
-
var currentMeshSideA, currentMeshSideB,
|
|
1488
|
-
|
|
1491
|
+
Polytree.union = function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1492
|
+
var currentMeshSideA, currentMeshSideB, polytree, trianglesSet;
|
|
1493
|
+
polytree = new Polytree();
|
|
1489
1494
|
trianglesSet = new Set();
|
|
1490
|
-
if (
|
|
1495
|
+
if (polytreeA.box.intersectsBox(polytreeB.box)) {
|
|
1491
1496
|
currentMeshSideA = void 0;
|
|
1492
1497
|
currentMeshSideB = void 0;
|
|
1493
|
-
if (
|
|
1494
|
-
currentMeshSideA =
|
|
1495
|
-
|
|
1496
|
-
}
|
|
1497
|
-
if (
|
|
1498
|
-
currentMeshSideB =
|
|
1499
|
-
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
if (
|
|
1513
|
-
|
|
1514
|
-
}
|
|
1515
|
-
if (
|
|
1516
|
-
|
|
1498
|
+
if (polytreeA.mesh) {
|
|
1499
|
+
currentMeshSideA = polytreeA.mesh.material.side;
|
|
1500
|
+
polytreeA.mesh.material.side = DoubleSide;
|
|
1501
|
+
}
|
|
1502
|
+
if (polytreeB.mesh) {
|
|
1503
|
+
currentMeshSideB = polytreeB.mesh.material.side;
|
|
1504
|
+
polytreeB.mesh.material.side = DoubleSide;
|
|
1505
|
+
}
|
|
1506
|
+
polytreeA.resetPolygons(false);
|
|
1507
|
+
polytreeB.resetPolygons(false);
|
|
1508
|
+
polytreeA.markIntesectingPolygons(polytreeB);
|
|
1509
|
+
polytreeB.markIntesectingPolygons(polytreeA);
|
|
1510
|
+
handleIntersectingPolytrees(polytreeA, polytreeB);
|
|
1511
|
+
polytreeA.deleteReplacedPolygons();
|
|
1512
|
+
polytreeB.deleteReplacedPolygons();
|
|
1513
|
+
polytreeA.deletePolygonsByStateRules(CSG_Rules.union.a);
|
|
1514
|
+
polytreeB.deletePolygonsByStateRules(CSG_Rules.union.b);
|
|
1515
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1516
|
+
polytreeB.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1517
|
+
if (polytreeA.mesh && polytreeA.mesh.material.side !== currentMeshSideA) {
|
|
1518
|
+
polytreeA.mesh.material.side = currentMeshSideA;
|
|
1519
|
+
}
|
|
1520
|
+
if (polytreeB.mesh && polytreeB.mesh.material.side !== currentMeshSideB) {
|
|
1521
|
+
polytreeB.mesh.material.side = currentMeshSideB;
|
|
1517
1522
|
}
|
|
1518
1523
|
} else {
|
|
1519
|
-
|
|
1520
|
-
|
|
1524
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1525
|
+
polytreeB.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1521
1526
|
}
|
|
1522
1527
|
trianglesSet.clear();
|
|
1523
1528
|
trianglesSet = void 0;
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
return
|
|
1529
|
+
polytree.markPolygonsAsOriginal();
|
|
1530
|
+
buildTargetPolytree && polytree.buildTree();
|
|
1531
|
+
return polytree;
|
|
1527
1532
|
};
|
|
1528
1533
|
|
|
1529
|
-
|
|
1530
|
-
var currentMeshSideA, currentMeshSideB,
|
|
1531
|
-
|
|
1534
|
+
Polytree.subtract = function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1535
|
+
var currentMeshSideA, currentMeshSideB, polytree, trianglesSet;
|
|
1536
|
+
polytree = new Polytree();
|
|
1532
1537
|
trianglesSet = new Set();
|
|
1533
|
-
if (
|
|
1538
|
+
if (polytreeA.box.intersectsBox(polytreeB.box)) {
|
|
1534
1539
|
currentMeshSideA = void 0;
|
|
1535
1540
|
currentMeshSideB = void 0;
|
|
1536
|
-
if (
|
|
1537
|
-
currentMeshSideA =
|
|
1538
|
-
|
|
1539
|
-
}
|
|
1540
|
-
if (
|
|
1541
|
-
currentMeshSideB =
|
|
1542
|
-
|
|
1543
|
-
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
if (
|
|
1558
|
-
|
|
1559
|
-
}
|
|
1560
|
-
if (
|
|
1561
|
-
|
|
1541
|
+
if (polytreeA.mesh) {
|
|
1542
|
+
currentMeshSideA = polytreeA.mesh.material.side;
|
|
1543
|
+
polytreeA.mesh.material.side = DoubleSide;
|
|
1544
|
+
}
|
|
1545
|
+
if (polytreeB.mesh) {
|
|
1546
|
+
currentMeshSideB = polytreeB.mesh.material.side;
|
|
1547
|
+
polytreeB.mesh.material.side = DoubleSide;
|
|
1548
|
+
}
|
|
1549
|
+
polytreeA.resetPolygons(false);
|
|
1550
|
+
polytreeB.resetPolygons(false);
|
|
1551
|
+
polytreeA.markIntesectingPolygons(polytreeB);
|
|
1552
|
+
polytreeB.markIntesectingPolygons(polytreeA);
|
|
1553
|
+
handleIntersectingPolytrees(polytreeA, polytreeB);
|
|
1554
|
+
polytreeA.deleteReplacedPolygons();
|
|
1555
|
+
polytreeB.deleteReplacedPolygons();
|
|
1556
|
+
polytreeA.deletePolygonsByStateRules(CSG_Rules.subtract.a);
|
|
1557
|
+
polytreeB.deletePolygonsByStateRules(CSG_Rules.subtract.b);
|
|
1558
|
+
polytreeB.deletePolygonsByIntersection(false);
|
|
1559
|
+
polytreeB.invert();
|
|
1560
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1561
|
+
polytreeB.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1562
|
+
if (polytreeA.mesh && polytreeA.mesh.material.side !== currentMeshSideA) {
|
|
1563
|
+
polytreeA.mesh.material.side = currentMeshSideA;
|
|
1564
|
+
}
|
|
1565
|
+
if (polytreeB.mesh && polytreeB.mesh.material.side !== currentMeshSideB) {
|
|
1566
|
+
polytreeB.mesh.material.side = currentMeshSideB;
|
|
1562
1567
|
}
|
|
1563
1568
|
} else {
|
|
1564
|
-
|
|
1569
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1565
1570
|
}
|
|
1566
1571
|
trianglesSet.clear();
|
|
1567
1572
|
trianglesSet = void 0;
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
//
|
|
1571
|
-
return
|
|
1573
|
+
polytree.markPolygonsAsOriginal();
|
|
1574
|
+
buildTargetPolytree && polytree.buildTree();
|
|
1575
|
+
// polytree.invert()
|
|
1576
|
+
return polytree;
|
|
1572
1577
|
};
|
|
1573
1578
|
|
|
1574
1579
|
/*
|
|
1575
1580
|
Intersect:
|
|
1576
1581
|
1. Delete all polygons in A that are:
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1582
|
+
a. inside and coplanar-back
|
|
1583
|
+
b. outside and coplanar-front
|
|
1584
|
+
c. outside and coplanar-back
|
|
1585
|
+
d. outside
|
|
1581
1586
|
2. Delete all polygons in B that are:
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
+
a. inside and coplanar-front
|
|
1588
|
+
b. inside and coplanar-back
|
|
1589
|
+
c. outside and coplanar-front
|
|
1590
|
+
d. outside and coplanar-back
|
|
1591
|
+
e. outside
|
|
1587
1592
|
*/
|
|
1588
|
-
|
|
1589
|
-
var currentMeshSideA, currentMeshSideB,
|
|
1590
|
-
|
|
1593
|
+
Polytree.intersect = function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1594
|
+
var currentMeshSideA, currentMeshSideB, polytree, trianglesSet;
|
|
1595
|
+
polytree = new Polytree();
|
|
1591
1596
|
trianglesSet = new Set();
|
|
1592
|
-
if (
|
|
1597
|
+
if (polytreeA.box.intersectsBox(polytreeB.box)) {
|
|
1593
1598
|
currentMeshSideA = void 0;
|
|
1594
1599
|
currentMeshSideB = void 0;
|
|
1595
|
-
if (
|
|
1596
|
-
currentMeshSideA =
|
|
1597
|
-
|
|
1598
|
-
}
|
|
1599
|
-
if (
|
|
1600
|
-
currentMeshSideB =
|
|
1601
|
-
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
if (
|
|
1617
|
-
if (
|
|
1618
|
-
|
|
1619
|
-
}
|
|
1620
|
-
}
|
|
1621
|
-
if (
|
|
1622
|
-
if (
|
|
1623
|
-
|
|
1600
|
+
if (polytreeA.mesh) {
|
|
1601
|
+
currentMeshSideA = polytreeA.mesh.material.side;
|
|
1602
|
+
polytreeA.mesh.material.side = DoubleSide;
|
|
1603
|
+
}
|
|
1604
|
+
if (polytreeB.mesh) {
|
|
1605
|
+
currentMeshSideB = polytreeB.mesh.material.side;
|
|
1606
|
+
polytreeB.mesh.material.side = DoubleSide;
|
|
1607
|
+
}
|
|
1608
|
+
polytreeA.resetPolygons(false);
|
|
1609
|
+
polytreeB.resetPolygons(false);
|
|
1610
|
+
polytreeA.markIntesectingPolygons(polytreeB);
|
|
1611
|
+
polytreeB.markIntesectingPolygons(polytreeA);
|
|
1612
|
+
handleIntersectingPolytrees(polytreeA, polytreeB);
|
|
1613
|
+
polytreeA.deleteReplacedPolygons();
|
|
1614
|
+
polytreeB.deleteReplacedPolygons();
|
|
1615
|
+
polytreeA.deletePolygonsByStateRules(CSG_Rules.intersect.a);
|
|
1616
|
+
polytreeB.deletePolygonsByStateRules(CSG_Rules.intersect.b);
|
|
1617
|
+
polytreeA.deletePolygonsByIntersection(false);
|
|
1618
|
+
polytreeB.deletePolygonsByIntersection(false);
|
|
1619
|
+
polytreeA.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1620
|
+
polytreeB.getPolygonCloneCallback(polytree.addPolygon.bind(polytree), trianglesSet);
|
|
1621
|
+
if (polytreeA.mesh) {
|
|
1622
|
+
if (polytreeA.mesh.material.side !== currentMeshSideA) {
|
|
1623
|
+
polytreeA.mesh.material.side = currentMeshSideA;
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
if (polytreeB.mesh) {
|
|
1627
|
+
if (polytreeB.mesh.material.side !== currentMeshSideB) {
|
|
1628
|
+
polytreeB.mesh.material.side = currentMeshSideB;
|
|
1624
1629
|
}
|
|
1625
1630
|
}
|
|
1626
1631
|
}
|
|
1627
1632
|
trianglesSet.clear();
|
|
1628
1633
|
trianglesSet = void 0;
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
return
|
|
1634
|
+
polytree.markPolygonsAsOriginal();
|
|
1635
|
+
buildTargetPolytree && polytree.buildTree();
|
|
1636
|
+
return polytree;
|
|
1632
1637
|
};
|
|
1633
1638
|
|
|
1634
|
-
|
|
1635
|
-
var
|
|
1636
|
-
|
|
1637
|
-
|
|
1639
|
+
Polytree.meshUnion = function(mesh1, mesh2, targetMaterial) {
|
|
1640
|
+
var polytreeA, polytreeB, resultMesh, resultPolytree;
|
|
1641
|
+
polytreeA = void 0;
|
|
1642
|
+
polytreeB = void 0;
|
|
1638
1643
|
if (targetMaterial && Array.isArray(targetMaterial)) {
|
|
1639
|
-
|
|
1640
|
-
|
|
1644
|
+
polytreeA = Polytree.fromMesh(mesh1, 0);
|
|
1645
|
+
polytreeB = Polytree.fromMesh(mesh2, 1);
|
|
1641
1646
|
} else {
|
|
1642
|
-
|
|
1643
|
-
|
|
1647
|
+
polytreeA = Polytree.fromMesh(mesh1);
|
|
1648
|
+
polytreeB = Polytree.fromMesh(mesh2);
|
|
1644
1649
|
targetMaterial = targetMaterial !== void 0 ? targetMaterial : (Array.isArray(mesh1.material) ? mesh1.material[0] : mesh1.material).clone();
|
|
1645
1650
|
}
|
|
1646
|
-
|
|
1647
|
-
resultMesh =
|
|
1648
|
-
|
|
1651
|
+
resultPolytree = Polytree.union(polytreeA, polytreeB, false);
|
|
1652
|
+
resultMesh = Polytree.toMesh(resultPolytree, targetMaterial);
|
|
1653
|
+
disposePolytree(polytreeA, polytreeB, resultPolytree);
|
|
1649
1654
|
return resultMesh;
|
|
1650
1655
|
};
|
|
1651
1656
|
|
|
1652
|
-
|
|
1653
|
-
var
|
|
1654
|
-
|
|
1655
|
-
|
|
1657
|
+
Polytree.meshSubtract = function(mesh1, mesh2, targetMaterial) {
|
|
1658
|
+
var polytreeA, polytreeB, resultMesh, resultPolytree;
|
|
1659
|
+
polytreeA = void 0;
|
|
1660
|
+
polytreeB = void 0;
|
|
1656
1661
|
if (targetMaterial && Array.isArray(targetMaterial)) {
|
|
1657
|
-
|
|
1658
|
-
|
|
1662
|
+
polytreeA = Polytree.fromMesh(mesh1, 0);
|
|
1663
|
+
polytreeB = Polytree.fromMesh(mesh2, 1);
|
|
1659
1664
|
} else {
|
|
1660
|
-
|
|
1661
|
-
|
|
1665
|
+
polytreeA = Polytree.fromMesh(mesh1);
|
|
1666
|
+
polytreeB = Polytree.fromMesh(mesh2);
|
|
1662
1667
|
targetMaterial = targetMaterial !== void 0 ? targetMaterial : (Array.isArray(mesh1.material) ? mesh1.material[0] : mesh1.material).clone();
|
|
1663
1668
|
}
|
|
1664
|
-
|
|
1665
|
-
resultMesh =
|
|
1666
|
-
|
|
1669
|
+
resultPolytree = Polytree.subtract(polytreeA, polytreeB, false);
|
|
1670
|
+
resultMesh = Polytree.toMesh(resultPolytree, targetMaterial);
|
|
1671
|
+
disposePolytree(polytreeA, polytreeB, resultPolytree);
|
|
1667
1672
|
return resultMesh;
|
|
1668
1673
|
};
|
|
1669
1674
|
|
|
1670
|
-
|
|
1671
|
-
var
|
|
1672
|
-
|
|
1673
|
-
|
|
1675
|
+
Polytree.meshIntersect = function(mesh1, mesh2, targetMaterial) {
|
|
1676
|
+
var polytreeA, polytreeB, resultMesh, resultPolytree;
|
|
1677
|
+
polytreeA = void 0;
|
|
1678
|
+
polytreeB = void 0;
|
|
1674
1679
|
if (targetMaterial && Array.isArray(targetMaterial)) {
|
|
1675
|
-
|
|
1676
|
-
|
|
1680
|
+
polytreeA = Polytree.fromMesh(mesh1, 0);
|
|
1681
|
+
polytreeB = Polytree.fromMesh(mesh2, 1);
|
|
1677
1682
|
} else {
|
|
1678
|
-
|
|
1679
|
-
|
|
1683
|
+
polytreeA = Polytree.fromMesh(mesh1);
|
|
1684
|
+
polytreeB = Polytree.fromMesh(mesh2);
|
|
1680
1685
|
targetMaterial = targetMaterial !== void 0 ? targetMaterial : (Array.isArray(mesh1.material) ? mesh1.material[0] : mesh1.material).clone();
|
|
1681
1686
|
}
|
|
1682
|
-
|
|
1683
|
-
resultMesh =
|
|
1684
|
-
|
|
1687
|
+
resultPolytree = Polytree.intersect(polytreeA, polytreeB, false);
|
|
1688
|
+
resultMesh = Polytree.toMesh(resultPolytree, targetMaterial);
|
|
1689
|
+
disposePolytree(polytreeA, polytreeB, resultPolytree);
|
|
1685
1690
|
return resultMesh;
|
|
1686
1691
|
};
|
|
1687
1692
|
|
|
@@ -1689,45 +1694,45 @@ _asyncUnionID = 0;
|
|
|
1689
1694
|
|
|
1690
1695
|
_asyncUnionArrayID = 0;
|
|
1691
1696
|
|
|
1692
|
-
|
|
1697
|
+
Polytree.disposePolytree = true;
|
|
1693
1698
|
|
|
1694
|
-
|
|
1699
|
+
Polytree.async = {
|
|
1695
1700
|
batchSize: 100,
|
|
1696
|
-
union: function(
|
|
1701
|
+
union: function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1697
1702
|
return new Promise(function(resolve, reject) {
|
|
1698
1703
|
var e, result;
|
|
1699
1704
|
try {
|
|
1700
1705
|
// const id = _asyncUnionID++
|
|
1701
1706
|
// console.log("Promise Union ##{id} started")
|
|
1702
|
-
result =
|
|
1707
|
+
result = Polytree.union(polytreeA, polytreeB, buildTargetPolytree);
|
|
1703
1708
|
resolve(result);
|
|
1704
|
-
return
|
|
1709
|
+
return disposePolytree(polytreeA, polytreeB);
|
|
1705
1710
|
} catch (error) {
|
|
1706
1711
|
e = error;
|
|
1707
1712
|
return reject(e);
|
|
1708
1713
|
}
|
|
1709
1714
|
});
|
|
1710
1715
|
},
|
|
1711
|
-
subtract: function(
|
|
1716
|
+
subtract: function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1712
1717
|
return new Promise(function(resolve, reject) {
|
|
1713
1718
|
var e, result;
|
|
1714
1719
|
try {
|
|
1715
|
-
result =
|
|
1720
|
+
result = Polytree.subtract(polytreeA, polytreeB, buildTargetPolytree);
|
|
1716
1721
|
resolve(result);
|
|
1717
|
-
return
|
|
1722
|
+
return disposePolytree(polytreeA, polytreeB);
|
|
1718
1723
|
} catch (error) {
|
|
1719
1724
|
e = error;
|
|
1720
1725
|
return reject(e);
|
|
1721
1726
|
}
|
|
1722
1727
|
});
|
|
1723
1728
|
},
|
|
1724
|
-
intersect: function(
|
|
1729
|
+
intersect: function(polytreeA, polytreeB, buildTargetPolytree = true) {
|
|
1725
1730
|
return new Promise(function(resolve, reject) {
|
|
1726
1731
|
var e, result;
|
|
1727
1732
|
try {
|
|
1728
|
-
result =
|
|
1733
|
+
result = Polytree.intersect(polytreeA, polytreeB, buildTargetPolytree);
|
|
1729
1734
|
resolve(result);
|
|
1730
|
-
return
|
|
1735
|
+
return disposePolytree(polytreeA, polytreeB);
|
|
1731
1736
|
} catch (error) {
|
|
1732
1737
|
e = error;
|
|
1733
1738
|
return reject(e);
|
|
@@ -1736,89 +1741,89 @@ OctreeCSG.async = {
|
|
|
1736
1741
|
},
|
|
1737
1742
|
unionArray: function(objArr, materialIndexMax = 2e308) {
|
|
1738
1743
|
return new Promise(function(resolve, reject) {
|
|
1739
|
-
var batch, batches, currentIndex, e, hasLeftOver, i, k, l,
|
|
1744
|
+
var batch, batches, currentIndex, e, hasLeftOver, i, k, l, leftOverPolytree, mainPolytree, mainPolytreeUsed, materialIndex, polytreesArray, promise, promises, ref, ref1, result, tempPolytree, usingBatches;
|
|
1740
1745
|
try {
|
|
1741
|
-
usingBatches =
|
|
1746
|
+
usingBatches = Polytree.async.batchSize > 4 && Polytree.async.batchSize < objArr.length;
|
|
1742
1747
|
// const id = _asyncUnionArrayID++
|
|
1743
1748
|
// console.log("Promise Union Array ##{id}", usingBatches)
|
|
1744
|
-
|
|
1745
|
-
|
|
1749
|
+
mainPolytree = void 0;
|
|
1750
|
+
mainPolytreeUsed = false;
|
|
1746
1751
|
promises = [];
|
|
1747
1752
|
if (usingBatches) {
|
|
1748
1753
|
batches = [];
|
|
1749
1754
|
currentIndex = 0;
|
|
1750
1755
|
while (currentIndex < objArr.length) {
|
|
1751
|
-
batches.push(objArr.slice(currentIndex, currentIndex +
|
|
1752
|
-
currentIndex +=
|
|
1756
|
+
batches.push(objArr.slice(currentIndex, currentIndex + Polytree.async.batchSize));
|
|
1757
|
+
currentIndex += Polytree.async.batchSize;
|
|
1753
1758
|
}
|
|
1754
1759
|
batch = batches.shift();
|
|
1755
1760
|
while (batch) {
|
|
1756
|
-
promise =
|
|
1761
|
+
promise = Polytree.async.unionArray(batch, 0);
|
|
1757
1762
|
promises.push(promise);
|
|
1758
1763
|
batch = batches.shift();
|
|
1759
1764
|
}
|
|
1760
1765
|
usingBatches = true;
|
|
1761
|
-
|
|
1766
|
+
mainPolytreeUsed = true;
|
|
1762
1767
|
objArr.length = 0;
|
|
1763
1768
|
} else {
|
|
1764
|
-
|
|
1769
|
+
polytreesArray = [];
|
|
1765
1770
|
for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
1766
1771
|
materialIndex = i > materialIndexMax ? materialIndexMax : i;
|
|
1767
|
-
|
|
1772
|
+
tempPolytree = void 0;
|
|
1768
1773
|
if (objArr[i].isMesh) {
|
|
1769
|
-
|
|
1774
|
+
tempPolytree = Polytree.fromMesh(objArr[i], materialIndexMax > -1 ? materialIndex : void 0);
|
|
1770
1775
|
} else {
|
|
1771
|
-
|
|
1776
|
+
tempPolytree = objArr[i];
|
|
1772
1777
|
if (materialIndexMax > -1) {
|
|
1773
|
-
|
|
1778
|
+
tempPolytree.setPolygonIndex(materialIndex);
|
|
1774
1779
|
}
|
|
1775
1780
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1781
|
+
tempPolytree.polytreeIndex = i;
|
|
1782
|
+
polytreesArray.push(tempPolytree);
|
|
1778
1783
|
}
|
|
1779
|
-
|
|
1784
|
+
mainPolytree = polytreesArray.shift();
|
|
1780
1785
|
result = void 0;
|
|
1781
1786
|
hasLeftOver = false;
|
|
1782
|
-
|
|
1783
|
-
for (i = l = 0, ref1 =
|
|
1784
|
-
if (i + 1 >=
|
|
1785
|
-
|
|
1787
|
+
leftOverPolytree = void 0;
|
|
1788
|
+
for (i = l = 0, ref1 = polytreesArray.length; l < ref1; i = l += 2) {
|
|
1789
|
+
if (i + 1 >= polytreesArray.length) {
|
|
1790
|
+
leftOverPolytree = polytreesArray[i];
|
|
1786
1791
|
hasLeftOver = true;
|
|
1787
1792
|
break;
|
|
1788
1793
|
}
|
|
1789
|
-
promise =
|
|
1794
|
+
promise = Polytree.async.union(polytreesArray[i], polytreesArray[i + 1]);
|
|
1790
1795
|
promises.push(promise);
|
|
1791
1796
|
}
|
|
1792
|
-
if (
|
|
1793
|
-
promise =
|
|
1797
|
+
if (leftOverPolytree) {
|
|
1798
|
+
promise = Polytree.async.union(mainPolytree, leftOverPolytree);
|
|
1794
1799
|
promises.push(promise);
|
|
1795
|
-
|
|
1800
|
+
mainPolytreeUsed = true;
|
|
1796
1801
|
}
|
|
1797
1802
|
}
|
|
1798
1803
|
return Promise.allSettled(promises).then(function(results) {
|
|
1799
|
-
var
|
|
1800
|
-
|
|
1804
|
+
var polytrees;
|
|
1805
|
+
polytrees = [];
|
|
1801
1806
|
results.forEach(function(r) {
|
|
1802
1807
|
if (r.status === "fulfilled") {
|
|
1803
|
-
return
|
|
1808
|
+
return polytrees.push(r.value);
|
|
1804
1809
|
}
|
|
1805
1810
|
});
|
|
1806
|
-
if (!
|
|
1807
|
-
|
|
1811
|
+
if (!mainPolytreeUsed) {
|
|
1812
|
+
polytrees.unshift(mainPolytree);
|
|
1808
1813
|
}
|
|
1809
|
-
if (
|
|
1810
|
-
if (
|
|
1811
|
-
return resolve(
|
|
1812
|
-
} else if (
|
|
1813
|
-
return
|
|
1814
|
+
if (polytrees.length > 0) {
|
|
1815
|
+
if (polytrees.length === 1) {
|
|
1816
|
+
return resolve(polytrees[0]);
|
|
1817
|
+
} else if (polytrees.length > 3) {
|
|
1818
|
+
return Polytree.async.unionArray(polytrees, usingBatches ? 0 : -1).then(function(result) {
|
|
1814
1819
|
return resolve(result);
|
|
1815
1820
|
}).catch(function(e) {
|
|
1816
1821
|
return reject(e);
|
|
1817
1822
|
});
|
|
1818
1823
|
} else {
|
|
1819
|
-
return
|
|
1820
|
-
if (
|
|
1821
|
-
return
|
|
1824
|
+
return Polytree.async.union(polytrees[0], polytrees[1]).then(function(result) {
|
|
1825
|
+
if (polytrees.length === 3) {
|
|
1826
|
+
return Polytree.async.union(result, polytrees[2]).then(function(result) {
|
|
1822
1827
|
return resolve(result);
|
|
1823
1828
|
}).catch(function(e) {
|
|
1824
1829
|
return reject(e);
|
|
@@ -1831,7 +1836,7 @@ OctreeCSG.async = {
|
|
|
1831
1836
|
});
|
|
1832
1837
|
}
|
|
1833
1838
|
} else {
|
|
1834
|
-
return reject('Unable to find any result
|
|
1839
|
+
return reject('Unable to find any result polytree');
|
|
1835
1840
|
}
|
|
1836
1841
|
});
|
|
1837
1842
|
} catch (error) {
|
|
@@ -1842,87 +1847,87 @@ OctreeCSG.async = {
|
|
|
1842
1847
|
},
|
|
1843
1848
|
subtractArray: function(objArr, materialIndexMax = 2e308) {
|
|
1844
1849
|
return new Promise(function(resolve, reject) {
|
|
1845
|
-
var batch, batches, currentIndex, e, hasLeftOver, i, k, l,
|
|
1850
|
+
var batch, batches, currentIndex, e, hasLeftOver, i, k, l, leftOverPolytree, mainPolytree, mainPolytreeUsed, materialIndex, polytreesArray, promise, promises, ref, ref1, result, tempPolytree, usingBatches;
|
|
1846
1851
|
try {
|
|
1847
|
-
usingBatches =
|
|
1848
|
-
|
|
1849
|
-
|
|
1852
|
+
usingBatches = Polytree.async.batchSize > 4 && Polytree.async.batchSize < objArr.length;
|
|
1853
|
+
mainPolytree = void 0;
|
|
1854
|
+
mainPolytreeUsed = false;
|
|
1850
1855
|
promises = [];
|
|
1851
1856
|
if (usingBatches) {
|
|
1852
1857
|
batches = [];
|
|
1853
1858
|
currentIndex = 0;
|
|
1854
1859
|
while (currentIndex < objArr.length) {
|
|
1855
|
-
batches.push(objArr.slice(currentIndex, currentIndex +
|
|
1856
|
-
currentIndex +=
|
|
1860
|
+
batches.push(objArr.slice(currentIndex, currentIndex + Polytree.async.batchSize));
|
|
1861
|
+
currentIndex += Polytree.async.batchSize;
|
|
1857
1862
|
}
|
|
1858
1863
|
batch = batches.shift();
|
|
1859
1864
|
while (batch) {
|
|
1860
|
-
promise =
|
|
1865
|
+
promise = Polytree.async.subtractArray(batch, 0);
|
|
1861
1866
|
promises.push(promise);
|
|
1862
1867
|
batch = batches.shift();
|
|
1863
1868
|
}
|
|
1864
1869
|
usingBatches = true;
|
|
1865
|
-
|
|
1870
|
+
mainPolytreeUsed = true;
|
|
1866
1871
|
objArr.length = 0;
|
|
1867
1872
|
} else {
|
|
1868
|
-
|
|
1873
|
+
polytreesArray = [];
|
|
1869
1874
|
for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
1870
1875
|
materialIndex = i > materialIndexMax ? materialIndexMax : i;
|
|
1871
|
-
|
|
1876
|
+
tempPolytree = void 0;
|
|
1872
1877
|
if (objArr[i].isMesh) {
|
|
1873
|
-
|
|
1878
|
+
tempPolytree = Polytree.fromMesh(objArr[i], materialIndexMax > -1 ? materialIndex : void 0);
|
|
1874
1879
|
} else {
|
|
1875
|
-
|
|
1880
|
+
tempPolytree = objArr[i];
|
|
1876
1881
|
if (materialIndexMax > -1) {
|
|
1877
|
-
|
|
1882
|
+
tempPolytree.setPolygonIndex(materialIndex);
|
|
1878
1883
|
}
|
|
1879
1884
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1885
|
+
tempPolytree.polytreeIndex = i;
|
|
1886
|
+
polytreesArray.push(tempPolytree);
|
|
1882
1887
|
}
|
|
1883
|
-
|
|
1888
|
+
mainPolytree = polytreesArray.shift();
|
|
1884
1889
|
result = void 0;
|
|
1885
1890
|
hasLeftOver = false;
|
|
1886
|
-
|
|
1887
|
-
for (i = l = 0, ref1 =
|
|
1888
|
-
if (i + 1 >=
|
|
1889
|
-
|
|
1891
|
+
leftOverPolytree = void 0;
|
|
1892
|
+
for (i = l = 0, ref1 = polytreesArray.length; l < ref1; i = l += 2) {
|
|
1893
|
+
if (i + 1 >= polytreesArray.length) {
|
|
1894
|
+
leftOverPolytree = polytreesArray[i];
|
|
1890
1895
|
hasLeftOver = true;
|
|
1891
1896
|
break;
|
|
1892
1897
|
}
|
|
1893
|
-
promise =
|
|
1898
|
+
promise = Polytree.async.subtract(polytreesArray[i], polytreesArray[i + 1]);
|
|
1894
1899
|
promises.push(promise);
|
|
1895
1900
|
}
|
|
1896
|
-
if (
|
|
1897
|
-
promise =
|
|
1901
|
+
if (leftOverPolytree) {
|
|
1902
|
+
promise = Polytree.async.subtract(mainPolytree, leftOverPolytree);
|
|
1898
1903
|
promises.push(promise);
|
|
1899
|
-
|
|
1904
|
+
mainPolytreeUsed = true;
|
|
1900
1905
|
}
|
|
1901
1906
|
}
|
|
1902
1907
|
return Promise.allSettled(promises).then(function(results) {
|
|
1903
|
-
var
|
|
1904
|
-
|
|
1908
|
+
var polytrees;
|
|
1909
|
+
polytrees = [];
|
|
1905
1910
|
results.forEach(function(r) {
|
|
1906
1911
|
if (r.status === "fulfilled") {
|
|
1907
|
-
return
|
|
1912
|
+
return polytrees.push(r.value);
|
|
1908
1913
|
}
|
|
1909
1914
|
});
|
|
1910
|
-
if (!
|
|
1911
|
-
|
|
1915
|
+
if (!mainPolytreeUsed) {
|
|
1916
|
+
polytrees.unshift(mainPolytree);
|
|
1912
1917
|
}
|
|
1913
|
-
if (
|
|
1914
|
-
if (
|
|
1915
|
-
return resolve(
|
|
1916
|
-
} else if (
|
|
1917
|
-
return
|
|
1918
|
+
if (polytrees.length > 0) {
|
|
1919
|
+
if (polytrees.length === 1) {
|
|
1920
|
+
return resolve(polytrees[0]);
|
|
1921
|
+
} else if (polytrees.length > 3) {
|
|
1922
|
+
return Polytree.async.subtractArray(polytrees, usingBatches ? 0 : -1).then(function(result) {
|
|
1918
1923
|
return resolve(result);
|
|
1919
1924
|
}).catch(function(e) {
|
|
1920
1925
|
return reject(e);
|
|
1921
1926
|
});
|
|
1922
1927
|
} else {
|
|
1923
|
-
return
|
|
1924
|
-
if (
|
|
1925
|
-
return
|
|
1928
|
+
return Polytree.async.subtract(polytrees[0], polytrees[1]).then(function(result) {
|
|
1929
|
+
if (polytrees.length === 3) {
|
|
1930
|
+
return Polytree.async.subtract(result, polytrees[2]).then(function(result) {
|
|
1926
1931
|
return resolve(result);
|
|
1927
1932
|
}).catch(function(e) {
|
|
1928
1933
|
return reject(e);
|
|
@@ -1935,7 +1940,7 @@ OctreeCSG.async = {
|
|
|
1935
1940
|
});
|
|
1936
1941
|
}
|
|
1937
1942
|
} else {
|
|
1938
|
-
return reject('Unable to find any result
|
|
1943
|
+
return reject('Unable to find any result polytree');
|
|
1939
1944
|
}
|
|
1940
1945
|
});
|
|
1941
1946
|
} catch (error) {
|
|
@@ -1946,87 +1951,87 @@ OctreeCSG.async = {
|
|
|
1946
1951
|
},
|
|
1947
1952
|
intersectArray: function(objArr, materialIndexMax = 2e308) {
|
|
1948
1953
|
return new Promise(function(resolve, reject) {
|
|
1949
|
-
var batch, batches, currentIndex, e, hasLeftOver, i, k, l,
|
|
1954
|
+
var batch, batches, currentIndex, e, hasLeftOver, i, k, l, leftOverPolytree, mainPolytree, mainPolytreeUsed, materialIndex, polytreesArray, promise, promises, ref, ref1, result, tempPolytree, usingBatches;
|
|
1950
1955
|
try {
|
|
1951
|
-
usingBatches =
|
|
1952
|
-
|
|
1953
|
-
|
|
1956
|
+
usingBatches = Polytree.async.batchSize > 4 && Polytree.async.batchSize < objArr.length;
|
|
1957
|
+
mainPolytree = void 0;
|
|
1958
|
+
mainPolytreeUsed = false;
|
|
1954
1959
|
promises = [];
|
|
1955
1960
|
if (usingBatches) {
|
|
1956
1961
|
batches = [];
|
|
1957
1962
|
currentIndex = 0;
|
|
1958
1963
|
while (currentIndex < objArr.length) {
|
|
1959
|
-
batches.push(objArr.slice(currentIndex, currentIndex +
|
|
1960
|
-
currentIndex +=
|
|
1964
|
+
batches.push(objArr.slice(currentIndex, currentIndex + Polytree.async.batchSize));
|
|
1965
|
+
currentIndex += Polytree.async.batchSize;
|
|
1961
1966
|
}
|
|
1962
1967
|
batch = batches.shift();
|
|
1963
1968
|
while (batch) {
|
|
1964
|
-
promise =
|
|
1969
|
+
promise = Polytree.async.intersectArray(batch, 0);
|
|
1965
1970
|
promises.push(promise);
|
|
1966
1971
|
batch = batches.shift();
|
|
1967
1972
|
}
|
|
1968
1973
|
usingBatches = true;
|
|
1969
|
-
|
|
1974
|
+
mainPolytreeUsed = true;
|
|
1970
1975
|
objArr.length = 0;
|
|
1971
1976
|
} else {
|
|
1972
|
-
|
|
1977
|
+
polytreesArray = [];
|
|
1973
1978
|
for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
1974
1979
|
materialIndex = i > materialIndexMax ? materialIndexMax : i;
|
|
1975
|
-
|
|
1980
|
+
tempPolytree = void 0;
|
|
1976
1981
|
if (objArr[i].isMesh) {
|
|
1977
|
-
|
|
1982
|
+
tempPolytree = Polytree.fromMesh(objArr[i], materialIndexMax > -1 ? materialIndex : void 0);
|
|
1978
1983
|
} else {
|
|
1979
|
-
|
|
1984
|
+
tempPolytree = objArr[i];
|
|
1980
1985
|
if (materialIndexMax > -1) {
|
|
1981
|
-
|
|
1986
|
+
tempPolytree.setPolygonIndex(materialIndex);
|
|
1982
1987
|
}
|
|
1983
1988
|
}
|
|
1984
|
-
|
|
1985
|
-
|
|
1989
|
+
tempPolytree.polytreeIndex = i;
|
|
1990
|
+
polytreesArray.push(tempPolytree);
|
|
1986
1991
|
}
|
|
1987
|
-
|
|
1992
|
+
mainPolytree = polytreesArray.shift();
|
|
1988
1993
|
result = void 0;
|
|
1989
1994
|
hasLeftOver = false;
|
|
1990
|
-
|
|
1991
|
-
for (i = l = 0, ref1 =
|
|
1992
|
-
if (i + 1 >=
|
|
1993
|
-
|
|
1995
|
+
leftOverPolytree = void 0;
|
|
1996
|
+
for (i = l = 0, ref1 = polytreesArray.length; l < ref1; i = l += 2) {
|
|
1997
|
+
if (i + 1 >= polytreesArray.length) {
|
|
1998
|
+
leftOverPolytree = polytreesArray[i];
|
|
1994
1999
|
hasLeftOver = true;
|
|
1995
2000
|
break;
|
|
1996
2001
|
}
|
|
1997
|
-
promise =
|
|
2002
|
+
promise = Polytree.async.intersect(polytreesArray[i], polytreesArray[i + 1]);
|
|
1998
2003
|
promises.push(promise);
|
|
1999
2004
|
}
|
|
2000
|
-
if (
|
|
2001
|
-
promise =
|
|
2005
|
+
if (leftOverPolytree) {
|
|
2006
|
+
promise = Polytree.async.intersect(mainPolytree, leftOverPolytree);
|
|
2002
2007
|
promises.push(promise);
|
|
2003
|
-
|
|
2008
|
+
mainPolytreeUsed = true;
|
|
2004
2009
|
}
|
|
2005
2010
|
}
|
|
2006
2011
|
return Promise.allSettled(promises).then(function(results) {
|
|
2007
|
-
var
|
|
2008
|
-
|
|
2012
|
+
var polytrees;
|
|
2013
|
+
polytrees = [];
|
|
2009
2014
|
results.forEach(function(r) {
|
|
2010
2015
|
if (r.status === "fulfilled") {
|
|
2011
|
-
return
|
|
2016
|
+
return polytrees.push(r.value);
|
|
2012
2017
|
}
|
|
2013
2018
|
});
|
|
2014
|
-
if (!
|
|
2015
|
-
|
|
2019
|
+
if (!mainPolytreeUsed) {
|
|
2020
|
+
polytrees.unshift(mainPolytree);
|
|
2016
2021
|
}
|
|
2017
|
-
if (
|
|
2018
|
-
if (
|
|
2019
|
-
return resolve(
|
|
2020
|
-
} else if (
|
|
2021
|
-
return
|
|
2022
|
+
if (polytrees.length > 0) {
|
|
2023
|
+
if (polytrees.length === 1) {
|
|
2024
|
+
return resolve(polytrees[0]);
|
|
2025
|
+
} else if (polytrees.length > 3) {
|
|
2026
|
+
return Polytree.async.intersectArray(polytrees, usingBatches ? 0 : -1).then(function(result) {
|
|
2022
2027
|
return resolve(result);
|
|
2023
2028
|
}).catch(function(e) {
|
|
2024
2029
|
return reject(e);
|
|
2025
2030
|
});
|
|
2026
2031
|
} else {
|
|
2027
|
-
return
|
|
2028
|
-
if (
|
|
2029
|
-
return
|
|
2032
|
+
return Polytree.async.intersect(polytrees[0], polytrees[1]).then(function(result) {
|
|
2033
|
+
if (polytrees.length === 3) {
|
|
2034
|
+
return Polytree.async.intersect(result, polytrees[2]).then(function(result) {
|
|
2030
2035
|
return resolve(result);
|
|
2031
2036
|
}).catch(function(e) {
|
|
2032
2037
|
return reject(e);
|
|
@@ -2039,7 +2044,7 @@ OctreeCSG.async = {
|
|
|
2039
2044
|
});
|
|
2040
2045
|
}
|
|
2041
2046
|
} else {
|
|
2042
|
-
return reject('Unable to find any result
|
|
2047
|
+
return reject('Unable to find any result polytree');
|
|
2043
2048
|
}
|
|
2044
2049
|
});
|
|
2045
2050
|
} catch (error) {
|
|
@@ -2048,78 +2053,78 @@ OctreeCSG.async = {
|
|
|
2048
2053
|
}
|
|
2049
2054
|
});
|
|
2050
2055
|
},
|
|
2051
|
-
operation: function(obj,
|
|
2056
|
+
operation: function(obj, returnPolytrees = false, buildTargetPolytree = true, options = {
|
|
2052
2057
|
objCounter: 0
|
|
2053
2058
|
}, firstRun = true) {
|
|
2054
2059
|
return new Promise(function(resolve, reject) {
|
|
2055
|
-
var e, material,
|
|
2060
|
+
var e, material, polytreeA, polytreeB, promise, promises, resultPolytree;
|
|
2056
2061
|
try {
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2062
|
+
polytreeA = void 0;
|
|
2063
|
+
polytreeB = void 0;
|
|
2064
|
+
resultPolytree = void 0;
|
|
2060
2065
|
material = void 0;
|
|
2061
2066
|
if (obj.material) {
|
|
2062
2067
|
material = obj.material;
|
|
2063
2068
|
}
|
|
2064
2069
|
promises = [];
|
|
2065
2070
|
if (obj.objA) {
|
|
2066
|
-
promise = handleObjectForOp_async(obj.objA,
|
|
2071
|
+
promise = handleObjectForOp_async(obj.objA, returnPolytrees, buildTargetPolytree, options, 0);
|
|
2067
2072
|
promises.push(promise);
|
|
2068
2073
|
}
|
|
2069
2074
|
if (obj.objB) {
|
|
2070
|
-
promise = handleObjectForOp_async(obj.objB,
|
|
2075
|
+
promise = handleObjectForOp_async(obj.objB, returnPolytrees, buildTargetPolytree, options, 1);
|
|
2071
2076
|
promises.push(promise);
|
|
2072
2077
|
}
|
|
2073
2078
|
return Promise.allSettled(promises).then(function(results) {
|
|
2074
|
-
var
|
|
2075
|
-
|
|
2079
|
+
var polytrees, resultPromise;
|
|
2080
|
+
polytrees = [];
|
|
2076
2081
|
results.forEach(function(r) {
|
|
2077
2082
|
if (r.status === "fulfilled") {
|
|
2078
2083
|
if (r.value.objIndex === 0) {
|
|
2079
|
-
return
|
|
2084
|
+
return polytreeA = r.value;
|
|
2080
2085
|
} else if (r.value.objIndex === 1) {
|
|
2081
|
-
return
|
|
2086
|
+
return polytreeB = r.value;
|
|
2082
2087
|
}
|
|
2083
2088
|
}
|
|
2084
2089
|
});
|
|
2085
|
-
if (
|
|
2086
|
-
obj.objA =
|
|
2087
|
-
|
|
2088
|
-
obj.objB =
|
|
2089
|
-
|
|
2090
|
+
if (returnPolytrees === true) {
|
|
2091
|
+
obj.objA = polytreeA.original;
|
|
2092
|
+
polytreeA = polytreeA.result;
|
|
2093
|
+
obj.objB = polytreeB.original;
|
|
2094
|
+
polytreeB = polytreeB.result;
|
|
2090
2095
|
}
|
|
2091
2096
|
resultPromise = void 0;
|
|
2092
2097
|
switch (obj.op) {
|
|
2093
2098
|
case 'union':
|
|
2094
|
-
resultPromise =
|
|
2099
|
+
resultPromise = Polytree.async.union(polytreeA, polytreeB, buildTargetPolytree);
|
|
2095
2100
|
break;
|
|
2096
2101
|
case 'subtract':
|
|
2097
|
-
resultPromise =
|
|
2102
|
+
resultPromise = Polytree.async.subtract(polytreeA, polytreeB, buildTargetPolytree);
|
|
2098
2103
|
break;
|
|
2099
2104
|
case 'intersect':
|
|
2100
|
-
resultPromise =
|
|
2105
|
+
resultPromise = Polytree.async.intersect(polytreeA, polytreeB, buildTargetPolytree);
|
|
2101
2106
|
}
|
|
2102
|
-
return resultPromise.then(function(
|
|
2107
|
+
return resultPromise.then(function(resultPolytree) {
|
|
2103
2108
|
var mesh;
|
|
2104
2109
|
if (firstRun && material) {
|
|
2105
|
-
mesh =
|
|
2106
|
-
if (!
|
|
2107
|
-
|
|
2110
|
+
mesh = Polytree.toMesh(resultPolytree, material);
|
|
2111
|
+
if (!returnPolytrees) {
|
|
2112
|
+
disposePolytree(resultPolytree);
|
|
2108
2113
|
}
|
|
2109
|
-
resolve(
|
|
2114
|
+
resolve(returnPolytrees ? {
|
|
2110
2115
|
result: mesh,
|
|
2111
2116
|
operationTree: obj
|
|
2112
2117
|
} : mesh);
|
|
2113
|
-
} else if (firstRun &&
|
|
2118
|
+
} else if (firstRun && returnPolytrees) {
|
|
2114
2119
|
resolve({
|
|
2115
|
-
result:
|
|
2120
|
+
result: resultPolytree,
|
|
2116
2121
|
operationTree: obj
|
|
2117
2122
|
});
|
|
2118
2123
|
} else {
|
|
2119
|
-
resolve(
|
|
2124
|
+
resolve(resultPolytree);
|
|
2120
2125
|
}
|
|
2121
|
-
if (!
|
|
2122
|
-
return
|
|
2126
|
+
if (!returnPolytrees) {
|
|
2127
|
+
return disposePolytree(polytreeA, polytreeB);
|
|
2123
2128
|
}
|
|
2124
2129
|
}).catch(function(e) {
|
|
2125
2130
|
return reject(e);
|
|
@@ -2133,126 +2138,126 @@ OctreeCSG.async = {
|
|
|
2133
2138
|
}
|
|
2134
2139
|
};
|
|
2135
2140
|
|
|
2136
|
-
|
|
2137
|
-
var i, k, materialIndex,
|
|
2138
|
-
|
|
2141
|
+
Polytree.unionArray = function(objArr, materialIndexMax = 2e308) {
|
|
2142
|
+
var i, k, materialIndex, polytreeA, polytreeB, polytreesArray, ref, resultPolytree, tempPolytree;
|
|
2143
|
+
polytreesArray = [];
|
|
2139
2144
|
for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
2140
2145
|
materialIndex = i > materialIndexMax ? materialIndexMax : i;
|
|
2141
|
-
|
|
2146
|
+
tempPolytree = void 0;
|
|
2142
2147
|
if (objArr[i].isMesh) {
|
|
2143
|
-
|
|
2148
|
+
tempPolytree = Polytree.fromMesh(objArr[i], materialIndex);
|
|
2144
2149
|
} else {
|
|
2145
|
-
|
|
2146
|
-
|
|
2150
|
+
tempPolytree = objArr[i];
|
|
2151
|
+
tempPolytree.setPolygonIndex(materialIndex);
|
|
2147
2152
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2153
|
+
tempPolytree.polytreeIndex = i;
|
|
2154
|
+
polytreesArray.push(tempPolytree);
|
|
2150
2155
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
while (
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2156
|
+
polytreeA = polytreesArray.shift();
|
|
2157
|
+
polytreeB = polytreesArray.shift();
|
|
2158
|
+
while (polytreeA && polytreeB) {
|
|
2159
|
+
resultPolytree = Polytree.union(polytreeA, polytreeB);
|
|
2160
|
+
disposePolytree(polytreeA, polytreeB);
|
|
2161
|
+
polytreeA = resultPolytree;
|
|
2162
|
+
polytreeB = polytreesArray.shift();
|
|
2158
2163
|
}
|
|
2159
|
-
return
|
|
2164
|
+
return polytreeA;
|
|
2160
2165
|
};
|
|
2161
2166
|
|
|
2162
|
-
|
|
2163
|
-
var i, k, materialIndex,
|
|
2164
|
-
|
|
2167
|
+
Polytree.subtractArray = function(objArr, materialIndexMax = 2e308) {
|
|
2168
|
+
var i, k, materialIndex, polytreeA, polytreeB, polytreesArray, ref, resultPolytree, tempPolytree;
|
|
2169
|
+
polytreesArray = [];
|
|
2165
2170
|
for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
2166
2171
|
materialIndex = i > materialIndexMax ? materialIndexMax : i;
|
|
2167
|
-
|
|
2172
|
+
tempPolytree = void 0;
|
|
2168
2173
|
if (objArr[i].isMesh) {
|
|
2169
|
-
|
|
2174
|
+
tempPolytree = Polytree.fromMesh(objArr[i], materialIndex);
|
|
2170
2175
|
} else {
|
|
2171
|
-
|
|
2172
|
-
|
|
2176
|
+
tempPolytree = objArr[i];
|
|
2177
|
+
tempPolytree.setPolygonIndex(materialIndex);
|
|
2173
2178
|
}
|
|
2174
|
-
|
|
2175
|
-
|
|
2179
|
+
tempPolytree.polytreeIndex = i;
|
|
2180
|
+
polytreesArray.push(tempPolytree);
|
|
2176
2181
|
}
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
while (
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2182
|
+
polytreeA = polytreesArray.shift();
|
|
2183
|
+
polytreeB = polytreesArray.shift();
|
|
2184
|
+
while (polytreeA && polytreeB) {
|
|
2185
|
+
resultPolytree = Polytree.subtract(polytreeA, polytreeB);
|
|
2186
|
+
disposePolytree(polytreeA, polytreeB);
|
|
2187
|
+
polytreeA = resultPolytree;
|
|
2188
|
+
polytreeB = polytreesArray.shift();
|
|
2184
2189
|
}
|
|
2185
|
-
return
|
|
2190
|
+
return polytreeA;
|
|
2186
2191
|
};
|
|
2187
2192
|
|
|
2188
|
-
|
|
2189
|
-
var i, k, materialIndex,
|
|
2190
|
-
|
|
2193
|
+
Polytree.intersectArray = function(objArr, materialIndexMax = 2e308) {
|
|
2194
|
+
var i, k, materialIndex, polytreeA, polytreeB, polytreesArray, ref, resultPolytree, tempPolytree;
|
|
2195
|
+
polytreesArray = [];
|
|
2191
2196
|
for (i = k = 0, ref = objArr.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
2192
2197
|
materialIndex = i > materialIndexMax ? materialIndexMax : i;
|
|
2193
|
-
|
|
2198
|
+
tempPolytree = void 0;
|
|
2194
2199
|
if (objArr[i].isMesh) {
|
|
2195
|
-
|
|
2200
|
+
tempPolytree = Polytree.fromMesh(objArr[i], materialIndex);
|
|
2196
2201
|
} else {
|
|
2197
|
-
|
|
2198
|
-
|
|
2202
|
+
tempPolytree = objArr[i];
|
|
2203
|
+
tempPolytree.setPolygonIndex(materialIndex);
|
|
2199
2204
|
}
|
|
2200
|
-
|
|
2201
|
-
|
|
2205
|
+
tempPolytree.polytreeIndex = i;
|
|
2206
|
+
polytreesArray.push(tempPolytree);
|
|
2202
2207
|
}
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
while (
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2208
|
+
polytreeA = polytreesArray.shift();
|
|
2209
|
+
polytreeB = polytreesArray.shift();
|
|
2210
|
+
while (polytreeA && polytreeB) {
|
|
2211
|
+
resultPolytree = Polytree.intersect(polytreeA, polytreeB);
|
|
2212
|
+
disposePolytree(polytreeA, polytreeB);
|
|
2213
|
+
polytreeA = resultPolytree;
|
|
2214
|
+
polytreeB = polytreesArray.shift();
|
|
2210
2215
|
}
|
|
2211
|
-
return
|
|
2216
|
+
return polytreeA;
|
|
2212
2217
|
};
|
|
2213
2218
|
|
|
2214
|
-
|
|
2219
|
+
Polytree.operation = function(obj, returnPolytrees = false, buildTargetPolytree = true, options = {
|
|
2215
2220
|
objCounter: 0
|
|
2216
2221
|
}, firstRun = true) {
|
|
2217
|
-
var material, mesh,
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2222
|
+
var material, mesh, polytreeA, polytreeB, resultPolytree;
|
|
2223
|
+
polytreeA = void 0;
|
|
2224
|
+
polytreeB = void 0;
|
|
2225
|
+
resultPolytree = void 0;
|
|
2221
2226
|
material = void 0;
|
|
2222
2227
|
if (obj.material) {
|
|
2223
2228
|
material = obj.material;
|
|
2224
2229
|
}
|
|
2225
2230
|
if (obj.objA) {
|
|
2226
|
-
|
|
2227
|
-
if (
|
|
2228
|
-
obj.objA =
|
|
2229
|
-
|
|
2231
|
+
polytreeA = handleObjectForOp(obj.objA, returnPolytrees, buildTargetPolytree, options);
|
|
2232
|
+
if (returnPolytrees === true) {
|
|
2233
|
+
obj.objA = polytreeA.original;
|
|
2234
|
+
polytreeA = polytreeA.result;
|
|
2230
2235
|
}
|
|
2231
2236
|
}
|
|
2232
2237
|
if (obj.objB) {
|
|
2233
|
-
|
|
2234
|
-
if (
|
|
2235
|
-
obj.objB =
|
|
2236
|
-
|
|
2238
|
+
polytreeB = handleObjectForOp(obj.objB, returnPolytrees, buildTargetPolytree, options);
|
|
2239
|
+
if (returnPolytrees === true) {
|
|
2240
|
+
obj.objB = polytreeB.original;
|
|
2241
|
+
polytreeB = polytreeB.result;
|
|
2237
2242
|
}
|
|
2238
2243
|
}
|
|
2239
2244
|
switch (obj.op) {
|
|
2240
2245
|
case 'union':
|
|
2241
|
-
|
|
2246
|
+
resultPolytree = Polytree.union(polytreeA, polytreeB, buildTargetPolytree);
|
|
2242
2247
|
break;
|
|
2243
2248
|
case 'subtract':
|
|
2244
|
-
|
|
2249
|
+
resultPolytree = Polytree.subtract(polytreeA, polytreeB, buildTargetPolytree);
|
|
2245
2250
|
break;
|
|
2246
2251
|
case 'intersect':
|
|
2247
|
-
|
|
2252
|
+
resultPolytree = Polytree.intersect(polytreeA, polytreeB, buildTargetPolytree);
|
|
2248
2253
|
}
|
|
2249
|
-
if (!
|
|
2250
|
-
|
|
2254
|
+
if (!returnPolytrees) {
|
|
2255
|
+
disposePolytree(polytreeA, polytreeB);
|
|
2251
2256
|
}
|
|
2252
2257
|
if (firstRun && material) {
|
|
2253
|
-
mesh =
|
|
2254
|
-
|
|
2255
|
-
if (
|
|
2258
|
+
mesh = Polytree.toMesh(resultPolytree, material);
|
|
2259
|
+
disposePolytree(resultPolytree);
|
|
2260
|
+
if (returnPolytrees) {
|
|
2256
2261
|
return {
|
|
2257
2262
|
result: mesh,
|
|
2258
2263
|
operationTree: obj
|
|
@@ -2261,37 +2266,37 @@ OctreeCSG.operation = function(obj, returnOctrees = false, buildTargetOctree = t
|
|
|
2261
2266
|
return mesh;
|
|
2262
2267
|
}
|
|
2263
2268
|
}
|
|
2264
|
-
if (firstRun &&
|
|
2269
|
+
if (firstRun && returnPolytrees) {
|
|
2265
2270
|
return {
|
|
2266
|
-
result:
|
|
2271
|
+
result: resultPolytree,
|
|
2267
2272
|
operationTree: obj
|
|
2268
2273
|
};
|
|
2269
2274
|
}
|
|
2270
|
-
return
|
|
2275
|
+
return resultPolytree;
|
|
2271
2276
|
};
|
|
2272
2277
|
|
|
2273
|
-
handleObjectForOp = function(obj,
|
|
2278
|
+
handleObjectForOp = function(obj, returnPolytrees, buildTargetPolytree, options) {
|
|
2274
2279
|
var returnObj;
|
|
2275
2280
|
returnObj = void 0;
|
|
2276
2281
|
if (obj.isMesh) {
|
|
2277
|
-
returnObj =
|
|
2278
|
-
if (
|
|
2282
|
+
returnObj = Polytree.fromMesh(obj, options.objCounter++);
|
|
2283
|
+
if (returnPolytrees) {
|
|
2279
2284
|
returnObj = {
|
|
2280
2285
|
result: returnObj,
|
|
2281
2286
|
original: returnObj.clone()
|
|
2282
2287
|
};
|
|
2283
2288
|
}
|
|
2284
|
-
} else if (obj.
|
|
2289
|
+
} else if (obj.isPolytree) {
|
|
2285
2290
|
returnObj = obj;
|
|
2286
|
-
if (
|
|
2291
|
+
if (returnPolytrees) {
|
|
2287
2292
|
returnObj = {
|
|
2288
2293
|
result: obj,
|
|
2289
2294
|
original: obj.clone()
|
|
2290
2295
|
};
|
|
2291
2296
|
}
|
|
2292
2297
|
} else if (obj.op) {
|
|
2293
|
-
returnObj =
|
|
2294
|
-
if (
|
|
2298
|
+
returnObj = Polytree.operation(obj, returnPolytrees, buildTargetPolytree, options, false);
|
|
2299
|
+
if (returnPolytrees) {
|
|
2295
2300
|
returnObj = {
|
|
2296
2301
|
result: returnObj,
|
|
2297
2302
|
original: obj
|
|
@@ -2301,14 +2306,14 @@ handleObjectForOp = function(obj, returnOctrees, buildTargetOctree, options) {
|
|
|
2301
2306
|
return returnObj;
|
|
2302
2307
|
};
|
|
2303
2308
|
|
|
2304
|
-
handleObjectForOp_async = function(obj,
|
|
2309
|
+
handleObjectForOp_async = function(obj, returnPolytrees, buildTargetPolytree, options, objIndex) {
|
|
2305
2310
|
return new Promise(function(resolve, reject) {
|
|
2306
2311
|
var e, returnObj;
|
|
2307
2312
|
try {
|
|
2308
2313
|
returnObj = void 0;
|
|
2309
2314
|
if (obj.isMesh) {
|
|
2310
|
-
returnObj =
|
|
2311
|
-
if (
|
|
2315
|
+
returnObj = Polytree.fromMesh(obj, options.objCounter++);
|
|
2316
|
+
if (returnPolytrees) {
|
|
2312
2317
|
returnObj = {
|
|
2313
2318
|
result: returnObj,
|
|
2314
2319
|
original: returnObj.clone()
|
|
@@ -2316,9 +2321,9 @@ handleObjectForOp_async = function(obj, returnOctrees, buildTargetOctree, option
|
|
|
2316
2321
|
}
|
|
2317
2322
|
returnObj.objIndex = objIndex;
|
|
2318
2323
|
return resolve(returnObj);
|
|
2319
|
-
} else if (obj.
|
|
2324
|
+
} else if (obj.isPolytree) {
|
|
2320
2325
|
returnObj = obj;
|
|
2321
|
-
if (
|
|
2326
|
+
if (returnPolytrees) {
|
|
2322
2327
|
returnObj = {
|
|
2323
2328
|
result: obj,
|
|
2324
2329
|
original: obj.clone()
|
|
@@ -2327,8 +2332,8 @@ handleObjectForOp_async = function(obj, returnOctrees, buildTargetOctree, option
|
|
|
2327
2332
|
returnObj.objIndex = objIndex;
|
|
2328
2333
|
return resolve(returnObj);
|
|
2329
2334
|
} else if (obj.op) {
|
|
2330
|
-
return
|
|
2331
|
-
if (
|
|
2335
|
+
return Polytree.async.operation(obj, returnPolytrees, buildTargetPolytree, options, false).then(function(returnObj) {
|
|
2336
|
+
if (returnPolytrees) {
|
|
2332
2337
|
returnObj = {
|
|
2333
2338
|
result: returnObj,
|
|
2334
2339
|
original: obj
|
|
@@ -2388,9 +2393,9 @@ tmpm3 = new Matrix3();
|
|
|
2388
2393
|
|
|
2389
2394
|
ttvv0 = new Vector3();
|
|
2390
2395
|
|
|
2391
|
-
|
|
2396
|
+
Polytree.toGeometry = function(polytree) {
|
|
2392
2397
|
var colors, defaultGroup, geometry, groupBase, groups, i, index, k, l, len1, m, normals, polygon, polygons, positions, ref, ref1, triangleCount, uvs, vertices, verticesLen;
|
|
2393
|
-
polygons =
|
|
2398
|
+
polygons = polytree.getPolygons();
|
|
2394
2399
|
triangleCount = polygons.length;
|
|
2395
2400
|
// let validPolygons = [];
|
|
2396
2401
|
// let trianglesSet = new Set();
|
|
@@ -2472,19 +2477,19 @@ OctreeCSG.toGeometry = function(octree) {
|
|
|
2472
2477
|
return geometry;
|
|
2473
2478
|
};
|
|
2474
2479
|
|
|
2475
|
-
|
|
2480
|
+
Polytree.toMesh = function(polytree, toMaterial) {
|
|
2476
2481
|
var geometry;
|
|
2477
|
-
geometry =
|
|
2482
|
+
geometry = Polytree.toGeometry(polytree);
|
|
2478
2483
|
return new Mesh(geometry, toMaterial);
|
|
2479
2484
|
};
|
|
2480
2485
|
|
|
2481
|
-
|
|
2482
|
-
var color, colorattr, geometry, group, groups, i, index, j, k, l, len1, m, normal, normalattr,
|
|
2483
|
-
if (obj.
|
|
2486
|
+
Polytree.fromMesh = function(obj, objectIndex, polytree = new Polytree(), buildTargetPolytree = true) {
|
|
2487
|
+
var color, colorattr, geometry, group, groups, i, index, j, k, l, len1, m, n, normal, normalattr, polygon, polys, pos, posattr, positionIndex, ref, ref1, uvCoords, uvIndex, uvattr, vertexIndex, vertices;
|
|
2488
|
+
if (obj.isPolytree) {
|
|
2484
2489
|
return obj;
|
|
2485
2490
|
}
|
|
2486
|
-
if (
|
|
2487
|
-
|
|
2491
|
+
if (Polytree.rayIntersectTriangleType === "regular") {
|
|
2492
|
+
polytree.originalMatrixWorld = obj.matrixWorld.clone();
|
|
2488
2493
|
}
|
|
2489
2494
|
obj.updateWorldMatrix(true, true);
|
|
2490
2495
|
geometry = obj.geometry;
|
|
@@ -2501,23 +2506,23 @@ OctreeCSG.fromMesh = function(obj, objectIndex, octree = new OctreeCSG(), buildT
|
|
|
2501
2506
|
for (i = k = 0, ref = index.length; k < ref; i = k += 3) {
|
|
2502
2507
|
vertices = [];
|
|
2503
2508
|
for (j = l = 0; l < 3; j = ++l) {
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
pos = new Vector3(posattr.array[
|
|
2508
|
-
normal = new Vector3(normalattr.array[
|
|
2509
|
+
vertexIndex = index[i + j];
|
|
2510
|
+
positionIndex = vertexIndex * 3;
|
|
2511
|
+
uvIndex = vertexIndex * 2;
|
|
2512
|
+
pos = new Vector3(posattr.array[positionIndex], posattr.array[positionIndex + 1], posattr.array[positionIndex + 2]);
|
|
2513
|
+
normal = new Vector3(normalattr.array[positionIndex], normalattr.array[positionIndex + 1], normalattr.array[positionIndex + 2]);
|
|
2509
2514
|
pos.applyMatrix4(obj.matrix);
|
|
2510
2515
|
normal.applyMatrix3(tmpm3);
|
|
2511
|
-
|
|
2512
|
-
x: uvattr.array[
|
|
2513
|
-
y: uvattr.array[
|
|
2516
|
+
uvCoords = uvattr ? {
|
|
2517
|
+
x: uvattr.array[uvIndex],
|
|
2518
|
+
y: uvattr.array[uvIndex + 1]
|
|
2514
2519
|
} : void 0;
|
|
2515
2520
|
color = colorattr ? {
|
|
2516
|
-
x: colorattr.array[
|
|
2517
|
-
y: colorattr.array[
|
|
2518
|
-
z: colorattr.array[
|
|
2521
|
+
x: colorattr.array[uvIndex],
|
|
2522
|
+
y: colorattr.array[uvIndex + 1],
|
|
2523
|
+
z: colorattr.array[uvIndex + 2]
|
|
2519
2524
|
} : void 0;
|
|
2520
|
-
vertices.push(new Vertex(pos, normal,
|
|
2525
|
+
vertices.push(new Vertex(pos, normal, uvCoords, color));
|
|
2521
2526
|
}
|
|
2522
2527
|
if ((objectIndex === void 0) && groups && groups.length > 0) {
|
|
2523
2528
|
polygon = void 0;
|
|
@@ -2537,18 +2542,18 @@ OctreeCSG.fromMesh = function(obj, objectIndex, octree = new OctreeCSG(), buildT
|
|
|
2537
2542
|
polys.push(polygon);
|
|
2538
2543
|
}
|
|
2539
2544
|
}
|
|
2540
|
-
for (i =
|
|
2545
|
+
for (i = n = 0, ref1 = polys.length; (0 <= ref1 ? n < ref1 : n > ref1); i = 0 <= ref1 ? ++n : --n) {
|
|
2541
2546
|
if (isValidTriangle(polys[i].triangle)) {
|
|
2542
|
-
|
|
2547
|
+
polytree.addPolygon(polys[i]);
|
|
2543
2548
|
} else {
|
|
2544
2549
|
polys[i].delete();
|
|
2545
2550
|
}
|
|
2546
2551
|
}
|
|
2547
|
-
|
|
2548
|
-
if (
|
|
2549
|
-
|
|
2552
|
+
buildTargetPolytree && polytree.buildTree();
|
|
2553
|
+
if (Polytree.usePolytreeRay !== true) {
|
|
2554
|
+
polytree.mesh = obj;
|
|
2550
2555
|
}
|
|
2551
|
-
return
|
|
2556
|
+
return polytree;
|
|
2552
2557
|
};
|
|
2553
2558
|
|
|
2554
2559
|
isValidTriangle = function(triangle) {
|
|
@@ -2622,9 +2627,9 @@ Plane = class Plane {
|
|
|
2622
2627
|
};
|
|
2623
2628
|
|
|
2624
2629
|
Plane.fromPoints = function(a, b, c) {
|
|
2625
|
-
var
|
|
2626
|
-
|
|
2627
|
-
return new Plane(
|
|
2630
|
+
var planeNormal;
|
|
2631
|
+
planeNormal = triangleVertex0.copy(b).sub(a).cross(triangleVertex1.copy(c).sub(a)).normalize().clone();
|
|
2632
|
+
return new Plane(planeNormal, planeNormal.dot(a));
|
|
2628
2633
|
};
|
|
2629
2634
|
|
|
2630
2635
|
// class Polygon
|
|
@@ -2758,10 +2763,10 @@ Polygon = class Polygon {
|
|
|
2758
2763
|
|
|
2759
2764
|
};
|
|
2760
2765
|
|
|
2761
|
-
|
|
2762
|
-
if (
|
|
2763
|
-
return
|
|
2764
|
-
return
|
|
2766
|
+
disposePolytree = function(...polytrees) {
|
|
2767
|
+
if (Polytree.disposePolytree) {
|
|
2768
|
+
return polytrees.forEach(function(polytree) {
|
|
2769
|
+
return polytree.delete();
|
|
2765
2770
|
});
|
|
2766
2771
|
}
|
|
2767
2772
|
};
|
|
@@ -2832,23 +2837,23 @@ polyInside_WindingNumber_buffer = function(trianglesArr, point, coplanar) {
|
|
|
2832
2837
|
};
|
|
2833
2838
|
|
|
2834
2839
|
// -----
|
|
2835
|
-
|
|
2836
|
-
var
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
if (
|
|
2840
|
-
if (
|
|
2841
|
-
|
|
2840
|
+
handleIntersectingPolytrees = function(polytreeA, polytreeB, bothPolytrees = true) {
|
|
2841
|
+
var polytreeA_buffer, polytreeB_buffer;
|
|
2842
|
+
polytreeA_buffer = void 0;
|
|
2843
|
+
polytreeB_buffer = void 0;
|
|
2844
|
+
if (Polytree.useWindingNumber === true) {
|
|
2845
|
+
if (bothPolytrees) {
|
|
2846
|
+
polytreeA_buffer = prepareTriangleBuffer(polytreeA.getPolygons());
|
|
2842
2847
|
}
|
|
2843
|
-
|
|
2848
|
+
polytreeB_buffer = prepareTriangleBuffer(polytreeB.getPolygons());
|
|
2844
2849
|
}
|
|
2845
|
-
|
|
2846
|
-
if (
|
|
2847
|
-
|
|
2850
|
+
polytreeA.handleIntersectingPolygons(polytreeB, polytreeB_buffer);
|
|
2851
|
+
if (bothPolytrees) {
|
|
2852
|
+
polytreeB.handleIntersectingPolygons(polytreeA, polytreeA_buffer);
|
|
2848
2853
|
}
|
|
2849
|
-
if (
|
|
2850
|
-
|
|
2851
|
-
return
|
|
2854
|
+
if (polytreeA_buffer !== void 0) {
|
|
2855
|
+
polytreeA_buffer = void 0;
|
|
2856
|
+
return polytreeB_buffer = void 0;
|
|
2852
2857
|
}
|
|
2853
2858
|
};
|
|
2854
2859
|
|
|
@@ -2912,28 +2917,17 @@ rayIntersectsTriangle = function(ray, triangle, target = new Vector3()) {
|
|
|
2912
2917
|
return null;
|
|
2913
2918
|
};
|
|
2914
2919
|
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
OctreeCSG.useOctreeRay = true;
|
|
2920
|
+
Polytree.rayIntersectsTriangle = rayIntersectsTriangle;
|
|
2918
2921
|
|
|
2919
|
-
|
|
2922
|
+
Polytree.usePolytreeRay = true;
|
|
2920
2923
|
|
|
2921
|
-
|
|
2924
|
+
Polytree.useWindingNumber = false;
|
|
2922
2925
|
|
|
2923
|
-
|
|
2926
|
+
Polytree.rayIntersectTriangleType = "MollerTrumbore"; // "regular" (three.js' ray.intersectTriangle; "MollerTrumbore" (Moller Trumbore algorithm);
|
|
2924
2927
|
|
|
2925
|
-
|
|
2928
|
+
Polytree.maxLevel = 16;
|
|
2926
2929
|
|
|
2927
|
-
|
|
2928
|
-
module.exports = {
|
|
2929
|
-
default: OctreeCSG,
|
|
2930
|
-
CSG: OctreeCSG,
|
|
2931
|
-
OctreeCSG: OctreeCSG,
|
|
2932
|
-
Polygon: Polygon,
|
|
2933
|
-
Plane: Plane,
|
|
2934
|
-
Vertex: Vertex,
|
|
2935
|
-
rayIntersectsTriangle: rayIntersectsTriangle
|
|
2936
|
-
};
|
|
2930
|
+
Polytree.polygonsPerTree = 100;
|
|
2937
2931
|
// Generated by CoffeeScript 2.7.0
|
|
2938
2932
|
|
|
2939
2933
|
/* Determines the intersection segment (if any) between two triangles in 3D space.
|
|
@@ -3324,6 +3318,7 @@ resolveCoplanarTriangleIntersection = function(vertex1TriangleA, vertex2Triangle
|
|
|
3324
3318
|
};
|
|
3325
3319
|
|
|
3326
3320
|
trianglesOverlap2D = function(vertex1TriangleA, vertex2TriangleA, vertex3TriangleA, vertex1TriangleB, vertex2TriangleB, vertex3TriangleB) {
|
|
3321
|
+
var aE, aMax, aMin, aS, bE, bMax, bMin, bS, extractSegment, isLineDegenerate, maxAx, maxAy, maxBx, maxBy, minAx, minAy, minBx, minBy, spanAx, spanAy;
|
|
3327
3322
|
// Early handle point-degenerate cases explicitly and efficiently.
|
|
3328
3323
|
if (pointsEqual2D(vertex1TriangleB, vertex2TriangleB, EPS2D) && pointsEqual2D(vertex2TriangleB, vertex3TriangleB, EPS2D)) {
|
|
3329
3324
|
return pointInTriangleInclusive2D(vertex1TriangleB, vertex1TriangleA, vertex2TriangleA, vertex3TriangleA, EPS2D);
|
|
@@ -3331,6 +3326,60 @@ trianglesOverlap2D = function(vertex1TriangleA, vertex2TriangleA, vertex3Triangl
|
|
|
3331
3326
|
if (pointsEqual2D(vertex1TriangleA, vertex2TriangleA, EPS2D) && pointsEqual2D(vertex2TriangleA, vertex3TriangleA, EPS2D)) {
|
|
3332
3327
|
return pointInTriangleInclusive2D(vertex1TriangleA, vertex1TriangleB, vertex2TriangleB, vertex3TriangleB, EPS2D);
|
|
3333
3328
|
}
|
|
3329
|
+
// If both are line-degenerate (not points): reduce to segment overlap test.
|
|
3330
|
+
isLineDegenerate = function(v1, v2, v3) {
|
|
3331
|
+
return (pointsEqual2D(v1, v2, EPS2D) && !pointsEqual2D(v2, v3, EPS2D)) || (pointsEqual2D(v2, v3, EPS2D) && !pointsEqual2D(v1, v2, EPS2D)) || (pointsEqual2D(v3, v1, EPS2D) && !pointsEqual2D(v1, v2, EPS2D));
|
|
3332
|
+
};
|
|
3333
|
+
extractSegment = function(v1, v2, v3) {
|
|
3334
|
+
// Return the two distinct endpoints in stable order.
|
|
3335
|
+
if (pointsEqual2D(v1, v2, EPS2D)) {
|
|
3336
|
+
return [v2, v3];
|
|
3337
|
+
} else if (pointsEqual2D(v2, v3, EPS2D)) {
|
|
3338
|
+
return [v1, v2];
|
|
3339
|
+
} else {
|
|
3340
|
+
return [
|
|
3341
|
+
v1,
|
|
3342
|
+
v2 // fallback (should not reach if collinear case handled earlier)
|
|
3343
|
+
];
|
|
3344
|
+
}
|
|
3345
|
+
};
|
|
3346
|
+
if (isLineDegenerate(vertex1TriangleA, vertex2TriangleA, vertex3TriangleA) && isLineDegenerate(vertex1TriangleB, vertex2TriangleB, vertex3TriangleB)) {
|
|
3347
|
+
[aS, aE] = extractSegment(vertex1TriangleA, vertex2TriangleA, vertex3TriangleA);
|
|
3348
|
+
[bS, bE] = extractSegment(vertex1TriangleB, vertex2TriangleB, vertex3TriangleB);
|
|
3349
|
+
// Fast reject by axis-aligned bounding boxes.
|
|
3350
|
+
minAx = Math.min(aS.x, aE.x);
|
|
3351
|
+
maxAx = Math.max(aS.x, aE.x);
|
|
3352
|
+
minAy = Math.min(aS.y, aE.y);
|
|
3353
|
+
maxAy = Math.max(aS.y, aE.y);
|
|
3354
|
+
minBx = Math.min(bS.x, bE.x);
|
|
3355
|
+
maxBx = Math.max(bS.x, bE.x);
|
|
3356
|
+
minBy = Math.min(bS.y, bE.y);
|
|
3357
|
+
maxBy = Math.max(bS.y, bE.y);
|
|
3358
|
+
if (maxAx < minBx - EPS2D || maxBx < minAx - EPS2D || maxAy < minBy - EPS2D || maxBy < minAy - EPS2D) {
|
|
3359
|
+
return false;
|
|
3360
|
+
}
|
|
3361
|
+
// Collinear check: orientation of any mixed triple should be ~0; since we know each triangle is a line, test one.
|
|
3362
|
+
if (Math.abs(triangleOrientation2D(aS, aE, bS)) > EPS2D) {
|
|
3363
|
+
return false;
|
|
3364
|
+
}
|
|
3365
|
+
// 1D overlap test along dominant axis (choose axis with larger span to reduce precision issues).
|
|
3366
|
+
spanAx = Math.abs(aE.x - aS.x);
|
|
3367
|
+
spanAy = Math.abs(aE.y - aS.y);
|
|
3368
|
+
if (spanAx >= spanAy) {
|
|
3369
|
+
// Project onto X.
|
|
3370
|
+
aMin = Math.min(aS.x, aE.x) - EPS2D;
|
|
3371
|
+
aMax = Math.max(aS.x, aE.x) + EPS2D;
|
|
3372
|
+
bMin = Math.min(bS.x, bE.x) - EPS2D;
|
|
3373
|
+
bMax = Math.max(bS.x, bE.x) + EPS2D;
|
|
3374
|
+
return !(aMax < bMin || bMax < aMin);
|
|
3375
|
+
} else {
|
|
3376
|
+
aMin = Math.min(aS.y, aE.y) - EPS2D;
|
|
3377
|
+
aMax = Math.max(aS.y, aE.y) + EPS2D;
|
|
3378
|
+
bMin = Math.min(bS.y, bE.y) - EPS2D;
|
|
3379
|
+
bMax = Math.max(bS.y, bE.y) + EPS2D;
|
|
3380
|
+
return !(aMax < bMin || bMax < aMin);
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3334
3383
|
if (triangleOrientation2D(vertex1TriangleA, vertex2TriangleA, vertex3TriangleA) < 0) { // If triangle A is CW.
|
|
3335
3384
|
if (triangleOrientation2D(vertex1TriangleB, vertex2TriangleB, vertex3TriangleB) < 0) { // If both A and B are CW → reorder both.
|
|
3336
3385
|
return triangleIntersectionCCW2D(vertex1TriangleA, vertex3TriangleA, vertex2TriangleA, vertex1TriangleB, vertex3TriangleB, vertex2TriangleB); // Only A is CW → reorder A.
|
|
@@ -3389,132 +3438,79 @@ triangleIntersectionCCW2D = function(vertex1TriangleA, vertex2TriangleA, vertex3
|
|
|
3389
3438
|
};
|
|
3390
3439
|
|
|
3391
3440
|
intersectionTestEdge2D = function(vertex1TriangleA, vertex2TriangleA, vertex3TriangleA, vertex1TriangleB, vertex2TriangleB, vertex3TriangleB) {
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
return false; // Then vertex3TriangleB is outside edge vertex1TriangleB-vertex2TriangleA.
|
|
3414
|
-
}
|
|
3441
|
+
var a1, a2, b1, b2, edgesA, edgesB, i, j, len, len1, segmentIntersectsInclusive;
|
|
3442
|
+
segmentIntersectsInclusive = function(a1, a2, b1, b2) {
|
|
3443
|
+
var maxAx, maxAy, maxBx, maxBy, minAx, minAy, minBx, minBy, o1, o2, o3, o4;
|
|
3444
|
+
// Fast reject by bounding boxes.
|
|
3445
|
+
minAx = Math.min(a1.x, a2.x);
|
|
3446
|
+
maxAx = Math.max(a1.x, a2.x);
|
|
3447
|
+
minAy = Math.min(a1.y, a2.y);
|
|
3448
|
+
maxAy = Math.max(a1.y, a2.y);
|
|
3449
|
+
minBx = Math.min(b1.x, b2.x);
|
|
3450
|
+
maxBx = Math.max(b1.x, b2.x);
|
|
3451
|
+
minBy = Math.min(b1.y, b2.y);
|
|
3452
|
+
maxBy = Math.max(b1.y, b2.y);
|
|
3453
|
+
if (maxAx < minBx || maxBx < minAx || maxAy < minBy || maxBy < minAy) {
|
|
3454
|
+
return false;
|
|
3455
|
+
}
|
|
3456
|
+
o1 = triangleOrientation2D(a1, a2, b1);
|
|
3457
|
+
o2 = triangleOrientation2D(a1, a2, b2);
|
|
3458
|
+
o3 = triangleOrientation2D(b1, b2, a1);
|
|
3459
|
+
o4 = triangleOrientation2D(b1, b2, a2);
|
|
3460
|
+
if ((o1 > 0 && o2 < 0 || o1 < 0 && o2 > 0) && (o3 > 0 && o4 < 0 || o3 < 0 && o4 > 0)) {
|
|
3461
|
+
return true; // Proper intersection.
|
|
3415
3462
|
}
|
|
3416
|
-
} else {
|
|
3417
3463
|
|
|
3418
|
-
//
|
|
3419
|
-
if (
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3464
|
+
// Collinear / endpoint inclusion checks.
|
|
3465
|
+
if (Math.abs(o1) <= EPS2D && pointOnSegmentInclusive2D(b1, a1, a2, EPS2D)) {
|
|
3466
|
+
return true;
|
|
3467
|
+
}
|
|
3468
|
+
if (Math.abs(o2) <= EPS2D && pointOnSegmentInclusive2D(b2, a1, a2, EPS2D)) {
|
|
3469
|
+
return true;
|
|
3470
|
+
}
|
|
3471
|
+
if (Math.abs(o3) <= EPS2D && pointOnSegmentInclusive2D(a1, b1, b2, EPS2D)) {
|
|
3472
|
+
return true;
|
|
3473
|
+
}
|
|
3474
|
+
if (Math.abs(o4) <= EPS2D && pointOnSegmentInclusive2D(a2, b1, b2, EPS2D)) {
|
|
3475
|
+
return true;
|
|
3476
|
+
}
|
|
3477
|
+
return false;
|
|
3478
|
+
};
|
|
3479
|
+
edgesA = [[vertex1TriangleA, vertex2TriangleA], [vertex2TriangleA, vertex3TriangleA], [vertex3TriangleA, vertex1TriangleA]];
|
|
3480
|
+
edgesB = [[vertex1TriangleB, vertex2TriangleB], [vertex2TriangleB, vertex3TriangleB], [vertex3TriangleB, vertex1TriangleB]];
|
|
3481
|
+
for (i = 0, len = edgesA.length; i < len; i++) {
|
|
3482
|
+
[a1, a2] = edgesA[i];
|
|
3483
|
+
for (j = 0, len1 = edgesB.length; j < len1; j++) {
|
|
3484
|
+
[b1, b2] = edgesB[j];
|
|
3485
|
+
if (segmentIntersectsInclusive(a1, a2, b1, b2)) {
|
|
3486
|
+
return true;
|
|
3435
3487
|
}
|
|
3436
|
-
} else {
|
|
3437
|
-
return false;
|
|
3438
3488
|
}
|
|
3439
3489
|
}
|
|
3490
|
+
return false;
|
|
3440
3491
|
};
|
|
3441
3492
|
|
|
3442
3493
|
intersectionTestVertex2D = function(vertex1TriangleA, vertex2TriangleA, vertex3TriangleA, vertex1TriangleB, vertex2TriangleB, vertex3TriangleB) {
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
return true; // Then vertex2TriangleA is outside edge vertex3TriangleA-vertex1TriangleB.
|
|
3462
|
-
} else {
|
|
3463
|
-
return false; // Then vertex1TriangleA is outside edge vertex1TriangleB-vertex3TriangleA.
|
|
3464
|
-
}
|
|
3465
|
-
} else {
|
|
3466
|
-
return false; // Then vertex3TriangleB is on the left of edge vertex2TriangleB-vertex2TriangleA.
|
|
3467
|
-
}
|
|
3468
|
-
}
|
|
3469
|
-
} else {
|
|
3470
|
-
|
|
3471
|
-
// If vertex1TriangleA is on or to the left of edge vertex2TriangleB-vertex2TriangleA.
|
|
3472
|
-
if (triangleOrientation2D(vertex1TriangleA, vertex2TriangleB, vertex2TriangleA) <= 0) {
|
|
3473
|
-
// If vertex3TriangleB is on or to the left of edge vertex2TriangleB-vertex3TriangleA.
|
|
3474
|
-
if (triangleOrientation2D(vertex3TriangleB, vertex2TriangleB, vertex3TriangleA) <= 0) {
|
|
3475
|
-
// If vertex2TriangleA is on or to the left of edge vertex3TriangleA-vertex2TriangleB.
|
|
3476
|
-
if (triangleOrientation2D(vertex2TriangleA, vertex3TriangleA, vertex2TriangleB) >= 0) {
|
|
3477
|
-
return true; // Then vertex2TriangleA is outside edge vertex3TriangleA-vertex2TriangleB.
|
|
3478
|
-
} else {
|
|
3479
|
-
return false; // Then vertex3TriangleB is outside edge vertex2TriangleB-vertex3TriangleA.
|
|
3480
|
-
}
|
|
3481
|
-
} else {
|
|
3482
|
-
return false; // Then vertex1TriangleA is outside edge vertex2TriangleB-vertex2TriangleA.
|
|
3483
|
-
}
|
|
3484
|
-
} else {
|
|
3485
|
-
return false; // Then vertex3TriangleB is outside edge vertex1TriangleB-vertex2TriangleA.
|
|
3486
|
-
}
|
|
3487
|
-
}
|
|
3488
|
-
} else {
|
|
3489
|
-
|
|
3490
|
-
// If vertex3TriangleB is on or to the left of edge vertex1TriangleB-vertex3TriangleA.
|
|
3491
|
-
if (triangleOrientation2D(vertex3TriangleB, vertex1TriangleB, vertex3TriangleA) >= 0) {
|
|
3492
|
-
// If vertex2TriangleA is on or to the left of edge vertex3TriangleA-vertex3TriangleB.
|
|
3493
|
-
if (triangleOrientation2D(vertex2TriangleA, vertex3TriangleA, vertex3TriangleB) >= 0) {
|
|
3494
|
-
// If vertex1TriangleA is on or to the left of edge vertex1TriangleB-vertex3TriangleA.
|
|
3495
|
-
if (triangleOrientation2D(vertex1TriangleA, vertex1TriangleB, vertex3TriangleA) >= 0) {
|
|
3496
|
-
return true; // Then vertex1TriangleA is outside edge vertex1TriangleB-vertex3TriangleA.
|
|
3497
|
-
} else {
|
|
3498
|
-
return false; // Then vertex2TriangleA is outside edge vertex3TriangleA-vertex3TriangleB.
|
|
3499
|
-
}
|
|
3500
|
-
} else {
|
|
3501
|
-
|
|
3502
|
-
// If vertex2TriangleA is on or to the left of edge vertex3TriangleA-vertex2TriangleB.
|
|
3503
|
-
if (triangleOrientation2D(vertex2TriangleA, vertex3TriangleA, vertex2TriangleB) >= 0) {
|
|
3504
|
-
// If vertex3TriangleB is on or to the left of edge vertex3TriangleA-vertex2TriangleB.
|
|
3505
|
-
if (triangleOrientation2D(vertex3TriangleB, vertex3TriangleA, vertex2TriangleB) >= 0) {
|
|
3506
|
-
return true; // Then vertex3TriangleB is outside edge vertex3TriangleA-vertex2TriangleB.
|
|
3507
|
-
} else {
|
|
3508
|
-
return false; // Then vertex2TriangleA is outside edge vertex3TriangleA-vertex2TriangleB.
|
|
3509
|
-
}
|
|
3510
|
-
} else {
|
|
3511
|
-
return false; // Then vertex3TriangleB is outside edge vertex1TriangleB-vertex3TriangleA.
|
|
3512
|
-
}
|
|
3513
|
-
}
|
|
3514
|
-
} else {
|
|
3515
|
-
return false;
|
|
3516
|
-
}
|
|
3494
|
+
if (pointInTriangleInclusive2D(vertex1TriangleB, vertex1TriangleA, vertex2TriangleA, vertex3TriangleA, EPS2D)) {
|
|
3495
|
+
// Returns true if any vertex of triangle B lies inside (or on) triangle A OR any vertex of triangle A lies inside (or on) triangle B.
|
|
3496
|
+
return true;
|
|
3497
|
+
}
|
|
3498
|
+
if (pointInTriangleInclusive2D(vertex2TriangleB, vertex1TriangleA, vertex2TriangleA, vertex3TriangleA, EPS2D)) {
|
|
3499
|
+
return true;
|
|
3500
|
+
}
|
|
3501
|
+
if (pointInTriangleInclusive2D(vertex3TriangleB, vertex1TriangleA, vertex2TriangleA, vertex3TriangleA, EPS2D)) {
|
|
3502
|
+
return true;
|
|
3503
|
+
}
|
|
3504
|
+
if (pointInTriangleInclusive2D(vertex1TriangleA, vertex1TriangleB, vertex2TriangleB, vertex3TriangleB, EPS2D)) {
|
|
3505
|
+
return true;
|
|
3506
|
+
}
|
|
3507
|
+
if (pointInTriangleInclusive2D(vertex2TriangleA, vertex1TriangleB, vertex2TriangleB, vertex3TriangleB, EPS2D)) {
|
|
3508
|
+
return true;
|
|
3509
|
+
}
|
|
3510
|
+
if (pointInTriangleInclusive2D(vertex3TriangleA, vertex1TriangleB, vertex2TriangleB, vertex3TriangleB, EPS2D)) {
|
|
3511
|
+
return true;
|
|
3517
3512
|
}
|
|
3513
|
+
return false;
|
|
3518
3514
|
};
|
|
3519
3515
|
|
|
3520
3516
|
constructIntersection = function(vertex1TriangleA, vertex2TriangleA, vertex3TriangleA, vertex1TriangleB, vertex2TriangleB, vertex3TriangleB, additions) {
|
|
@@ -3539,11 +3535,17 @@ constructIntersection = function(vertex1TriangleA, vertex2TriangleA, vertex3Tria
|
|
|
3539
3535
|
tempVector1.subVectors(vertex1TriangleA, vertex1TriangleB);
|
|
3540
3536
|
tempVector2.subVectors(vertex1TriangleA, vertex3TriangleA);
|
|
3541
3537
|
alpha = tempVector1.dot(additions.normal2) / tempVector2.dot(additions.normal2);
|
|
3538
|
+
if (!isFinite(alpha)) {
|
|
3539
|
+
return false;
|
|
3540
|
+
}
|
|
3542
3541
|
tempVector1.copy(tempVector2).multiplyScalar(alpha);
|
|
3543
3542
|
additions.source.subVectors(vertex1TriangleA, tempVector1);
|
|
3544
3543
|
tempVector1.subVectors(vertex1TriangleB, vertex1TriangleA);
|
|
3545
3544
|
tempVector2.subVectors(vertex1TriangleB, vertex3TriangleB);
|
|
3546
3545
|
alpha = tempVector1.dot(additions.normal1) / tempVector2.dot(additions.normal1);
|
|
3546
|
+
if (!isFinite(alpha)) {
|
|
3547
|
+
return false;
|
|
3548
|
+
}
|
|
3547
3549
|
tempVector1.copy(tempVector2).multiplyScalar(alpha);
|
|
3548
3550
|
additions.target.subVectors(vertex1TriangleB, tempVector1);
|
|
3549
3551
|
return true;
|
|
@@ -3552,11 +3554,17 @@ constructIntersection = function(vertex1TriangleA, vertex2TriangleA, vertex3Tria
|
|
|
3552
3554
|
tempVector1.subVectors(vertex1TriangleB, vertex1TriangleA);
|
|
3553
3555
|
tempVector2.subVectors(vertex1TriangleB, vertex2TriangleB);
|
|
3554
3556
|
alpha = tempVector1.dot(additions.normal1) / tempVector2.dot(additions.normal1);
|
|
3557
|
+
if (!isFinite(alpha)) {
|
|
3558
|
+
return false;
|
|
3559
|
+
}
|
|
3555
3560
|
tempVector1.copy(tempVector2).multiplyScalar(alpha);
|
|
3556
3561
|
additions.source.subVectors(vertex1TriangleB, tempVector1);
|
|
3557
3562
|
tempVector1.subVectors(vertex1TriangleB, vertex1TriangleA);
|
|
3558
3563
|
tempVector2.subVectors(vertex1TriangleB, vertex3TriangleB);
|
|
3559
3564
|
alpha = tempVector1.dot(additions.normal1) / tempVector2.dot(additions.normal1);
|
|
3565
|
+
if (!isFinite(alpha)) {
|
|
3566
|
+
return false;
|
|
3567
|
+
}
|
|
3560
3568
|
tempVector1.copy(tempVector2).multiplyScalar(alpha);
|
|
3561
3569
|
additions.target.subVectors(vertex1TriangleB, tempVector1);
|
|
3562
3570
|
return true;
|
|
@@ -3577,11 +3585,17 @@ constructIntersection = function(vertex1TriangleA, vertex2TriangleA, vertex3Tria
|
|
|
3577
3585
|
tempVector1.subVectors(vertex1TriangleB, vertex1TriangleA);
|
|
3578
3586
|
tempVector2.subVectors(vertex1TriangleB, vertex2TriangleB);
|
|
3579
3587
|
alpha = tempVector1.dot(additions.normal1) / tempVector2.dot(additions.normal1);
|
|
3588
|
+
if (!isFinite(alpha)) {
|
|
3589
|
+
return false;
|
|
3590
|
+
}
|
|
3580
3591
|
tempVector1.copy(tempVector2).multiplyScalar(alpha);
|
|
3581
3592
|
additions.source.subVectors(vertex1TriangleB, tempVector1);
|
|
3582
3593
|
tempVector1.subVectors(vertex1TriangleB, vertex1TriangleA);
|
|
3583
3594
|
tempVector2.subVectors(vertex1TriangleB, vertex3TriangleB);
|
|
3584
3595
|
alpha = tempVector1.dot(additions.normal1) / tempVector2.dot(additions.normal1);
|
|
3596
|
+
if (!isFinite(alpha)) {
|
|
3597
|
+
return false;
|
|
3598
|
+
}
|
|
3585
3599
|
tempVector1.copy(tempVector2).multiplyScalar(alpha);
|
|
3586
3600
|
additions.target.subVectors(vertex1TriangleB, tempVector1);
|
|
3587
3601
|
return true;
|
|
@@ -3590,11 +3604,17 @@ constructIntersection = function(vertex1TriangleA, vertex2TriangleA, vertex3Tria
|
|
|
3590
3604
|
tempVector1.subVectors(vertex1TriangleA, vertex1TriangleB);
|
|
3591
3605
|
tempVector2.subVectors(vertex1TriangleA, vertex3TriangleA);
|
|
3592
3606
|
alpha = tempVector1.dot(additions.normal2) / tempVector2.dot(additions.normal2);
|
|
3607
|
+
if (!isFinite(alpha)) {
|
|
3608
|
+
return false;
|
|
3609
|
+
}
|
|
3593
3610
|
tempVector1.copy(tempVector2).multiplyScalar(alpha);
|
|
3594
3611
|
additions.source.subVectors(vertex1TriangleA, tempVector1);
|
|
3595
3612
|
tempVector1.subVectors(vertex1TriangleA, vertex1TriangleB);
|
|
3596
3613
|
tempVector2.subVectors(vertex1TriangleA, vertex2TriangleA);
|
|
3597
3614
|
alpha = tempVector1.dot(additions.normal2) / tempVector2.dot(additions.normal2);
|
|
3615
|
+
if (!isFinite(alpha)) {
|
|
3616
|
+
return false;
|
|
3617
|
+
}
|
|
3598
3618
|
tempVector1.copy(tempVector2).multiplyScalar(alpha);
|
|
3599
3619
|
additions.target.subVectors(vertex1TriangleA, tempVector1);
|
|
3600
3620
|
return true;
|
|
@@ -3603,5 +3623,31 @@ constructIntersection = function(vertex1TriangleA, vertex2TriangleA, vertex3Tria
|
|
|
3603
3623
|
}
|
|
3604
3624
|
return false; // If none of the above, no intersection found.
|
|
3605
3625
|
};
|
|
3626
|
+
// Generated by CoffeeScript 2.7.0
|
|
3627
|
+
module.exports.Polytree = Polytree;
|
|
3628
|
+
|
|
3629
|
+
module.exports.Plane = Plane;
|
|
3630
|
+
|
|
3631
|
+
module.exports.Vertex = Vertex;
|
|
3632
|
+
|
|
3633
|
+
module.exports.Polygon = Polygon;
|
|
3634
|
+
|
|
3635
|
+
module.exports.rayIntersectsTriangle = rayIntersectsTriangle;
|
|
3636
|
+
|
|
3637
|
+
module.exports.triangleIntersectsTriangle = triangleIntersectsTriangle;
|
|
3638
|
+
|
|
3639
|
+
module.exports.resolveTriangleIntersection = resolveTriangleIntersection;
|
|
3640
|
+
|
|
3641
|
+
module.exports.resolveCoplanarTriangleIntersection = resolveCoplanarTriangleIntersection;
|
|
3642
|
+
|
|
3643
|
+
module.exports.trianglesOverlap2D = trianglesOverlap2D;
|
|
3644
|
+
|
|
3645
|
+
module.exports.triangleOrientation2D = triangleOrientation2D;
|
|
3646
|
+
|
|
3647
|
+
module.exports.triangleIntersectionCCW2D = triangleIntersectionCCW2D;
|
|
3648
|
+
|
|
3649
|
+
module.exports.intersectionTestEdge2D = intersectionTestEdge2D;
|
|
3650
|
+
|
|
3651
|
+
module.exports.intersectionTestVertex2D = intersectionTestVertex2D;
|
|
3606
3652
|
|
|
3607
|
-
module.exports =
|
|
3653
|
+
module.exports.constructIntersection = constructIntersection;
|