@jgphilpott/polytree
Version: 
A modern, high-performance spatial querying library designed specifically for three.js and Node.
1 lines • 62.7 kB
JavaScript
import{Vector2,Vector3,Box3,Line3,Sphere,Matrix3,Triangle,Ray,Raycaster,Mesh,DoubleSide,BufferGeometry,BufferAttribute,Plane as ThreePlane}from"three";var ASYNC_OPERATION_TIMEOUT,DEBUG_COLOR_BACK,DEBUG_COLOR_COPLANAR,DEBUG_COLOR_FRONT,DEBUG_COLOR_SPANNING,DEBUG_GEOMETRY_VALIDATION,DEBUG_INTERSECTION_VERIFICATION,DEBUG_PERFORMANCE_TIMING,DEBUG_VERBOSE_LOGGING,DEFAULT_BUFFER_SIZE,DEFAULT_COORDINATE_PRECISION,DEFAULT_MATERIAL_INDEX,GARBAGE_COLLECTION_THRESHOLD,GEOMETRY_CACHE_SIZE,INTERSECTION_CACHE_SIZE,MAX_REFINEMENT_ITERATIONS,MAX_WORKER_THREADS,MEMORY_USAGE_WARNING_LIMIT,POINT_COINCIDENCE_THRESHOLD,POLYTREE_MAX_DEPTH,POLYTREE_MAX_POLYGONS_PER_NODE,POLYTREE_MIN_NODE_SIZE,meshOperationNormalVector,meshOperationVertexVector,polygonID,calculateWindingNumberFromBuffer,checkMemoryUsage,clearGeometryCache,clearIntersectionCache,createIntersectionCacheKey,createVector2Buffer,createVector3Buffer,disposePolytreeResources,extractCoordinatesFromArray,geometryCache,geometryCacheKeys,handleIntersectingPolytrees,intersectionCache,intersectionCacheKeys,operationCounter,prepareTriangleBufferFromPolygons,roundPointCoordinates,signedVolumeOfTriangle,sortRaycastIntersectionsByDistance,splitPolygonByPlane,splitPolygonVertexArray,testPolygonInsideUsingWindingNumber,testRayTriangleIntersection,handleObjectForOperation,operationHandler,Polytree,convertToPolytree,uniteRules,subtractRules,intersectRules,Plane,Polygon,constructIntersection,intersectionTestEdge2D,intersectionTestVertex2D,isUniqueTriangle,isValidTriangle,pointInTriangleInclusive2D,pointOnSegmentInclusive2D,pointsEqual2D,resolveCoplanarTriangleIntersection,resolveTriangleIntersection,triangleIntersectionCCW2D,triangleIntersectsTriangle,triangleOrientation2D,trianglesOverlap2D,Vertex,GEOMETRIC_EPSILON=1e-8,RAY_INTERSECTION_EPSILON=1e-12,TRIANGLE_2D_EPSILON=1e-14,WINDING_NUMBER_FULL_ROTATION=4*Math.PI,POLYGON_COPLANAR=0,POLYGON_FRONT=1,POLYGON_BACK=2,POLYGON_SPANNING=3,temporaryVector3Primary=new Vector3,temporaryVector3Secondary=new Vector3,temporaryVector3Tertiary=new Vector3,temporaryVector3Quaternary=new Vector3,temporaryBoundingBox=new Box3,temporaryRaycaster=new Raycaster,temporaryRay=new Ray,defaultRayDirection=new Vector3(0,0,1),windingNumberVector1=new Vector3,windingNumberVector2=new Vector3,windingNumberVector3=new Vector3,windingNumberTestPoint=new Vector3,windingNumberEpsilonOffsets=[new Vector3(GEOMETRIC_EPSILON,0,0),new Vector3(0,GEOMETRIC_EPSILON,0),new Vector3(0,0,GEOMETRIC_EPSILON),new Vector3(-GEOMETRIC_EPSILON,0,0),new Vector3(0,-GEOMETRIC_EPSILON,0),new Vector3(0,0,-GEOMETRIC_EPSILON)],windingNumberEpsilonOffsetsCount=windingNumberEpsilonOffsets.length,windingNumberMatrix3=new Matrix3,rayTriangleEdge1=new Vector3,rayTriangleEdge2=new Vector3,rayTriangleHVector=new Vector3,rayTriangleSVector=new Vector3,rayTriangleQVector=new Vector3,temporaryTriangleVertex=new Vector3,temporaryTriangleVertexSecondary=new Vector3,temporaryMatrix3=new Matrix3,temporaryMatrixWithNormalCalc=new Matrix3;temporaryMatrixWithNormalCalc.getNormalMatrix=function(e){return this.setFromMatrix4(e).invert().transpose()},meshOperationNormalVector=new Vector3,meshOperationVertexVector=new Vector3,POLYTREE_MAX_DEPTH=1e3,POLYTREE_MIN_NODE_SIZE=1e-6,MAX_REFINEMENT_ITERATIONS=1e4,DEFAULT_COORDINATE_PRECISION=15,POINT_COINCIDENCE_THRESHOLD=1e-15,DEFAULT_BUFFER_SIZE=16384,GARBAGE_COLLECTION_THRESHOLD=POLYTREE_MAX_POLYGONS_PER_NODE=1e5,INTERSECTION_CACHE_SIZE=GEOMETRY_CACHE_SIZE=ASYNC_OPERATION_TIMEOUT=MAX_WORKER_THREADS=1/(DEFAULT_MATERIAL_INDEX=0),polygonID=0,DEBUG_INTERSECTION_VERIFICATION=DEBUG_GEOMETRY_VALIDATION=DEBUG_PERFORMANCE_TIMING=DEBUG_VERBOSE_LOGGING=!(MEMORY_USAGE_WARNING_LIMIT=.95),DEBUG_COLOR_FRONT=65280,DEBUG_COLOR_BACK=16711680,DEBUG_COLOR_COPLANAR=255,DEBUG_COLOR_SPANNING=16776960,intersectionCache=new Map,intersectionCacheKeys=[],geometryCache=new Map,geometryCacheKeys=[],operationCounter=0,clearIntersectionCache=function(){var e,r,t,o,n;if(INTERSECTION_CACHE_SIZE!==1/0&&intersectionCache.size>INTERSECTION_CACHE_SIZE){for(n=[],o=(t=intersectionCacheKeys.splice(e=0,Math.floor(INTERSECTION_CACHE_SIZE/2))).length;e<o;e++)r=t[e],n.push(intersectionCache.delete(r));return n}},clearGeometryCache=function(){var e,r,t,o,n;if(GEOMETRY_CACHE_SIZE!==1/0&&geometryCache.size>GEOMETRY_CACHE_SIZE){for(n=[],o=(t=geometryCacheKeys.splice(e=0,Math.floor(GEOMETRY_CACHE_SIZE/2))).length;e<o;e++)r=t[e],n.push(geometryCache.delete(r));return n}},createIntersectionCacheKey=function(e,r){return e.id+"_"+r.id},checkMemoryUsage=function(){var e,r,t;return"undefined"!=typeof process&&process.memoryUsage?(r=(t=process.memoryUsage()).heapUsed/1024/1024,e=t.heapTotal/1024/1024,t=t.heapUsed/t.heapTotal,DEBUG_VERBOSE_LOGGING&&console.log(`Memory usage: ${r.toFixed(2)}MB / ${e.toFixed(2)}MB (${(100*t).toFixed(1)}%)`),MEMORY_USAGE_WARNING_LIMIT<t&&(console.warn(`Memory usage is high: ${(100*t).toFixed(1)}%`),"function"==typeof("undefined"!=typeof global&&null!==global?global.gc:void 0))&&(console.log("Triggering garbage collection..."),global.gc()),t):0},createVector2Buffer=function(e=DEFAULT_BUFFER_SIZE){return{top:0,array:new Float32Array(2*e),write:function(e){return this.array[this.top++]=e.x,this.array[this.top++]=e.y}}},createVector3Buffer=function(e=DEFAULT_BUFFER_SIZE){return{top:0,array:new Float32Array(3*e),write:function(e){return this.array[this.top++]=e.x,this.array[this.top++]=e.y,this.array[this.top++]=e.z}}},sortRaycastIntersectionsByDistance=function(e,r){return e.distance-r.distance},roundPointCoordinates=function(e,r=DEFAULT_COORDINATE_PRECISION){return e.x=+e.x.toFixed(r),e.y=+e.y.toFixed(r),e.z=+e.z.toFixed(r),e},extractCoordinatesFromArray=function(e,r){return{x:e[r],y:e[r+1],z:e[r+2]}},splitPolygonByPlane=function(e,r,t=[]){for(var o,n,i,a,s,l,c,y,u,p,h,g,d,m,P,f,E,T={polygon:e,type:"undecided"},I=0,O=[],_=c=0,b=e.vertices.length;0<=b?c<b:b<c;_=0<=b?++c:--c)I|=E=(E=r.normal.dot(e.vertices[_].pos)-r.distanceFromOrigin)<-GEOMETRIC_EPSILON?POLYGON_BACK:GEOMETRIC_EPSILON<E?POLYGON_FRONT:POLYGON_COPLANAR,O.push(E);switch(I){case POLYGON_COPLANAR:T.type=0<r.normal.dot(e.plane.normal)?"coplanar-front":"coplanar-back",t.push(T);break;case POLYGON_FRONT:T.type="front",t.push(T);break;case POLYGON_BACK:T.type="back",t.push(T);break;case POLYGON_SPANNING:for(l=[],n=[],_=u=0,m=e.vertices.length;0<=m?u<m:m<u;_=0<=m?++u:--u)d=O[g=(_+1)%e.vertices.length],i=e.vertices[_],g=e.vertices[g],(y=O[_])!==POLYGON_BACK&&l.push(i),y!==POLYGON_FRONT&&n.push(y!==POLYGON_BACK?i.clone():i),(y|d)===POLYGON_SPANNING&&(y=(r.distanceFromOrigin-r.normal.dot(i.pos))/r.normal.dot(temporaryTriangleVertex.copy(g.pos).sub(i.pos)),d=i.interpolate(g,y),l.push(d),n.push(d.clone()));if(3<=l.length)if(3<l.length)for(a=p=0,P=(s=splitPolygonVertexArray(l)).length;0<=P?p<P:P<p;a=0<=P?++p:--p)t.push({polygon:new Polygon(s[a],e.shared),type:"front"});else t.push({polygon:new Polygon(l,e.shared),type:"front"});if(3<=n.length)if(3<n.length)for(a=h=0,f=(o=splitPolygonVertexArray(n)).length;0<=f?h<f:f<h;a=0<=f?++h:--h)t.push({polygon:new Polygon(o[a],e.shared),type:"back"});else t.push({polygon:new Polygon(n,e.shared),type:"back"})}return 0===t.length&&t.push(T),t},splitPolygonVertexArray=function(e){var r,t,o,n,i=[];if(4<e.length)for(console.warn("[splitPolygonVertexArray] vertexArray.length > 4",e.length),o=r=3,t=e.length;3<=t?r<=t:t<=r;o=3<=t?++r:--r)(n=[]).push(e[0].clone()),n.push(e[o-2].clone()),n.push(e[o-1].clone()),i.push(n);else e[0].pos.distanceTo(e[2].pos)<=e[1].pos.distanceTo(e[3].pos)?i.push([e[0].clone(),e[1].clone(),e[2].clone()],[e[0].clone(),e[2].clone(),e[3].clone()]):i.push([e[0].clone(),e[1].clone(),e[3].clone()],[e[1].clone(),e[2].clone(),e[3].clone()]);return i},calculateWindingNumberFromBuffer=function(e,r){for(var t,o,n,i,a=0,s=t=0,l=e.length;t<l;s=t+=9)windingNumberVector1.subVectors(extractCoordinatesFromArray(e,s),r),windingNumberVector2.subVectors(extractCoordinatesFromArray(e,s+3),r),windingNumberVector3.subVectors(extractCoordinatesFromArray(e,s+6),r),o=windingNumberVector1.length(),n=windingNumberVector2.length(),i=windingNumberVector3.length(),o<POINT_COINCIDENCE_THRESHOLD||n<POINT_COINCIDENCE_THRESHOLD||i<POINT_COINCIDENCE_THRESHOLD||(windingNumberMatrix3.set(windingNumberVector1.x,windingNumberVector1.y,windingNumberVector1.z,windingNumberVector2.x,windingNumberVector2.y,windingNumberVector2.z,windingNumberVector3.x,windingNumberVector3.y,windingNumberVector3.z),a+=2*Math.atan2(windingNumberMatrix3.determinant(),o*n*i+windingNumberVector1.dot(windingNumberVector2)*i+windingNumberVector2.dot(windingNumberVector3)*o+windingNumberVector3.dot(windingNumberVector1)*n));return a=Math.round(a/WINDING_NUMBER_FULL_ROTATION)},testPolygonInsideUsingWindingNumber=function(e,r,t){var o,n,i,a=!1;if(windingNumberTestPoint.copy(r),0===calculateWindingNumberFromBuffer(e,windingNumberTestPoint)){if(t)for(n=o=0,i=Math.min(windingNumberEpsilonOffsetsCount,MAX_REFINEMENT_ITERATIONS);0<=i?o<i:i<o;n=0<=i?++o:--o)if(windingNumberTestPoint.copy(r).add(windingNumberEpsilonOffsets[n]),0!==calculateWindingNumberFromBuffer(e,windingNumberTestPoint)){a=!0;break}}else a=!0;return a},prepareTriangleBufferFromPolygons=function(e){for(var r,t,o=e.length,n=new Float32Array(3*o*3),i=0,a=r=0,s=o;0<=s?r<s:s<r;a=0<=s?++r:--r)t=e[a].triangle,n[i++]=t.a.x,n[i++]=t.a.y,n[i++]=t.a.z,n[i++]=t.b.x,n[i++]=t.b.y,n[i++]=t.b.z,n[i++]=t.c.x,n[i++]=t.c.y,n[i++]=t.c.z;return n},testRayTriangleIntersection=function(e,r,t=new Vector3){var o,n;return rayTriangleEdge1.subVectors(r.b,r.a),rayTriangleEdge2.subVectors(r.c,r.a),rayTriangleHVector.crossVectors(e.direction,rayTriangleEdge2),o=rayTriangleEdge1.dot(rayTriangleHVector),!(-RAY_INTERSECTION_EPSILON<o&&o<RAY_INTERSECTION_EPSILON||(o=1/o,rayTriangleSVector.subVectors(e.origin,r.a),(r=o*rayTriangleSVector.dot(rayTriangleHVector))<0)||1<r||(rayTriangleQVector.crossVectors(rayTriangleSVector,rayTriangleEdge1),(n=o*e.direction.dot(rayTriangleQVector))<0)||1<r+n||(r=o*rayTriangleEdge2.dot(rayTriangleQVector),!(RAY_INTERSECTION_EPSILON<r)))?t.copy(e.direction).multiplyScalar(r).add(e.origin):null},handleIntersectingPolytrees=function(e,r,t=!0){var o,n;GARBAGE_COLLECTION_THRESHOLD<=++operationCounter&&(operationCounter=0,clearIntersectionCache(),clearGeometryCache(),checkMemoryUsage()),!(n=o=void 0)===Polytree.useWindingNumber&&(t&&(o=prepareTriangleBufferFromPolygons(e.getPolygons())),n=prepareTriangleBufferFromPolygons(r.getPolygons())),e.handleIntersectingPolygons(r,n),t&&r.handleIntersectingPolygons(e,o),void 0!==o&&(o=void 0)},signedVolumeOfTriangle=function(e,r,t){return temporaryVector3Primary.copy(r).cross(t),e.dot(temporaryVector3Primary)/6},disposePolytreeResources=function(...e){if(Polytree.disposePolytree)return e.forEach(function(e){return e.delete()})},operationHandler=function(u,p=!1,h=!0,g={objCounter:0},d=!0,m=!0){var e,r,t,o,n,i;if(m)return new Promise(function(o,t){var n,i,e,r,a,s,l,c,y;try{return i=y=n=void 0,a=null!=(l=u.objA)?l.material:void 0,s=null!=(c=u.objB)?c.material:void 0,u.material&&(i=u.material),r=[],u.objA&&(e=handleObjectForOperation(u.objA,p,h,g,0,m),r.push(e)),u.objB&&(e=handleObjectForOperation(u.objB,p,h,g,1,m),r.push(e)),Promise.allSettled(r).then(function(e){var r;switch(e.forEach(function(e){if("fulfilled"===e.status)return 0===e.value.objIndex?n=e.value:1===e.value.objIndex?y=e.value:void 0}),!0===p&&(n&&(u.objA=n.original,n=n.result),y)&&(u.objB=y.original,y=y.result),r=void 0,u.op){case"unite":r=n&&y?Polytree.async.unite(n,y,h):Promise.resolve(n||y||new Polytree);break;case"subtract":r=n&&y?Polytree.async.subtract(n,y,h):Promise.resolve(n||new Polytree);break;case"intersect":r=n&&y?Polytree.async.intersect(n,y,h):Promise.resolve(new Polytree);break;default:r=Promise.resolve(new Polytree)}return r.then(function(e){var r,t;if(e&&!e.box&&e.bounds&&e.buildTree(),d&&!p){if(r=e.getPolygons(),!e||0===r.length)return void o(void 0);if(i)t=Polytree.toMesh(e,i);else{if(r=void 0,a)r=(r=Array.isArray(a)?a[0]:a).clone();else{if(!s)return void o(void 0);r=(r=Array.isArray(s)?s[0]:s).clone()}t=Polytree.toMesh(e,r)}disposePolytreeResources(e),o(t)}else d&&p?i?(t=Polytree.toMesh(e,i),disposePolytreeResources(e),o({result:t,operationTree:u})):o({result:e,operationTree:u}):o(e);if(!p&&(n||y))return disposePolytreeResources(n,y)}).catch(function(e){return t(e)})})}catch(e){return t(e)}});switch(o=n=i=t=void 0,u.material&&(o=u.material),u.objA&&(t=handleObjectForOperation(u.objA,p,h,g,void 0,m),!0===p)&&(u.objA=t.original,t=t.result),u.objB&&(i=handleObjectForOperation(u.objB,p,h,g,void 0,m),!0===p)&&(u.objB=i.original,i=i.result),u.op){case"unite":n=t&&i?Polytree.unite(t,i,!1):t||i||new Polytree;break;case"subtract":n=t&&i?Polytree.subtract(t,i,!1):t||new Polytree;break;case"intersect":n=t&&i?Polytree.intersect(t,i,!1):new Polytree;break;default:n=new Polytree}if(n&&!n.box&&n.bounds&&n.buildTree(),p||(t||i)&&disposePolytreeResources(t,i),!d||p)return d&&p?{result:n,operationTree:u}:n;if(e=n.getPolygons(),n&&0!==e.length){if(o)r=Polytree.toMesh(n,o);else{if(e=void 0,null==(o=u.objA)||!o.material)return;e=(e=Array.isArray(u.objA.material)?u.objA.material[0]:u.objA.material).clone(),r=Polytree.toMesh(n,e)}return disposePolytreeResources(n),r}},handleObjectForOperation=function(o,n,i,a,s,l=!0){var e;return l?new Promise(function(r,t){var e;try{return e=void 0,o.isMesh?(e=Polytree.fromMesh(o,a.objCounter++),(e=n?{result:e,original:e.clone()}:e).objIndex=s,r(e)):o.isPolytree?(e=o,(e=n?{result:o,original:o.clone()}:e).objIndex=s,r(e)):o.op?Polytree.operation(o,n,i,a,!1,l).then(function(e){return(e=n?{result:e,original:o}:e).objIndex=s,r(e)}):void 0}catch(e){return t(e)}}):(e=void 0,o.isMesh?(e=Polytree.fromMesh(o,a.objCounter++),n&&(e={result:e,original:e.clone()})):o.isPolytree?(e=o,n&&(e={result:o,original:o.clone()})):o.op&&(e=Polytree.operation(o,n,i,a,!1,l),n)&&(e={result:e,original:o}),e)},(Polytree=function(){class b{constructor(e=null,r=null){this.box=e,this.polygons=[],this.replacedPolygons=[],this.parent=r,this.subTrees=[],this.level=0,this.originalMatrixWorld,this.mesh,this.polygonArrays=void 0,this.addPolygonsArrayToRoot(this.polygons)}isEmpty(){return 0===this.polygons.length}getMesh(){for(var e,r=new Set,t=this;t&&!r.has(t);){if(r.add(t),!t.parent)return null!=(e=t.mesh)?e:null;t=t.parent}return null}newPolytree(e,r){return new this.constructor(e,r)}setPolygonIndex(r){return void 0!==r&&this.polygonArrays?this.polygonArrays.forEach(function(e){if(null!=e&&e.length)return e.forEach(function(e){return e.shared=r})}):void 0}clone(){return(new this.constructor).copy(this)}copy(e){var r,t,o,n,i;if(e&&(this.deletePolygonsArrayFromRoot(this.polygons),this.polygons=e.polygons?e.polygons.map(function(e){return e.clone()}):[],this.addPolygonsArrayToRoot(this.polygons),this.replacedPolygons=e.replacedPolygons?e.replacedPolygons.map(function(e){return e.clone()}):[],e.mesh&&(this.mesh=e.mesh),e.originalMatrixWorld&&(this.originalMatrixWorld=e.originalMatrixWorld.clone()),this.box=e.box?e.box.clone():null,this.level=null!=(o=e.level)?o:0,e.subTrees))for(r=t=0,n=e.subTrees.length;0<=n?t<n:n<t;r=0<=n?++t:--t)i=new this.constructor(void 0,this).copy(e.subTrees[r]),this.subTrees.push(i);return this}unite(e,r,t=null){return b.unite(e,r,t)}subtract(e,r,t=null){return b.subtract(e,r,t)}intersect(e,r,t=null){return b.intersect(e,r,t)}addPolygonsArrayToRoot(e){return this.parent?this.parent.addPolygonsArrayToRoot(e):(void 0===this.polygonArrays&&(this.polygonArrays=[]),this.polygonArrays.push(e))}deletePolygonsArrayFromRoot(e){return this.parent?this.parent.deletePolygonsArrayFromRoot(e):-1<(e=this.polygonArrays.indexOf(e))?this.polygonArrays.splice(e,1):void 0}addPolygon(e,r){var t;return this.bounds||(this.bounds=new Box3),t=e.triangle,r&&!isUniqueTriangle(t,r)||(this.bounds.expandByPoint(t.a),this.bounds.expandByPoint(t.b),this.bounds.expandByPoint(t.c),this.polygons.push(e)),this}calcBox(){var e;return this.bounds||(this.bounds=new Box3),this.box=this.bounds.clone(),e=POLYTREE_MIN_NODE_SIZE,this.box.min.x-=e,this.box.min.y-=e,this.box.min.z-=e,this.box.max.x+=e,this.box.max.y+=e,this.box.max.z+=e,this}split(e){var r,t,o,n,i,a,s,l,c,y,u,p,h,g,d,m,P,f,E,T=[];if(this.box){for(o=temporaryVector3Secondary.copy(this.box.max).sub(this.box.min).multiplyScalar(.5),P=i=0;i<=1;P=++i)for(f=a=0;a<=1;f=++a)for(E=l=0;l<=1;E=++l)r=new Box3,m=temporaryVector3Primary.set(P,f,E),r.min.copy(this.box.min).add(m.multiply(o)),r.max.copy(r.min).add(o),r.expandByScalar(GEOMETRIC_EPSILON),T.push(this.newPolytree(r,this));for(h=void 0;h=this.polygons.pop();){for(t=!1,n=y=0,g=T.length;0<=g?y<g:g<y;n=0<=g?++y:--y)T[n].box.containsPoint(h.getMidpoint())&&(T[n].polygons.push(h),t=!0);if(!t)throw new Error(`Unable to find subtree for triangle at level ${e}.`)}for(n=p=0,d=T.length;0<=d?p<d:d<p;n=0<=d?++p:--p)T[n].level=e+1,s=T[n].polygons.length,u=T[n].box.getSize(temporaryVector3Tertiary).length(),c=Math.min(b.maxLevel,POLYTREE_MAX_DEPTH),Math.min(b.polygonsPerTree,POLYTREE_MAX_POLYGONS_PER_NODE)<s&&e<c&&POLYTREE_MIN_NODE_SIZE<u&&T[n].split(e+1),this.subTrees.push(T[n])}return this}buildTree(){return this.calcBox(),this.split(0),this.processTree(),this}processTree(){var e,r,t,o,n,i;if(!this.isEmpty()){for(temporaryBoundingBox.copy(this.box),e=r=0,o=this.polygons.length;0<=o?r<o:o<r;e=0<=o?++r:--r)this.box.expandByPoint(this.polygons[e].triangle.a),this.box.expandByPoint(this.polygons[e].triangle.b),this.box.expandByPoint(this.polygons[e].triangle.c);this.expandParentBox()}for(i=[],e=t=0,n=this.subTrees.length;0<=n?t<n:n<t;e=0<=n?++t:--t)i.push(this.subTrees[e].processTree());return i}expandParentBox(e=new Set){if(this.parent&&!e.has(this.parent))return e.add(this.parent),this.parent.box.expandByPoint(this.box.min),this.parent.box.expandByPoint(this.box.max),this.parent.expandParentBox(e)}invert(){return this.polygonArrays.forEach(function(e){if(e.length)return e.forEach(function(e){return e.flip()})})}getPolygons(i=[]){return this.polygonArrays.forEach(function(e){var r,t,o,n;if(e.length){for(n=[],r=t=0,o=e.length;0<=o?t<o:o<t;r=0<=o?++t:--t)e[r].valid&&-1===i.indexOf(e[r])?n.push(i.push(e[r])):n.push(void 0);return n}}),i}getTriangles(r=[]){return this.getPolygons().forEach(function(e){return r.push(e.triangle)}),r}getRayPolygons(e,r=[]){var t,o,n,i,a;if(0<this.polygons.length)for(t=o=0,i=this.polygons.length;0<=i?o<i:i<o;t=0<=i?++o:--o)this.polygons[t].valid&&this.polygons[t].originalValid&&-1===r.indexOf(this.polygons[t])&&r.push(this.polygons[t]);for(0<this.replacedPolygons.length&&r.push(...this.replacedPolygons),t=n=0,a=this.subTrees.length;0<=a?n<a:a<n;t=0<=a?++n:--n)e.intersectsBox(this.subTrees[t].box)&&this.subTrees[t].getRayPolygons(e,r);return r}getRayTriangles(e,r=[]){return this.getRayPolygons(e).forEach(function(e){return r.push(e.triangle)}),r}rayIntersect(e,r,t=[]){var o,n,i,a,s,l,c;if(0===e.direction.length())return[];for(o=1e100,n=i=0,l=(s=this.getRayPolygons(e)).length;0<=l?i<l:l<i;n=0<=l?++i:--i)c=void 0,"regular"===b.rayIntersectTriangleType?(c=e.intersectTriangle(s[n].triangle.a,s[n].triangle.b,s[n].triangle.c,!1,temporaryVector3Primary))&&(temporaryVector3Primary.applyMatrix4(r),(o=temporaryVector3Primary.distanceTo(e.origin))<0||1/0<o?console.warn("[rayIntersect] Failed ray distance check.",e):t.push({distance:o,polygon:s[n],position:temporaryVector3Primary.clone()})):(c=testRayTriangleIntersection(e,s[n].triangle,temporaryVector3Primary))&&(o=(a=c.clone().sub(e.origin).length())<o?a:o)<1e100&&t.push({distance:o,polygon:s[n],position:c.clone().add(e.origin)});return t.length&&t.sort(sortRaycastIntersectionsByDistance),t}getIntersectingPolygons(i=[]){return this.polygonArrays.forEach(function(e){var r,t,o,n;if(e.length){for(n=[],r=t=0,o=e.length;0<=o?t<o:o<t;r=0<=o?++t:--t)e[r].valid&&e[r].intersects?n.push(i.push(e[r])):n.push(void 0);return n}}),i}getPolygonsIntersectingPolygon(e,r=[]){var t,o,n,i,a,s,l,c,y;if(this.box.intersectsTriangle(e.triangle)&&0<this.polygons.length){if(t=this.polygons.slice(),0<this.replacedPolygons.length)for(o=n=0,l=this.replacedPolygons.length;0<=l?n<l:l<n;o=0<=l?++n:--n)t.push(this.replacedPolygons[o]);for(o=i=0,c=t.length;0<=c?i<c:c<i;o=0<=c?++i:--i)(s=t[o]).originalValid&&s.valid&&s.intersects&&triangleIntersectsTriangle(e.triangle,s.triangle)&&r.push(s)}for(o=a=0,y=this.subTrees.length;0<=y?a<y:y<a;o=0<=y?++a:--a)this.subTrees[o].getPolygonsIntersectingPolygon(e,r);return r}replacePolygon(e,r){var t,o,n,i,a;for(Array.isArray(r)||(r=[r]),0<this.polygons.length&&-1<(n=this.polygons.indexOf(e))&&(!0===e.originalValid?this.replacedPolygons.push(e):e.setInvalid(),this.polygons.splice(n,1,...r)),a=[],t=o=0,i=this.subTrees.length;0<=i?o<i:i<o;t=0<=i?++o:--o)a.push(this.subTrees[t].replacePolygon(e,r));return a}deletePolygonsByStateRules(h,g=!0){return this.polygonArrays.forEach(function(p){if(p.length)return p.filter(function(e){return!0===e.valid&&!0===e.intersects}).forEach(function(e){for(var r,t,o,n,i,a,s,l,c=!1,y=t=0,u=h.length;0<=u?t<u:u<t;y=0<=u?++t:--t)if(h[y].array){if((s=h[y].rule).includes(e.state)&&("undecided"!==e.previousState&&s.includes(e.previousState)||"undecided"===e.previousState)){for(c=!0,l={},s.forEach(function(e){return l[e]=!1}),s.forEach(function(e){return e,!1}),l[e.state]=!0,r=o=0,i=e.previousStates.length;0<=i?o<i:i<o;r=0<=i?++o:--o){if(!s.includes(e.previousStates[r])){c=!1;break}l[e.previousStates[r]]=!0}if(c){for(a in l)if(!1===l[a]){c=!1;break}if(c)break}}}else if(e.checkAllStates(h[y].rule)){c=!0;break}if(c&&(-1<(n=p.indexOf(e))&&(e.setInvalid(),p.splice(n,1)),g))return e.delete()})})}deletePolygonsByIntersection(o,n=!0){if(void 0!==o)return this.polygonArrays.forEach(function(t){if(t.length)return t.slice().forEach(function(e){var r;if(e.valid&&e.intersects===o&&(-1<(r=t.indexOf(e))&&(e.setInvalid(),t.splice(r,1)),n))return e.delete()})})}isPolygonIntersecting(e){return!!this.box.intersectsTriangle(e.triangle)}markIntesectingPolygons(r){return this.polygonArrays.forEach(function(e){if(e.length)return e.forEach(function(e){return e.intersects=r.isPolygonIntersecting(e)})})}resetPolygons(r=!0){return this.polygonArrays.forEach(function(e){if(e.length)return e.forEach(function(e){return e.reset(r)})})}handleIntersectingPolygons(e,r){var t,o,n,i,a,s,l,c,y,u,p,h,g,d,m,P,f,E,T,I,O,_;if(0<this.polygons.length){for(t=(g=this.polygons.filter(function(e){return!0===e.valid&&!0===e.intersects&&"undecided"===e.state})).pop();t;)if("undecided"===t.state&&t.valid){if(0<(_=e.getPolygonsIntersectingPolygon(t)).length)for(a=s=0,d=_.length;0<=d?s<d:d<s;a=0<=d?++s:--s){if(O=_[a],1<(I=splitPolygonByPlane(t,O.plane)).length){for(o=l=0,m=I.length;0<=m?l<m:m<l;o=0<=m?++l:--l)(h=I[o].polygon).intersects=t.intersects,h.newPolygon=!0,g.push(h);this.replacePolygon(t,I.map(function(e){return e.polygon}));break}if(t.id!==I[0].polygon.id){I[0].polygon.intersects=t.intersects,I[0].polygon.newPolygon=!0,g.push(I[0].polygon),this.replacePolygon(t,I[0].polygon);break}"coplanar-front"!==I[0].type&&"coplanar-back"!==I[0].type||(t.setState(I[0].type),t.coplanar=!0)}t=g.pop()}for(t=(g=this.polygons.filter(function(e){return!0===e.valid&&!0===e.intersects})).pop(),n=!1;t;)if(t.valid){if(n=!1,e.box.containsPoint(t.getMidpoint()))if(!0===b.useWindingNumber)n=testPolygonInsideUsingWindingNumber(r,t.getMidpoint(),t.coplanar);else if(p=roundPointCoordinates(temporaryVector3Secondary.copy(t.getMidpoint())),!0!==b.usePolytreeRay&&e.mesh){if(defaultRayDirection.copy(t.plane.normal),temporaryRaycaster.set(p,defaultRayDirection),!(n=(i=temporaryRaycaster.intersectObject(e.mesh)).length&&0<defaultRayDirection.dot(i[0].face.normal)?!0:n)&&t.coplanar)for(a=c=0,P=windingNumberEpsilonOffsetsCount;0<=P?c<P:P<c;a=0<=P?++c:--c)if(temporaryRaycaster.ray.origin.copy(p).add(windingNumberEpsilonOffsets[a]),(i=temporaryRaycaster.intersectObject(e.mesh)).length&&0<defaultRayDirection.dot(i[0].face.normal)){n=!0;break}}else if(temporaryRay.origin.copy(p),defaultRayDirection.copy(t.plane.normal),temporaryRay.direction.copy(t.plane.normal),!(n=(i=e.rayIntersect(temporaryRay,e.originalMatrixWorld)).length&&0<defaultRayDirection.dot(i[0].polygon.plane.normal)?!0:n)&&t.coplanar)for(a=y=0,f=windingNumberEpsilonOffsetsCount;0<=f?y<f:f<y;a=0<=f?++y:--y)if(temporaryRay.origin.copy(p).add(windingNumberEpsilonOffsets[a]),defaultRayDirection.copy(t.plane.normal),temporaryRay.direction.copy(t.plane.normal),(i=e.rayIntersect(temporaryRay,e.originalMatrixWorld)).length&&0<defaultRayDirection.dot(i[0].polygon.plane.normal)){n=!0;break}!0===n?t.setState("inside"):t.setState("outside"),t=g.pop()}}for(T=[],o=u=0,E=this.subTrees.length;0<=E?u<E:E<u;o=0<=E?++u:--u)T.push(this.subTrees[o].handleIntersectingPolygons(e,r));return T}applyMatrix(e,r,t=!0){var o,n,i,a,s;if(e.isMesh&&(e.updateMatrix(),e=e.matrix),this.box&&this.box.makeEmpty(),r=r||temporaryMatrixWithNormalCalc.getNormalMatrix(e),0<this.polygons.length)for(o=n=0,a=this.polygons.length;0<=a?n<a:a<n;o=0<=a?++n:--n)this.polygons[o].valid&&this.polygons[o].applyMatrix(e,r);for(o=i=0,s=this.subTrees.length;0<=s?i<s:s<i;o=0<=s?++i:--i)this.subTrees[o].applyMatrix(e,r,!1);if(t)return this.processTree()}triangleSphereIntersect(e,r){var t,o,n,i,a,s,l,c,y=new Vector3,u=new Vector3,p=new Line3,h=new ThreePlane;if(r.getPlane(h),e.intersectsPlane(h)){if(n=Math.abs(h.distanceToSphere(e)),s=e.radius*e.radius-n*n,a=h.projectPoint(e.center,y),r.containsPoint(e.center))return{depth:Math.abs(h.distanceToSphere(e)),normal:h.normal.clone(),point:a.clone()};for(o=i=0,l=(c=[[r.a,r.b],[r.b,r.c],[r.c,r.a]]).length;0<=l?i<l:l<i;o=0<=l?++i:--i)if(p.set(c[o][0],c[o][1]),p.closestPointToPoint(a,!0,u),(t=u.distanceToSquared(e.center))<s)return{depth:e.radius-Math.sqrt(t),normal:e.center.clone().sub(u).normalize(),point:u.clone()}}return!1}getSphereTriangles(e,o){for(var n,i,r,a,t=[],s=r=0,l=this.subTrees.length;0<=l?r<l:l<r;s=0<=l?++r:--r)i=this.subTrees[s],e.intersectsBox(i.box)&&(0<i.polygons.length?t.push((()=>{var e,r,t=[];for(a=e=0,r=i.polygons.length;0<=r?e<r:r<e;a=0<=r?++e:--e)(n=i.polygons[a]).valid&&(-1===o.indexOf(n.triangle)?t.push(o.push(n.triangle)):t.push(void 0));return t})()):t.push(i.getSphereTriangles(e,o)));return t}sphereIntersect(e){var r,t,o,n,i=!1,a=void 0,s=[],l=new Sphere;for(l.copy(e),this.getSphereTriangles(e,s),n=r=0,o=s.length;0<=o?r<o:o<r;n=0<=o?++r:--r)(a=this.triangleSphereIntersect(l,s[n]))&&(i=!0,l.center.add(a.normal.multiplyScalar(a.depth)));return!!i&&(t=(e=l.center.clone().sub(e.center)).length(),{normal:e.normalize(),depth:t})}fromGraphNode(e){var r;return e.updateWorldMatrix(!0,!0),r=this,e.traverse(function(e){if(!0===e.isMesh)return b.fromMesh(e,void 0,r,!1)}),this.buildTree()}deleteReplacedPolygons(){var e,r,t,o;for(0<this.replacedPolygons.length&&(this.replacedPolygons.forEach(function(e){return e.delete()}),this.replacedPolygons.length=0),o=[],e=r=0,t=this.subTrees.length;0<=t?r<t:t<r;e=0<=t?++r:--r)o.push(this.subTrees[e].deleteReplacedPolygons());return o}markPolygonsAsOriginal(){return this.polygonArrays.forEach(function(e){if(e.length)return e.forEach(function(e){return e.originalValid=!0})})}getPolygonCloneCallback(i,a){return this.polygonArrays.forEach(function(e){var r,t,o,n;if(e.length){for(n=[],r=t=0,o=e.length;0<=o?t<o:o<t;r=0<=o?++t:--t)e[r].valid?n.push(i(e[r].clone(),a)):n.push(void 0);return n}})}delete(e=!0){var r,t,o;if(0<this.polygons.length&&e&&(this.polygons.forEach(function(e){return e.delete()}),this.polygons.length=0),0<this.replacedPolygons.length&&e&&(this.replacedPolygons.forEach(function(e){return e.delete()}),this.replacedPolygons.length=0),this.polygonArrays&&(this.polygonArrays.length=0),this.subTrees.length){for(r=t=0,o=this.subTrees.length;0<=o?t<o:o<t;r=0<=o?++t:--t)this.subTrees[r].delete(e);this.subTrees.length=0}return this.mesh=void 0,this.originalMatrixWorld=void 0,this.box=void 0,this.parent=void 0,this.level=void 0}dispose(e=!0){return this.delete(e)}}return b.prototype.isPolytree=!0,b.usePolytreeRay=!0,b.disposePolytree=!0,b.useWindingNumber=!1,b.maxLevel=POLYTREE_MAX_DEPTH,b.polygonsPerTree=POLYTREE_MAX_POLYGONS_PER_NODE,b.rayIntersectTriangleType="MollerTrumbore",b.operation=operationHandler,b.rayIntersectsTriangle=testRayTriangleIntersection,b}.call(this)).toGeometry=function(e){for(var r,t,o,n,i,a,s,l,c,y,u,p,h,g,d,m=[],P=[],f=void 0,E=void 0,T=0,I=e.getPolygons(),O=0,_=I.length;O<_;O++)y=I[O],T+=Math.max(0,y.vertices.length-2);for(u=createVector3Buffer(3*T),c=createVector3Buffer(3*T),i=0,a=I.length;i<a;i++)for(d=(g=(y=I[i]).vertices).length,void 0===y.shared||m[y.shared]||(m[y.shared]=[]),0<d&&(void 0!==g[0].uv&&(f=f||createVector2Buffer(3*T)),void 0!==g[0].color)&&(E=E||createVector3Buffer(3*T)),o=s=3,p=d;3<=p?s<=p:p<=s;o=3<=p?++s:--s)(void 0===y.shared?P:m[y.shared]).push(u.top/3,u.top/3+1,u.top/3+2),u.write(g[0].pos),u.write(g[o-2].pos),u.write(g[o-1].pos),c.write(g[0].normal),c.write(g[o-2].normal),c.write(g[o-1].normal),null!=f&&(f.write(g[0].uv),f.write(g[o-2].uv),f.write(g[o-1].uv)),null!=E&&(E.write(g[0].color),E.write(g[o-2].color),E.write(g[o-1].color));if((r=new BufferGeometry).setAttribute("position",new BufferAttribute(u.array,3)),r.setAttribute("normal",new BufferAttribute(c.array,3)),f&&r.setAttribute("uv",new BufferAttribute(f.array,2)),E&&r.setAttribute("color",new BufferAttribute(E.array,3)),0<m.length){for(n=[],o=l=t=0,h=m.length;0<=h?l<h:h<l;o=0<=h?++l:--l)m[o]=m[o]||[],r.addGroup(t,m[o].length,o),t+=m[o].length,n=n.concat(m[o]);P.length&&(r.addGroup(t,P.length,m.length),n=n.concat(P)),r.setIndex(n)}return r},Polytree.toMesh=function(e,r){e=Polytree.toGeometry(e);return new Mesh(e,r)},Polytree.fromMesh=function(e,r,t=new Polytree,o=!0){var n,i,a,s,l,c,y,u,p,h,g,d,m,P,f,E,T,I,O,_,b,N,V,R;if(e.isPolytree)return e;for("regular"===Polytree.rayIntersectTriangleType&&(t.originalMatrixWorld=e.matrixWorld.clone()),e.updateWorldMatrix(!0,!0),i=e.geometry,temporaryMatrixWithNormalCalc.getNormalMatrix(e.matrix),s=i.groups,N=i.attributes.uv,n=i.attributes.color,T=i.attributes.position,m=i.attributes.normal,f=[],l=u=0,I=(c=i.index?i.index.array:Array(T.array.length/T.itemSize|0).fill().map(function(e,r){return r})).length;u<I;l=u+=3){for(R=[],y=p=0;p<3;y=++p)b=2*(V=c[l+y]),E=new Vector3(T.array[V=3*V],T.array[1+V],T.array[2+V]),V=new Vector3(m.array[V],m.array[1+V],m.array[2+V]),E.applyMatrix4(e.matrix),V.applyMatrix3(temporaryMatrixWithNormalCalc),_=N?{x:N.array[b],y:N.array[1+b]}:void 0,b=n?{x:n.array[b],y:n.array[1+b],z:n.array[2+b]}:void 0,R.push(new Vertex(E,V,_,b));if(void 0===r&&s&&0<s.length){for(P=void 0,g=0,h=s.length;g<h;g++)a=s[g],c[l]>=a.start&&c[l]<a.start+a.count&&((P=new Polygon(R,a.materialIndex)).originalValid=!0);P&&f.push(P)}else(P=new Polygon(R,r)).originalValid=!0,f.push(P)}for(l=d=0,O=f.length;0<=O?d<O:O<d;l=0<=O?++d:--d)isValidTriangle(f[l].triangle)?t.addPolygon(f[l]):f[l].delete();return o&&t.buildTree(),!0!==Polytree.usePolytreeRay&&(t.mesh=e),t},Polytree.getSurface=function(e){var r,t,o,n,i,a,s,l,c=0;if(!e)throw new Error("Input is required.");if(!(e=e.geometry||e)||!e.attributes)throw new Error("No geometry found.");if(!(n=e.attributes.position))throw new Error("Geometry has no position attribute.");for(r=o=0,i=(t=e.index?e.index.array:Array(n.array.length/n.itemSize|0).fill().map(function(e,r){return r})).length;o<i;r=o+=3)a=3*t[r+0],s=3*t[r+1],l=3*t[r+2],a=new Vector3(n.array[a],n.array[1+a],n.array[2+a]),s=new Vector3(n.array[s],n.array[1+s],n.array[2+s]),l=new Vector3(n.array[l],n.array[1+l],n.array[2+l]),c+=new Triangle(a,s,l).getArea();return c},Polytree.prototype.getSurface=function(e){return Polytree.getSurface(e)},Polytree.getVolume=function(e){var r,t,o,n,i,a,s,l=0,c=new Vector3,y=new Vector3,u=new Vector3,p=null;if(e.isMesh)p=e.geometry;else{if(!e.isBufferGeometry)throw new Error("Input must be a Three.js Mesh or BufferGeometry.");p=e}if(!(e=("function"==typeof p.toBuffer?p.toBuffer():void 0)||p).isBufferGeometry)throw new Error("Unable to convert input to BufferGeometry.");if(!(i=e.attributes.position))return 0;if(e.index)for(r=o=0,a=(t=e.index).count/3;0<=a?o<a:a<o;r=0<=a?++o:--o)c.fromBufferAttribute(i,t.array[3*r+0]),y.fromBufferAttribute(i,t.array[3*r+1]),u.fromBufferAttribute(i,t.array[3*r+2]),l+=signedVolumeOfTriangle(c,y,u);else for(r=n=0,s=i.count/3;0<=s?n<s:s<n;r=0<=s?++n:--n)c.fromBufferAttribute(i,3*r+0),y.fromBufferAttribute(i,3*r+1),u.fromBufferAttribute(i,3*r+2),l+=signedVolumeOfTriangle(c,y,u);return Math.abs(l)},Polytree.prototype.getVolume=function(e){return Polytree.getVolume(e)},convertToPolytree=function(e){return e?e.isPolytree?{polytree:e,shouldCleanup:!1}:e.isMesh?{polytree:Polytree.fromMesh(e),shouldCleanup:!0}:e.isBufferGeometry?(e=new Mesh(e,{isMaterial:!0,type:"MeshBasicMaterial"}),{polytree:Polytree.fromMesh(e),shouldCleanup:!0}):null:null},Polytree.closestPointToPoint=function(e,r,t={},o=1/0){var n,i,a,s,l,c,y,u,p,h;if(e&&r&&(e=convertToPolytree(e))){for({polytree:e,shouldCleanup:c}=e,n=o,a=i=null,s=0,l=(h=e.getTriangles()).length;s<l;s++)u=h[s],y=new Triangle(u.a,u.b,u.c),p=new Vector3,y.closestPointToPoint(r,p),(y=p.distanceTo(r))<n&&(n=y,i=p.clone(),a=u);if(i)return t.point=i,t.distance=n,t.triangle=a,c&&e.delete(),t;c&&e.delete()}return null},Polytree.distanceToPoint=function(e,r){e=Polytree.closestPointToPoint(e,r);return(null!=e?e.distance:void 0)||1/0},Polytree.intersectsSphere=function(e,r){var t,o,n,i,a,s,l;if(e&&r&&(e=convertToPolytree(e))){for({polytree:i,shouldCleanup:a}=e,o=0,n=(l=i.getTriangles()).length;o<n;o++)if(s=l[o],s=new Triangle(s.a,s.b,s.c),t=new Vector3,s.closestPointToPoint(r.center,t),t.distanceTo(r.center)<=r.radius)return a&&i.delete(),!0;a&&i.delete()}return!1},Polytree.intersectsBox=function(e,r){var t,o,n,i,a,s;if(e&&r&&(e=convertToPolytree(e))){for({polytree:n,shouldCleanup:i}=e,t=0,o=(s=n.getTriangles()).length;t<o;t++)if(a=s[t],a=new Triangle(a.a,a.b,a.c),r.intersectsTriangle(a))return i&&n.delete(),!0;i&&n.delete()}return!1},Polytree.intersectPlane=function(e,r,t=[]){var o,n,i,a,s,l,c,y,u,p,h,g,d;if(e&&r&&(e=convertToPolytree(e))){for({polytree:e,shouldCleanup:y}=e,a=0,l=(d=e.getTriangles()).length;a<l;a++){for(h=d[a],new Triangle(h.a,h.b,h.c),i=[],s=0,c=(g=[[h.a,h.b],[h.b,h.c],[h.c,h.a]]).length;s<c;s++)u=(o=g[s])[0],o=o[1],(p=r.normal.dot(u)+r.constant)*(n=r.normal.dot(o)+r.constant)<0&&(p=p/(p-n),(n=new Vector3).lerpVectors(u,o,p),i.push(n));2===i.length&&t.push(new Line3(i[0],i[1]))}y&&e.delete()}return t},Polytree.sliceIntoLayers=function(e,r,t,o,n=new Vector3(0,0,1)){var i,a,s,l,c,y,u,p,h,g,d,m,P,f,E,T,I,O;if(!(e&&0<r&&t<o))return[];if(!(e=convertToPolytree(e)))return[];for({polytree:P,shouldCleanup:e}=e,p=[],i=t;i<=o;){for(m=n.clone(),d=-i,u=[],c=0,h=(O=P.getTriangles()).length;c<h;c++){for(l=[],y=0,g=(I=[[(T=O[c]).a,T.b],[T.b,T.c],[T.c,T.a]]).length;y<g;y++)f=(a=I[y])[0],a=a[1],(E=m.dot(f)+d)*(s=m.dot(a)+d)<0&&(E=E/(E-s),(s=new Vector3).lerpVectors(f,a,E),l.push(s));2===l.length&&u.push(new Line3(l[0],l[1]))}p.push(u),i+=r}return e&&P.delete(),p},Polytree.shapecast=function(e,r,t=null){var o,n,i,a,s,l,c,y;if(!e||!r)return[];if(!(i=convertToPolytree(e)))return[];for({polytree:e,shouldCleanup:s}=i,a=[],o=0,n=(y=e.getTriangles()).length;o<n;o++)c=y[o],r(l=new Triangle(c.a,c.b,c.c),c)&&(t?null!=(i=t(l,c))&&a.push(i):a.push(c));return s&&e.delete(),a},Polytree.getTrianglesNearPoint=function(e,t,o){return e&&t&&0<o?Polytree.shapecast(e,function(e,r){return e.a.distanceTo(t)<=o||e.b.distanceTo(t)<=o||e.c.distanceTo(t)<=o}):[]},uniteRules={a:[{array:!0,rule:["inside","coplanar-back"]},{array:!(Polytree.estimateVolumeViaSampling=function(e,r=1e4,t=null){var o,n,i,a,s,l,c,y,u,p,h;if(!e)return 0;if(!(e=convertToPolytree(e)))return 0;if({polytree:c,shouldCleanup:e}=e,!t)for(t=new Box3,a=0,l=(h=c.getTriangles()).length;a<l;a++)p=h[a],t.expandByPoint(p.a),t.expandByPoint(p.b),t.expandByPoint(p.c);if(o=new Vector3,t.getSize(o),0==(n=o.x*o.y*o.z))return 0;for(s=i=0,y=r;0<=y?s<y:y<s;0<=y?++s:--s)u=new Vector3(t.min.x+Math.random()*o.x,t.min.y+Math.random()*o.y,t.min.z+Math.random()*o.z),u=new Ray(u,new Vector3(1,0,0)),c.rayIntersect(u,{elements:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],isMatrix4:!0}).length%2==1&&i++;return r=i/r,e&&c.delete(),r*n}),rule:"inside"}],b:[{array:!0,rule:["inside","coplanar-back"]},{array:!0,rule:["inside","coplanar-front"]},{array:!1,rule:"inside"}]},Polytree.unite=function(e,r,t=!0){var o,n,i;return t?e.isPolytree&&r.isPolytree?Polytree.async.unite(e,r,!0):(o=Polytree.fromMesh(e),n=Polytree.fromMesh(r),i=(i=Array.isArray(e.material)?e.material[0]:e.material).clone(),Polytree.async.unite(o,n,!1).then(function(e){var r=Polytree.toMesh(e,i);return disposePolytreeResources(o,n,e),r})):e.isPolytree&&r.isPolytree?(o=e,n=r,this.uniteCore(o,n,!0)):(o=Polytree.fromMesh(e),n=Polytree.fromMesh(r),i=(i=Array.isArray(e.material)?e.material[0]:e.material).clone(),t=this.uniteCore(o,n,!1),r=Polytree.toMesh(t,i),disposePolytreeResources(o,n,t),r)},subtractRules={a:[{array:!0,rule:["inside","coplanar-back"]},{array:!0,rule:["inside","coplanar-front"]},{array:!(Polytree.uniteCore=function(e,r,t=!0){var o,n,i=new Polytree,a=new Set;return e.box.intersectsBox(r.box)?(n=o=void 0,e.mesh&&(o=e.mesh.material.side,e.mesh.material.side=DoubleSide),r.mesh&&(n=r.mesh.material.side,r.mesh.material.side=DoubleSide),e.resetPolygons(!1),r.resetPolygons(!1),e.markIntesectingPolygons(r),r.markIntesectingPolygons(e),handleIntersectingPolytrees(e,r),e.deleteReplacedPolygons(),r.deleteReplacedPolygons(),e.deletePolygonsByStateRules(uniteRules.a),r.deletePolygonsByStateRules(uniteRules.b),e.getPolygonCloneCallback(i.addPolygon.bind(i),a),r.getPolygonCloneCallback(i.addPolygon.bind(i),a),e.mesh&&e.mesh.material.side!==o&&(e.mesh.material.side=o),r.mesh&&r.mesh.material.side!==n&&(r.mesh.material.side=n)):(e.getPolygonCloneCallback(i.addPolygon.bind(i),a),r.getPolygonCloneCallback(i.addPolygon.bind(i),a)),a.clear(),a=void 0,i.markPolygonsAsOriginal(),t&&i.buildTree(),i}),rule:"inside"}],b:[{array:!0,rule:["outside","coplanar-back"]},{array:!0,rule:["outside","coplanar-front"]},{array:!0,rule:["inside","coplanar-front"]},{array:!1,rule:"outside"}]},Polytree.subtract=function(e,r,t=!0){var o,n,i;return t?e.isPolytree&&r.isPolytree?Polytree.async.subtract(e,r,!0):(o=Polytree.fromMesh(e),n=Polytree.fromMesh(r),i=(i=Array.isArray(e.material)?e.material[0]:e.material).clone(),Polytree.async.subtract(o,n,!1).then(function(e){var r=Polytree.toMesh(e,i);return disposePolytreeResources(o,n,e),r})):e.isPolytree&&r.isPolytree?(o=e,n=r,this.subtractCore(o,n,!0)):(o=Polytree.fromMesh(e),n=Polytree.fromMesh(r),i=(i=Array.isArray(e.material)?e.material[0]:e.material).clone(),t=this.subtractCore(o,n,!1),r=Polytree.toMesh(t,i),disposePolytreeResources(o,n,t),r)},intersectRules={a:[{array:!0,rule:["inside","coplanar-back"]},{array:!0,rule:["outside","coplanar-front"]},{array:!0,rule:["outside","coplanar-back"]},{array:!(Polytree.subtractCore=function(e,r,t=!0){var o,n,i=new Polytree,a=new Set;return e.box.intersectsBox(r.box)?(n=o=void 0,e.mesh&&(o=e.mesh.material.side,e.mesh.material.side=DoubleSide),r.mesh&&(n=r.mesh.material.side,r.mesh.material.side=DoubleSide),e.resetPolygons(!1),r.resetPolygons(!1),e.markIntesectingPolygons(r),r.markIntesectingPolygons(e),handleIntersectingPolytrees(e,r),e.deleteReplacedPolygons(),r.deleteReplacedPolygons(),e.deletePolygonsByStateRules(subtractRules.a),r.deletePolygonsByStateRules(subtractRules.b),r.deletePolygonsByIntersection(!1),r.invert(),e.getPolygonCloneCallback(i.addPolygon.bind(i),a),r.getPolygonCloneCallback(i.addPolygon.bind(i),a),e.mesh&&e.mesh.material.side!==o&&(e.mesh.material.side=o),r.mesh&&r.mesh.material.side!==n&&(r.mesh.material.side=n)):e.getPolygonCloneCallback(i.addPolygon.bind(i),a),a.clear(),a=void 0,i.markPolygonsAsOriginal(),t&&i.buildTree(),i}),rule:"outside"}],b:[{array:!0,rule:["inside","coplanar-front"]},{array:!0,rule:["inside","coplanar-back"]},{array:!0,rule:["outside","coplanar-front"]},{array:!0,rule:["outside","coplanar-back"]},{array:!1,rule:"outside"}]},Polytree.intersect=function(e,r,t=!0){var o,n,i;return t?e.isPolytree&&r.isPolytree?Polytree.async.intersect(e,r,!0):(o=Polytree.fromMesh(e),n=Polytree.fromMesh(r),i=(i=Array.isArray(e.material)?e.material[0]:e.material).clone(),Polytree.async.intersect(o,n,!1).then(function(e){var r=Polytree.toMesh(e,i);return disposePolytreeResources(o,n,e),r})):e.isPolytree&&r.isPolytree?(o=e,n=r,this.intersectCore(o,n,!0)):(o=Polytree.fromMesh(e),n=Polytree.fromMesh(r),i=(i=Array.isArray(e.material)?e.material[0]:e.material).clone(),t=this.intersectCore(o,n,!1),r=Polytree.toMesh(t,i),disposePolytreeResources(o,n,t),r)},Polytree.intersectCore=function(e,r,t=!0){var o,n,i=new Polytree,a=new Set;return e.box.intersectsBox(r.box)&&(n=o=void 0,e.mesh&&(o=e.mesh.material.side,e.mesh.material.side=DoubleSide),r.mesh&&(n=r.mesh.material.side,r.mesh.material.side=DoubleSide),e.resetPolygons(!1),r.resetPolygons(!1),e.markIntesectingPolygons(r),r.markIntesectingPolygons(e),handleIntersectingPolytrees(e,r),e.deleteReplacedPolygons(),r.deleteReplacedPolygons(),e.deletePolygonsByStateRules(intersectRules.a),r.deletePolygonsByStateRules(intersectRules.b),e.deletePolygonsByIntersection(!1),r.deletePolygonsByIntersection(!1),e.getPolygonCloneCallback(i.addPolygon.bind(i),a),r.getPolygonCloneCallback(i.addPolygon.bind(i),a),e.mesh&&e.mesh.material.side!==o&&(e.mesh.material.side=o),r.mesh)&&r.mesh.material.side!==n&&(r.mesh.material.side=n),a.clear(),a=void 0,i.markPolygonsAsOriginal(),t&&i.buildTree(),i},Polytree.async={batchSize:DEFAULT_BUFFER_SIZE,maxWorkerThreads:MAX_WORKER_THREADS,unite:function(n,i,a=!0){return new Promise(function(r,t){var e,o=null;ASYNC_OPERATION_TIMEOUT!==1/0&&(o=setTimeout(function(){return t(new Error(`Union operation timed out after ${ASYNC_OPERATION_TIMEOUT}ms`))},ASYNC_OPERATION_TIMEOUT));try{return e=Polytree.uniteCore(n,i,a),disposePolytreeResources(n,i),o&&clearTimeout(o),r(e)}catch(e){return r=e,o&&clearTimeout(o),disposePolytreeResources(n,i),t(r)}})},subtract:function(n,i,a=!0){return new Promise(function(r,t){var e,o=null;ASYNC_OPERATION_TIMEOUT!==1/0&&(o=setTimeout(function(){return t(new Error(`Subtract operation timed out after ${ASYNC_OPERATION_TIMEOUT}ms`))},ASYNC_OPERATION_TIMEOUT));try{return e=Polytree.subtractCore(n,i,a),disposePolytreeResources(n,i),o&&clearTimeout(o),r(e)}catch(e){return r=e,o&&clearTimeout(o),disposePolytreeResources(n,i),t(r)}})},intersect:function(n,i,a=!0){return new Promise(function(r,t){var e,o=null;ASYNC_OPERATION_TIMEOUT!==1/0&&(o=setTimeout(function(){return t(new Error(`Intersect operation timed out after ${ASYNC_OPERATION_TIMEOUT}ms`))},ASYNC_OPERATION_TIMEOUT));try{return e=Polytree.intersectCore(n,i,a),disposePolytreeResources(n,i),o&&clearTimeout(o),r(e)}catch(e){return r=e,o&&clearTimeout(o),disposePolytreeResources(n,i),t(r)}})},uniteArray:function(e,r=1/0){return Polytree.async.processArrayWithOperation(e,r,Polytree.async.unite,Polytree.async.uniteArray,"union")},subtractArray:function(e,r=1/0){return Polytree.async.processArrayWithOperation(e,r,Polytree.async.subtract,Polytree.async.subtractArray,"subtraction")},intersectArray:function(e,r=1/0){return Polytree.async.processArrayWithOperation(e,r,Polytree.async.intersect,Polytree.async.intersectArray,"intersection")},operation:function(e,r=!1,t=!0,o={objCounter:0},n=!0){return Polytree.operation(e,r,t,o,n,!0)},processArrayWithOperation:function(O,_,b,N,V){return new Promise(function(t,o){var e,r,n,i,a,s,l,c,y,u,p,h,g,d,m,P,f,E,T,I;try{if(I=4<Polytree.async.batchSize&&Polytree.async.batchSize<O.length,p=void 0,l=!1,d=[],I){for(e=[],a=0;a<O.length;)e.push(O.slice(a,a+Polytree.async.batchSize)),a+=Polytree.async.batchSize;for(i=e.shift();i;)r=N(i,0),d.push(r),i=e.shift();l=I=!0,O.length=0}else{for(f=[],g=s=0,E=O.length;0<=E?s<E:E<s;g=0<=E?++s:--s)h=_<g?_:g,n=void 0,O[g].isMesh?n=Polytree.fromMesh(O[g],-1<_?h:void 0):(n=O[g],-1<_&&n.setPolygonIndex(h)),n.polytreeIndex=g,f.push(n);for(p=f.shift(),y=void 0,P=c=0,T=f.length;c<T;P=c+=2){if(f.length<=P+1){y=f[P];break}m=b(f[P],f[P+1]),d.push(m)}y&&(u=b(p,y),d.push(u),l=!0)}return Promise.allSettled(d).then(function(e){var r=[];return e.forEach(function(e){if("fulfilled"===e.status)return r.push(e.value)}),l||r.unshift(p),0<r.length?1===r.length?t(r[0]):3<r.length?N(r,I?0:-1).then(function(e){return t(e)}).catch(function(e){return o(e)}):b(r[0],r[1]).then(function(e){return 3===r.length?b(e,r[2]).then(function(e){return t(e)}).catch(function(e){return o(e)}):t(e)}).catch(function(e){return o(e)}):o(`Unable to find any result polytree after ${V} operation.`)})}catch(e){return o(e)}})}},Plane=class Plane{constructor(e,r){this.normal=e,this.distanceFromOrigin=r}clone(){return new Plane(this.normal.clone(),this.distanceFromOrigin)}flip(){return this.normal.negate(),this.distanceFromOrigin=-this.distanceFromOrigin}equals(e){return this.normal.equals(e.normal)&&this.distanceFromOrigin===e.distanceFromOrigin}delete(){return this.normal=void 0,this.distanceFromOrigin=void 0}static fromPoints(e,r,t){r=temporaryTriangleVertex.copy(r).sub(e).cross(temporaryTriangleVertexSecondary.copy(t).sub(e)).normalize().clone();return new Plane(r,r.dot(e))}},Polygon=class Polygon{constructor(e,r){this.id=polygonID++,this.vertices=e.map(function(e){return e.clone()}),this.shared=r,this.plane=Plane.fromPoints(this.vertices[0].pos,this.vertices[1].pos,this.vertices[2].pos),this.triangle=new Triangle(this.vertices[0].pos,this.vertices[1].pos,this.vertices[2].pos),this.intersects=!1,this.state="undecided",this.previousState="undecided",this.previousStates=[],this.valid=!0,this.coplanar=!1,this.originalValid=!1,this.newPolygon=!1}getMidpoint(){return this.triangle.midPoint||(this.triangle.midPoint=this.triangle.getMidpoint(new Vector3))}applyMatrix(r,t){if(t=t||temporaryMatrixWithNormalCalc.getNormalMatrix(r),this.vertices.forEach(function(e){return e.pos.applyMatrix4(r),e.normal.applyMatrix3(t)}),this.plane.delete(),this.plane=Plane.fromPoints(this.vertices[0].pos,this.vertices[1].pos,this.vertices[2].pos),this.triangle.set(this.vertices[0].pos,this.vertices[1].pos,this.vertices[2].pos),this.triangle.midPoint)return this.triangle.getMidpoint(this.triangle.midPoint)}flip(){var e;return this.vertices.reverse().forEach(function(e){return e.flip()}),e=this.triangle.a,this.triangle.a=this.triangle.c,this.triangle.c=e,this.plane.flip()}reset(e=!0){return this.intersects=!1,this.state="undecided",this.previousState="undecided",this.previousStates.length=0,this.valid=!0,this.coplanar=!1,e&&(this.originalValid=!1),this.newPolygon=!1}setState(e,r){if(this.state!==r)return this.previousState=this.state,"undecided"!==this.state&&this.previousStates.push(this.state),this.state=e}checkAllStates(e){var r,t,o;if(this.state!==e||this.previousState!==e&&"undecided"!==this.previousState)return!1;for(r=0,t=(o=this.previousStates).length;r<t;r++)if(o[r]!==e)return!1;return!0}setInvalid(){return this.valid=!1}setValid(){return this.valid=!0}static createWithDefaultMaterial(e){return new Polygon(e,DEFAULT_MATERIAL_INDEX)}clone(){var e=new Polygon(this.vertices.map(function(e){return e.clone()}),this.shared);return e.intersects=this.intersects,e.valid=this.valid,e.coplanar=this.coplanar,e.state=this.state,e.originalValid=this.originalValid,e.newPolygon=this.newPolygon,e.previousState=this.previousState,e.previousStates=this.previousStates.slice(),this.triangle.midPoint&&(e.triangle.midPoint=this.triangle.midPoint.clone()),e}delete(){return this.vertices.forEach(function(e){return e.delete()}),this.vertices.length=0,this.plane&&(this.plane.delete(),this.plane=void 0),this.triangle=void 0,this.shared=void 0,this.setInvalid()}},isValidTriangle=function(e){return!e.a.equals(e.b)&&!e.a.equals(e.c)&&!e.b.equals(e.c)},isUniqueTriangle=function(e,r,t){var o=`{${e.a.x},${e.a.y},${e.a.z}}-{${e.b.x},${e.b.y},${e.b.z}}-{${e.c.x},${e.c.y},${e.c.z}}`;return!0!==r.has(o)&&(r.add(o),t&&t.set(e,e),!0)},pointsEqual2D=function(e,r,t=TRIANGLE_2D_EPSILON){return Math.abs(e.x-r.x)<=t&&Math.abs(e.y-r.y)<=t},pointOnSegmentInclusive2D=function(e,r,t,o=TRIANGLE_2D_EPSILON){var n,i,a;return pointsEqual2D(r,t,o)?pointsEqual2D(e,r,o)||pointsEqual2D(e,t,o):!(Math.abs(triangleOrientation2D(e,r,t))>o)&&(i=Math.min(r.x,t.x)-o,n=Math.max(r.x,t.x)+o,a=Math.min(r.y,t.y)-o,r=Math.max(r.y,t.y)+o,e.x>=i)&&e.x<=n&&e.y>=a&&e.y<=r},pointInTriangleInclusive2D=function(e,r,t,o,n=TRIANGLE_2D_EPSILON){var i,a,s,l=triangleOrientation2D(r,t,o);return n<l?(i=triangleOrientation2D(e,r,t),a=triangleOrientation2D(e,t,o),s=triangleOrientation2D(e,o,r),-n<=i&&-n<=a&&-n<=s):l<-n?(i=triangleOrientation2D(e,r,t),a=triangleOrientation2D(e,t,o),s=triangleOrientation2D(e,o,r),i<=n&&a<=n&&s<=n):pointsEqual2D(r,t,n)&&pointsEqual2D(t,o,n)?pointsEqual2D(e,r,n):pointsEqual2D(r,t,n)?pointOnSegmentInclusive2D(e,t,o,n):pointsEqual2D(t,o,n)||pointsEqual2D(o,r,n)?pointOnSegmentInclusive2D(e,r,t,n):pointOnSegmentInclusive2D(e,r,t,n)||pointOnSegmentInclusive2D(e,t,o,n)||pointOnSegmentInclusive2D(e,o,r,n)},triangleIntersectsTriangle=function(e,r,t={coplanar:!1,source:new Vector3,target:new Vector3}){var o,n,i,a,s,l,c,y,u=e.a,p=e.b,e=e.c,h=r.a,g=r.b,r=r.c;return temporaryVector3Primary.copy(h).sub(r),temporaryVector3Secondary.copy(g).sub(r),y=(new Vector3).copy(temporaryVector3Primary).cross(temporaryVector3Secondary),temporaryVector3Primary.copy(u).sub(r),o=temporaryVector3Primary.dot(y),temporaryVector3Primary.copy(p).sub(r),i=temporaryVector3Primary.dot(y),temporaryVector3Primary.copy(e).sub(r),s=temporaryVector3Primary.dot(y),!(0<o*i&&0<o*s||(temporaryVector3Primary.copy(p).sub(u),temporaryVector3Secondary.copy(e).sub(u),c=(new Vector3).copy(temporaryVector3Primary).cross(temporaryVector3Secondary),temporaryVector3Primary.copy(h).sub(e),n=temporaryVector3Primary.dot(c),temporaryVector3Primary.copy(g).sub(e),a=temporaryVector3Primary.dot(c),temporaryVector3Primary.copy(r).sub(e),l=temporaryVector3Primary.dot(c),0<n*a&&0<n*l))&&(t.normal1=c,t.normal2=y,0<o?0<i?resolveTriangleIntersection(e,u,p,h,r,g,n,l,a,t):0<