remesh-threejs 0.2.0 → 0.3.0
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 +106 -5
- package/dist/index.d.ts +253 -0
- package/dist/remesh-threejs.cjs +1 -1
- package/dist/remesh-threejs.cjs.map +1 -1
- package/dist/remesh-threejs.js +389 -8
- package/dist/remesh-threejs.js.map +1 -1
- package/package.json +1 -1
package/dist/remesh-threejs.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("three");function t(e){return e}function n(e){return e}function i(e){return e}function s(e){return e}function o(e){return e}var r=(e=>(e.Manifold="manifold",e.OpenBook="open_book",e.SkeletonBranching="skeleton_branching",e.NonManifoldOther="non_manifold_other",e))(r||{}),a=(e=>(e.Manifold="manifold",e.NonManifold="non_manifold",e.Feature="feature",e.Boundary="boundary",e))(a||{});const l={iterations:5,preserveBoundary:!0,minEdgeLengthRatio:.4,maxEdgeLengthRatio:1.333,minTriangleQuality:.3,maxNormalDeviation:Math.PI/6,useAcceleration:!0,chunkSize:0,memoryBudget:0,verbose:!1};class c{constructor(e,t){this.id=e,this.position=t,this.halfedge=null,this.type=r.Manifold,this.isMarked=!1}degree(){if(!this.halfedge)return null;let e=0,t=this.halfedge;do{if(e++,!t.twin||!t.twin.next)break;if(t=t.twin.next,e>1e4)throw new Error(`Vertex ${this.id}: degree calculation exceeded maximum iterations`)}while(t!==this.halfedge);return e}forEachOutgoingHalfedge(e){if(!this.halfedge)return;let t=this.halfedge,n=0;do{if(e(t),!t.twin||!t.twin.next)break;if(t=t.twin.next,n++,n>1e4)throw new Error(`Vertex ${this.id}: halfedge iteration exceeded maximum iterations`)}while(t!==this.halfedge)}getOutgoingHalfedges(){const e=[];return this.forEachOutgoingHalfedge(t=>e.push(t)),e}forEachNeighbor(e){this.forEachOutgoingHalfedge(t=>{e(t.vertex)})}getNeighbors(){const e=[];return this.forEachNeighbor(t=>e.push(t)),e}isBoundary(){if(!this.halfedge)return!0;let e=!1;return this.forEachOutgoingHalfedge(t=>{t.face||(e=!0)}),e}canMoveFreely(){return this.type===r.Manifold}isSkeletonConstrained(){return this.type===r.OpenBook}isPositionFixed(){return this.type===r.SkeletonBranching||this.type===r.NonManifoldOther}isOnSkeleton(){return this.type!==r.Manifold}}class h{constructor(e,t,n){this.id=e,this.twin=null,this.next=null,this.prev=null,this.face=null,this.vertex=t,this.edge=n}getSourceVertex(){var e;return(null==(e=this.twin)?void 0:e.vertex)??null}getTargetVertex(){return this.vertex}isBoundary(){return null===this.face}getOppositeHalfedge(){var e;return(null==(e=this.next)?void 0:e.next)??null}getOppositeVertex(){var e;return(null==(e=this.next)?void 0:e.vertex)??null}getVector(){const e=this.getSourceVertex();return e?{x:this.vertex.position.x-e.position.x,y:this.vertex.position.y-e.position.y,z:this.vertex.position.z-e.position.z}:null}}class u{constructor(e,t,n){this.id=e,this.allHalfedges=[],this.type=a.Manifold,this.isInPath=!1,this.halfedge=t,this.length=n,this.allHalfedges.push(t)}addHalfedge(e){this.allHalfedges.push(e),this.updateType()}getHalfedgeCount(){return this.allHalfedges.length}updateType(){const e=this.getFaceCount();0===e||1===e?this.type=a.Boundary:2===e?this.type!==a.Feature&&(this.type=a.Manifold):this.type=a.NonManifold}getFaceCount(){let e=0;for(const t of this.allHalfedges)null!==t.face&&e++;return e}getVertices(){const e=this.halfedge.getSourceVertex(),t=this.halfedge.getTargetVertex();return e?[e,t]:[null,null]}getFaces(){const e=[];for(const t of this.allHalfedges)null!==t.face&&e.push(t.face);return e}getTwoFaces(){var e;return[this.halfedge.face,(null==(e=this.halfedge.twin)?void 0:e.face)??null]}isBoundary(){return this.type===a.Boundary}isNonManifold(){return this.type===a.NonManifold}isSkeletonEdge(){return this.type===a.NonManifold||this.type===a.Feature||this.type===a.Boundary}canFlip(){if(this.type!==a.Manifold)return!1;if(2!==this.getFaceCount())return!1;const[e,t]=this.getVertices();if(!e||!t)return!1;const n=e.degree(),i=t.degree();return!(null===n||null===i||n<=1||i<=1)}getOtherVertex(e){const[t,n]=this.getVertices();return t&&n?e.id===t.id?n:e.id===n.id?t:null:null}markAsFeature(){this.type===a.Manifold&&(this.type=a.Feature)}}class g{constructor(e,t){this.id=e,this.isMarked=!1,this.halfedge=t}getVertices(){const e=this.halfedge,t=e.next,n=null==t?void 0:t.next;return t&&n?[e.vertex,t.vertex,n.vertex]:null}getHalfedges(){const e=this.halfedge,t=e.next,n=null==t?void 0:t.next;return t&&n?[e,t,n]:null}forEachHalfedge(e){const t=this.getHalfedges();if(t)for(const n of t)e(n)}forEachVertex(e){const t=this.getVertices();if(t)for(const n of t)e(n)}getCentroid(){const e=this.getVertices();if(!e)return null;const[t,n,i]=e;return{x:(t.position.x+n.position.x+i.position.x)/3,y:(t.position.y+n.position.y+i.position.y)/3,z:(t.position.z+n.position.z+i.position.z)/3}}getNormal(){const e=this.getVertices();if(!e)return null;const[t,n,i]=e,s=n.position.x-t.position.x,o=n.position.y-t.position.y,r=n.position.z-t.position.z,a=i.position.x-t.position.x,l=i.position.y-t.position.y,c=i.position.z-t.position.z,h=o*c-r*l,u=r*a-s*c,g=s*l-o*a,d=Math.sqrt(h*h+u*u+g*g);return d<1e-10?{x:0,y:0,z:1}:{x:h/d,y:u/d,z:g/d}}getArea(){const e=this.getVertices();if(!e)return null;const[t,n,i]=e,s=n.position.x-t.position.x,o=n.position.y-t.position.y,r=n.position.z-t.position.z,a=i.position.x-t.position.x,l=i.position.y-t.position.y,c=i.position.z-t.position.z,h=o*c-r*l,u=r*a-s*c,g=s*l-o*a;return Math.sqrt(h*h+u*u+g*g)/2}getQuality(){const e=this.getVertices();if(!e)return null;const[t,n,i]=e,s=Math.sqrt(Math.pow(n.position.x-i.position.x,2)+Math.pow(n.position.y-i.position.y,2)+Math.pow(n.position.z-i.position.z,2)),o=Math.sqrt(Math.pow(t.position.x-i.position.x,2)+Math.pow(t.position.y-i.position.y,2)+Math.pow(t.position.z-i.position.z,2)),r=Math.sqrt(Math.pow(t.position.x-n.position.x,2)+Math.pow(t.position.y-n.position.y,2)+Math.pow(t.position.z-n.position.z,2)),a=(s+o+r)/2,l=a*(a-s)*(a-o)*(a-r);if(l<=0)return 0;const c=Math.sqrt(l),h=s*o*r/(4*c);if(h<1e-10)return 0;const u=2*(c/a)/h;return Math.max(0,Math.min(1,u))}containsVertex(e){const t=this.getVertices();return!!t&&t.some(t=>t.id===e.id)}getOppositeHalfedge(e){const t=this.getHalfedges();if(!t)return null;for(const n of t){const t=n.getSourceVertex();if(t&&t.id!==e.id&&n.vertex.id!==e.id)return n}return null}isDegenerate(e=1e-10){const t=this.getArea();return null===t||t<e}}class d{constructor(){this.vertices=new Map,this.edges=new Map,this.halfedges=new Map,this.faces=new Map,this.nextVertexId=0,this.nextEdgeId=0,this.nextHalfedgeId=0,this.nextFaceId=0,this.edgeMap=new Map}static fromBufferGeometry(n,o){const r=new d,a=n.attributes.position;if(!a)throw new Error("Geometry must have a position attribute");const l=n.index;if(!l)throw new Error("Geometry must be indexed");const u=a.count,f=l.count/3;if(l.count%3!=0)throw new Error("Geometry must be triangulated (indices count must be divisible by 3)");for(let i=0;i<u;i++){const n=a.getX(i),s=a.getY(i),o=a.getZ(i),l=new c(t(r.nextVertexId++),new e.Vector3(n,s,o));r.vertices.set(l.id,l)}for(let e=0;e<f;e++){const n=l.getX(3*e+0),o=l.getX(3*e+1),a=l.getX(3*e+2),c=r.vertices.get(t(n)),u=r.vertices.get(t(o)),d=r.vertices.get(t(a));if(!c||!u||!d)throw new Error(`Vertex not found in face ${e}: ${n}, ${o}, ${a}`);const f=r.getOrCreateEdge(n,o),p=r.getOrCreateEdge(o,a),x=r.getOrCreateEdge(a,n),y=new g(s(r.nextFaceId++),null);r.faces.set(y.id,y);const m=new h(i(r.nextHalfedgeId++),u,f),v=new h(i(r.nextHalfedgeId++),d,p),z=new h(i(r.nextHalfedgeId++),c,x);r.halfedges.set(m.id,m),r.halfedges.set(v.id,v),r.halfedges.set(z.id,z),f.addHalfedge(m),p.addHalfedge(v),x.addHalfedge(z),m.next=v,v.next=z,z.next=m,m.prev=z,v.prev=m,z.prev=v,m.face=y,v.face=y,z.face=y,y.halfedge=m,c.halfedge||(c.halfedge=m),u.halfedge||(u.halfedge=v),d.halfedge||(d.halfedge=z),f.halfedge=m,p.halfedge=v,x.halfedge=z}return r.setupTwinHalfedges(),o&&o.length>0&&r.markFeatureEdges(o),r.classifyVertices(),r}getOrCreateEdge(e,t){const n=this.makeEdgeKey(e,t);let i=this.edgeMap.get(n);if(!i){const s=this.vertices.get(e),o=this.vertices.get(t);if(!s||!o)throw new Error(`Vertex not found: ${e} or ${t}`);const r=o.position.x-s.position.x,a=o.position.y-s.position.y,l=o.position.z-s.position.z,c=Math.sqrt(r*r+a*a+l*l);i=new u(this.nextEdgeId++,null,c),i.allHalfedges=[],this.edgeMap.set(n,i),this.edges.set(i.id,i)}return i}makeEdgeKey(e,t){return e<t?`${e},${t}`:`${t},${e}`}setupTwinHalfedges(){var e;for(const t of this.edges.values()){const e=t.allHalfedges,n=e.length;0!==n&&(1===n?(e[0].twin=null,t.type=a.Boundary):2===n?(e[0].twin=e[1],e[1].twin=e[0],t.type=a.Manifold):(this.setupNonManifoldTwins(t,e),t.type=a.NonManifold))}for(const t of this.halfedges.values())if(null!==t.twin){const n=null==(e=t.prev)?void 0:e.vertex;n&&(n.halfedge=t)}}setupNonManifoldTwins(e,t){const[n,i]=e.getVertices();if(!n||!i)return;const s=[],o=[];for(const a of t)a.vertex.id===n.id?s.push(a):o.push(a);const r=Math.min(s.length,o.length);for(let a=0;a<r;a++)s[a].twin=o[a],o[a].twin=s[a];for(let a=r;a<s.length;a++)s[a].twin=null;for(let a=r;a<o.length;a++)o[a].twin=null}markFeatureEdges(e){for(const[t,n]of e){const e=this.makeEdgeKey(t,n),i=this.edgeMap.get(e);i&&i.type===a.Manifold&&i.markAsFeature()}}classifyVertices(){for(const e of this.vertices.values())e.type=this.classifyVertex(e)}classifyVertex(e){let t=0;return e.forEachOutgoingHalfedge(e=>{e.edge.isSkeletonEdge()&&t++}),0===t?r.Manifold:2===t?r.OpenBook:r.SkeletonBranching}toBufferGeometry(){return new e.Vector3.constructor}getVertices(){return Array.from(this.vertices.values())}getEdges(){return Array.from(this.edges.values())}getFaces(){return Array.from(this.faces.values())}getHalfedges(){return Array.from(this.halfedges.values())}get vertexCount(){return this.vertices.size}get edgeCount(){return this.edges.size}get faceCount(){return this.faces.size}get halfedgeCount(){return this.halfedges.size}getNonManifoldEdges(){return this.getEdges().filter(e=>e.type===a.NonManifold)}getBoundaryEdges(){return this.getEdges().filter(e=>e.type===a.Boundary)}getFeatureEdges(){return this.getEdges().filter(e=>e.type===a.Feature)}getSkeletonEdges(){return this.getEdges().filter(e=>e.isSkeletonEdge())}isManifold(){return 0===this.getNonManifoldEdges().length}hasBoundary(){return this.getBoundaryEdges().length>0}getVertex(e){return this.vertices.get(e)}getEdge(e){return this.edges.get(e)}getFace(e){return this.faces.get(e)}getHalfedge(e){return this.halfedges.get(e)}getEdgeBetween(e,t){const n=this.makeEdgeKey(e.id,t.id);return this.edgeMap.get(n)}createVertex(e){const t=new c(this.nextVertexId++,e);return this.vertices.set(t.id,t),t}createFace(e,t,n){const i=this.getOrCreateEdge(e.id,t.id),s=this.getOrCreateEdge(t.id,n.id),o=this.getOrCreateEdge(n.id,e.id),r=new g(this.nextFaceId++,null);this.faces.set(r.id,r);const a=new h(this.nextHalfedgeId++,t,i),l=new h(this.nextHalfedgeId++,n,s),c=new h(this.nextHalfedgeId++,e,o);return this.halfedges.set(a.id,a),this.halfedges.set(l.id,l),this.halfedges.set(c.id,c),i.addHalfedge(a),s.addHalfedge(l),o.addHalfedge(c),a.next=l,l.next=c,c.next=a,a.prev=c,l.prev=a,c.prev=l,a.face=r,l.face=r,c.face=r,r.halfedge=a,e.halfedge||(e.halfedge=a),t.halfedge||(t.halfedge=l),n.halfedge||(n.halfedge=c),i.halfedge=a,s.halfedge=l,o.halfedge=c,r}getStats(){const e=this.getNonManifoldEdges().length,t=this.getBoundaryEdges().length,n=this.getFeatureEdges().length,i=this.vertexCount-this.edgeCount+this.faceCount;return{vertexCount:this.vertexCount,edgeCount:this.edgeCount,faceCount:this.faceCount,nonManifoldEdgeCount:e,boundaryEdgeCount:t,featureEdgeCount:n,eulerCharacteristic:i}}}function f(e,t){const n=t.x-e.x,i=t.y-e.y,s=t.z-e.z;return n*n+i*i+s*s}function p(e,t){return Math.sqrt(f(e,t))}function x(e,t){return e.x*t.x+e.y*t.y+e.z*t.z}function y(e,t){return{x:e.y*t.z-e.z*t.y,y:e.z*t.x-e.x*t.z,z:e.x*t.y-e.y*t.x}}function m(e){return Math.sqrt(e.x*e.x+e.y*e.y+e.z*e.z)}function v(e){return e.x*e.x+e.y*e.y+e.z*e.z}function z(e){const t=m(e);return t<1e-10?{x:0,y:0,z:0}:{x:e.x/t,y:e.y/t,z:e.z/t}}function M(e,t){return{x:e.x+t.x,y:e.y+t.y,z:e.z+t.z}}function E(e,t){return{x:e.x-t.x,y:e.y-t.y,z:e.z-t.z}}function w(e,t){return{x:e.x*t,y:e.y*t,z:e.z*t}}function V(e,t,n){return{x:e.x+(t.x-e.x)*n,y:e.y+(t.y-e.y)*n,z:e.z+(t.z-e.z)*n}}function k(e,t){return{x:(e.x+t.x)/2,y:(e.y+t.y)/2,z:(e.z+t.z)/2}}function C(e,t){const n=m(e),i=m(t);if(n<1e-10||i<1e-10)return 0;const s=x(e,t)/(n*i);return Math.acos(Math.max(-1,Math.min(1,s)))}function S(e,t,n){const i=E(n,t),s=v(i);if(s<1e-10)return{...t};return M(t,w(i,Math.max(0,Math.min(1,x(E(e,t),i)/s))))}function b(e,t,n){return m(y(E(t,e),E(n,e)))/2}function B(e,t,n){return z(y(E(t,e),E(n,e)))}function F(e,t,n){const i=p(t,n),s=p(e,n),o=p(e,t),r=b(e,t,n);return r<1e-10?null:i*s*o/(4*r)}function _(e,t,n){const i=(p(t,n)+p(e,n)+p(e,t))/2,s=b(e,t,n);return i<1e-10?null:s/i}function H(e,t,n,i){const s=z(M(B(e,t,n),B(e,i,t)));let o;o=Math.abs(s.x)<.9?z(y(s,{x:1,y:0,z:0})):z(y(s,{x:0,y:1,z:0}));const r=y(s,o),a=e=>({x:x(e,o),y:x(e,r)}),l=a(e),c=a(t),h=a(n),u=a(i),g=(e,t)=>e.x*t.y-e.y*t.x,d={x:c.x-l.x,y:c.y-l.y},f={x:h.x-l.x,y:h.y-l.y},p={x:u.x-l.x,y:u.y-l.y};if(g(d,f)*g(d,p)>=0)return!1;const m={x:u.x-h.x,y:u.y-h.y},v={x:l.x-h.x,y:l.y-h.y},E={x:c.x-h.x,y:c.y-h.y};return g(m,v)*g(m,E)<0}class I{constructor(e){this.id=e,this.vertices=[],this.edges=[],this.isClosed=!1,this._totalLength=0,this._cumulativeLengths=[]}get startVertex(){return this.vertices[0]}get endVertex(){return this.vertices[this.vertices.length-1]}get totalLength(){return this._totalLength}get vertexCount(){return this.vertices.length}get edgeCount(){return this.edges.length}addVertex(e){if(this.vertices.length>0){const t=this.vertices[this.vertices.length-1],n=p({x:t.position.x,y:t.position.y,z:t.position.z},{x:e.position.x,y:e.position.y,z:e.position.z});this._totalLength+=n}this._cumulativeLengths.push(this._totalLength),this.vertices.push(e)}addEdge(e){this.edges.push(e)}recomputeLengths(){this._totalLength=0,this._cumulativeLengths=[0];for(let e=1;e<this.vertices.length;e++){const t=this.vertices[e-1],n=this.vertices[e],i=p({x:t.position.x,y:t.position.y,z:t.position.z},{x:n.position.x,y:n.position.y,z:n.position.z});this._totalLength+=i,this._cumulativeLengths.push(this._totalLength)}}getParameterAtVertex(e){return 0===this._totalLength||e<0||e>=this.vertices.length?0:(this._cumulativeLengths[e]??0)/this._totalLength}getPositionAt(e){if(0===this.vertices.length)return null;if(1===this.vertices.length){const e=this.vertices[0];return{x:e.position.x,y:e.position.y,z:e.position.z}}const t=(e=Math.max(0,Math.min(1,e)))*this._totalLength;for(let i=1;i<this.vertices.length;i++){const e=this._cumulativeLengths[i-1]??0,n=this._cumulativeLengths[i]??0;if(t<=n){const s=this.vertices[i-1],o=this.vertices[i],r=n-e;if(r<1e-10)return{x:s.position.x,y:s.position.y,z:s.position.z};const a=(t-e)/r;return V({x:s.position.x,y:s.position.y,z:s.position.z},{x:o.position.x,y:o.position.y,z:o.position.z},a)}}const n=this.vertices[this.vertices.length-1];return{x:n.position.x,y:n.position.y,z:n.position.z}}projectPoint(e){if(0===this.vertices.length)return null;if(1===this.vertices.length){const t=this.vertices[0],n={x:t.position.x,y:t.position.y,z:t.position.z};return{point:n,parameter:0,distance:p(e,n)}}let t=null,n=0,i=1/0;for(let s=1;s<this.vertices.length;s++){const o=this.vertices[s-1],r=this.vertices[s],a={x:o.position.x,y:o.position.y,z:o.position.z},l=S(e,a,{x:r.position.x,y:r.position.y,z:r.position.z}),c=p(e,l);if(c<i){i=c,t=l;const e=this._cumulativeLengths[s-1]??0;if((this._cumulativeLengths[s]??0)-e<1e-10)n=e/this._totalLength;else{n=(e+p(a,l))/this._totalLength}}}return t?{point:t,parameter:n,distance:i}:null}getVertex(e){return this.vertices[e]}getEdge(e){return this.edges[e]}containsVertex(e){return this.vertices.some(t=>t.id===e.id)}containsEdge(e){return this.edges.some(t=>t.id===e.id)}indexOfVertex(e){return this.vertices.findIndex(t=>t.id===e.id)}forEachVertex(e){this.vertices.forEach(e)}forEachEdge(e){this.edges.forEach(e)}clone(e){const t=new I(e);return t.vertices=[...this.vertices],t.edges=[...this.edges],t.isClosed=this.isClosed,t._totalLength=this._totalLength,t._cumulativeLengths=[...this._cumulativeLengths],t}}class O{constructor(e){this.nextSegmentId=0,this.mesh=e}build(){const e=this.mesh.getSkeletonEdges(),t=[],n=[];for(const i of this.mesh.getVertices())i.type===r.SkeletonBranching?t.push(i):i.type===r.OpenBook&&n.push(i);return{segments:this.buildSegments(e,t),skeletonEdges:e,branchingVertices:t,openBookVertices:n}}buildSegments(e,t){const n=[],i=new Set,s=new Set(t.map(e=>e.id));for(const o of t){const t=this.getIncidentSkeletonEdges(o,e);for(const e of t){if(i.has(e.id))continue;const t=this.traceSegment(o,e,s,i);t&&n.push(t)}}for(const o of e){if(i.has(o.id))continue;const e=this.traceClosedLoop(o,i);e&&n.push(e)}return n}getIncidentSkeletonEdges(e,t){const n=new Set(t.map(e=>e.id)),i=[];return e.forEachOutgoingHalfedge(e=>{n.has(e.edge.id)&&(i.some(t=>t.id===e.edge.id)||i.push(e.edge))}),i}traceSegment(e,t,n,i){var s,o;const r=new I(this.createSegmentId());r.addVertex(e);let a=e,l=t;for(;l&&!i.has(l.id);){i.add(l.id),r.addEdge(l);const e=l.getOtherVertex(a);if(!e)break;if(r.addVertex(e),a=e,n.has(a.id))break;l=this.getNextSkeletonEdge(a,l,i)}return r.vertices.length>2&&(null==(s=r.startVertex)?void 0:s.id)===(null==(o=r.endVertex)?void 0:o.id)&&(r.isClosed=!0,r.vertices.pop()),r.recomputeLengths(),r}traceClosedLoop(e,t){const[n,i]=e.getVertices();if(!n||!i)return null;const s=new I(this.createSegmentId());s.addVertex(n),s.addEdge(e),s.addVertex(i),t.add(e.id);let o=i,r=this.getNextSkeletonEdge(o,e,t);for(;r&&!t.has(r.id);){t.add(r.id),s.addEdge(r);const e=r.getOtherVertex(o);if(!e)break;if(e.id===n.id){s.isClosed=!0;break}s.addVertex(e),o=e,r=this.getNextSkeletonEdge(o,r,t)}return s.recomputeLengths(),s}getNextSkeletonEdge(e,t,n){let i=null;return e.forEachOutgoingHalfedge(e=>{e.edge.id!==t.id&&e.edge.isSkeletonEdge()&&!n.has(e.edge.id)&&(i=e.edge)}),i}createSegmentId(){return this.nextSegmentId++}}class N{constructor(e){this.segments=new Map,this.skeletonEdges=[],this.branchingVertices=[],this.openBookVertices=[],this.vertexToSegment=new Map,this.isBuilt=!1,this.mesh=e}build(){const e=new O(this.mesh).build();this.applyBuildResult(e),this.isBuilt=!0}applyBuildResult(e){this.segments.clear(),this.vertexToSegment.clear();for(const t of e.segments){this.segments.set(t.id,t);for(let e=1;e<t.vertices.length-1;e++){const n=t.vertices[e];n&&this.vertexToSegment.set(n.id,t)}}this.skeletonEdges=e.skeletonEdges,this.branchingVertices=e.branchingVertices,this.openBookVertices=e.openBookVertices}rebuild(){this.build()}getSegments(){return Array.from(this.segments.values())}getSegment(e){return this.segments.get(e)}getSegmentForVertex(e){return this.vertexToSegment.get(e.id)}getSkeletonEdges(){return this.skeletonEdges}getBranchingVertices(){return this.branchingVertices}getOpenBookVertices(){return this.openBookVertices}get segmentCount(){return this.segments.size}get skeletonEdgeCount(){return this.skeletonEdges.length}get branchingVertexCount(){return this.branchingVertices.length}get openBookVertexCount(){return this.openBookVertices.length}get built(){return this.isBuilt}projectPoint(e){let t=null;for(const n of this.segments.values()){const i=n.projectPoint(e);i&&(!t||i.distance<t.distance)&&(t={point:i.point,segment:n,parameter:i.parameter,distance:i.distance})}return t}isVertexOnSkeleton(e){return e.isOnSkeleton()}isEdgeOnSkeleton(e){return e.isSkeletonEdge()}getAllSkeletonVertices(){return[...this.branchingVertices,...this.openBookVertices]}getTotalLength(){let e=0;for(const t of this.segments.values())e+=t.totalLength;return e}getStats(){let e=0;for(const t of this.segments.values())t.isClosed&&e++;return{segmentCount:this.segmentCount,skeletonEdgeCount:this.skeletonEdgeCount,branchingVertexCount:this.branchingVertexCount,openBookVertexCount:this.openBookVertexCount,totalLength:this.getTotalLength(),closedLoopCount:e}}}function L(e){const t=new N(e);return t.build(),t}class ${constructor(e){this.skeleton=e}constrainPosition(e,t){switch(e.type){case r.Manifold:return{position:t,wasConstrained:!1,constraintDistance:0};case r.OpenBook:return this.constrainToSegment(e,t);case r.SkeletonBranching:case r.NonManifoldOther:return{position:{x:e.position.x,y:e.position.y,z:e.position.z},wasConstrained:!0,constraintDistance:p(t,{x:e.position.x,y:e.position.y,z:e.position.z})};default:return{position:t,wasConstrained:!1,constraintDistance:0}}}constrainToSegment(e,t){const n=this.skeleton.getSegmentForVertex(e);if(!n){const n=this.skeleton.projectPoint(t);return n?{position:n.point,wasConstrained:!0,segment:n.segment,constraintDistance:n.distance}:{position:{x:e.position.x,y:e.position.y,z:e.position.z},wasConstrained:!0,constraintDistance:p(t,{x:e.position.x,y:e.position.y,z:e.position.z})}}const i=n.projectPoint(t);return i?{position:i.point,wasConstrained:!0,segment:n,constraintDistance:i.distance}:{position:{x:e.position.x,y:e.position.y,z:e.position.z},wasConstrained:!0,segment:n,constraintDistance:0}}canMoveFreely(e){return e.type===r.Manifold}isFixed(e){return e.type===r.SkeletonBranching||e.type===r.NonManifoldOther}isConstrainedToSegment(e){return e.type===r.OpenBook}getConstraintSegment(e){if(e.type===r.OpenBook)return this.skeleton.getSegmentForVertex(e)}getAllowedDirection(e){if(e.type!==r.OpenBook)return null;const t=this.skeleton.getSegmentForVertex(e);if(!t||t.vertices.length<2)return null;const n=t.indexOfVertex(e);if(n<0)return null;let i,s;if(0===n){const e=t.vertices[0],n=t.vertices[1];i={x:e.position.x,y:e.position.y,z:e.position.z},s={x:n.position.x,y:n.position.y,z:n.position.z}}else if(n===t.vertices.length-1){const e=t.vertices[n-1],o=t.vertices[n];i={x:e.position.x,y:e.position.y,z:e.position.z},s={x:o.position.x,y:o.position.y,z:o.position.z}}else{const e=t.vertices[n-1],o=t.vertices[n+1];i={x:e.position.x,y:e.position.y,z:e.position.z},s={x:o.position.x,y:o.position.y,z:o.position.z}}const o=s.x-i.x,a=s.y-i.y,l=s.z-i.z,c=Math.sqrt(o*o+a*a+l*l);return c<1e-10?null:{x:o/c,y:a/c,z:l/c}}}function A(e){return new $(e)}function q(e){const t=[],n=[],i=e.attributes.position;if(!i)return t.push("Geometry must have a position attribute"),{isValid:!1,errors:t,warnings:n};const s=e.index;if(!s)return t.push("Geometry must be indexed"),{isValid:!1,errors:t,warnings:n};s.count%3!=0&&t.push(`Index count (${s.count}) must be divisible by 3 for triangle mesh`);const o=i.count;for(let c=0;c<s.count;c++){const e=s.getX(c);if(e<0||e>=o){t.push(`Invalid index ${e} at position ${c} (vertex count: ${o})`);break}}let r=0;const a=s.count/3;for(let c=0;c<a;c++){const e=s.getX(3*c),t=s.getX(3*c+1),n=s.getX(3*c+2);e!==t&&t!==n&&n!==e||r++}r>0&&n.push(`Found ${r} degenerate triangle(s) with repeated vertices`);let l=0;for(let c=0;c<o;c++){const e=i.getX(c),t=i.getY(c),n=i.getZ(c);isFinite(e)&&isFinite(t)&&isFinite(n)||l++}return l>0&&t.push(`Found ${l} vertex position(s) with NaN or Infinity values`),{isValid:0===t.length,errors:t,warnings:n}}function P(e,t={}){const{featureEdges:n,validate:i=!0}=t;if(i){const t=q(e);if(!t.isValid)throw new Error(`Invalid geometry: ${t.errors.join("; ")}`)}return d.fromBufferGeometry(e,n)}function T(t,n={}){const{computeNormals:i=!0,smoothNormals:s=!0}=n,o=new e.BufferGeometry,r=t.getFaces();if(0===r.length)return o;const a=t.getVertices(),l=new Map;a.forEach((e,t)=>{l.set(e.id,t)});const c=new Float32Array(3*a.length);a.forEach((e,t)=>{c[3*t]=e.position.x,c[3*t+1]=e.position.y,c[3*t+2]=e.position.z});const h=[];for(const e of r){const t=e.getVertices();if(!t)continue;const[n,i,s]=t,o=l.get(n.id),r=l.get(i.id),a=l.get(s.id);void 0!==o&&void 0!==r&&void 0!==a&&h.push(o,r,a)}return o.setAttribute("position",new e.BufferAttribute(c,3)),o.setIndex(h),i&&(s?function(t,n,i){const s=n.getVertices(),o=new Float32Array(3*s.length),r=new Uint32Array(s.length);for(const e of n.getFaces()){const t=e.getNormal();if(!t)continue;const n=e.getVertices();if(n)for(const e of n){const n=i.get(e.id);if(void 0===n)continue;const s=3*n;o[s]=(o[s]??0)+t.x,o[s+1]=(o[s+1]??0)+t.y,o[s+2]=(o[s+2]??0)+t.z,r[n]=(r[n]??0)+1}}for(let e=0;e<s.length;e++){const t=r[e]??0;if(0===t)continue;const n=3*e,i=(o[n]??0)/t,s=(o[n+1]??0)/t,a=(o[n+2]??0)/t,l=Math.sqrt(i*i+s*s+a*a);l>1e-10?(o[3*e]=i/l,o[3*e+1]=s/l,o[3*e+2]=a/l):(o[3*e]=0,o[3*e+1]=1,o[3*e+2]=0)}t.setAttribute("normal",new e.BufferAttribute(o,3))}(o,t,l):o.computeVertexNormals()),o}function G(t){const n=new e.BufferGeometry,i=t.getSkeletonEdges();if(0===i.length)return n;const s=new Float32Array(6*i.length);let o=0;for(const e of i){const[t,n]=e.getVertices();t&&n&&(s[o++]=t.position.x,s[o++]=t.position.y,s[o++]=t.position.z,s[o++]=n.position.x,s[o++]=n.position.y,s[o++]=n.position.z)}return n.setAttribute("position",new e.BufferAttribute(s.slice(0,o),3)),n}function Q(t){const n=T(t,{computeNormals:!0}),i=t.getVertices(),s=new Float32Array(3*i.length),o=new Map;i.forEach((e,t)=>{o.set(e.id,t)});for(const e of i){const t=o.get(e.id);if(void 0===t)continue;let n=0,i=0,r=0;switch(e.type){case"manifold":n=.2,i=.8,r=.2;break;case"open_book":n=.2,i=.4,r=.9;break;case"skeleton_branching":n=.9,i=.2,r=.2;break;case"non_manifold_other":n=.9,i=.2,r=.9}s[3*t]=n,s[3*t+1]=i,s[3*t+2]=r}return n.setAttribute("color",new e.BufferAttribute(s,3)),n}function R(t){const n=t.getFaces();if(0===n.length)return new e.BufferGeometry;const i=new Float32Array(9*n.length),s=new Float32Array(9*n.length),o=new Float32Array(9*n.length);let r=0;for(const e of n){const t=e.getVertices(),n=e.getNormal(),a=e.getQuality()??0;if(!t||!n)continue;const l=a<.5?1:2-2*a,c=a<.5?2*a:1,h=.1;for(const e of t)i[r]=e.position.x,i[r+1]=e.position.y,i[r+2]=e.position.z,s[r]=l,s[r+1]=c,s[r+2]=h,o[r]=n.x,o[r+1]=n.y,o[r+2]=n.z,r+=3}const a=new e.BufferGeometry;return a.setAttribute("position",new e.BufferAttribute(i.slice(0,r),3)),a.setAttribute("color",new e.BufferAttribute(s.slice(0,r),3)),a.setAttribute("normal",new e.BufferAttribute(o.slice(0,r),3)),a}class D{constructor(e){if(this.cells=new Map,this.itemPositions=new Map,e<=0)throw new Error("Cell size must be positive");this.cellSize=e}getCellKey(e,t,n){return`${Math.floor(e/this.cellSize)},${Math.floor(t/this.cellSize)},${Math.floor(n/this.cellSize)}`}getCellIndices(e,t,n){return[Math.floor(e/this.cellSize),Math.floor(t/this.cellSize),Math.floor(n/this.cellSize)]}insert(e,t){const n=this.getCellKey(t.x,t.y,t.z);let i=this.cells.get(n);i||(i=[],this.cells.set(n,i)),i.push(e),this.itemPositions.set(e,t)}remove(e){const t=this.itemPositions.get(e);if(!t)return!1;const n=this.getCellKey(t.x,t.y,t.z),i=this.cells.get(n);if(i){const t=i.indexOf(e);-1!==t&&(i.splice(t,1),0===i.length&&this.cells.delete(n))}return this.itemPositions.delete(e),!0}update(e,t){this.remove(e),this.insert(e,t)}queryRadius(e,t){const n=[],i=t*t,s=this.getCellIndices(e.x-t,e.y-t,e.z-t),o=this.getCellIndices(e.x+t,e.y+t,e.z+t);for(let r=s[0];r<=o[0];r++)for(let t=s[1];t<=o[1];t++)for(let a=s[2];a<=o[2];a++){const s=`${r},${t},${a}`,o=this.cells.get(s);if(o)for(const t of o){const s=this.itemPositions.get(t);if(s){const o=s.x-e.x,r=s.y-e.y,a=s.z-e.z;o*o+r*r+a*a<=i&&n.push(t)}}}return n}queryKNearest(e,t,n){let i=this.cellSize,s=[];for(;s.length<t&&!(void 0!==n&&i>n);){s=[];const t=this.queryRadius(e,i);for(const n of t){const t=this.itemPositions.get(n);if(t){const i=t.x-e.x,o=t.y-e.y,r=t.z-e.z;s.push({item:n,distSq:i*i+o*o+r*r})}}i*=2}return s.sort((e,t)=>e.distSq-t.distSq),s.slice(0,t).map(e=>e.item)}clear(){this.cells.clear(),this.itemPositions.clear()}get size(){return this.itemPositions.size}get cellCount(){return this.cells.size}getPosition(e){return this.itemPositions.get(e)}has(e){return this.itemPositions.has(e)}*[Symbol.iterator](){for(const e of this.itemPositions.keys())yield e}getAll(){return Array.from(this.itemPositions.keys())}}function j(e){return{min:{x:Math.min(e.v0.x,e.v1.x,e.v2.x),y:Math.min(e.v0.y,e.v1.y,e.v2.y),z:Math.min(e.v0.z,e.v1.z,e.v2.z)},max:{x:Math.max(e.v0.x,e.v1.x,e.v2.x),y:Math.max(e.v0.y,e.v1.y,e.v2.y),z:Math.max(e.v0.z,e.v1.z,e.v2.z)}}}function X(e,t){return{min:{x:Math.min(e.min.x,t.min.x),y:Math.min(e.min.y,t.min.y),z:Math.min(e.min.z,t.min.z)},max:{x:Math.max(e.max.x,t.max.x),y:Math.max(e.max.y,t.max.y),z:Math.max(e.max.z,t.max.z)}}}function K(e,t){let n=0;return e.x<t.min.x?n+=(t.min.x-e.x)**2:e.x>t.max.x&&(n+=(e.x-t.max.x)**2),e.y<t.min.y?n+=(t.min.y-e.y)**2:e.y>t.max.y&&(n+=(e.y-t.max.y)**2),e.z<t.min.z?n+=(t.min.z-e.z)**2:e.z>t.max.z&&(n+=(e.z-t.max.z)**2),n}function U(e,t){const n=t.v0,i=t.v1,s=t.v2,o=i.x-n.x,r=i.y-n.y,a=i.z-n.z,l=s.x-n.x,c=s.y-n.y,h=s.z-n.z,u=e.x-n.x,g=e.y-n.y,d=e.z-n.z,f=o*u+r*g+a*d,p=l*u+c*g+h*d;if(f<=0&&p<=0)return n;const x=e.x-i.x,y=e.y-i.y,m=e.z-i.z,v=o*x+r*y+a*m,z=l*x+c*y+h*m;if(v>=0&&z<=v)return i;const M=f*z-v*p;if(M<=0&&f>=0&&v<=0){const e=f/(f-v);return{x:n.x+e*o,y:n.y+e*r,z:n.z+e*a}}const E=e.x-s.x,w=e.y-s.y,V=e.z-s.z,k=o*E+r*w+a*V,C=l*E+c*w+h*V;if(C>=0&&k<=C)return s;const S=k*p-f*C;if(S<=0&&p>=0&&C<=0){const e=p/(p-C);return{x:n.x+e*l,y:n.y+e*c,z:n.z+e*h}}const b=v*C-k*z;if(b<=0&&z-v>=0&&k-C>=0){const e=(z-v)/(z-v+(k-C));return{x:i.x+e*(s.x-i.x),y:i.y+e*(s.y-i.y),z:i.z+e*(s.z-i.z)}}const B=1/(b+S+M),F=S*B,_=M*B;return{x:n.x+o*F+l*_,y:n.y+r*F+c*_,z:n.z+a*F+h*_}}class Y{constructor(e=4){this.root=null,this.triangles=[],this.maxLeafSize=e}build(e){if(this.triangles=e,0===e.length)return void(this.root=null);const t=e.map((e,t)=>t);this.root=this.buildNode(t)}buildNode(e){let t=j(this.triangles[e[0]]);for(let h=1;h<e.length;h++)t=X(t,j(this.triangles[e[h]]));if(e.length<=this.maxLeafSize)return{bounds:t,triangleIndices:e};const n=t.max.x-t.min.x,i=t.max.y-t.min.y,s=t.max.z-t.min.z;let o="x";i>n&&i>s?o="y":s>n&&s>i&&(o="z");const r=e.map(e=>{return{index:e,centroid:(t=this.triangles[e],{x:(t.v0.x+t.v1.x+t.v2.x)/3,y:(t.v0.y+t.v1.y+t.v2.y)/3,z:(t.v0.z+t.v1.z+t.v2.z)/3})};var t});r.sort((e,t)=>e.centroid[o]-t.centroid[o]);const a=Math.floor(r.length/2),l=r.slice(0,a).map(e=>e.index),c=r.slice(a).map(e=>e.index);return 0===l.length||0===c.length?{bounds:t,triangleIndices:e}:{bounds:t,left:this.buildNode(l),right:this.buildNode(c)}}closestPoint(e){if(!this.root||0===this.triangles.length)return null;let t=null,n=1/0;const i=[this.root];for(;i.length>0;){const s=i.pop();if(!(K(e,s.bounds)>=n))if(s.triangleIndices)for(const i of s.triangleIndices){const s=U(e,this.triangles[i]),o=f(e,s);o<n&&(n=o,t={point:s,distance:Math.sqrt(o),triangleIndex:i})}else if(s.left&&s.right){K(e,s.left.bounds)<K(e,s.right.bounds)?(i.push(s.right),i.push(s.left)):(i.push(s.left),i.push(s.right))}else s.left?i.push(s.left):s.right&&i.push(s.right)}return t}queryRadius(e,t){const n=[],i=t*t;if(!this.root)return n;const s=[this.root];for(;s.length>0;){const t=s.pop();if(!(K(e,t.bounds)>i))if(t.triangleIndices)for(const s of t.triangleIndices){f(e,U(e,this.triangles[s]))<=i&&n.push(s)}else t.left&&s.push(t.left),t.right&&s.push(t.right)}return n}get triangleCount(){return this.triangles.length}getTriangle(e){return this.triangles[e]}}function Z(e){const t=e.getEdges(),n=e.getVertices();let i=0,s=0,o=0;const l=[];for(const r of t)switch(r.type){case a.Manifold:case a.Feature:i++;break;case a.NonManifold:s++,l.push(W(r));break;case a.Boundary:o++}let c=0,h=0,u=0;const g=[];for(const a of n){u+=a.degree()??0,a.type===r.Manifold?c++:(h++,g.push(J(a)))}const d=n.length>0?u/n.length:0,f=e.vertexCount-e.edgeCount+e.faceCount;return{isManifold:0===s,hasBoundary:o>0,vertexCount:e.vertexCount,edgeCount:e.edgeCount,faceCount:e.faceCount,manifoldEdgeCount:i,nonManifoldEdgeCount:s,boundaryEdgeCount:o,manifoldVertexCount:c,nonManifoldVertexCount:h,nonManifoldEdges:l,nonManifoldVertices:g,eulerCharacteristic:f,averageVertexDegree:d}}function W(e){const[t,n]=e.getVertices();return{edgeId:e.id,vertexIndices:[t?t.id:-1,n?n.id:-1],faceCount:e.getFaceCount(),positions:[t?{x:t.position.x,y:t.position.y,z:t.position.z}:{x:0,y:0,z:0},n?{x:n.position.x,y:n.position.y,z:n.position.z}:{x:0,y:0,z:0}]}}function J(e){let t=0;return e.forEachOutgoingHalfedge(e=>{e.edge.isSkeletonEdge()&&t++}),{vertexId:e.id,position:{x:e.position.x,y:e.position.y,z:e.position.z},type:e.type,skeletonEdgeCount:t}}function ee(e){const t={manifold:0,openBook:0,skeletonBranching:0,nonManifoldOther:0,total:0};for(const n of e.getVertices())switch(n.type=te(n),t.total++,n.type){case r.Manifold:t.manifold++;break;case r.OpenBook:t.openBook++;break;case r.SkeletonBranching:t.skeletonBranching++;break;case r.NonManifoldOther:t.nonManifoldOther++}return t}function te(e){let t=0,n=0,i=!1,s=!1;if(e.forEachOutgoingHalfedge(e=>{n++,e.edge.isSkeletonEdge()&&t++,e.edge.isBoundary()&&(i=!0),e.edge.isNonManifold()&&(s=!0)}),0===n)return r.Manifold;if(s)return 2===t?r.OpenBook:1===t||t>2?r.SkeletonBranching:r.NonManifoldOther;if(i){if(2===t)return r.OpenBook;if(1===t||t>2)return r.SkeletonBranching}return 0===t?r.Manifold:2===t?r.OpenBook:r.SkeletonBranching}function ne(e,t){return e.getVertices().filter(e=>e.type===t)}function ie(e){return ne(e,r.Manifold)}function se(e){return e.getVertices().filter(e=>e.type!==r.Manifold)}function oe(e){e.classifyVertices()}function re(e){const t=[],n=[];return function(e,t){for(const n of e.getVertices())n.halfedge&&(e.getHalfedge(n.halfedge.id)||t.push({type:"invalid_vertex_halfedge",message:`Vertex ${n.id} references non-existent halfedge ${n.halfedge.id}`,elementIds:[n.id]})),isFinite(n.position.x)&&isFinite(n.position.y)&&isFinite(n.position.z)||t.push({type:"invalid_vertex_position",message:`Vertex ${n.id} has invalid position`,elementIds:[n.id]})}(e,t),function(e,t,n){for(const i of e.getEdges())if(0!==i.allHalfedges.length){e.getHalfedge(i.halfedge.id)||t.push({type:"invalid_edge_halfedge",message:`Edge ${i.id} references non-existent halfedge`,elementIds:[i.id]}),(i.length<=0||!isFinite(i.length))&&n.push({type:"invalid_edge_length",message:`Edge ${i.id} has invalid length: ${i.length}`,elementIds:[i.id]});for(const e of i.allHalfedges)e.edge.id!==i.id&&t.push({type:"halfedge_edge_mismatch",message:`Halfedge ${e.id} in edge ${i.id} references different edge ${e.edge.id}`,elementIds:[i.id,e.id]})}else t.push({type:"edge_no_halfedges",message:`Edge ${i.id} has no halfedges`,elementIds:[i.id]})}(e,t,n),function(e,t,n){var i;for(const s of e.getFaces()){if(!s.halfedge){t.push({type:"face_no_halfedge",message:`Face ${s.id} has no halfedge`,elementIds:[s.id]});continue}if(!e.getHalfedge(s.halfedge.id)){t.push({type:"invalid_face_halfedge",message:`Face ${s.id} references non-existent halfedge`,elementIds:[s.id]});continue}const o=s.getHalfedges();if(o){for(const e of o)(null==(i=e.face)?void 0:i.id)!==s.id&&t.push({type:"halfedge_face_mismatch",message:`Halfedge ${e.id} in face ${s.id} references different face`,elementIds:[s.id,e.id]});s.isDegenerate()&&n.push({type:"degenerate_face",message:`Face ${s.id} is degenerate (near-zero area)`,elementIds:[s.id]})}else t.push({type:"face_invalid_loop",message:`Face ${s.id} has invalid halfedge loop`,elementIds:[s.id]})}}(e,t,n),function(e,t){for(const n of e.getHalfedges())n.next?e.getHalfedge(n.next.id)||t.push({type:"halfedge_invalid_next",message:`Halfedge ${n.id} has invalid next pointer`,elementIds:[n.id]}):t.push({type:"halfedge_no_next",message:`Halfedge ${n.id} has no next pointer`,elementIds:[n.id]}),n.prev?e.getHalfedge(n.prev.id)||t.push({type:"halfedge_invalid_prev",message:`Halfedge ${n.id} has invalid prev pointer`,elementIds:[n.id]}):t.push({type:"halfedge_no_prev",message:`Halfedge ${n.id} has no prev pointer`,elementIds:[n.id]}),n.next&&n.next.prev!==n&&t.push({type:"halfedge_next_prev_mismatch",message:`Halfedge ${n.id}: next.prev does not point back`,elementIds:[n.id]}),n.prev&&n.prev.next!==n&&t.push({type:"halfedge_prev_next_mismatch",message:`Halfedge ${n.id}: prev.next does not point back`,elementIds:[n.id]}),n.twin&&(e.getHalfedge(n.twin.id)?n.twin.twin!==n&&t.push({type:"halfedge_twin_mismatch",message:`Halfedge ${n.id}: twin.twin does not point back`,elementIds:[n.id]}):t.push({type:"halfedge_invalid_twin",message:`Halfedge ${n.id} has invalid twin pointer`,elementIds:[n.id]})),e.getVertex(n.vertex.id)||t.push({type:"halfedge_invalid_vertex",message:`Halfedge ${n.id} references non-existent vertex`,elementIds:[n.id]}),e.getEdge(n.edge.id)||t.push({type:"halfedge_invalid_edge",message:`Halfedge ${n.id} references non-existent edge`,elementIds:[n.id]})}(e,t),{isValid:0===t.length,errors:t,warnings:n}}function ae(e){return re(e).isValid}function le(e){if(e.isSkeletonEdge())return!1;if(!e.canFlip())return!1;const t=ce(e);return!!t&&H(t.v0,t.v1,t.v2,t.v3)}function ce(e){const t=e.halfedge,n=t.twin;if(!n||!t.face||!n.face)return null;const i=t.next,s=n.next;if(!i||!s)return null;const o=n.vertex,r=t.vertex,a=i.vertex,l=s.vertex;return{v0:{x:o.position.x,y:o.position.y,z:o.position.z},v1:{x:r.position.x,y:r.position.y,z:r.position.z},v2:{x:a.position.x,y:a.position.y,z:a.position.z},v3:{x:l.position.x,y:l.position.y,z:l.position.z}}}function he(e,t){if(!le(t))return{success:!1,reason:"Edge cannot be flipped"};const n=t.halfedge,i=n.twin;if(!i)return{success:!1,reason:"Edge has no twin"};const s=n.next,o=n.prev,r=i.next,a=i.prev,l=i.vertex,c=n.vertex,h=s.vertex,u=r.vertex,g=n.face,d=i.face;if(!g||!d)return{success:!1,reason:"Missing faces"};const f=p({x:h.position.x,y:h.position.y,z:h.position.z},{x:u.position.x,y:u.position.y,z:u.position.z});return t.length=f,n.vertex=u,i.vertex=h,n.next=a,n.prev=s,a.next=s,a.prev=n,s.next=n,s.prev=a,i.next=o,i.prev=r,o.next=r,o.prev=i,r.next=i,r.prev=o,n.face=g,a.face=g,s.face=g,i.face=d,o.face=d,r.face=d,g.halfedge=n,d.halfedge=i,l.halfedge===n&&(l.halfedge=r),c.halfedge===i&&(c.halfedge=s),{success:!0,newLength:f}}function ue(e){const t=e.halfedge,n=t.twin;if(!n||!t.face||!n.face)return!0;const i=ce(e);if(!i)return!0;return ge(i.v2,i.v0,i.v1)+ge(i.v3,i.v0,i.v1)<=Math.PI+1e-10}function ge(e,t,n){const i=t.x-e.x,s=t.y-e.y,o=t.z-e.z,r=n.x-e.x,a=n.y-e.y,l=n.z-e.z,c=i*r+s*a+o*l,h=Math.sqrt(i*i+s*s+o*o),u=Math.sqrt(r*r+a*a+l*l);if(h<1e-10||u<1e-10)return 0;const g=Math.max(-1,Math.min(1,c/(h*u)));return Math.acos(g)}function de(e,t){const n=e.getEdges(),i=t??10*n.length;let s=0,o=0;for(;o<i;){o++;let e=!1;for(const t of n)if(!ue(t)&&le(t)){he(0,t).success&&(s++,e=!0)}if(!e)break}return s}function fe(t,n,i=.5){const[s,o]=n.getVertices();if(!s||!o)return{success:!1,reason:"Edge has no vertices"};const r=s.position.x,a=s.position.y,l=s.position.z,c={x:r+(o.position.x-r)*i,y:a+(o.position.y-a)*i,z:l+(o.position.z-l)*i},h=t.createVertex(new e.Vector3(c.x,c.y,c.z));n.isSkeletonEdge();const u=[],g=[],d=n.getFaces();if(0===d.length)return{success:!0,newVertex:h,newEdges:[],newFaces:[]};for(const e of d){if(!e)continue;const i=e.getHalfedges();if(!i)continue;let s=null;for(const e of i)if(e.edge.id===n.id){s=e;break}s&&pe(t,e,s,h,u,g)}return n.length=n.length*i,t.classifyVertices(),{success:!0,newVertex:h,newEdges:u,newFaces:g}}function pe(e,t,n,i,s,o){const r=n.next.vertex,a=n.vertex,l=e.createFace(i,a,r);o.push(l),n.vertex=i,i.halfedge||(i.halfedge=n)}function xe(e,t){const n=[];let i=0;const s=[];for(const o of e.getEdges())o.length>t&&s.push(o);for(const o of s){const t=fe(e,o);t.success&&t.newVertex&&(i++,n.push(t.newVertex))}return{splitCount:i,newVertices:n}}function ye(e){const[t,n]=e.getVertices();return!(!t||!n)&&((t.type!==r.SkeletonBranching&&t.type!==r.NonManifoldOther||n.type!==r.SkeletonBranching&&n.type!==r.NonManifoldOther)&&(n.type===r.SkeletonBranching||(n.type,r.NonManifoldOther),!!function(e,t){const n=new Set,i=new Set;e.forEachNeighbor(e=>{n.add(e.id)}),t.forEachNeighbor(e=>{i.add(e.id)});let s=0;for(const a of n)a!==e.id&&a!==t.id&&i.has(a)&&s++;const o=me(e,t),r=o.length;return s<=r}(t,n)))}function me(e,t){const n=new Set,i=[];return e.forEachOutgoingHalfedge(e=>{e.face&&n.add(e.face.id)}),t.forEachOutgoingHalfedge(e=>{e.face&&n.has(e.face.id)&&i.push(e.face)}),i}function ve(e,t){var n;if(!ye(t))return{success:!1,reason:"Edge cannot be contracted"};const[i,s]=t.getVertices();if(!i||!s)return{success:!1,reason:"Edge has no vertices"};const{keepVertex:o,removeVertex:a,newPosition:l}=function(e,t){const n=e=>{switch(e.type){case r.SkeletonBranching:case r.NonManifoldOther:return 3;case r.OpenBook:return 2;case r.Manifold:return 1;default:return 0}},i=n(e),s=n(t);let o,a,l;i>=s?(o=e,a=t):(o=t,a=e);l=o.type===r.SkeletonBranching||o.type===r.NonManifoldOther||o.type===r.OpenBook&&a.type===r.Manifold?{x:o.position.x,y:o.position.y,z:o.position.z}:k({x:e.position.x,y:e.position.y,z:e.position.z},{x:t.position.x,y:t.position.y,z:t.position.z});return{keepVertex:o,removeVertex:a,newPosition:l}}(i,s);o.position.set(l.x,l.y,l.z);const c=me(i,s);var h;h=o,a.forEachOutgoingHalfedge(e=>{e.twin&&(e.twin.vertex=h)});for(const r of c)e.faces.delete(r.id);e.edges.delete(t.id);for(const r of t.allHalfedges)e.halfedges.delete(r.id);if(e.vertices.delete(a.id),o.halfedge&&!e.halfedges.has(o.halfedge.id))for(const r of e.halfedges.values())if((null==(n=r.getSourceVertex())?void 0:n.id)===o.id){o.halfedge=r;break}return e.classifyVertices(),{success:!0,remainingVertex:o,removedFaces:c}}function ze(e,t){let n=0,i=0,s=[];for(const o of e.getEdges())o.length<t&&ye(o)&&s.push(o);for(;s.length>0;){const t=s.pop();if(!e.edges.has(t.id)||!ye(t))continue;ve(e,t).success&&(n++,i++)}return{contractCount:n,removedVertices:i}}function Me(e){const t=e.getNeighbors();if(0===t.length)return null;let n=0,i=0,s=0;for(const c of t)n+=c.position.x,i+=c.position.y,s+=c.position.z;n/=t.length,i/=t.length,s/=t.length;const o={x:n,y:i,z:s},r=function(e){let t=0,n=0,i=0,s=0;if(e.forEachOutgoingHalfedge(e=>{if(e.face){const o=e.face.getNormal();o&&(t+=o.x,n+=o.y,i+=o.z,s++)}}),0===s)return null;return z({x:t/s,y:n/s,z:i/s})}(e);if(!r)return o;const a={x:e.position.x,y:e.position.y,z:e.position.z},l=E(o,a);return M(a,E(l,w(r,x(l,r))))}function Ee(e,t,n,i){if(t.type===r.SkeletonBranching||t.type===r.NonManifoldOther)return{success:!1,reason:"Vertex is fixed"};const s={x:t.position.x,y:t.position.y,z:t.position.z};let o=n,a=!1;if(i){const e=i.constrainPosition(t,n);o=e.position,a=e.wasConstrained}if(!function(e,t){const n={x:e.position.x,y:e.position.y,z:e.position.z};e.position.set(t.x,t.y,t.z);let i=!0;return e.forEachOutgoingHalfedge(e=>{if(e.face){const t=e.face.getArea();null!==t&&t<1e-10&&(i=!1)}}),e.position.set(n.x,n.y,n.z),i}(t,o))return{success:!1,reason:"Relocation would create invalid geometry"};t.position.set(o.x,o.y,o.z),function(e){e.forEachOutgoingHalfedge(e=>{const t=e.getSourceVertex();t&&(e.edge.length=p({x:t.position.x,y:t.position.y,z:t.position.z},{x:e.vertex.position.x,y:e.vertex.position.y,z:e.vertex.position.z}))})}(t);return{success:!0,newPosition:o,wasConstrained:a,distanceMoved:p(s,o)}}function we(e,t,n,i=.5){const s=Me(t);if(!s)return{success:!1,reason:"Cannot compute smoothing target"};const o=t.position.x,r=t.position.y,a=t.position.z;return Ee(0,t,{x:o+(s.x-o)*i,y:r+(s.y-r)*i,z:a+(s.z-a)*i},n)}function Ve(e,t,n=.5){let i=0,s=0;for(const o of e.getVertices())if(o.type===r.Manifold||o.type===r.OpenBook){const e=we(0,o,t,n);e.success&&(i++,s+=e.distanceMoved??0)}return{smoothedCount:i,totalDistance:s}}function ke(e,t=.3){const n=e.getFaces(),i=e.getEdges(),s=[],o=[];for(const v of n){const e=v.getQuality();null!==e&&s.push(e);const t=v.getArea();null!==t&&o.push(t)}const r=i.map(e=>e.length),a=s.length>0?Math.min(...s):0,l=s.length>0?Math.max(...s):0,c=s.length>0?s.reduce((e,t)=>e+t,0)/s.length:0,h=s.length>0?s.reduce((e,t)=>e+Math.pow(t-c,2),0)/s.length:0,u=Math.sqrt(h),g=s.filter(e=>e<t).length,d=r.length>0?Math.min(...r):0,f=r.length>0?Math.max(...r):0,p=r.length>0?r.reduce((e,t)=>e+t,0)/r.length:0,x=o.length>0?Math.min(...o):0,y=o.length>0?Math.max(...o):0,m=o.reduce((e,t)=>e+t,0);return{minQuality:a,maxQuality:l,averageQuality:c,stdDevQuality:u,poorQualityCount:g,minEdgeLength:d,maxEdgeLength:f,averageEdgeLength:p,minArea:x,maxArea:y,totalArea:m}}function Ce(e,t=.3){return e.getFaces().filter(e=>{const n=e.getQuality();return null!==n&&n<t})}function Se(e,t,n=1.333){const i=t*n;return e.getEdges().filter(e=>e.length>i)}function be(e,t,n=.4){const i=t*n;return e.getEdges().filter(e=>e.length<i)}function Be(e,t){const n=e.getVertices();if(0===n.length)return 1;let i=1/0,s=1/0,o=1/0,r=-1/0,a=-1/0,l=-1/0;for(const h of n)i=Math.min(i,h.position.x),s=Math.min(s,h.position.y),o=Math.min(o,h.position.z),r=Math.max(r,h.position.x),a=Math.max(a,h.position.y),l=Math.max(l,h.position.z);const c=Math.sqrt(Math.pow(r-i,2)+Math.pow(a-s,2)+Math.pow(l-o,2));if(void 0!==t&&t>0){const n=ke(e);if(n.totalArea>0)return Math.sqrt(n.totalArea/(2*t))}return c/Math.sqrt(n.length)}function Fe(e,t=8){return e.getVertices().filter(e=>{const n=e.degree();return null!==n&&n>t})}function _e(e,t=4){return e.getVertices().filter(e=>{const n=e.degree();return null!==n&&n<t})}class He{constructor(e,t={}){this.skeleton=null,this.constraints=null,this.mesh=e;const n=t.targetEdgeLength??Be(e);this.options={...l,...t,targetEdgeLength:n},this.state={iteration:0,edgeSplits:0,edgeContractions:0,edgeFlips:0,vertexRelocations:0,quality:ke(e)},e.isManifold()||(this.skeleton=L(e),this.constraints=A(this.skeleton))}iterate(){this.state.iteration++;const e=this.options.targetEdgeLength,t=e*this.options.minEdgeLengthRatio,n=e*this.options.maxEdgeLengthRatio,i=xe(this.mesh,n);this.state.edgeSplits+=i.splitCount;const s=ze(this.mesh,t);this.state.edgeContractions+=s.contractCount;const o=de(this.mesh);this.state.edgeFlips+=o;const r=Ve(this.mesh,this.constraints??void 0,.5);return this.state.vertexRelocations+=r.smoothedCount,this.skeleton&&(i.splitCount>0||s.contractCount>0)&&this.skeleton.rebuild(),this.state.quality=ke(this.mesh,this.options.minTriangleQuality),this.options.verbose&&console.warn(`Iteration ${this.state.iteration}: splits=${i.splitCount}, contractions=${s.contractCount}, flips=${o}, smoothed=${r.smoothedCount}, avgQuality=${this.state.quality.averageQuality.toFixed(3)}`),{...this.state}}run(e){const t=e??this.options.iterations,n=Date.now(),i={vertices:this.mesh.vertexCount,faces:this.mesh.faceCount};for(let o=0;o<t;o++){const e=this.state.quality.averageQuality;this.iterate();const t=this.state.quality.averageQuality-e;if(Math.abs(t)<.001&&o>0){this.options.verbose&&console.warn(`Converged after ${o+1} iterations`);break}}const s=Date.now()-n;return{inputVertices:i.vertices,inputFaces:i.faces,outputVertices:this.mesh.vertexCount,outputFaces:this.mesh.faceCount,iterations:this.state.iteration,finalQuality:this.state.quality.averageQuality,nonManifoldEdges:this.mesh.getNonManifoldEdges().length,skeletonEdges:this.mesh.getSkeletonEdges().length,edgeFlips:this.state.edgeFlips,edgeSplits:this.state.edgeSplits,edgeContractions:this.state.edgeContractions,vertexRelocations:this.state.vertexRelocations,processingTimeMs:s}}hasConverged(){return this.state.quality.averageQuality>.9||0===this.state.quality.poorQualityCount}getMesh(){return this.mesh}getSkeleton(){return this.skeleton}getQuality(){return this.state.quality}getState(){return{...this.state}}toBufferGeometry(){return T(this.mesh)}}exports.AdaptiveRemesher=He,exports.BVH=Y,exports.BufferGeometryExporter=class{constructor(e={}){this.options=e}export(e){return T(e,this.options)}exportSkeleton(e){return G(e)}exportClassification(e){return Q(e)}exportQuality(e){return R(e)}setComputeNormals(e){return this.options.computeNormals=e,this}setSmoothNormals(e){return this.options.smoothNormals=e,this}},exports.BufferGeometryImporter=class{constructor(e={}){this.options=e}import(e){return P(e,this.options)}validate(e){return q(e)}setFeatureEdges(e){return this.options.featureEdges=e,this}setValidation(e){return this.options.validate=e,this}},exports.DEFAULT_REMESH_OPTIONS=l,exports.Edge=u,exports.EdgeContractor=class{constructor(e){this.mesh=e}contract(e){return ve(this.mesh,e)}canContract(e){return ye(e)}contractShortEdges(e){return ze(this.mesh,e)}shouldContract(e,t,n=.4){return e.length<t*n}},exports.EdgeFlipper=class{constructor(e){this.mesh=e}flip(e){return he(this.mesh,e)}canFlip(e){return le(e)}isDelaunay(e){return ue(e)}makeDelaunay(e){return de(this.mesh,e)}},exports.EdgeSplitter=class{constructor(e){this.mesh=e}split(e,t=.5){return fe(this.mesh,e,t)}splitLongEdges(e){return xe(this.mesh,e)}shouldSplit(e,t,n=1.333){return e.length>t*n}},exports.EdgeType=a,exports.Face=g,exports.FeatureSkeleton=N,exports.Halfedge=h,exports.ManifoldAnalyzer=class{constructor(){this.mesh=null,this.cachedResult=null}load(e){return this.mesh=d.fromBufferGeometry(e),this.cachedResult=null,this}loadMesh(e){return this.mesh=e,this.cachedResult=null,this}analyze(){if(!this.mesh)throw new Error("No mesh loaded. Call load() first.");return this.cachedResult||(this.cachedResult=Z(this.mesh)),this.cachedResult}isManifold(){return this.analyze().isManifold}hasBoundary(){return this.analyze().hasBoundary}getNonManifoldEdges(){return this.analyze().nonManifoldEdges}getNonManifoldVertices(){return this.analyze().nonManifoldVertices}getMesh(){return this.mesh}clearCache(){return this.cachedResult=null,this}},exports.NonManifoldMesh=d,exports.QualityMetrics=class{constructor(e){this.mesh=e}computeStats(e=.3){return ke(this.mesh,e)}getPoorQualityFaces(e=.3){return Ce(this.mesh,e)}getLongEdges(e,t=1.333){return Se(this.mesh,e,t)}getShortEdges(e,t=.4){return be(this.mesh,e,t)}computeTargetEdgeLength(e){return Be(this.mesh,e)}getHighValenceVertices(e=8){return Fe(this.mesh,e)}getLowValenceVertices(e=4){return _e(this.mesh,e)}},exports.SkeletonBuilder=O,exports.SkeletonConstraints=$,exports.SkeletonSegment=I,exports.SpatialHash=D,exports.TopologyValidator=class{constructor(e){this.mesh=e}validate(){return re(this.mesh)}isValid(){return ae(this.mesh)}getErrors(){return this.validate().errors}getWarnings(){return this.validate().warnings}},exports.Vertex=c,exports.VertexClassifier=class{constructor(e){this.mesh=e}classifyAll(){return ee(this.mesh)}getByType(e){return ne(this.mesh,e)}getManifold(){return ie(this.mesh)}getNonManifold(){return se(this.mesh)}reclassify(){oe(this.mesh)}},exports.VertexRelocator=class{constructor(e,t){this.constraints=null,this.mesh=e,this.constraints=t??null}setConstraints(e){this.constraints=e}relocate(e,t){return Ee(this.mesh,e,t,this.constraints??void 0)}smooth(e,t=.5){return we(this.mesh,e,this.constraints??void 0,t)}smoothAll(e=.5){return Ve(this.mesh,this.constraints??void 0,e)}canRelocate(e){return e.type===r.Manifold||e.type===r.OpenBook}},exports.VertexType=r,exports.add=M,exports.analyzeManifold=function(e){return Z(d.fromBufferGeometry(e))},exports.analyzeMesh=Z,exports.angleAtVertex=function(e,t,n){return C(E(e,t),E(n,t))},exports.angleBetween=C,exports.barycentricCoordinates=function(e,t,n,i){const s=E(n,t),o=E(i,t),r=E(e,t),a=x(s,s),l=x(s,o),c=x(o,o),h=x(r,s),u=x(r,o),g=a*c-l*l;if(Math.abs(g)<1e-10)return null;const d=(c*h-l*u)/g,f=(a*u-l*h)/g;return{u:1-d-f,v:d,w:f}},exports.buildSkeleton=function(e){return new O(e).build()},exports.canContractEdge=ye,exports.canFlipEdge=function(e){return"manifold"===e},exports.canFlipEdgeGeometric=le,exports.canMoveFreely=function(e){return"manifold"===e},exports.classifyAllVertices=ee,exports.classifyVertex=te,exports.computeMeshQuality=ke,exports.computeTangentialSmoothing=Me,exports.computeTargetEdgeLength=Be,exports.computeTriangleAspectRatio=function(e){const t=e.getHalfedges();if(!t)return null;const n=t.map(e=>e.edge.length),i=Math.min(...n),s=Math.max(...n);return i<1e-10?1/0:s/i},exports.contractEdge=ve,exports.contractShortEdges=ze,exports.cotangent=function(e,t,n){const i=E(e,t),s=E(n,t),o=x(i,s),r=m(y(i,s));return Math.abs(r)<1e-10?0:o/r},exports.createBVHFromMesh=function(e){const t=[];for(const i of e.getFaces()){const e=i.getVertices();e&&t.push({v0:{x:e[0].position.x,y:e[0].position.y,z:e[0].position.z},v1:{x:e[1].position.x,y:e[1].position.y,z:e[1].position.z},v2:{x:e[2].position.x,y:e[2].position.y,z:e[2].position.z}})}const n=new Y;return n.build(t),n},exports.createEdgeId=n,exports.createFaceId=s,exports.createHalfedgeId=i,exports.createRemesher=function(e,t={}){const n=d.fromBufferGeometry(e,t.featureEdges);return new He(n,t)},exports.createSegmentId=o,exports.createSkeleton=L,exports.createSkeletonConstraints=A,exports.createSpatialHash=function(e,t,n){let i=n;if(void 0===i&&e.length>1){let n=1/0,s=1/0,o=1/0,r=-1/0,a=-1/0,l=-1/0;for(const i of e){const e=t(i);n=Math.min(n,e.x),s=Math.min(s,e.y),o=Math.min(o,e.z),r=Math.max(r,e.x),a=Math.max(a,e.y),l=Math.max(l,e.z)}i=Math.sqrt((r-n)**2+(a-s)**2+(l-o)**2)/Math.sqrt(e.length)}const s=new D(i??1);for(const o of e)s.insert(o,t(o));return s},exports.createVertexId=t,exports.cross=y,exports.distance=p,exports.distanceSquared=f,exports.dot=x,exports.exportBufferGeometry=T,exports.exportClassificationGeometry=Q,exports.exportQualityGeometry=R,exports.exportSkeletonGeometry=G,exports.flipEdge=he,exports.fromVector3=function(e){return{x:e.x,y:e.y,z:e.z}},exports.getHighValenceVertices=Fe,exports.getLongEdges=Se,exports.getLowValenceVertices=_e,exports.getManifoldVertices=ie,exports.getNonManifoldVertices=se,exports.getOpenBookVertices=function(e){return ne(e,r.OpenBook)},exports.getPoorQualityFaces=Ce,exports.getShortEdges=be,exports.getSkeletonBranchingVertices=function(e){return ne(e,r.SkeletonBranching)},exports.getVerticesByType=ne,exports.importBufferGeometry=P,exports.isDelaunay=ue,exports.isManifold=function(e){return d.fromBufferGeometry(e).isManifold()},exports.isPointInTriangle=function(e,t,n,i){const s=E(n,t),o=E(i,t),r=E(e,t),a=x(s,s),l=x(s,o),c=x(o,o),h=x(r,s),u=x(r,o),g=a*c-l*l;if(Math.abs(g)<1e-10)return!1;const d=(c*h-l*u)/g,f=(a*u-l*h)/g;return 1-d-f>=0&&d>=0&&f>=0},exports.isPositionFixed=function(e){return"skeleton_branching"===e||"non_manifold_other"===e},exports.isQuadConvex=H,exports.isSkeletonConstrained=function(e){return"open_book"===e},exports.isSkeletonEdge=function(e){return"non_manifold"===e||"feature"===e||"boundary"===e},exports.isTopologyValid=ae,exports.length=m,exports.lengthSquared=v,exports.lerp=V,exports.makeDelaunay=de,exports.midpoint=k,exports.normalize=z,exports.projectPointOnLine=function(e,t,n){const i=E(n,t),s=v(i);return s<1e-10?{...t}:M(t,w(i,x(E(e,t),i)/s))},exports.projectPointOnSegment=S,exports.reclassifyVertices=oe,exports.relocateVertex=Ee,exports.remesh=function(e,t={}){const n=d.fromBufferGeometry(e,t.featureEdges),i=new He(n,t),s=i.run();return{geometry:i.toBufferGeometry(),stats:s}},exports.scale=w,exports.smoothAllVertices=Ve,exports.smoothVertex=we,exports.splitEdge=fe,exports.splitLongEdges=xe,exports.subtract=E,exports.toNumber=function(e){return e},exports.triangleArea=b,exports.triangleCentroid=function(e,t,n){return{x:(e.x+t.x+n.x)/3,y:(e.y+t.y+n.y)/3,z:(e.z+t.z+n.z)/3}},exports.triangleCircumcenter=function(e,t,n){const i=E(t,e),s=E(n,e),o=y(i,s),r=2*v(o);if(r<1e-10)return null;const a=v(i),l=v(s),c=w(y(o,i),l),h=w(y(s,o),a),u=w(M(c,h),1/r);return M(e,u)},exports.triangleCircumradius=F,exports.triangleInradius=_,exports.triangleNormal=B,exports.triangleQuality=function(e,t,n){const i=_(e,t,n),s=F(e,t,n);return null===i||null===s||s<1e-10?0:Math.max(0,Math.min(1,2*i/s))},exports.validateGeometry=q,exports.validateTopology=re;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("three");function t(e){return e}function s(e){return e}function n(e){return e}function i(e){return e}function o(e){return e}var r=(e=>(e.Manifold="manifold",e.OpenBook="open_book",e.SkeletonBranching="skeleton_branching",e.NonManifoldOther="non_manifold_other",e))(r||{}),a=(e=>(e.Manifold="manifold",e.NonManifold="non_manifold",e.Feature="feature",e.Boundary="boundary",e))(a||{});const l={iterations:5,preserveBoundary:!0,minEdgeLengthRatio:.4,maxEdgeLengthRatio:1.333,minTriangleQuality:.3,maxNormalDeviation:Math.PI/6,useAcceleration:!0,chunkSize:0,memoryBudget:0,verbose:!1};class c{constructor(e,t){this.id=e,this.position=t,this.halfedge=null,this.type=r.Manifold,this.isMarked=!1}degree(){if(!this.halfedge)return null;let e=0,t=this.halfedge;do{if(e++,!t.twin||!t.twin.next)break;if(t=t.twin.next,e>1e4)throw new Error(`Vertex ${this.id}: degree calculation exceeded maximum iterations`)}while(t!==this.halfedge);return e}forEachOutgoingHalfedge(e){if(!this.halfedge)return;let t=this.halfedge,s=0;do{if(e(t),!t.twin||!t.twin.next)break;if(t=t.twin.next,s++,s>1e4)throw new Error(`Vertex ${this.id}: halfedge iteration exceeded maximum iterations`)}while(t!==this.halfedge)}getOutgoingHalfedges(){const e=[];return this.forEachOutgoingHalfedge(t=>e.push(t)),e}forEachNeighbor(e){this.forEachOutgoingHalfedge(t=>{e(t.vertex)})}getNeighbors(){const e=[];return this.forEachNeighbor(t=>e.push(t)),e}isBoundary(){if(!this.halfedge)return!0;let e=!1;return this.forEachOutgoingHalfedge(t=>{t.face||(e=!0)}),e}canMoveFreely(){return this.type===r.Manifold}isSkeletonConstrained(){return this.type===r.OpenBook}isPositionFixed(){return this.type===r.SkeletonBranching||this.type===r.NonManifoldOther}isOnSkeleton(){return this.type!==r.Manifold}}class h{constructor(e,t,s){this.id=e,this.twin=null,this.next=null,this.prev=null,this.face=null,this.vertex=t,this.edge=s}getSourceVertex(){var e;return(null==(e=this.twin)?void 0:e.vertex)??null}getTargetVertex(){return this.vertex}isBoundary(){return null===this.face}getOppositeHalfedge(){var e;return(null==(e=this.next)?void 0:e.next)??null}getOppositeVertex(){var e;return(null==(e=this.next)?void 0:e.vertex)??null}getVector(){const e=this.getSourceVertex();return e?{x:this.vertex.position.x-e.position.x,y:this.vertex.position.y-e.position.y,z:this.vertex.position.z-e.position.z}:null}}class u{constructor(e,t,s){this.id=e,this.allHalfedges=[],this.type=a.Manifold,this.isInPath=!1,this.halfedge=t,this.length=s,this.allHalfedges.push(t)}addHalfedge(e){this.allHalfedges.push(e),this.updateType()}getHalfedgeCount(){return this.allHalfedges.length}updateType(){const e=this.getFaceCount();0===e||1===e?this.type=a.Boundary:2===e?this.type!==a.Feature&&(this.type=a.Manifold):this.type=a.NonManifold}getFaceCount(){let e=0;for(const t of this.allHalfedges)null!==t.face&&e++;return e}getVertices(){const e=this.halfedge.getSourceVertex(),t=this.halfedge.getTargetVertex();return e?[e,t]:[null,null]}getFaces(){const e=[];for(const t of this.allHalfedges)null!==t.face&&e.push(t.face);return e}getTwoFaces(){var e;return[this.halfedge.face,(null==(e=this.halfedge.twin)?void 0:e.face)??null]}isBoundary(){return this.type===a.Boundary}isNonManifold(){return this.type===a.NonManifold}isSkeletonEdge(){return this.type===a.NonManifold||this.type===a.Feature||this.type===a.Boundary}canFlip(){if(this.type!==a.Manifold)return!1;if(2!==this.getFaceCount())return!1;const[e,t]=this.getVertices();if(!e||!t)return!1;const s=e.degree(),n=t.degree();return!(null===s||null===n||s<=1||n<=1)}getOtherVertex(e){const[t,s]=this.getVertices();return t&&s?e.id===t.id?s:e.id===s.id?t:null:null}markAsFeature(){this.type===a.Manifold&&(this.type=a.Feature)}}class d{constructor(e,t){this.id=e,this.isMarked=!1,this.halfedge=t}getVertices(){const e=this.halfedge,t=e.next,s=null==t?void 0:t.next;return t&&s?[e.vertex,t.vertex,s.vertex]:null}getHalfedges(){const e=this.halfedge,t=e.next,s=null==t?void 0:t.next;return t&&s?[e,t,s]:null}forEachHalfedge(e){const t=this.getHalfedges();if(t)for(const s of t)e(s)}forEachVertex(e){const t=this.getVertices();if(t)for(const s of t)e(s)}getCentroid(){const e=this.getVertices();if(!e)return null;const[t,s,n]=e;return{x:(t.position.x+s.position.x+n.position.x)/3,y:(t.position.y+s.position.y+n.position.y)/3,z:(t.position.z+s.position.z+n.position.z)/3}}getNormal(){const e=this.getVertices();if(!e)return null;const[t,s,n]=e,i=s.position.x-t.position.x,o=s.position.y-t.position.y,r=s.position.z-t.position.z,a=n.position.x-t.position.x,l=n.position.y-t.position.y,c=n.position.z-t.position.z,h=o*c-r*l,u=r*a-i*c,d=i*l-o*a,g=Math.sqrt(h*h+u*u+d*d);return g<1e-10?{x:0,y:0,z:1}:{x:h/g,y:u/g,z:d/g}}getArea(){const e=this.getVertices();if(!e)return null;const[t,s,n]=e,i=s.position.x-t.position.x,o=s.position.y-t.position.y,r=s.position.z-t.position.z,a=n.position.x-t.position.x,l=n.position.y-t.position.y,c=n.position.z-t.position.z,h=o*c-r*l,u=r*a-i*c,d=i*l-o*a;return Math.sqrt(h*h+u*u+d*d)/2}getQuality(){const e=this.getVertices();if(!e)return null;const[t,s,n]=e,i=Math.sqrt(Math.pow(s.position.x-n.position.x,2)+Math.pow(s.position.y-n.position.y,2)+Math.pow(s.position.z-n.position.z,2)),o=Math.sqrt(Math.pow(t.position.x-n.position.x,2)+Math.pow(t.position.y-n.position.y,2)+Math.pow(t.position.z-n.position.z,2)),r=Math.sqrt(Math.pow(t.position.x-s.position.x,2)+Math.pow(t.position.y-s.position.y,2)+Math.pow(t.position.z-s.position.z,2)),a=(i+o+r)/2,l=a*(a-i)*(a-o)*(a-r);if(l<=0)return 0;const c=Math.sqrt(l),h=i*o*r/(4*c);if(h<1e-10)return 0;const u=2*(c/a)/h;return Math.max(0,Math.min(1,u))}containsVertex(e){const t=this.getVertices();return!!t&&t.some(t=>t.id===e.id)}getOppositeHalfedge(e){const t=this.getHalfedges();if(!t)return null;for(const s of t){const t=s.getSourceVertex();if(t&&t.id!==e.id&&s.vertex.id!==e.id)return s}return null}isDegenerate(e=1e-10){const t=this.getArea();return null===t||t<e}}class g{constructor(){this.vertices=new Map,this.edges=new Map,this.halfedges=new Map,this.faces=new Map,this.nextVertexId=0,this.nextEdgeId=0,this.nextHalfedgeId=0,this.nextFaceId=0,this.edgeMap=new Map}static fromBufferGeometry(s,o){const r=new g,a=s.attributes.position;if(!a)throw new Error("Geometry must have a position attribute");const l=s.index;if(!l)throw new Error("Geometry must be indexed");const u=a.count,f=l.count/3;if(l.count%3!=0)throw new Error("Geometry must be triangulated (indices count must be divisible by 3)");for(let n=0;n<u;n++){const s=a.getX(n),i=a.getY(n),o=a.getZ(n),l=new c(t(r.nextVertexId++),new e.Vector3(s,i,o));r.vertices.set(l.id,l)}for(let e=0;e<f;e++){const s=l.getX(3*e+0),o=l.getX(3*e+1),a=l.getX(3*e+2),c=r.vertices.get(t(s)),u=r.vertices.get(t(o)),g=r.vertices.get(t(a));if(!c||!u||!g)throw new Error(`Vertex not found in face ${e}: ${s}, ${o}, ${a}`);const f=r.getOrCreateEdge(s,o),p=r.getOrCreateEdge(o,a),x=r.getOrCreateEdge(a,s),y=new d(i(r.nextFaceId++),null);r.faces.set(y.id,y);const m=new h(n(r.nextHalfedgeId++),u,f),v=new h(n(r.nextHalfedgeId++),g,p),z=new h(n(r.nextHalfedgeId++),c,x);r.halfedges.set(m.id,m),r.halfedges.set(v.id,v),r.halfedges.set(z.id,z),f.addHalfedge(m),p.addHalfedge(v),x.addHalfedge(z),m.next=v,v.next=z,z.next=m,m.prev=z,v.prev=m,z.prev=v,m.face=y,v.face=y,z.face=y,y.halfedge=m,c.halfedge||(c.halfedge=m),u.halfedge||(u.halfedge=v),g.halfedge||(g.halfedge=z),f.halfedge=m,p.halfedge=v,x.halfedge=z}return r.setupTwinHalfedges(),o&&o.length>0&&r.markFeatureEdges(o),r.classifyVertices(),r}getOrCreateEdge(e,t){const s=this.makeEdgeKey(e,t);let n=this.edgeMap.get(s);if(!n){const i=this.vertices.get(e),o=this.vertices.get(t);if(!i||!o)throw new Error(`Vertex not found: ${e} or ${t}`);const r=o.position.x-i.position.x,a=o.position.y-i.position.y,l=o.position.z-i.position.z,c=Math.sqrt(r*r+a*a+l*l);n=new u(this.nextEdgeId++,null,c),n.allHalfedges=[],this.edgeMap.set(s,n),this.edges.set(n.id,n)}return n}makeEdgeKey(e,t){return e<t?`${e},${t}`:`${t},${e}`}setupTwinHalfedges(){var e;for(const t of this.edges.values()){const e=t.allHalfedges,s=e.length;0!==s&&(1===s?(e[0].twin=null,t.type=a.Boundary):2===s?(e[0].twin=e[1],e[1].twin=e[0],t.type=a.Manifold):(this.setupNonManifoldTwins(t,e),t.type=a.NonManifold))}for(const t of this.halfedges.values())if(null!==t.twin){const s=null==(e=t.prev)?void 0:e.vertex;s&&(s.halfedge=t)}}setupNonManifoldTwins(e,t){const[s,n]=e.getVertices();if(!s||!n)return;const i=[],o=[];for(const a of t)a.vertex.id===s.id?i.push(a):o.push(a);const r=Math.min(i.length,o.length);for(let a=0;a<r;a++)i[a].twin=o[a],o[a].twin=i[a];for(let a=r;a<i.length;a++)i[a].twin=null;for(let a=r;a<o.length;a++)o[a].twin=null}markFeatureEdges(e){for(const[t,s]of e){const e=this.makeEdgeKey(t,s),n=this.edgeMap.get(e);n&&n.type===a.Manifold&&n.markAsFeature()}}classifyVertices(){for(const e of this.vertices.values())e.type=this.classifyVertex(e)}classifyVertex(e){let t=0;return e.forEachOutgoingHalfedge(e=>{e.edge.isSkeletonEdge()&&t++}),0===t?r.Manifold:2===t?r.OpenBook:r.SkeletonBranching}toBufferGeometry(){return new e.Vector3.constructor}getVertices(){return Array.from(this.vertices.values())}getEdges(){return Array.from(this.edges.values())}getFaces(){return Array.from(this.faces.values())}getHalfedges(){return Array.from(this.halfedges.values())}get vertexCount(){return this.vertices.size}get edgeCount(){return this.edges.size}get faceCount(){return this.faces.size}get halfedgeCount(){return this.halfedges.size}getNonManifoldEdges(){return this.getEdges().filter(e=>e.type===a.NonManifold)}getBoundaryEdges(){return this.getEdges().filter(e=>e.type===a.Boundary)}getFeatureEdges(){return this.getEdges().filter(e=>e.type===a.Feature)}getSkeletonEdges(){return this.getEdges().filter(e=>e.isSkeletonEdge())}isManifold(){return 0===this.getNonManifoldEdges().length}hasBoundary(){return this.getBoundaryEdges().length>0}getVertex(e){return this.vertices.get(e)}getEdge(e){return this.edges.get(e)}getFace(e){return this.faces.get(e)}getHalfedge(e){return this.halfedges.get(e)}getEdgeBetween(e,t){const s=this.makeEdgeKey(e.id,t.id);return this.edgeMap.get(s)}createVertex(e){const t=new c(this.nextVertexId++,e);return this.vertices.set(t.id,t),t}createFace(e,t,s){const n=this.getOrCreateEdge(e.id,t.id),i=this.getOrCreateEdge(t.id,s.id),o=this.getOrCreateEdge(s.id,e.id),r=new d(this.nextFaceId++,null);this.faces.set(r.id,r);const a=new h(this.nextHalfedgeId++,t,n),l=new h(this.nextHalfedgeId++,s,i),c=new h(this.nextHalfedgeId++,e,o);return this.halfedges.set(a.id,a),this.halfedges.set(l.id,l),this.halfedges.set(c.id,c),n.addHalfedge(a),i.addHalfedge(l),o.addHalfedge(c),a.next=l,l.next=c,c.next=a,a.prev=c,l.prev=a,c.prev=l,a.face=r,l.face=r,c.face=r,r.halfedge=a,e.halfedge||(e.halfedge=a),t.halfedge||(t.halfedge=l),s.halfedge||(s.halfedge=c),n.halfedge=a,i.halfedge=l,o.halfedge=c,r}getStats(){const e=this.getNonManifoldEdges().length,t=this.getBoundaryEdges().length,s=this.getFeatureEdges().length,n=this.vertexCount-this.edgeCount+this.faceCount;return{vertexCount:this.vertexCount,edgeCount:this.edgeCount,faceCount:this.faceCount,nonManifoldEdgeCount:e,boundaryEdgeCount:t,featureEdgeCount:s,eulerCharacteristic:n}}}function f(e,t){const s=t.x-e.x,n=t.y-e.y,i=t.z-e.z;return s*s+n*n+i*i}function p(e,t){return Math.sqrt(f(e,t))}function x(e,t){return e.x*t.x+e.y*t.y+e.z*t.z}function y(e,t){return{x:e.y*t.z-e.z*t.y,y:e.z*t.x-e.x*t.z,z:e.x*t.y-e.y*t.x}}function m(e){return Math.sqrt(e.x*e.x+e.y*e.y+e.z*e.z)}function v(e){return e.x*e.x+e.y*e.y+e.z*e.z}function z(e){const t=m(e);return t<1e-10?{x:0,y:0,z:0}:{x:e.x/t,y:e.y/t,z:e.z/t}}function M(e,t){return{x:e.x+t.x,y:e.y+t.y,z:e.z+t.z}}function w(e,t){return{x:e.x-t.x,y:e.y-t.y,z:e.z-t.z}}function V(e,t){return{x:e.x*t,y:e.y*t,z:e.z*t}}function E(e,t,s){return{x:e.x+(t.x-e.x)*s,y:e.y+(t.y-e.y)*s,z:e.z+(t.z-e.z)*s}}function k(e,t){return{x:(e.x+t.x)/2,y:(e.y+t.y)/2,z:(e.z+t.z)/2}}function C(e,t){const s=m(e),n=m(t);if(s<1e-10||n<1e-10)return 0;const i=x(e,t)/(s*n);return Math.acos(Math.max(-1,Math.min(1,i)))}function S(e,t,s){const n=w(s,t),i=v(n);if(i<1e-10)return{...t};return M(t,V(n,Math.max(0,Math.min(1,x(w(e,t),n)/i))))}function b(e,t,s){return m(y(w(t,e),w(s,e)))/2}function F(e,t,s){return z(y(w(t,e),w(s,e)))}function B(e,t,s){const n=p(t,s),i=p(e,s),o=p(e,t),r=b(e,t,s);return r<1e-10?null:n*i*o/(4*r)}function H(e,t,s){const n=(p(t,s)+p(e,s)+p(e,t))/2,i=b(e,t,s);return n<1e-10?null:i/n}function _(e,t,s,n){const i=z(M(F(e,t,s),F(e,n,t)));let o;o=Math.abs(i.x)<.9?z(y(i,{x:1,y:0,z:0})):z(y(i,{x:0,y:1,z:0}));const r=y(i,o),a=e=>({x:x(e,o),y:x(e,r)}),l=a(e),c=a(t),h=a(s),u=a(n),d=(e,t)=>e.x*t.y-e.y*t.x,g={x:c.x-l.x,y:c.y-l.y},f={x:h.x-l.x,y:h.y-l.y},p={x:u.x-l.x,y:u.y-l.y};if(d(g,f)*d(g,p)>=0)return!1;const m={x:u.x-h.x,y:u.y-h.y},v={x:l.x-h.x,y:l.y-h.y},w={x:c.x-h.x,y:c.y-h.y};return d(m,v)*d(m,w)<0}class I{constructor(e){this.id=e,this.vertices=[],this.edges=[],this.isClosed=!1,this._totalLength=0,this._cumulativeLengths=[]}get startVertex(){return this.vertices[0]}get endVertex(){return this.vertices[this.vertices.length-1]}get totalLength(){return this._totalLength}get vertexCount(){return this.vertices.length}get edgeCount(){return this.edges.length}addVertex(e){if(this.vertices.length>0){const t=this.vertices[this.vertices.length-1],s=p({x:t.position.x,y:t.position.y,z:t.position.z},{x:e.position.x,y:e.position.y,z:e.position.z});this._totalLength+=s}this._cumulativeLengths.push(this._totalLength),this.vertices.push(e)}addEdge(e){this.edges.push(e)}recomputeLengths(){this._totalLength=0,this._cumulativeLengths=[0];for(let e=1;e<this.vertices.length;e++){const t=this.vertices[e-1],s=this.vertices[e],n=p({x:t.position.x,y:t.position.y,z:t.position.z},{x:s.position.x,y:s.position.y,z:s.position.z});this._totalLength+=n,this._cumulativeLengths.push(this._totalLength)}}getParameterAtVertex(e){return 0===this._totalLength||e<0||e>=this.vertices.length?0:(this._cumulativeLengths[e]??0)/this._totalLength}getPositionAt(e){if(0===this.vertices.length)return null;if(1===this.vertices.length){const e=this.vertices[0];return{x:e.position.x,y:e.position.y,z:e.position.z}}const t=(e=Math.max(0,Math.min(1,e)))*this._totalLength;for(let n=1;n<this.vertices.length;n++){const e=this._cumulativeLengths[n-1]??0,s=this._cumulativeLengths[n]??0;if(t<=s){const i=this.vertices[n-1],o=this.vertices[n],r=s-e;if(r<1e-10)return{x:i.position.x,y:i.position.y,z:i.position.z};const a=(t-e)/r;return E({x:i.position.x,y:i.position.y,z:i.position.z},{x:o.position.x,y:o.position.y,z:o.position.z},a)}}const s=this.vertices[this.vertices.length-1];return{x:s.position.x,y:s.position.y,z:s.position.z}}projectPoint(e){if(0===this.vertices.length)return null;if(1===this.vertices.length){const t=this.vertices[0],s={x:t.position.x,y:t.position.y,z:t.position.z};return{point:s,parameter:0,distance:p(e,s)}}let t=null,s=0,n=1/0;for(let i=1;i<this.vertices.length;i++){const o=this.vertices[i-1],r=this.vertices[i],a={x:o.position.x,y:o.position.y,z:o.position.z},l=S(e,a,{x:r.position.x,y:r.position.y,z:r.position.z}),c=p(e,l);if(c<n){n=c,t=l;const e=this._cumulativeLengths[i-1]??0;if((this._cumulativeLengths[i]??0)-e<1e-10)s=e/this._totalLength;else{s=(e+p(a,l))/this._totalLength}}}return t?{point:t,parameter:s,distance:n}:null}getVertex(e){return this.vertices[e]}getEdge(e){return this.edges[e]}containsVertex(e){return this.vertices.some(t=>t.id===e.id)}containsEdge(e){return this.edges.some(t=>t.id===e.id)}indexOfVertex(e){return this.vertices.findIndex(t=>t.id===e.id)}forEachVertex(e){this.vertices.forEach(e)}forEachEdge(e){this.edges.forEach(e)}clone(e){const t=new I(e);return t.vertices=[...this.vertices],t.edges=[...this.edges],t.isClosed=this.isClosed,t._totalLength=this._totalLength,t._cumulativeLengths=[...this._cumulativeLengths],t}}class O{constructor(e){this.nextSegmentId=0,this.mesh=e}build(){const e=this.mesh.getSkeletonEdges(),t=[],s=[];for(const n of this.mesh.getVertices())n.type===r.SkeletonBranching?t.push(n):n.type===r.OpenBook&&s.push(n);return{segments:this.buildSegments(e,t),skeletonEdges:e,branchingVertices:t,openBookVertices:s}}buildSegments(e,t){const s=[],n=new Set,i=new Set(t.map(e=>e.id));for(const o of t){const t=this.getIncidentSkeletonEdges(o,e);for(const e of t){if(n.has(e.id))continue;const t=this.traceSegment(o,e,i,n);t&&s.push(t)}}for(const o of e){if(n.has(o.id))continue;const e=this.traceClosedLoop(o,n);e&&s.push(e)}return s}getIncidentSkeletonEdges(e,t){const s=new Set(t.map(e=>e.id)),n=[];return e.forEachOutgoingHalfedge(e=>{s.has(e.edge.id)&&(n.some(t=>t.id===e.edge.id)||n.push(e.edge))}),n}traceSegment(e,t,s,n){var i,o;const r=new I(this.createSegmentId());r.addVertex(e);let a=e,l=t;for(;l&&!n.has(l.id);){n.add(l.id),r.addEdge(l);const e=l.getOtherVertex(a);if(!e)break;if(r.addVertex(e),a=e,s.has(a.id))break;l=this.getNextSkeletonEdge(a,l,n)}return r.vertices.length>2&&(null==(i=r.startVertex)?void 0:i.id)===(null==(o=r.endVertex)?void 0:o.id)&&(r.isClosed=!0,r.vertices.pop()),r.recomputeLengths(),r}traceClosedLoop(e,t){const[s,n]=e.getVertices();if(!s||!n)return null;const i=new I(this.createSegmentId());i.addVertex(s),i.addEdge(e),i.addVertex(n),t.add(e.id);let o=n,r=this.getNextSkeletonEdge(o,e,t);for(;r&&!t.has(r.id);){t.add(r.id),i.addEdge(r);const e=r.getOtherVertex(o);if(!e)break;if(e.id===s.id){i.isClosed=!0;break}i.addVertex(e),o=e,r=this.getNextSkeletonEdge(o,r,t)}return i.recomputeLengths(),i}getNextSkeletonEdge(e,t,s){let n=null;return e.forEachOutgoingHalfedge(e=>{e.edge.id!==t.id&&e.edge.isSkeletonEdge()&&!s.has(e.edge.id)&&(n=e.edge)}),n}createSegmentId(){return this.nextSegmentId++}}class N{constructor(e){this.segments=new Map,this.skeletonEdges=[],this.branchingVertices=[],this.openBookVertices=[],this.vertexToSegment=new Map,this.isBuilt=!1,this.mesh=e}build(){const e=new O(this.mesh).build();this.applyBuildResult(e),this.isBuilt=!0}applyBuildResult(e){this.segments.clear(),this.vertexToSegment.clear();for(const t of e.segments){this.segments.set(t.id,t);for(let e=1;e<t.vertices.length-1;e++){const s=t.vertices[e];s&&this.vertexToSegment.set(s.id,t)}}this.skeletonEdges=e.skeletonEdges,this.branchingVertices=e.branchingVertices,this.openBookVertices=e.openBookVertices}rebuild(){this.build()}getSegments(){return Array.from(this.segments.values())}getSegment(e){return this.segments.get(e)}getSegmentForVertex(e){return this.vertexToSegment.get(e.id)}getSkeletonEdges(){return this.skeletonEdges}getBranchingVertices(){return this.branchingVertices}getOpenBookVertices(){return this.openBookVertices}get segmentCount(){return this.segments.size}get skeletonEdgeCount(){return this.skeletonEdges.length}get branchingVertexCount(){return this.branchingVertices.length}get openBookVertexCount(){return this.openBookVertices.length}get built(){return this.isBuilt}projectPoint(e){let t=null;for(const s of this.segments.values()){const n=s.projectPoint(e);n&&(!t||n.distance<t.distance)&&(t={point:n.point,segment:s,parameter:n.parameter,distance:n.distance})}return t}isVertexOnSkeleton(e){return e.isOnSkeleton()}isEdgeOnSkeleton(e){return e.isSkeletonEdge()}getAllSkeletonVertices(){return[...this.branchingVertices,...this.openBookVertices]}getTotalLength(){let e=0;for(const t of this.segments.values())e+=t.totalLength;return e}getStats(){let e=0;for(const t of this.segments.values())t.isClosed&&e++;return{segmentCount:this.segmentCount,skeletonEdgeCount:this.skeletonEdgeCount,branchingVertexCount:this.branchingVertexCount,openBookVertexCount:this.openBookVertexCount,totalLength:this.getTotalLength(),closedLoopCount:e}}}function $(e){const t=new N(e);return t.build(),t}class A{constructor(e){this.skeleton=e}constrainPosition(e,t){switch(e.type){case r.Manifold:return{position:t,wasConstrained:!1,constraintDistance:0};case r.OpenBook:return this.constrainToSegment(e,t);case r.SkeletonBranching:case r.NonManifoldOther:return{position:{x:e.position.x,y:e.position.y,z:e.position.z},wasConstrained:!0,constraintDistance:p(t,{x:e.position.x,y:e.position.y,z:e.position.z})};default:return{position:t,wasConstrained:!1,constraintDistance:0}}}constrainToSegment(e,t){const s=this.skeleton.getSegmentForVertex(e);if(!s){const s=this.skeleton.projectPoint(t);return s?{position:s.point,wasConstrained:!0,segment:s.segment,constraintDistance:s.distance}:{position:{x:e.position.x,y:e.position.y,z:e.position.z},wasConstrained:!0,constraintDistance:p(t,{x:e.position.x,y:e.position.y,z:e.position.z})}}const n=s.projectPoint(t);return n?{position:n.point,wasConstrained:!0,segment:s,constraintDistance:n.distance}:{position:{x:e.position.x,y:e.position.y,z:e.position.z},wasConstrained:!0,segment:s,constraintDistance:0}}canMoveFreely(e){return e.type===r.Manifold}isFixed(e){return e.type===r.SkeletonBranching||e.type===r.NonManifoldOther}isConstrainedToSegment(e){return e.type===r.OpenBook}getConstraintSegment(e){if(e.type===r.OpenBook)return this.skeleton.getSegmentForVertex(e)}getAllowedDirection(e){if(e.type!==r.OpenBook)return null;const t=this.skeleton.getSegmentForVertex(e);if(!t||t.vertices.length<2)return null;const s=t.indexOfVertex(e);if(s<0)return null;let n,i;if(0===s){const e=t.vertices[0],s=t.vertices[1];n={x:e.position.x,y:e.position.y,z:e.position.z},i={x:s.position.x,y:s.position.y,z:s.position.z}}else if(s===t.vertices.length-1){const e=t.vertices[s-1],o=t.vertices[s];n={x:e.position.x,y:e.position.y,z:e.position.z},i={x:o.position.x,y:o.position.y,z:o.position.z}}else{const e=t.vertices[s-1],o=t.vertices[s+1];n={x:e.position.x,y:e.position.y,z:e.position.z},i={x:o.position.x,y:o.position.y,z:o.position.z}}const o=i.x-n.x,a=i.y-n.y,l=i.z-n.z,c=Math.sqrt(o*o+a*a+l*l);return c<1e-10?null:{x:o/c,y:a/c,z:l/c}}}function L(e){return new A(e)}function T(e){const t=[],s=[],n=e.attributes.position;if(!n)return t.push("Geometry must have a position attribute"),{isValid:!1,errors:t,warnings:s};const i=e.index;if(!i)return t.push("Geometry must be indexed"),{isValid:!1,errors:t,warnings:s};i.count%3!=0&&t.push(`Index count (${i.count}) must be divisible by 3 for triangle mesh`);const o=n.count;for(let c=0;c<i.count;c++){const e=i.getX(c);if(e<0||e>=o){t.push(`Invalid index ${e} at position ${c} (vertex count: ${o})`);break}}let r=0;const a=i.count/3;for(let c=0;c<a;c++){const e=i.getX(3*c),t=i.getX(3*c+1),s=i.getX(3*c+2);e!==t&&t!==s&&s!==e||r++}r>0&&s.push(`Found ${r} degenerate triangle(s) with repeated vertices`);let l=0;for(let c=0;c<o;c++){const e=n.getX(c),t=n.getY(c),s=n.getZ(c);isFinite(e)&&isFinite(t)&&isFinite(s)||l++}return l>0&&t.push(`Found ${l} vertex position(s) with NaN or Infinity values`),{isValid:0===t.length,errors:t,warnings:s}}function P(e,t={}){const{featureEdges:s,validate:n=!0}=t;if(n){const t=T(e);if(!t.isValid)throw new Error(`Invalid geometry: ${t.errors.join("; ")}`)}return g.fromBufferGeometry(e,s)}function q(t,s={}){const{computeNormals:n=!0,smoothNormals:i=!0}=s,o=new e.BufferGeometry,r=t.getFaces();if(0===r.length)return o;const a=t.getVertices(),l=new Map;a.forEach((e,t)=>{l.set(e.id,t)});const c=new Float32Array(3*a.length);a.forEach((e,t)=>{c[3*t]=e.position.x,c[3*t+1]=e.position.y,c[3*t+2]=e.position.z});const h=[];for(const e of r){const t=e.getVertices();if(!t)continue;const[s,n,i]=t,o=l.get(s.id),r=l.get(n.id),a=l.get(i.id);void 0!==o&&void 0!==r&&void 0!==a&&h.push(o,r,a)}return o.setAttribute("position",new e.BufferAttribute(c,3)),o.setIndex(h),n&&(i?function(t,s,n){const i=s.getVertices(),o=new Float32Array(3*i.length),r=new Uint32Array(i.length);for(const e of s.getFaces()){const t=e.getNormal();if(!t)continue;const s=e.getVertices();if(s)for(const e of s){const s=n.get(e.id);if(void 0===s)continue;const i=3*s;o[i]=(o[i]??0)+t.x,o[i+1]=(o[i+1]??0)+t.y,o[i+2]=(o[i+2]??0)+t.z,r[s]=(r[s]??0)+1}}for(let e=0;e<i.length;e++){const t=r[e]??0;if(0===t)continue;const s=3*e,n=(o[s]??0)/t,i=(o[s+1]??0)/t,a=(o[s+2]??0)/t,l=Math.sqrt(n*n+i*i+a*a);l>1e-10?(o[3*e]=n/l,o[3*e+1]=i/l,o[3*e+2]=a/l):(o[3*e]=0,o[3*e+1]=1,o[3*e+2]=0)}t.setAttribute("normal",new e.BufferAttribute(o,3))}(o,t,l):o.computeVertexNormals()),o}function D(t){const s=new e.BufferGeometry,n=t.getSkeletonEdges();if(0===n.length)return s;const i=new Float32Array(6*n.length);let o=0;for(const e of n){const[t,s]=e.getVertices();t&&s&&(i[o++]=t.position.x,i[o++]=t.position.y,i[o++]=t.position.z,i[o++]=s.position.x,i[o++]=s.position.y,i[o++]=s.position.z)}return s.setAttribute("position",new e.BufferAttribute(i.slice(0,o),3)),s}function R(t){const s=q(t,{computeNormals:!0}),n=t.getVertices(),i=new Float32Array(3*n.length),o=new Map;n.forEach((e,t)=>{o.set(e.id,t)});for(const e of n){const t=o.get(e.id);if(void 0===t)continue;let s=0,n=0,r=0;switch(e.type){case"manifold":s=.2,n=.8,r=.2;break;case"open_book":s=.2,n=.4,r=.9;break;case"skeleton_branching":s=.9,n=.2,r=.2;break;case"non_manifold_other":s=.9,n=.2,r=.9}i[3*t]=s,i[3*t+1]=n,i[3*t+2]=r}return s.setAttribute("color",new e.BufferAttribute(i,3)),s}function G(t){const s=t.getFaces();if(0===s.length)return new e.BufferGeometry;const n=new Float32Array(9*s.length),i=new Float32Array(9*s.length),o=new Float32Array(9*s.length);let r=0;for(const e of s){const t=e.getVertices(),s=e.getNormal(),a=e.getQuality()??0;if(!t||!s)continue;const l=a<.5?1:2-2*a,c=a<.5?2*a:1,h=.1;for(const e of t)n[r]=e.position.x,n[r+1]=e.position.y,n[r+2]=e.position.z,i[r]=l,i[r+1]=c,i[r+2]=h,o[r]=s.x,o[r+1]=s.y,o[r+2]=s.z,r+=3}const a=new e.BufferGeometry;return a.setAttribute("position",new e.BufferAttribute(n.slice(0,r),3)),a.setAttribute("color",new e.BufferAttribute(i.slice(0,r),3)),a.setAttribute("normal",new e.BufferAttribute(o.slice(0,r),3)),a}class Q{constructor(e){if(this.cells=new Map,this.itemPositions=new Map,e<=0)throw new Error("Cell size must be positive");this.cellSize=e}getCellKey(e,t,s){return`${Math.floor(e/this.cellSize)},${Math.floor(t/this.cellSize)},${Math.floor(s/this.cellSize)}`}getCellIndices(e,t,s){return[Math.floor(e/this.cellSize),Math.floor(t/this.cellSize),Math.floor(s/this.cellSize)]}insert(e,t){const s=this.getCellKey(t.x,t.y,t.z);let n=this.cells.get(s);n||(n=[],this.cells.set(s,n)),n.push(e),this.itemPositions.set(e,t)}remove(e){const t=this.itemPositions.get(e);if(!t)return!1;const s=this.getCellKey(t.x,t.y,t.z),n=this.cells.get(s);if(n){const t=n.indexOf(e);-1!==t&&(n.splice(t,1),0===n.length&&this.cells.delete(s))}return this.itemPositions.delete(e),!0}update(e,t){this.remove(e),this.insert(e,t)}queryRadius(e,t){const s=[],n=t*t,i=this.getCellIndices(e.x-t,e.y-t,e.z-t),o=this.getCellIndices(e.x+t,e.y+t,e.z+t);for(let r=i[0];r<=o[0];r++)for(let t=i[1];t<=o[1];t++)for(let a=i[2];a<=o[2];a++){const i=`${r},${t},${a}`,o=this.cells.get(i);if(o)for(const t of o){const i=this.itemPositions.get(t);if(i){const o=i.x-e.x,r=i.y-e.y,a=i.z-e.z;o*o+r*r+a*a<=n&&s.push(t)}}}return s}queryKNearest(e,t,s){let n=this.cellSize,i=[];for(;i.length<t&&!(void 0!==s&&n>s);){i=[];const t=this.queryRadius(e,n);for(const s of t){const t=this.itemPositions.get(s);if(t){const n=t.x-e.x,o=t.y-e.y,r=t.z-e.z;i.push({item:s,distSq:n*n+o*o+r*r})}}n*=2}return i.sort((e,t)=>e.distSq-t.distSq),i.slice(0,t).map(e=>e.item)}clear(){this.cells.clear(),this.itemPositions.clear()}get size(){return this.itemPositions.size}get cellCount(){return this.cells.size}getPosition(e){return this.itemPositions.get(e)}has(e){return this.itemPositions.has(e)}*[Symbol.iterator](){for(const e of this.itemPositions.keys())yield e}getAll(){return Array.from(this.itemPositions.keys())}}function j(e){return{min:{x:Math.min(e.v0.x,e.v1.x,e.v2.x),y:Math.min(e.v0.y,e.v1.y,e.v2.y),z:Math.min(e.v0.z,e.v1.z,e.v2.z)},max:{x:Math.max(e.v0.x,e.v1.x,e.v2.x),y:Math.max(e.v0.y,e.v1.y,e.v2.y),z:Math.max(e.v0.z,e.v1.z,e.v2.z)}}}function K(e,t){return{min:{x:Math.min(e.min.x,t.min.x),y:Math.min(e.min.y,t.min.y),z:Math.min(e.min.z,t.min.z)},max:{x:Math.max(e.max.x,t.max.x),y:Math.max(e.max.y,t.max.y),z:Math.max(e.max.z,t.max.z)}}}function X(e,t){let s=0;return e.x<t.min.x?s+=(t.min.x-e.x)**2:e.x>t.max.x&&(s+=(e.x-t.max.x)**2),e.y<t.min.y?s+=(t.min.y-e.y)**2:e.y>t.max.y&&(s+=(e.y-t.max.y)**2),e.z<t.min.z?s+=(t.min.z-e.z)**2:e.z>t.max.z&&(s+=(e.z-t.max.z)**2),s}function W(e,t){const s=t.v0,n=t.v1,i=t.v2,o=n.x-s.x,r=n.y-s.y,a=n.z-s.z,l=i.x-s.x,c=i.y-s.y,h=i.z-s.z,u=e.x-s.x,d=e.y-s.y,g=e.z-s.z,f=o*u+r*d+a*g,p=l*u+c*d+h*g;if(f<=0&&p<=0)return s;const x=e.x-n.x,y=e.y-n.y,m=e.z-n.z,v=o*x+r*y+a*m,z=l*x+c*y+h*m;if(v>=0&&z<=v)return n;const M=f*z-v*p;if(M<=0&&f>=0&&v<=0){const e=f/(f-v);return{x:s.x+e*o,y:s.y+e*r,z:s.z+e*a}}const w=e.x-i.x,V=e.y-i.y,E=e.z-i.z,k=o*w+r*V+a*E,C=l*w+c*V+h*E;if(C>=0&&k<=C)return i;const S=k*p-f*C;if(S<=0&&p>=0&&C<=0){const e=p/(p-C);return{x:s.x+e*l,y:s.y+e*c,z:s.z+e*h}}const b=v*C-k*z;if(b<=0&&z-v>=0&&k-C>=0){const e=(z-v)/(z-v+(k-C));return{x:n.x+e*(i.x-n.x),y:n.y+e*(i.y-n.y),z:n.z+e*(i.z-n.z)}}const F=1/(b+S+M),B=S*F,H=M*F;return{x:s.x+o*B+l*H,y:s.y+r*B+c*H,z:s.z+a*B+h*H}}class U{constructor(e=4){this.root=null,this.triangles=[],this.maxLeafSize=e}build(e){if(this.triangles=e,0===e.length)return void(this.root=null);const t=e.map((e,t)=>t);this.root=this.buildNode(t)}buildNode(e){let t=j(this.triangles[e[0]]);for(let h=1;h<e.length;h++)t=K(t,j(this.triangles[e[h]]));if(e.length<=this.maxLeafSize)return{bounds:t,triangleIndices:e};const s=t.max.x-t.min.x,n=t.max.y-t.min.y,i=t.max.z-t.min.z;let o="x";n>s&&n>i?o="y":i>s&&i>n&&(o="z");const r=e.map(e=>{return{index:e,centroid:(t=this.triangles[e],{x:(t.v0.x+t.v1.x+t.v2.x)/3,y:(t.v0.y+t.v1.y+t.v2.y)/3,z:(t.v0.z+t.v1.z+t.v2.z)/3})};var t});r.sort((e,t)=>e.centroid[o]-t.centroid[o]);const a=Math.floor(r.length/2),l=r.slice(0,a).map(e=>e.index),c=r.slice(a).map(e=>e.index);return 0===l.length||0===c.length?{bounds:t,triangleIndices:e}:{bounds:t,left:this.buildNode(l),right:this.buildNode(c)}}closestPoint(e){if(!this.root||0===this.triangles.length)return null;let t=null,s=1/0;const n=[this.root];for(;n.length>0;){const i=n.pop();if(!(X(e,i.bounds)>=s))if(i.triangleIndices)for(const n of i.triangleIndices){const i=W(e,this.triangles[n]),o=f(e,i);o<s&&(s=o,t={point:i,distance:Math.sqrt(o),triangleIndex:n})}else if(i.left&&i.right){X(e,i.left.bounds)<X(e,i.right.bounds)?(n.push(i.right),n.push(i.left)):(n.push(i.left),n.push(i.right))}else i.left?n.push(i.left):i.right&&n.push(i.right)}return t}queryRadius(e,t){const s=[],n=t*t;if(!this.root)return s;const i=[this.root];for(;i.length>0;){const t=i.pop();if(!(X(e,t.bounds)>n))if(t.triangleIndices)for(const i of t.triangleIndices){f(e,W(e,this.triangles[i]))<=n&&s.push(i)}else t.left&&i.push(t.left),t.right&&i.push(t.right)}return s}get triangleCount(){return this.triangles.length}getTriangle(e){return this.triangles[e]}}function Y(e){const t=e.getEdges(),s=e.getVertices();let n=0,i=0,o=0;const l=[];for(const r of t)switch(r.type){case a.Manifold:case a.Feature:n++;break;case a.NonManifold:i++,l.push(Z(r));break;case a.Boundary:o++}let c=0,h=0,u=0;const d=[];for(const a of s){u+=a.degree()??0,a.type===r.Manifold?c++:(h++,d.push(J(a)))}const g=s.length>0?u/s.length:0,f=e.vertexCount-e.edgeCount+e.faceCount;return{isManifold:0===i,hasBoundary:o>0,vertexCount:e.vertexCount,edgeCount:e.edgeCount,faceCount:e.faceCount,manifoldEdgeCount:n,nonManifoldEdgeCount:i,boundaryEdgeCount:o,manifoldVertexCount:c,nonManifoldVertexCount:h,nonManifoldEdges:l,nonManifoldVertices:d,eulerCharacteristic:f,averageVertexDegree:g}}function Z(e){const[t,s]=e.getVertices();return{edgeId:e.id,vertexIndices:[t?t.id:-1,s?s.id:-1],faceCount:e.getFaceCount(),positions:[t?{x:t.position.x,y:t.position.y,z:t.position.z}:{x:0,y:0,z:0},s?{x:s.position.x,y:s.position.y,z:s.position.z}:{x:0,y:0,z:0}]}}function J(e){let t=0;return e.forEachOutgoingHalfedge(e=>{e.edge.isSkeletonEdge()&&t++}),{vertexId:e.id,position:{x:e.position.x,y:e.position.y,z:e.position.z},type:e.type,skeletonEdgeCount:t}}function ee(e){const t={manifold:0,openBook:0,skeletonBranching:0,nonManifoldOther:0,total:0};for(const s of e.getVertices())switch(s.type=te(s),t.total++,s.type){case r.Manifold:t.manifold++;break;case r.OpenBook:t.openBook++;break;case r.SkeletonBranching:t.skeletonBranching++;break;case r.NonManifoldOther:t.nonManifoldOther++}return t}function te(e){let t=0,s=0,n=!1,i=!1;if(e.forEachOutgoingHalfedge(e=>{s++,e.edge.isSkeletonEdge()&&t++,e.edge.isBoundary()&&(n=!0),e.edge.isNonManifold()&&(i=!0)}),0===s)return r.Manifold;if(i)return 2===t?r.OpenBook:1===t||t>2?r.SkeletonBranching:r.NonManifoldOther;if(n){if(2===t)return r.OpenBook;if(1===t||t>2)return r.SkeletonBranching}return 0===t?r.Manifold:2===t?r.OpenBook:r.SkeletonBranching}function se(e,t){return e.getVertices().filter(e=>e.type===t)}function ne(e){return se(e,r.Manifold)}function ie(e){return e.getVertices().filter(e=>e.type!==r.Manifold)}function oe(e){e.classifyVertices()}function re(e){const t=[],s=[];return function(e,t){for(const s of e.getVertices())s.halfedge&&(e.getHalfedge(s.halfedge.id)||t.push({type:"invalid_vertex_halfedge",message:`Vertex ${s.id} references non-existent halfedge ${s.halfedge.id}`,elementIds:[s.id]})),isFinite(s.position.x)&&isFinite(s.position.y)&&isFinite(s.position.z)||t.push({type:"invalid_vertex_position",message:`Vertex ${s.id} has invalid position`,elementIds:[s.id]})}(e,t),function(e,t,s){for(const n of e.getEdges())if(0!==n.allHalfedges.length){e.getHalfedge(n.halfedge.id)||t.push({type:"invalid_edge_halfedge",message:`Edge ${n.id} references non-existent halfedge`,elementIds:[n.id]}),(n.length<=0||!isFinite(n.length))&&s.push({type:"invalid_edge_length",message:`Edge ${n.id} has invalid length: ${n.length}`,elementIds:[n.id]});for(const e of n.allHalfedges)e.edge.id!==n.id&&t.push({type:"halfedge_edge_mismatch",message:`Halfedge ${e.id} in edge ${n.id} references different edge ${e.edge.id}`,elementIds:[n.id,e.id]})}else t.push({type:"edge_no_halfedges",message:`Edge ${n.id} has no halfedges`,elementIds:[n.id]})}(e,t,s),function(e,t,s){var n;for(const i of e.getFaces()){if(!i.halfedge){t.push({type:"face_no_halfedge",message:`Face ${i.id} has no halfedge`,elementIds:[i.id]});continue}if(!e.getHalfedge(i.halfedge.id)){t.push({type:"invalid_face_halfedge",message:`Face ${i.id} references non-existent halfedge`,elementIds:[i.id]});continue}const o=i.getHalfedges();if(o){for(const e of o)(null==(n=e.face)?void 0:n.id)!==i.id&&t.push({type:"halfedge_face_mismatch",message:`Halfedge ${e.id} in face ${i.id} references different face`,elementIds:[i.id,e.id]});i.isDegenerate()&&s.push({type:"degenerate_face",message:`Face ${i.id} is degenerate (near-zero area)`,elementIds:[i.id]})}else t.push({type:"face_invalid_loop",message:`Face ${i.id} has invalid halfedge loop`,elementIds:[i.id]})}}(e,t,s),function(e,t){for(const s of e.getHalfedges())s.next?e.getHalfedge(s.next.id)||t.push({type:"halfedge_invalid_next",message:`Halfedge ${s.id} has invalid next pointer`,elementIds:[s.id]}):t.push({type:"halfedge_no_next",message:`Halfedge ${s.id} has no next pointer`,elementIds:[s.id]}),s.prev?e.getHalfedge(s.prev.id)||t.push({type:"halfedge_invalid_prev",message:`Halfedge ${s.id} has invalid prev pointer`,elementIds:[s.id]}):t.push({type:"halfedge_no_prev",message:`Halfedge ${s.id} has no prev pointer`,elementIds:[s.id]}),s.next&&s.next.prev!==s&&t.push({type:"halfedge_next_prev_mismatch",message:`Halfedge ${s.id}: next.prev does not point back`,elementIds:[s.id]}),s.prev&&s.prev.next!==s&&t.push({type:"halfedge_prev_next_mismatch",message:`Halfedge ${s.id}: prev.next does not point back`,elementIds:[s.id]}),s.twin&&(e.getHalfedge(s.twin.id)?s.twin.twin!==s&&t.push({type:"halfedge_twin_mismatch",message:`Halfedge ${s.id}: twin.twin does not point back`,elementIds:[s.id]}):t.push({type:"halfedge_invalid_twin",message:`Halfedge ${s.id} has invalid twin pointer`,elementIds:[s.id]})),e.getVertex(s.vertex.id)||t.push({type:"halfedge_invalid_vertex",message:`Halfedge ${s.id} references non-existent vertex`,elementIds:[s.id]}),e.getEdge(s.edge.id)||t.push({type:"halfedge_invalid_edge",message:`Halfedge ${s.id} references non-existent edge`,elementIds:[s.id]})}(e,t),{isValid:0===t.length,errors:t,warnings:s}}function ae(e){return re(e).isValid}function le(e){if(e.isSkeletonEdge())return!1;if(!e.canFlip())return!1;const t=ce(e);return!!t&&_(t.v0,t.v1,t.v2,t.v3)}function ce(e){const t=e.halfedge,s=t.twin;if(!s||!t.face||!s.face)return null;const n=t.next,i=s.next;if(!n||!i)return null;const o=s.vertex,r=t.vertex,a=n.vertex,l=i.vertex;return{v0:{x:o.position.x,y:o.position.y,z:o.position.z},v1:{x:r.position.x,y:r.position.y,z:r.position.z},v2:{x:a.position.x,y:a.position.y,z:a.position.z},v3:{x:l.position.x,y:l.position.y,z:l.position.z}}}function he(e,t){if(!le(t))return{success:!1,reason:"Edge cannot be flipped"};const s=t.halfedge,n=s.twin;if(!n)return{success:!1,reason:"Edge has no twin"};const i=s.next,o=s.prev,r=n.next,a=n.prev,l=n.vertex,c=s.vertex,h=i.vertex,u=r.vertex,d=s.face,g=n.face;if(!d||!g)return{success:!1,reason:"Missing faces"};const f=p({x:h.position.x,y:h.position.y,z:h.position.z},{x:u.position.x,y:u.position.y,z:u.position.z});return t.length=f,s.vertex=u,n.vertex=h,s.next=a,s.prev=i,a.next=i,a.prev=s,i.next=s,i.prev=a,n.next=o,n.prev=r,o.next=r,o.prev=n,r.next=n,r.prev=o,s.face=d,a.face=d,i.face=d,n.face=g,o.face=g,r.face=g,d.halfedge=s,g.halfedge=n,l.halfedge===s&&(l.halfedge=r),c.halfedge===n&&(c.halfedge=i),{success:!0,newLength:f}}function ue(e){const t=e.halfedge,s=t.twin;if(!s||!t.face||!s.face)return!0;const n=ce(e);if(!n)return!0;return de(n.v2,n.v0,n.v1)+de(n.v3,n.v0,n.v1)<=Math.PI+1e-10}function de(e,t,s){const n=t.x-e.x,i=t.y-e.y,o=t.z-e.z,r=s.x-e.x,a=s.y-e.y,l=s.z-e.z,c=n*r+i*a+o*l,h=Math.sqrt(n*n+i*i+o*o),u=Math.sqrt(r*r+a*a+l*l);if(h<1e-10||u<1e-10)return 0;const d=Math.max(-1,Math.min(1,c/(h*u)));return Math.acos(d)}function ge(e,t){const s=e.getEdges(),n=t??10*s.length;let i=0,o=0;for(;o<n;){o++;let e=!1;for(const t of s)if(!ue(t)&&le(t)){he(0,t).success&&(i++,e=!0)}if(!e)break}return i}function fe(t,s,n=.5){const[i,o]=s.getVertices();if(!i||!o)return{success:!1,reason:"Edge has no vertices"};const r=i.position.x,a=i.position.y,l=i.position.z,c={x:r+(o.position.x-r)*n,y:a+(o.position.y-a)*n,z:l+(o.position.z-l)*n},h=t.createVertex(new e.Vector3(c.x,c.y,c.z));s.isSkeletonEdge();const u=[],d=[],g=s.getFaces();if(0===g.length)return{success:!0,newVertex:h,newEdges:[],newFaces:[]};for(const e of g){if(!e)continue;const n=e.getHalfedges();if(!n)continue;let i=null;for(const e of n)if(e.edge.id===s.id){i=e;break}i&&pe(t,e,i,h,u,d)}return s.length=s.length*n,t.classifyVertices(),{success:!0,newVertex:h,newEdges:u,newFaces:d}}function pe(e,t,s,n,i,o){const r=s.next.vertex,a=s.vertex,l=e.createFace(n,a,r);o.push(l),s.vertex=n,n.halfedge||(n.halfedge=s)}function xe(e,t){const s=[];let n=0;const i=[];for(const o of e.getEdges())o.length>t&&i.push(o);for(const o of i){const t=fe(e,o);t.success&&t.newVertex&&(n++,s.push(t.newVertex))}return{splitCount:n,newVertices:s}}function ye(e){const[t,s]=e.getVertices();return!(!t||!s)&&((t.type!==r.SkeletonBranching&&t.type!==r.NonManifoldOther||s.type!==r.SkeletonBranching&&s.type!==r.NonManifoldOther)&&(s.type===r.SkeletonBranching||(s.type,r.NonManifoldOther),!!function(e,t){const s=new Set,n=new Set;e.forEachNeighbor(e=>{s.add(e.id)}),t.forEachNeighbor(e=>{n.add(e.id)});let i=0;for(const a of s)a!==e.id&&a!==t.id&&n.has(a)&&i++;const o=me(e,t),r=o.length;return i<=r}(t,s)))}function me(e,t){const s=new Set,n=[];return e.forEachOutgoingHalfedge(e=>{e.face&&s.add(e.face.id)}),t.forEachOutgoingHalfedge(e=>{e.face&&s.has(e.face.id)&&n.push(e.face)}),n}function ve(e,t){var s;if(!ye(t))return{success:!1,reason:"Edge cannot be contracted"};const[n,i]=t.getVertices();if(!n||!i)return{success:!1,reason:"Edge has no vertices"};const{keepVertex:o,removeVertex:a,newPosition:l}=function(e,t){const s=e=>{switch(e.type){case r.SkeletonBranching:case r.NonManifoldOther:return 3;case r.OpenBook:return 2;case r.Manifold:return 1;default:return 0}},n=s(e),i=s(t);let o,a,l;n>=i?(o=e,a=t):(o=t,a=e);l=o.type===r.SkeletonBranching||o.type===r.NonManifoldOther||o.type===r.OpenBook&&a.type===r.Manifold?{x:o.position.x,y:o.position.y,z:o.position.z}:k({x:e.position.x,y:e.position.y,z:e.position.z},{x:t.position.x,y:t.position.y,z:t.position.z});return{keepVertex:o,removeVertex:a,newPosition:l}}(n,i);o.position.set(l.x,l.y,l.z);const c=me(n,i);var h;h=o,a.forEachOutgoingHalfedge(e=>{e.twin&&(e.twin.vertex=h)});for(const r of c)e.faces.delete(r.id);e.edges.delete(t.id);for(const r of t.allHalfedges)e.halfedges.delete(r.id);if(e.vertices.delete(a.id),o.halfedge&&!e.halfedges.has(o.halfedge.id))for(const r of e.halfedges.values())if((null==(s=r.getSourceVertex())?void 0:s.id)===o.id){o.halfedge=r;break}return e.classifyVertices(),{success:!0,remainingVertex:o,removedFaces:c}}function ze(e,t){let s=0,n=0,i=[];for(const o of e.getEdges())o.length<t&&ye(o)&&i.push(o);for(;i.length>0;){const t=i.pop();if(!e.edges.has(t.id)||!ye(t))continue;ve(e,t).success&&(s++,n++)}return{contractCount:s,removedVertices:n}}function Me(e){const t=e.getNeighbors();if(0===t.length)return null;let s=0,n=0,i=0;for(const c of t)s+=c.position.x,n+=c.position.y,i+=c.position.z;s/=t.length,n/=t.length,i/=t.length;const o={x:s,y:n,z:i},r=function(e){let t=0,s=0,n=0,i=0;if(e.forEachOutgoingHalfedge(e=>{if(e.face){const o=e.face.getNormal();o&&(t+=o.x,s+=o.y,n+=o.z,i++)}}),0===i)return null;return z({x:t/i,y:s/i,z:n/i})}(e);if(!r)return o;const a={x:e.position.x,y:e.position.y,z:e.position.z},l=w(o,a);return M(a,w(l,V(r,x(l,r))))}function we(e,t,s,n){if(t.type===r.SkeletonBranching||t.type===r.NonManifoldOther)return{success:!1,reason:"Vertex is fixed"};const i={x:t.position.x,y:t.position.y,z:t.position.z};let o=s,a=!1;if(n){const e=n.constrainPosition(t,s);o=e.position,a=e.wasConstrained}if(!function(e,t){const s={x:e.position.x,y:e.position.y,z:e.position.z};e.position.set(t.x,t.y,t.z);let n=!0;return e.forEachOutgoingHalfedge(e=>{if(e.face){const t=e.face.getArea();null!==t&&t<1e-10&&(n=!1)}}),e.position.set(s.x,s.y,s.z),n}(t,o))return{success:!1,reason:"Relocation would create invalid geometry"};t.position.set(o.x,o.y,o.z),function(e){e.forEachOutgoingHalfedge(e=>{const t=e.getSourceVertex();t&&(e.edge.length=p({x:t.position.x,y:t.position.y,z:t.position.z},{x:e.vertex.position.x,y:e.vertex.position.y,z:e.vertex.position.z}))})}(t);return{success:!0,newPosition:o,wasConstrained:a,distanceMoved:p(i,o)}}function Ve(e,t,s,n=.5){const i=Me(t);if(!i)return{success:!1,reason:"Cannot compute smoothing target"};const o=t.position.x,r=t.position.y,a=t.position.z;return we(0,t,{x:o+(i.x-o)*n,y:r+(i.y-r)*n,z:a+(i.z-a)*n},s)}function Ee(e,t,s=.5){let n=0,i=0;for(const o of e.getVertices())if(o.type===r.Manifold||o.type===r.OpenBook){const e=Ve(0,o,t,s);e.success&&(n++,i+=e.distanceMoved??0)}return{smoothedCount:n,totalDistance:i}}function ke(e){if(0===e.length)return 0;let t=e[0];for(let s=1;s<e.length;s++){const n=e[s];n<t&&(t=n)}return t}function Ce(e){if(0===e.length)return 0;let t=e[0];for(let s=1;s<e.length;s++){const n=e[s];n>t&&(t=n)}return t}function Se(e,t=.3){const s=e.getFaces(),n=e.getEdges(),i=[],o=[];for(const v of s){const e=v.getQuality();null!==e&&i.push(e);const t=v.getArea();null!==t&&o.push(t)}const r=n.map(e=>e.length),a=ke(i),l=Ce(i),c=i.length>0?i.reduce((e,t)=>e+t,0)/i.length:0,h=i.length>0?i.reduce((e,t)=>e+Math.pow(t-c,2),0)/i.length:0,u=Math.sqrt(h),d=i.filter(e=>e<t).length,g=ke(r),f=Ce(r),p=r.length>0?r.reduce((e,t)=>e+t,0)/r.length:0,x=ke(o),y=Ce(o),m=o.reduce((e,t)=>e+t,0);return{minQuality:a,maxQuality:l,averageQuality:c,stdDevQuality:u,poorQualityCount:d,minEdgeLength:g,maxEdgeLength:f,averageEdgeLength:p,minArea:x,maxArea:y,totalArea:m}}function be(e,t=.3){return e.getFaces().filter(e=>{const s=e.getQuality();return null!==s&&s<t})}function Fe(e,t,s=1.333){const n=t*s;return e.getEdges().filter(e=>e.length>n)}function Be(e,t,s=.4){const n=t*s;return e.getEdges().filter(e=>e.length<n)}function He(e,t){const s=e.getVertices();if(0===s.length)return 1;let n=1/0,i=1/0,o=1/0,r=-1/0,a=-1/0,l=-1/0;for(const h of s)n=Math.min(n,h.position.x),i=Math.min(i,h.position.y),o=Math.min(o,h.position.z),r=Math.max(r,h.position.x),a=Math.max(a,h.position.y),l=Math.max(l,h.position.z);const c=Math.sqrt(Math.pow(r-n,2)+Math.pow(a-i,2)+Math.pow(l-o,2));if(void 0!==t&&t>0){const s=Se(e);if(s.totalArea>0)return Math.sqrt(s.totalArea/(2*t))}return c/Math.sqrt(s.length)}function _e(e,t=8){return e.getVertices().filter(e=>{const s=e.degree();return null!==s&&s>t})}function Ie(e,t=4){return e.getVertices().filter(e=>{const s=e.degree();return null!==s&&s<t})}class Oe{constructor(e,t={}){this.skeleton=null,this.constraints=null,this.mesh=e;const s=t.targetEdgeLength??He(e);this.options={...l,...t,targetEdgeLength:s},this.state={iteration:0,edgeSplits:0,edgeContractions:0,edgeFlips:0,vertexRelocations:0,quality:Se(e)},e.isManifold()||(this.skeleton=$(e),this.constraints=L(this.skeleton))}iterate(){this.state.iteration++;const e=this.options.targetEdgeLength,t=e*this.options.minEdgeLengthRatio,s=e*this.options.maxEdgeLengthRatio,n=xe(this.mesh,s);this.state.edgeSplits+=n.splitCount;const i=ze(this.mesh,t);this.state.edgeContractions+=i.contractCount;const o=ge(this.mesh);this.state.edgeFlips+=o;const r=Ee(this.mesh,this.constraints??void 0,.5);return this.state.vertexRelocations+=r.smoothedCount,this.skeleton&&(n.splitCount>0||i.contractCount>0)&&this.skeleton.rebuild(),this.state.quality=Se(this.mesh,this.options.minTriangleQuality),this.options.verbose&&console.warn(`Iteration ${this.state.iteration}: splits=${n.splitCount}, contractions=${i.contractCount}, flips=${o}, smoothed=${r.smoothedCount}, avgQuality=${this.state.quality.averageQuality.toFixed(3)}`),{...this.state}}run(e){const t=e??this.options.iterations,s=Date.now(),n={vertices:this.mesh.vertexCount,faces:this.mesh.faceCount};for(let o=0;o<t;o++){const e=this.state.quality.averageQuality;this.iterate();const t=this.state.quality.averageQuality-e;if(Math.abs(t)<.001&&o>0){this.options.verbose&&console.warn(`Converged after ${o+1} iterations`);break}}const i=Date.now()-s;return{inputVertices:n.vertices,inputFaces:n.faces,outputVertices:this.mesh.vertexCount,outputFaces:this.mesh.faceCount,iterations:this.state.iteration,finalQuality:this.state.quality.averageQuality,nonManifoldEdges:this.mesh.getNonManifoldEdges().length,skeletonEdges:this.mesh.getSkeletonEdges().length,edgeFlips:this.state.edgeFlips,edgeSplits:this.state.edgeSplits,edgeContractions:this.state.edgeContractions,vertexRelocations:this.state.vertexRelocations,processingTimeMs:i}}hasConverged(){return this.state.quality.averageQuality>.9||0===this.state.quality.poorQualityCount}getMesh(){return this.mesh}getSkeleton(){return this.skeleton}getQuality(){return this.state.quality}getState(){return{...this.state}}toBufferGeometry(){return q(this.mesh)}}class Ne{constructor(e,t=!1){this.mesh=e,this.verbose=t}execute(){const e=performance.now(),t=this.detect();if(0===t)return{operation:this.getName(),defectsFound:0,defectsFixed:0,timeMs:performance.now()-e,success:!0};const s=this.repair(),n=performance.now()-e,i={operation:this.getName(),defectsFound:t,defectsFixed:s,timeMs:n,success:s===t};return s<t&&(i.reason=`Only fixed ${s}/${t} defects`),i}}class $e extends Ne{constructor(){super(...arguments),this.isolatedVertices=[]}detect(){this.isolatedVertices=[];for(const e of this.mesh.vertices.values())e.halfedge&&0!==e.degree()||this.isolatedVertices.push(e);return this.verbose&&this.isolatedVertices.length>0&&console.log(`Found ${this.isolatedVertices.length} isolated vertices`),this.isolatedVertices.length}repair(){let e=0;for(const t of this.isolatedVertices)this.mesh.vertices.delete(t.id),e++;return this.verbose&&e>0&&console.log(`Removed ${e} isolated vertices`),e}getName(){return"Remove Isolated Vertices"}canParallelize(){return this.isolatedVertices.length>1e3}}class Ae extends Ne{constructor(e,t=!1,s=1e-10){super(e,t),this.degenerateFaces=[],this.areaThreshold=s}detect(){this.degenerateFaces=[];for(const e of this.mesh.faces.values()){const t=e.getVertices();if(!t||3!==t.length)continue;const[s,n,i]=t;if(s.id===n.id||n.id===i.id||i.id===s.id){this.degenerateFaces.push(e);continue}b(s.position,n.position,i.position)<this.areaThreshold&&this.degenerateFaces.push(e)}return this.verbose&&this.degenerateFaces.length>0&&console.log(`Found ${this.degenerateFaces.length} degenerate faces`),this.degenerateFaces.length}repair(){let e=0;for(const t of this.degenerateFaces){const s=t.getHalfedges();if(s){this.mesh.faces.delete(t.id);for(const e of s)this.mesh.halfedges.delete(e.id),e.edge.allHalfedges=e.edge.allHalfedges.filter(t=>t.id!==e.id);e++}}return this.verbose&&e>0&&console.log(`Removed ${e} degenerate faces`),e}getName(){return"Remove Degenerate Faces"}canParallelize(){return this.degenerateFaces.length>1e3}}class Le extends Ne{constructor(){super(...arguments),this.duplicates=new Map}detect(){this.duplicates.clear();const e=new Map;for(const s of this.mesh.faces.values()){const t=s.getVertices();if(!t)continue;const n=this.makeFaceKey(t);e.has(n)||e.set(n,[]),e.get(n).push(s)}let t=0;for(const[s,n]of e)n.length>1&&(this.duplicates.set(s,n),t+=n.length-1);return this.verbose&&t>0&&console.log(`Found ${t} duplicate faces in ${this.duplicates.size} groups`),t}repair(){let e=0;for(const t of this.duplicates.values())for(let s=1;s<t.length;s++){const n=t[s];if(!n)continue;this.mesh.faces.delete(n.id);const i=n.getHalfedges();if(i){for(const e of i)this.mesh.halfedges.delete(e.id),e.edge.allHalfedges=e.edge.allHalfedges.filter(t=>t.id!==e.id);e++}}return this.verbose&&e>0&&console.log(`Removed ${e} duplicate faces`),e}makeFaceKey(e){return e.map(e=>e.id).sort((e,t)=>e-t).join(",")}getName(){return"Remove Duplicate Faces"}canParallelize(){return!1}}class Te{constructor(e,t){this.operations=[],this.mesh=e instanceof g?e:g.fromBufferGeometry(e),this.options={useWorkers:(null==t?void 0:t.useWorkers)??("undefined"!=typeof navigator&&this.mesh.faces.size>((null==t?void 0:t.parallelThreshold)??1e4)),workerCount:(null==t?void 0:t.workerCount)??("undefined"!=typeof navigator&&navigator.hardwareConcurrency||4),useAcceleration:(null==t?void 0:t.useAcceleration)??!0,parallelThreshold:(null==t?void 0:t.parallelThreshold)??1e4,verbose:(null==t?void 0:t.verbose)??!1,validateAfterEach:(null==t?void 0:t.validateAfterEach)??!1},this.stats={input:{vertices:this.mesh.vertices.size,faces:this.mesh.faces.size,edges:this.mesh.edges.size},output:{vertices:this.mesh.vertices.size,faces:this.mesh.faces.size,edges:this.mesh.edges.size},operations:[],totalTimeMs:0,success:!0,totalDefectsFound:0,totalDefectsFixed:0}}removeIsolatedVertices(){return this.operations.push(new $e(this.mesh,this.options.verbose)),this}removeDegenerateFaces(e){return this.operations.push(new Ae(this.mesh,this.options.verbose,e)),this}removeDuplicateFaces(){return this.operations.push(new Le(this.mesh,this.options.verbose)),this}repairAll(){return this.removeIsolatedVertices(),this.removeDuplicateFaces(),this.removeDegenerateFaces(),this}execute(){const e=performance.now();this.stats.operations=[],this.stats.totalDefectsFound=0,this.stats.totalDefectsFixed=0,this.stats.success=!0;for(const t of this.operations){const e=t.execute();if(this.stats.operations.push(e),this.stats.totalDefectsFound+=e.defectsFound,this.stats.totalDefectsFixed+=e.defectsFixed,e.success||(this.stats.success=!1),this.options.validateAfterEach){const t=re(this.mesh);if(!t.isValid){const s=[...t.errors,...t.warnings];console.warn(`Topology validation failed after ${e.operation}:`,s),this.stats.success=!1}}}return this.stats.totalTimeMs=performance.now()-e,this.stats.output={vertices:this.mesh.vertices.size,faces:this.mesh.faces.size,edges:this.mesh.edges.size},this.operations=[],this.stats}getStats(){return this.stats}getMesh(){return this.mesh}toBufferGeometry(){return q(this.mesh)}validate(){const e=re(this.mesh);return{isValid:e.isValid,errors:[...e.errors.map(e=>e.message),...e.warnings.map(e=>e.message)]}}}exports.AdaptiveRemesher=Oe,exports.BVH=U,exports.BufferGeometryExporter=class{constructor(e={}){this.options=e}export(e){return q(e,this.options)}exportSkeleton(e){return D(e)}exportClassification(e){return R(e)}exportQuality(e){return G(e)}setComputeNormals(e){return this.options.computeNormals=e,this}setSmoothNormals(e){return this.options.smoothNormals=e,this}},exports.BufferGeometryImporter=class{constructor(e={}){this.options=e}import(e){return P(e,this.options)}validate(e){return T(e)}setFeatureEdges(e){return this.options.featureEdges=e,this}setValidation(e){return this.options.validate=e,this}},exports.DEFAULT_REMESH_OPTIONS=l,exports.DegenerateFaceRepair=Ae,exports.DuplicateFaceRepair=Le,exports.Edge=u,exports.EdgeContractor=class{constructor(e){this.mesh=e}contract(e){return ve(this.mesh,e)}canContract(e){return ye(e)}contractShortEdges(e){return ze(this.mesh,e)}shouldContract(e,t,s=.4){return e.length<t*s}},exports.EdgeFlipper=class{constructor(e){this.mesh=e}flip(e){return he(this.mesh,e)}canFlip(e){return le(e)}isDelaunay(e){return ue(e)}makeDelaunay(e){return ge(this.mesh,e)}},exports.EdgeSplitter=class{constructor(e){this.mesh=e}split(e,t=.5){return fe(this.mesh,e,t)}splitLongEdges(e){return xe(this.mesh,e)}shouldSplit(e,t,s=1.333){return e.length>t*s}},exports.EdgeType=a,exports.Face=d,exports.FeatureSkeleton=N,exports.Halfedge=h,exports.IsolatedVertexRepair=$e,exports.ManifoldAnalyzer=class{constructor(){this.mesh=null,this.cachedResult=null}load(e){return this.mesh=g.fromBufferGeometry(e),this.cachedResult=null,this}loadMesh(e){return this.mesh=e,this.cachedResult=null,this}analyze(){if(!this.mesh)throw new Error("No mesh loaded. Call load() first.");return this.cachedResult||(this.cachedResult=Y(this.mesh)),this.cachedResult}isManifold(){return this.analyze().isManifold}hasBoundary(){return this.analyze().hasBoundary}getNonManifoldEdges(){return this.analyze().nonManifoldEdges}getNonManifoldVertices(){return this.analyze().nonManifoldVertices}getMesh(){return this.mesh}clearCache(){return this.cachedResult=null,this}},exports.MeshRepairer=Te,exports.NonManifoldMesh=g,exports.QualityMetrics=class{constructor(e){this.mesh=e}computeStats(e=.3){return Se(this.mesh,e)}getPoorQualityFaces(e=.3){return be(this.mesh,e)}getLongEdges(e,t=1.333){return Fe(this.mesh,e,t)}getShortEdges(e,t=.4){return Be(this.mesh,e,t)}computeTargetEdgeLength(e){return He(this.mesh,e)}getHighValenceVertices(e=8){return _e(this.mesh,e)}getLowValenceVertices(e=4){return Ie(this.mesh,e)}},exports.RepairOperation=Ne,exports.SkeletonBuilder=O,exports.SkeletonConstraints=A,exports.SkeletonSegment=I,exports.SpatialHash=Q,exports.TopologyValidator=class{constructor(e){this.mesh=e}validate(){return re(this.mesh)}isValid(){return ae(this.mesh)}getErrors(){return this.validate().errors}getWarnings(){return this.validate().warnings}},exports.Vertex=c,exports.VertexClassifier=class{constructor(e){this.mesh=e}classifyAll(){return ee(this.mesh)}getByType(e){return se(this.mesh,e)}getManifold(){return ne(this.mesh)}getNonManifold(){return ie(this.mesh)}reclassify(){oe(this.mesh)}},exports.VertexRelocator=class{constructor(e,t){this.constraints=null,this.mesh=e,this.constraints=t??null}setConstraints(e){this.constraints=e}relocate(e,t){return we(this.mesh,e,t,this.constraints??void 0)}smooth(e,t=.5){return Ve(this.mesh,e,this.constraints??void 0,t)}smoothAll(e=.5){return Ee(this.mesh,this.constraints??void 0,e)}canRelocate(e){return e.type===r.Manifold||e.type===r.OpenBook}},exports.VertexType=r,exports.add=M,exports.analyzeManifold=function(e){return Y(g.fromBufferGeometry(e))},exports.analyzeMesh=Y,exports.angleAtVertex=function(e,t,s){return C(w(e,t),w(s,t))},exports.angleBetween=C,exports.barycentricCoordinates=function(e,t,s,n){const i=w(s,t),o=w(n,t),r=w(e,t),a=x(i,i),l=x(i,o),c=x(o,o),h=x(r,i),u=x(r,o),d=a*c-l*l;if(Math.abs(d)<1e-10)return null;const g=(c*h-l*u)/d,f=(a*u-l*h)/d;return{u:1-g-f,v:g,w:f}},exports.buildSkeleton=function(e){return new O(e).build()},exports.canContractEdge=ye,exports.canFlipEdge=function(e){return"manifold"===e},exports.canFlipEdgeGeometric=le,exports.canMoveFreely=function(e){return"manifold"===e},exports.classifyAllVertices=ee,exports.classifyVertex=te,exports.computeMeshQuality=Se,exports.computeTangentialSmoothing=Me,exports.computeTargetEdgeLength=He,exports.computeTriangleAspectRatio=function(e){const t=e.getHalfedges();if(!t)return null;const s=t.map(e=>e.edge.length),n=ke(s),i=Ce(s);return n<1e-10?1/0:i/n},exports.contractEdge=ve,exports.contractShortEdges=ze,exports.cotangent=function(e,t,s){const n=w(e,t),i=w(s,t),o=x(n,i),r=m(y(n,i));return Math.abs(r)<1e-10?0:o/r},exports.createBVHFromMesh=function(e){const t=[];for(const n of e.getFaces()){const e=n.getVertices();e&&t.push({v0:{x:e[0].position.x,y:e[0].position.y,z:e[0].position.z},v1:{x:e[1].position.x,y:e[1].position.y,z:e[1].position.z},v2:{x:e[2].position.x,y:e[2].position.y,z:e[2].position.z}})}const s=new U;return s.build(t),s},exports.createEdgeId=s,exports.createFaceId=i,exports.createHalfedgeId=n,exports.createRemesher=function(e,t={}){const s=g.fromBufferGeometry(e,t.featureEdges);return new Oe(s,t)},exports.createSegmentId=o,exports.createSkeleton=$,exports.createSkeletonConstraints=L,exports.createSpatialHash=function(e,t,s){let n=s;if(void 0===n&&e.length>1){let s=1/0,i=1/0,o=1/0,r=-1/0,a=-1/0,l=-1/0;for(const n of e){const e=t(n);s=Math.min(s,e.x),i=Math.min(i,e.y),o=Math.min(o,e.z),r=Math.max(r,e.x),a=Math.max(a,e.y),l=Math.max(l,e.z)}n=Math.sqrt((r-s)**2+(a-i)**2+(l-o)**2)/Math.sqrt(e.length)}const i=new Q(n??1);for(const o of e)i.insert(o,t(o));return i},exports.createVertexId=t,exports.cross=y,exports.distance=p,exports.distanceSquared=f,exports.dot=x,exports.exportBufferGeometry=q,exports.exportClassificationGeometry=R,exports.exportQualityGeometry=G,exports.exportSkeletonGeometry=D,exports.flipEdge=he,exports.fromVector3=function(e){return{x:e.x,y:e.y,z:e.z}},exports.getHighValenceVertices=_e,exports.getLongEdges=Fe,exports.getLowValenceVertices=Ie,exports.getManifoldVertices=ne,exports.getNonManifoldVertices=ie,exports.getOpenBookVertices=function(e){return se(e,r.OpenBook)},exports.getPoorQualityFaces=be,exports.getShortEdges=Be,exports.getSkeletonBranchingVertices=function(e){return se(e,r.SkeletonBranching)},exports.getVerticesByType=se,exports.importBufferGeometry=P,exports.isDelaunay=ue,exports.isManifold=function(e){return g.fromBufferGeometry(e).isManifold()},exports.isPointInTriangle=function(e,t,s,n){const i=w(s,t),o=w(n,t),r=w(e,t),a=x(i,i),l=x(i,o),c=x(o,o),h=x(r,i),u=x(r,o),d=a*c-l*l;if(Math.abs(d)<1e-10)return!1;const g=(c*h-l*u)/d,f=(a*u-l*h)/d;return 1-g-f>=0&&g>=0&&f>=0},exports.isPositionFixed=function(e){return"skeleton_branching"===e||"non_manifold_other"===e},exports.isQuadConvex=_,exports.isSkeletonConstrained=function(e){return"open_book"===e},exports.isSkeletonEdge=function(e){return"non_manifold"===e||"feature"===e||"boundary"===e},exports.isTopologyValid=ae,exports.length=m,exports.lengthSquared=v,exports.lerp=E,exports.makeDelaunay=ge,exports.midpoint=k,exports.normalize=z,exports.projectPointOnLine=function(e,t,s){const n=w(s,t),i=v(n);return i<1e-10?{...t}:M(t,V(n,x(w(e,t),n)/i))},exports.projectPointOnSegment=S,exports.reclassifyVertices=oe,exports.relocateVertex=we,exports.remesh=function(e,t={}){const s=g.fromBufferGeometry(e,t.featureEdges),n=new Oe(s,t),i=n.run();return{geometry:n.toBufferGeometry(),stats:i}},exports.removeDegenerateFaces=function(e,t){const s=new Te(e,t),n=s.removeDegenerateFaces(null==t?void 0:t.areaThreshold).execute();return{geometry:s.toBufferGeometry(),stats:n}},exports.removeDuplicateFaces=function(e,t){const s=new Te(e,t),n=s.removeDuplicateFaces().execute();return{geometry:s.toBufferGeometry(),stats:n}},exports.removeIsolatedVertices=function(e,t){const s=new Te(e,t),n=s.removeIsolatedVertices().execute();return{geometry:s.toBufferGeometry(),stats:n}},exports.repairMesh=function(e,t){const s=new Te(e,t),n=s.repairAll().execute();return{geometry:s.toBufferGeometry(),stats:n}},exports.scale=V,exports.smoothAllVertices=Ee,exports.smoothVertex=Ve,exports.splitEdge=fe,exports.splitLongEdges=xe,exports.subtract=w,exports.toNumber=function(e){return e},exports.triangleArea=b,exports.triangleCentroid=function(e,t,s){return{x:(e.x+t.x+s.x)/3,y:(e.y+t.y+s.y)/3,z:(e.z+t.z+s.z)/3}},exports.triangleCircumcenter=function(e,t,s){const n=w(t,e),i=w(s,e),o=y(n,i),r=2*v(o);if(r<1e-10)return null;const a=v(n),l=v(i),c=V(y(o,n),l),h=V(y(i,o),a),u=V(M(c,h),1/r);return M(e,u)},exports.triangleCircumradius=B,exports.triangleInradius=H,exports.triangleNormal=F,exports.triangleQuality=function(e,t,s){const n=H(e,t,s),i=B(e,t,s);return null===n||null===i||i<1e-10?0:Math.max(0,Math.min(1,2*n/i))},exports.validateGeometry=T,exports.validateTopology=re;
|
|
2
2
|
//# sourceMappingURL=remesh-threejs.cjs.map
|