markuno_lib 1.2.62 → 1.2.63

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/bin/markcad.js CHANGED
@@ -30,7 +30,7 @@ constructor(x,y){Array.isArray(x)?(this.x=x[0]||0,this.y=x[1]||0):x&&"object"==t
30
30
  /**
31
31
  * Restituisce il vettore normalizzato (lunghezza unitaria)
32
32
  * @returns {Punto2} Nuovo punto con le coordinate normalizzate
33
- */dir(){let l=this.len;return l?new Punto2(this.x/l,this.y/l):this}}
33
+ */dir(){let l=this.len;return l?new Punto2(this.x/l,this.y/l):this}distanza(p1){return new Punto2(p1.x-this.x,p1.y-this.y).len}}
34
34
  /**
35
35
  * Classe che rappresenta una linea 2D definita da due punti
36
36
  */class Linea2{
@@ -550,7 +550,7 @@ function calcoladivisioni(ff,notused,shape2,oggetti){return makedivisions(ff,sha
550
550
  * @param {object} gcad - contesto CAD con funzione tex()
551
551
  * @param {string} file - nome file o codice colore/parametri
552
552
  * @param {object} op - opzioni aggiuntive
553
- */const suffissoMap={"":{prop:"map",extra:null},n:{prop:"normalMap",extra:null},a:{prop:"aoMap",extra:"aoMapIntensity"},r:{prop:"roughnessMap",extra:null},h:{prop:"bumpMap",extra:"bumpScale"},t:{prop:"alphaMap",extra:null},m:{prop:"metalnessMap",extra:null},e:{prop:"emissiveMap",extra:["emissive","emissiveIntensity"]}};async function extractTextures(root,baseName){const counters={},out=[];function getName(suffix){counters[suffix]=(counters[suffix]||0)+1;let base=baseName;return suffix&&(base+=`_${suffix}`),counters[suffix]>1&&(base+=counters[suffix]),`${base}.webp`}return root.traverse((obj=>{if(obj.material){const materials=Array.isArray(obj.material)?obj.material:[obj.material];for(const mat of materials)for(const[suffix,{prop:prop}]of Object.entries(suffissoMap)){const tex=mat[prop];if(tex&&tex.image&&!tex._extracted){tex._extracted=!0;let promise,img=tex.image;if(img.toBlob)promise=new Promise((res=>img.toBlob(res,"image/webp")));else if(img instanceof ImageBitmap){const canvas=document.createElement("canvas");canvas.width=img.width,canvas.height=img.height;canvas.getContext("2d").drawImage(img,0,0),promise=new Promise((res=>canvas.toBlob(res,"image/webp")))}else{if(!(img instanceof HTMLImageElement))continue;{const canvas=document.createElement("canvas");canvas.width=img.naturalWidth||img.width,canvas.height=img.naturalHeight||img.height;canvas.getContext("2d").drawImage(img,0,0),promise=new Promise((res=>canvas.toBlob(res,"image/webp")))}}out.push(promise.then((blob=>new File([blob],getName(suffix),{type:"image/webp"}))))}}}})),root.traverse((obj=>{if(obj.material){const materials=Array.isArray(obj.material)?obj.material:[obj.material];for(const mat of materials)for(const{prop:prop}of Object.values(suffissoMap)){const tex=mat[prop];tex&&tex._extracted&&delete tex._extracted}}})),Promise.all(out)}function getfakeshadow2(w,h,map){const shape=(new THREE.Shape).moveTo(0,0).lineTo(w,0).lineTo(w,h).lineTo(0,h).lineTo(0,0),geometry=new THREE.ShapeGeometry(shape),pos=geometry.attributes.position,uv=new Float32Array(2*pos.count);for(let i=0;i<pos.count;i++)uv[2*i]=pos.getX(i)/w,uv[2*i+1]=pos.getY(i)/h;geometry.setAttribute("uv",new THREE.BufferAttribute(uv,2));const material=new THREE.MeshBasicMaterial({map:map,transparent:!0,alphaTest:.01,depthWrite:!1,side:THREE.DoubleSide}),mesh=new THREE.Mesh(geometry,material);return mesh.layers.set(9),mesh.rotation.x=Math.PI/2,mesh}function getfakeshadow(gcad,shape,alfa){let ky=`fk${shape.key}${alfa}`,{p1:p1,width:width,height:height}=shape.dims();gcad.texture||(gcad.texture={});let tm=gcad.texture[ky];tm||(tm=function createBlurredShadowTextureFromPoints(mshape,size=256,blurPx=32,alpha=.2,p1,width,height){if(!width||!height||!mshape.pt||mshape.pt.length<2)return;const minX=p1.x,minY=p1.y,shapeWidth=width,shapeHeight=height,points=mshape.pt,extra=2*blurPx,canvas=document.createElement("canvas");canvas.width=size+2*extra,canvas.height=size+2*extra;const ctx=canvas.getContext("2d");ctx.save(),ctx.translate(extra,extra),ctx.scale(size/shapeWidth,size/shapeHeight),ctx.translate(-minX,-minY),ctx.filter=`blur(${blurPx}px)`,ctx.beginPath(),ctx.moveTo(points[0].x,points[0].y);for(let i=1;i<points.length;i++)ctx.lineTo(points[i].x,points[i].y);ctx.closePath(),ctx.fillStyle=`rgba(0,0,0,${alpha})`,ctx.fill(),ctx.restore();const texture=new THREE.CanvasTexture(canvas);return texture.needsUpdate=!0,texture}(shape,256,32,alfa,p1,width,height),gcad.texture[ky]=tm);const fakeShape=function pointsToShape(points){const fakeShape=new THREE.Shape;fakeShape.moveTo(points[0].x,points[0].y);for(let i=1;i<points.length;i++)fakeShape.lineTo(points[i].x,points[i].y);return fakeShape}(shape.pt),shadowGeometry=new THREE.ShapeGeometry(fakeShape);!function applyUVtoShapeGeometry(geometry,minX,minY,width,height){const pos=geometry.attributes.position,uv=[];for(let i=0;i<pos.count;i++){const x=pos.getX(i),y=pos.getY(i);uv.push((x-minX)/width,(y-minY)/height)}geometry.setAttribute("uv",new THREE.Float32BufferAttribute(uv,2))}(shadowGeometry,p1.x,p1.y,width,height);const shadowMaterial=new THREE.MeshBasicMaterial({map:tm,transparent:!0,depthWrite:!1,side:THREE.DoubleSide});let ms=new THREE.Mesh(shadowGeometry,shadowMaterial);return ms.layers.set(9),ms.rotation.x=Math.PI/2,ms}function addmovpivot(gcad,grp,movimento,op={},x=0,y=0,z=0){if(movimento=clean(movimento,!0),!gcad.movs[movimento])return grp;gcad.movs[movimento];const pivotLocal=new THREE.Vector3(x,y,z),isZeroPivot=0===pivotLocal.lengthSq(),pivotGroup=new THREE.Group;pivotGroup.name=`pivot_${movimento}`;const movimentoGroup=new THREE.Group;if(movimentoGroup.name=`mov_${movimento}`,isZeroPivot)pivotGroup.position.copy(grp.position),pivotGroup.quaternion.copy(grp.quaternion),grp.position.set(0,0,0),grp.rotation.set(0,0,0);else{const pivotWorld=pivotLocal.clone().applyMatrix4(grp.matrixWorld);pivotGroup.position.copy(pivotWorld);const offset=pivotLocal.clone().negate();grp.position.add(offset),pivotGroup.quaternion.copy(grp.getWorldQuaternion(new THREE.Quaternion)),grp.rotation.set(0,0,0)}return movimentoGroup.add(grp),pivotGroup.add(movimentoGroup),op||(op={}),op.inmov=!1,op.key=movimento,op.dt=0,op.dtstart=!1,movimentoGroup.userData.mov={...op},pivotGroup}
553
+ */const suffissoMap={"":{prop:"map",extra:null},n:{prop:"normalMap",extra:null},a:{prop:"aoMap",extra:"aoMapIntensity"},r:{prop:"roughnessMap",extra:null},h:{prop:"bumpMap",extra:"bumpScale"},t:{prop:"alphaMap",extra:null},m:{prop:"metalnessMap",extra:null},e:{prop:"emissiveMap",extra:["emissive","emissiveIntensity"]}};async function extractTextures(root,baseName){const counters={},out=[];function getName(suffix){counters[suffix]=(counters[suffix]||0)+1;let base=baseName;return suffix&&(base+=`_${suffix}`),counters[suffix]>1&&(base+=counters[suffix]),`${base}.webp`}return root.traverse((obj=>{if(obj.material){const materials=Array.isArray(obj.material)?obj.material:[obj.material];for(const mat of materials)for(const[suffix,{prop:prop}]of Object.entries(suffissoMap)){const tex=mat[prop];if(tex&&tex.image&&!tex._extracted){tex._extracted=!0;let promise,img=tex.image;if(img.toBlob)promise=new Promise((res=>img.toBlob(res,"image/webp")));else if(img instanceof ImageBitmap){const canvas=document.createElement("canvas");canvas.width=img.width,canvas.height=img.height;canvas.getContext("2d").drawImage(img,0,0),promise=new Promise((res=>canvas.toBlob(res,"image/webp")))}else{if(!(img instanceof HTMLImageElement))continue;{const canvas=document.createElement("canvas");canvas.width=img.naturalWidth||img.width,canvas.height=img.naturalHeight||img.height;canvas.getContext("2d").drawImage(img,0,0),promise=new Promise((res=>canvas.toBlob(res,"image/webp")))}}out.push(promise.then((blob=>new File([blob],getName(suffix),{type:"image/webp"}))))}}}})),root.traverse((obj=>{if(obj.material){const materials=Array.isArray(obj.material)?obj.material:[obj.material];for(const mat of materials)for(const{prop:prop}of Object.values(suffissoMap)){const tex=mat[prop];tex&&tex._extracted&&delete tex._extracted}}})),Promise.all(out)}function uvswap(geom){if(geom&&geom.attributes){const uv=geom.attributes.uv;if(uv){const a=uv.array;for(let i=0,n=a.length;i<n;i+=2){const t=a[i];a[i]=a[i+1],a[i+1]=t}uv.needsUpdate=!0}const uv2=geom.attributes.uv2;if(uv2){const b=uv2.array;for(let i=0,n=b.length;i<n;i+=2){const t=b[i];b[i]=b[i+1],b[i+1]=t}uv2.needsUpdate=!0}}}function getfakeshadow2(w,h,map){const shape=(new THREE.Shape).moveTo(0,0).lineTo(w,0).lineTo(w,h).lineTo(0,h).lineTo(0,0),geometry=new THREE.ShapeGeometry(shape),pos=geometry.attributes.position,uv=new Float32Array(2*pos.count);for(let i=0;i<pos.count;i++)uv[2*i]=pos.getX(i)/w,uv[2*i+1]=pos.getY(i)/h;geometry.setAttribute("uv",new THREE.BufferAttribute(uv,2));const material=new THREE.MeshBasicMaterial({map:map,transparent:!0,alphaTest:.01,depthWrite:!1,side:THREE.DoubleSide}),mesh=new THREE.Mesh(geometry,material);return mesh.layers.set(9),mesh.rotation.x=Math.PI/2,mesh}function getfakeshadow(gcad,shape,alfa){let ky=`fk${shape.key}${alfa}`,{p1:p1,width:width,height:height}=shape.dims();gcad.texture||(gcad.texture={});let tm=gcad.texture[ky];tm||(tm=function createBlurredShadowTextureFromPoints(mshape,size=256,blurPx=32,alpha=.2,p1,width,height){if(!width||!height||!mshape.pt||mshape.pt.length<2)return;const minX=p1.x,minY=p1.y,shapeWidth=width,shapeHeight=height,points=mshape.pt,extra=2*blurPx,canvas=document.createElement("canvas");canvas.width=size+2*extra,canvas.height=size+2*extra;const ctx=canvas.getContext("2d");ctx.save(),ctx.translate(extra,extra),ctx.scale(size/shapeWidth,size/shapeHeight),ctx.translate(-minX,-minY),ctx.filter=`blur(${blurPx}px)`,ctx.beginPath(),ctx.moveTo(points[0].x,points[0].y);for(let i=1;i<points.length;i++)ctx.lineTo(points[i].x,points[i].y);ctx.closePath(),ctx.fillStyle=`rgba(0,0,0,${alpha})`,ctx.fill(),ctx.restore();const texture=new THREE.CanvasTexture(canvas);return texture.needsUpdate=!0,texture}(shape,256,32,alfa,p1,width,height),gcad.texture[ky]=tm);const fakeShape=function pointsToShape(points){const fakeShape=new THREE.Shape;fakeShape.moveTo(points[0].x,points[0].y);for(let i=1;i<points.length;i++)fakeShape.lineTo(points[i].x,points[i].y);return fakeShape}(shape.pt),shadowGeometry=new THREE.ShapeGeometry(fakeShape);!function applyUVtoShapeGeometry(geometry,minX,minY,width,height){const pos=geometry.attributes.position,uv=[];for(let i=0;i<pos.count;i++){const x=pos.getX(i),y=pos.getY(i);uv.push((x-minX)/width,(y-minY)/height)}geometry.setAttribute("uv",new THREE.Float32BufferAttribute(uv,2))}(shadowGeometry,p1.x,p1.y,width,height);const shadowMaterial=new THREE.MeshBasicMaterial({map:tm,transparent:!0,depthWrite:!1,side:THREE.DoubleSide});let ms=new THREE.Mesh(shadowGeometry,shadowMaterial);return ms.layers.set(9),ms.rotation.x=Math.PI/2,ms}function addmovpivot(gcad,grp,movimento,op={},x=0,y=0,z=0){if(movimento=clean(movimento,!0),!gcad.movs[movimento])return grp;gcad.movs[movimento];const pivotLocal=new THREE.Vector3(x,y,z),isZeroPivot=0===pivotLocal.lengthSq(),pivotGroup=new THREE.Group;pivotGroup.name=`pivot_${movimento}`;const movimentoGroup=new THREE.Group;if(movimentoGroup.name=`mov_${movimento}`,isZeroPivot)pivotGroup.position.copy(grp.position),pivotGroup.quaternion.copy(grp.quaternion),grp.position.set(0,0,0),grp.rotation.set(0,0,0);else{const pivotWorld=pivotLocal.clone().applyMatrix4(grp.matrixWorld);pivotGroup.position.copy(pivotWorld);const offset=pivotLocal.clone().negate();grp.position.add(offset),pivotGroup.quaternion.copy(grp.getWorldQuaternion(new THREE.Quaternion)),grp.rotation.set(0,0,0)}return movimentoGroup.add(grp),pivotGroup.add(movimentoGroup),op||(op={}),op.inmov=!1,op.key=movimento,op.dt=0,op.dtstart=!1,movimentoGroup.userData.mov={...op},pivotGroup}
554
554
  /**
555
555
  * Crea un gestore di movimento per animare oggetti 3D.
556
556
  * @param {string} key - Chiave identificativa del movimento
@@ -613,7 +613,7 @@ function getriferimento(dati,x=0,y=0,z=0,id="rif"){"string"==typeof dati&&(dati=
613
613
  * @param {Object} options - Opzioni di configurazione
614
614
  * @returns {Promise<THREE.Group>} Gruppo contenente il cilindro
615
615
  */
616
- function getcilindro(gcad,ori,h,r1,r2,mats=mwhite,options){options||(options={}),Array.isArray(mats)||(mats=[mats]);const cyl=function cylgeometry(gcad,h,r,rtop,segments=16){if(!r||!h)return null;let ky=hash(`cy${h}|${r}|${rtop||r}|${segments}`);if(!gcad.geo[ky]){const geometry=new THREE.CylinderGeometry(rtop||r,r,h,segments);gcad.geo[ky]=geometry}return gcad.geo[ky]}(gcad,h,r1,r2,options.sides||16);let grp=new THREE.Group;switch((ori||"").trim().toUpperCase()){case"X":case"L":grp.position.set(h/2,0,0),grp.rotation.z=Math.PI/2;break;case"Z":case"P":grp.position.set(0,0,h/2),grp.rotation.x=Math.PI/2;break;default:grp.position.set(0,h/2,0)}if(cyl){if(!options.nolines){let segments=edgesfromgeometry(cyl);grp.add(segments)}const matTop=mats[0]||mwhite,matBottom=mats[1]||matTop,matSides=mats[2]||matTop;grp.add(getmesh(cyl,[matTop,matBottom,matSides]))}return grp}
616
+ function getcilindro(gcad,ori,h,r1,r2,mats=mwhite,options){options||(options={}),Array.isArray(mats)||(mats=[mats]);const cyl=function cylgeometry(gcad,h,r,rtop,segments=16){if(!r||!h)return null;let ky=hash(`cy${h}|${r}|${rtop||r}|${segments}`);if(!gcad.geo[ky]){const geometry=new THREE.CylinderGeometry(rtop||r,r,h,segments);gcad.geo[ky]=geometry}return gcad.geo[ky]}(gcad,h,r1,r2,options.sides||16);let grp=new THREE.Group;switch((ori||"").trim().toUpperCase()){case"X":case"L":grp.position.set(h/2,0,0),grp.rotation.z=Math.PI/2;break;case"Z":case"P":grp.position.set(0,0,h/2),grp.rotation.x=Math.PI/2;break;default:grp.position.set(0,h/2,0)}if(cyl){if(!options.nolines){let segments=edgesfromgeometry(cyl);grp.add(segments)}options.uvswap&&uvswap(cyl);const matTop=mats[0]||mwhite,matBottom=mats[1]||matTop,matSides=mats[2]||matTop;grp.add(getmesh(cyl,[matTop,matBottom,matSides]))}return grp}
617
617
  /**
618
618
  * Crea un box 3D con linee di bordo opzionali
619
619
  * @param {number} x - Larghezza
@@ -622,7 +622,7 @@ function getcilindro(gcad,ori,h,r1,r2,mats=mwhite,options){options||(options={})
622
622
  * @param {THREE.Material} mat - Materiale da applicare
623
623
  * @param {Object} options - Opzioni di configurazione
624
624
  * @returns {Promise<THREE.Group>} Gruppo contenente il box
625
- */function scalauv(box){const uvAttr=box.attributes.uv;if(uvAttr){const arr=uvAttr.array;for(let i=0;i<arr.length;i++)arr[i]*=1e3;uvAttr.needsUpdate=!0}}function getface(gcad,x,y,mat,op={}){let{repeat:repeat,order:order}=op;const key=hash(`f:${x}|${y}|${repeat?1:0}`);if(!gcad.geo[key]){const geometry=new THREE.PlaneGeometry(x,y),uvs=geometry.attributes.uv;if(repeat)for(let i=0;i<uvs.count;i++)uvs.setXY(i,uvs.getX(i)*x,uvs.getY(i)*y);else{const tm=[[0,1e3],[1e3,1e3],[0,0],[1e3,0]];for(let i=0;i<uvs.count;i++){const t=tm[i];uvs.setXY(i,t[0],t[1])}}uvs.needsUpdate=!0,gcad.geo[key]=geometry}const plane=new THREE.Mesh(gcad.geo[key],mat);return"number"==typeof order&&(plane.renderOrder=order),plane.position.set(x/2,y/2,0),mat?.transparent&&plane.layers.set(2),plane}function getbox(gcad,x,y,z,mat,options){mat&&mat.isMaterial||(options=mat,mat=void 0),options||(options={});let{center:center=!1,nolines:nolines,centerbase:centerbase=!1,px:px=0,py:py=0,pz:pz=0}=options;const box=new THREE.BoxGeometry(x,y,z);scalauv(box);const grp=new THREE.Group;if(centerbase?grp.position.set(0,y/2,0):px||py||pz?grp.position.set(px||0,py||0,pz||0):center||grp.position.set(x/2,y/2,z/2),!nolines||!mat){let segments=edgesfromgeometry(box);grp.add(segments)}return mat&&grp.add(getmesh(box,mat)),grp}function getcyl(gcad,height,radius,mat,options){options||(options={});let{center:center=!1,nolines:nolines=!1,segments:segments=16,top:top=-1,bottom:bottom=-1,heightSegments:heightSegments=1,openEnded:openEnded=!1,thetaStart:thetaStart=0,thetaLength:thetaLength=2*Math.PI}=options;top<0&&(top=radius),bottom<0&&(bottom=radius);const cylinder=new THREE.CylinderGeometry(top,bottom,height,segments,heightSegments,openEnded,thetaStart,thetaLength);scalauv(cylinder);const mesh=getmesh(cylinder,mat||mwhite),grp=new THREE.Group;if(grp.add(mesh),grp.position.set(0,center?0:height/2,0),!nolines){let segs=edgesfromgeometry(cylinder);grp.add(segs)}return grp}
625
+ */function scalauv(box){const uvAttr=box.attributes.uv;if(uvAttr){const arr=uvAttr.array;for(let i=0;i<arr.length;i++)arr[i]*=1e3;uvAttr.needsUpdate=!0}}function getface(gcad,x,y,mat,op={}){let{repeat:repeat,order:order}=op;const key=hash(`f:${x}|${y}|${repeat?1:0}`);if(!gcad.geo[key]){const geometry=new THREE.PlaneGeometry(x,y),uvs=geometry.attributes.uv;if(repeat)for(let i=0;i<uvs.count;i++)uvs.setXY(i,uvs.getX(i)*x,uvs.getY(i)*y);else{const tm=[[0,1e3],[1e3,1e3],[0,0],[1e3,0]];for(let i=0;i<uvs.count;i++){const t=tm[i];uvs.setXY(i,t[0],t[1])}}uvs.needsUpdate=!0,gcad.geo[key]=geometry}const plane=new THREE.Mesh(gcad.geo[key],mat);return"number"==typeof order&&(plane.renderOrder=order),plane.position.set(x/2,y/2,0),mat?.transparent&&plane.layers.set(2),plane}function getbox(gcad,x,y,z,mat,options){mat&&mat.isMaterial||(options=mat,mat=void 0),options||(options={});let{center:center=!1,nolines:nolines,centerbase:centerbase=!1,px:px=0,py:py=0,pz:pz=0}=options;const box=new THREE.BoxGeometry(x,y,z);scalauv(box);const grp=new THREE.Group;if(centerbase?grp.position.set(0,y/2,0):px||py||pz?grp.position.set(px||0,py||0,pz||0):center||grp.position.set(x/2,y/2,z/2),!nolines||!mat){let segments=edgesfromgeometry(box);grp.add(segments)}return mat&&grp.add(getmesh(box,mat)),grp}function getcyl(gcad,height,radius,mat,options){options||(options={});let{center:center=!1,nolines:nolines=!1,segments:segments=16,top:top=-1,bottom:bottom=-1,heightSegments:heightSegments=1,openEnded:openEnded=!1,thetaStart:thetaStart=0,thetaLength:thetaLength=2*Math.PI}=options;top<0&&(top=radius),bottom<0&&(bottom=radius);const cylinder=new THREE.CylinderGeometry(top,bottom,height,segments,heightSegments,openEnded,thetaStart,thetaLength);scalauv(cylinder),options.uvswap&&uvswap(cylinder);const mesh=getmesh(cylinder,mat||mwhite),grp=new THREE.Group;if(grp.add(mesh),grp.position.set(0,center?0:height/2,0),!nolines){let segs=edgesfromgeometry(cylinder);grp.add(segs)}return grp}
626
626
  /**
627
627
  * Crea una sfera 3D come gruppo (mesh + edges opzionali).
628
628
  * @param {object} gcad - riferimento (non usato ma coerente con getbox)
@@ -630,7 +630,7 @@ function getcilindro(gcad,ori,h,r1,r2,mats=mwhite,options){options||(options={})
630
630
  * @param {THREE.Material} mat - materiale della mesh
631
631
  * @param {object} [options] - opzioni: {center: boolean, nolines: boolean}
632
632
  * @returns {THREE.Group}
633
- */function getsphere(gcad,r,mat,options){options||(options={});let{nolines:nolines,segmenti:segmenti=16}=options,grp=new THREE.Group;const sphere=new THREE.SphereGeometry(r,2*segmenti,segmenti);if(scalauv(sphere),!nolines){let segments=edgesfromgeometry(sphere);grp.add(segments)}return grp.add(getmesh(sphere,mat||mwhite)),grp}function getextrude(gcad,pts,h=10,holes=[],mat=void 0,op={}){mat&&mat.isMaterial||(op=mat,mat=void 0),op=op??{};let{stonda:stonda,sx:sx,sy:sy,round:round,nolines:nolines}=op,ky=hash(`${JSON.stringify(pts)}|${h}|${JSON.stringify(op)}|${JSON.stringify(holes)}`);sx=sx??stonda??0,sy=sy??stonda??0;let geom=gcad.geo[ky];if(!geom){const sh=function makeShape(points){const shape=new THREE.Shape;shape.moveTo(points[0].x,points[0].y);for(let i=1;i<points.length;i++)shape.lineTo(points[i].x,points[i].y);return shape.closePath(),shape}(pts);holes.forEach((hh=>sh.holes.push(function makePath(points){const path=new THREE.Path;path.moveTo(points[0].x,points[0].y);for(let i=1;i<points.length;i++)path.lineTo(points[i].x,points[i].y);return path.closePath(),path}(hh))));const benabled=sx>0&&sy>0;geom=new THREE.ExtrudeGeometry(sh,{depth:h,bevelEnabled:benabled,bevelSize:sx,bevelThickness:sy,bevelSegments:benabled?round?3:1:0,curveSegments:benabled?10:1}),gcad.geo[ky]=geom}return new THREE.Mesh(geom,mat||mwhite)}function getthorus(gcad,r,tuber=.2,mat,options){options||(options={});let{center:center,nolines:nolines,segmenti:segmenti=16,tubi:tubi=12}=options,grp=new THREE.Group;const thorus=new THREE.TorusGeometry(r,tuber,tubi,2*segmenti);if(scalauv(thorus),grp.position.set(0,center?0:r,0),!nolines){let segments=edgesfromgeometry(thorus);grp.add(segments)}return grp.add(getmesh(thorus,mat||mwhite)),grp}
633
+ */function getsphere(gcad,r,mat,options){options||(options={});let{nolines:nolines,segmenti:segmenti=16}=options,grp=new THREE.Group;const sphere=new THREE.SphereGeometry(r,2*segmenti,segmenti);if(scalauv(sphere),!nolines){let segments=edgesfromgeometry(sphere);grp.add(segments)}return grp.add(getmesh(sphere,mat||mwhite)),grp}function extrudelines(grp,pts,holes,h,sy=3){const addring=arr=>{const top=((arr,z)=>{if(!arr||arr.length<2)return null;const n=arr.length,pos=new Float32Array(3*(n+1));for(let i=0;i<=n;i++){const p=arr[i%n],o=3*i;pos[o]=p.x,pos[o+1]=p.y,pos[o+2]=z}const g=new THREE.BufferGeometry;return g.setAttribute("position",new THREE.BufferAttribute(pos,3)),new THREE.Line(g,materialline1)})(arr,-sy);top&&(top.layers.set(30),grp.add(top))};addring(pts);for(const hh of holes)addring(hh)}function getextrude(gcad,pts,h=10,holes=[],mat=void 0,op={}){mat&&mat.isMaterial||(op=mat,mat=void 0),op=op??{};let{stonda:stonda,sx:sx,sy:sy,round:round,nolines:nolines}=op,ky=hash(`${JSON.stringify(pts)}|${h}|${JSON.stringify(op)}|${JSON.stringify(holes)}`);sx=sx??stonda??0,sy=sy??stonda??0;let geom=gcad.geo[ky];if(!geom){const sh=function makeShape(points){const shape=new THREE.Shape;shape.moveTo(points[0].x,points[0].y);for(let i=1;i<points.length;i++)shape.lineTo(points[i].x,points[i].y);return shape.closePath(),shape}(pts);holes.forEach((hh=>sh.holes.push(function makePath(points){const path=new THREE.Path;path.moveTo(points[0].x,points[0].y);for(let i=1;i<points.length;i++)path.lineTo(points[i].x,points[i].y);return path.closePath(),path}(hh))));const benabled=sx>0&&sy>0;geom=new THREE.ExtrudeGeometry(sh,{depth:h,bevelEnabled:benabled,bevelSize:sx,bevelThickness:sy,bevelSegments:benabled?round?3:1:0,curveSegments:benabled?10:1}),gcad.geo[ky]=geom,op.uvswap&&uvswap(geom)}let tm=new THREE.Group;return tm.add(new THREE.Mesh(geom,mat||mwhite)),nolines||extrudelines(tm,pts,holes,0,sy),tm}function getthorus(gcad,r,tuber=.2,mat,options){options||(options={});let{center:center,nolines:nolines,segmenti:segmenti=16,tubi:tubi=12}=options,grp=new THREE.Group;const thorus=new THREE.TorusGeometry(r,tuber,tubi,2*segmenti);if(scalauv(thorus),grp.position.set(0,center?0:r,0),!nolines){let segments=edgesfromgeometry(thorus);grp.add(segments)}return grp.add(getmesh(thorus,mat||mwhite)),grp}
634
634
  /**
635
635
  * @param {BufferGeometry} geometry
636
636
  * @param {number} tolerance
@@ -641,7 +641,7 @@ function getcilindro(gcad,ori,h,r1,r2,mats=mwhite,options){options||(options={})
641
641
  * @param {number} drawMode
642
642
  * @return {BufferGeometry}
643
643
  */
644
- function toTrianglesDrawMode(geometry,drawMode){if(drawMode===TrianglesDrawMode)return console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."),geometry;if(drawMode===TriangleFanDrawMode||drawMode===TriangleStripDrawMode){let index=geometry.getIndex();if(null===index){const indices=[],position=geometry.getAttribute("position");if(void 0===position)return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."),geometry;for(let i=0;i<position.count;i++)indices.push(i);geometry.setIndex(indices),index=geometry.getIndex()}const numberOfTriangles=index.count-2,newIndices=[];if(drawMode===TriangleFanDrawMode)for(let i=1;i<=numberOfTriangles;i++)newIndices.push(index.getX(0)),newIndices.push(index.getX(i)),newIndices.push(index.getX(i+1));else for(let i=0;i<numberOfTriangles;i++)i%2==0?(newIndices.push(index.getX(i)),newIndices.push(index.getX(i+1)),newIndices.push(index.getX(i+2))):(newIndices.push(index.getX(i+2)),newIndices.push(index.getX(i+1)),newIndices.push(index.getX(i)));newIndices.length/3!==numberOfTriangles&&console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");const newGeometry=geometry.clone();return newGeometry.setIndex(newIndices),newGeometry.clearGroups(),newGeometry}return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",drawMode),geometry}function pannellogeometry(gcad,l,a,p,r1=0,r2=0,r3=0,r4=0,b=0,npt=2){let ky=hash(`pg--${l}|${a}|${p}|${r1}|${r2}|${r3}|${r4}|${b}|${npt}`);if(l-=.01,a-=.01,p-=.01,!gcad.geo[ky]){l-=2*b,a-=2*b,p-=2*b;let tm=getshape();const vv=[{x:r4,y:0},{x:a-r1,y:0},{x:a,y:r1},{x:a,y:p-r2},{x:a-r2,y:p},{x:r3,y:p},{x:0,y:p-r3},{x:0,y:r4}];tm.addpt(vv[0]),tm.addpt(vv[1]),r1&&tm.addpt(raccordabezier(vv[0],vv[1],vv[2],vv[3],npt)),tm.addpt(vv[2]),tm.addpt(vv[3]),r2&&tm.addpt(raccordabezier(vv[2],vv[3],vv[4],vv[5],npt)),tm.addpt(vv[4]),tm.addpt(vv[5]),r3&&tm.addpt(raccordabezier(vv[4],vv[5],vv[6],vv[7],npt)),tm.addpt(vv[6]),tm.addpt(vv[7]),r2&&tm.addpt(raccordabezier(vv[6],vv[7],vv[0],vv[1],npt)),tm.removeduplicate(.01);let pts=tm.pt;const shape=new THREE.Shape;shape.moveTo(pts[0].x,pts[0].y);for(let i=1;i<pts.length;i++)shape.lineTo(pts[i].x,pts[i].y);shape.lineTo(pts[0].x,pts[0].y);const extrudeSettings={depth:l,bevelEnabled:b>0,bevelThickness:b,bevelSize:b,bevelSegments:1};let xgeo=new THREE.ExtrudeGeometry(shape,extrudeSettings);xgeo=function mergeVertices(geometry,tolerance=1e-4){tolerance=Math.max(tolerance,Number.EPSILON);const hashToIndex={},indices=geometry.getIndex(),positions=geometry.getAttribute("position"),vertexCount=indices?indices.count:positions.count;let nextIndex=0;const attributeNames=Object.keys(geometry.attributes),tmpAttributes={},tmpMorphAttributes={},newIndices=[],getters=["getX","getY","getZ","getW"],setters=["setX","setY","setZ","setW"];for(let i=0,l=attributeNames.length;i<l;i++){const name=attributeNames[i],attr=geometry.attributes[name];tmpAttributes[name]=new attr.constructor(new attr.array.constructor(attr.count*attr.itemSize),attr.itemSize,attr.normalized);const morphAttributes=geometry.morphAttributes[name];morphAttributes&&(tmpMorphAttributes[name]||(tmpMorphAttributes[name]=[]),morphAttributes.forEach(((morphAttr,i)=>{const array=new morphAttr.array.constructor(morphAttr.count*morphAttr.itemSize);tmpMorphAttributes[name][i]=new morphAttr.constructor(array,morphAttr.itemSize,morphAttr.normalized)})))}const halfTolerance=.5*tolerance,exponent=Math.log10(1/tolerance),hashMultiplier=Math.pow(10,exponent),hashAdditive=halfTolerance*hashMultiplier;for(let i=0;i<vertexCount;i++){const index=indices?indices.getX(i):i;let hash="";for(let j=0,l=attributeNames.length;j<l;j++){const name=attributeNames[j],attribute=geometry.getAttribute(name),itemSize=attribute.itemSize;for(let k=0;k<itemSize;k++)hash+=~~(attribute[getters[k]](index)*hashMultiplier+hashAdditive)+","}if(hash in hashToIndex)newIndices.push(hashToIndex[hash]);else{for(let j=0,l=attributeNames.length;j<l;j++){const name=attributeNames[j],attribute=geometry.getAttribute(name),morphAttributes=geometry.morphAttributes[name],itemSize=attribute.itemSize,newArray=tmpAttributes[name],newMorphArrays=tmpMorphAttributes[name];for(let k=0;k<itemSize;k++){const getterFunc=getters[k],setterFunc=setters[k];if(newArray[setterFunc](nextIndex,attribute[getterFunc](index)),morphAttributes)for(let m=0,ml=morphAttributes.length;m<ml;m++)newMorphArrays[m][setterFunc](nextIndex,morphAttributes[m][getterFunc](index))}}hashToIndex[hash]=nextIndex,newIndices.push(nextIndex),nextIndex++}}const result=geometry.clone();for(const name in geometry.attributes){const tmpAttribute=tmpAttributes[name];if(result.setAttribute(name,new tmpAttribute.constructor(tmpAttribute.array.slice(0,nextIndex*tmpAttribute.itemSize),tmpAttribute.itemSize,tmpAttribute.normalized)),name in tmpMorphAttributes)for(let j=0;j<tmpMorphAttributes[name].length;j++){const tmpMorphAttribute=tmpMorphAttributes[name][j];result.morphAttributes[name][j]=new tmpMorphAttribute.constructor(tmpMorphAttribute.array.slice(0,nextIndex*tmpMorphAttribute.itemSize),tmpMorphAttribute.itemSize,tmpMorphAttribute.normalized)}}return result.setIndex(newIndices),result}(xgeo),xgeo.computeVertexNormals();const uv=xgeo.attributes.uv;let x1=Math.random()*l,y1=Math.random()*(a+p);for(let i=0;i<uv.count;i++)uv.setXY(i,uv.getY(i)+y1,uv.getX(i)+x1);uv.needsUpdate=!0,gcad.geo[ky]=xgeo}return gcad.geo[ky]}function getpannello(gcad,orientamento,x,y,z,mat1,mat2,options){options||(options={});let l,a,p,{r:r,r1:r1,r2:r2,r3:r3,r4:r4,b:b,npt:npt}=options;r1=r1||r||0,r2=r2||r||0,r3=r3||r||0,r4=r4||r||0,npt=npt||2,b=b||0,(b>=x/2||b>=y/2||b>=z/2)&&(b=0),l="L"==(orientamento=orientamento.trim().toUpperCase())[0]?x:"A"==orientamento[0]?y:z,a="L"==orientamento[1]?x:"A"==orientamento[1]?y:z,p="L"==orientamento[2]?x:"A"==orientamento[2]?y:z;let grp=new THREE.Group;if(!options.nolines){let segments=edgesfromgeometry(new THREE.BoxGeometry(x,y,z));segments.position.set(x/2,y/2,z/2),grp.add(segments)}let mesh=getmesh(pannellogeometry(gcad,l,a,p,r1,r2,r3,r4,b,npt),[mat2||mat1||mgreen,mat1||mred]);mesh.name="pannello",mesh.layers.set(1);let m2=mesh;return b&&(mesh.position.set(b,b,b),m2=new THREE.Group,m2.add(mesh)),mesh=function meshrotate(orientamento,mesh,x=0,y=0,z=0){switch(orientamento.trim().toUpperCase()){case"LPA":mesh.rotation.y=Math.PI/2,mesh.rotation.x=Math.PI,mesh.position.set(0,z,0);break;case"ALP":mesh.rotation.x=Math.PI/2,mesh.position.set(0,x,0);break;case"APL":mesh.rotation.x=-Math.PI/2,mesh.rotation.z=-Math.PI/2;break;case"PLA":break;case"PAL":mesh.rotation.z=Math.PI/2,mesh.position.set(z,0,0);break;case"LAP":mesh.rotation.y=Math.PI/2,mesh.rotation.z=Math.PI/2}return mesh}(orientamento,m2,l,a,p),grp.add(mesh),grp}async function getpannello2(gcad,orientamento,l,a,p,mat,round=0){let bb;switch((round<0||round>Math.max(l,a,p)/3)&&(round=0),orientamento){case"lap":bb=getextrude(gcad,getshape().fromrect(l-2*round,a-2*round).pt,p-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=p-round,bb.position.y=a-round,bb.rotation.x=Math.PI;break;case"alp":bb=getextrude(gcad,getshape().fromrect(a-2*round,l-2*round).pt,p-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=round,bb.position.y=a-round,bb.rotation.z=-Math.PI/2;break;case"apl":bb=getextrude(gcad,getshape().fromrect(a-2*round,p-2*round).pt,l-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=round,bb.position.y=round,bb.rotation.y=Math.PI/2,bb.rotation.z=Math.PI/2;break;case"pal":bb=getextrude(gcad,getshape().fromrect(p-2*round,a-2*round).pt,l-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=p-round,bb.position.y=round,bb.rotation.y=Math.PI/2;break;case"pla":bb=getextrude(gcad,getshape().fromrect(p-2*round,l-2*round).pt,a-2*round,[],mat,{round:round,stonda:round}),bb.rotation.z=-Math.PI/2,bb.rotation.x=-Math.PI/2,bb.position.x=round,bb.position.z=round,bb.position.y=round;break;default:bb=getextrude(gcad,getshape().fromrect(l-2*round,p-2*round).pt,a-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=round,bb.rotation.x=Math.PI/2,bb.position.y=a-round}return bb}function earcut(data,holeIndices,dim=2){const hasHoles=holeIndices&&holeIndices.length,outerLen=hasHoles?holeIndices[0]*dim:data.length;let outerNode=linkedList(data,0,outerLen,dim,!0);const triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;let minX,minY,invSize;if(hasHoles&&(outerNode=function eliminateHoles(data,holeIndices,outerNode,dim){const queue=[];for(let i=0,len=holeIndices.length;i<len;i++){const list=linkedList(data,holeIndices[i]*dim,i<len-1?holeIndices[i+1]*dim:data.length,dim,!1);list===list.next&&(list.steiner=!0),queue.push(getLeftmost(list))}queue.sort(compareXYSlope);for(let i=0;i<queue.length;i++)outerNode=eliminateHole(queue[i],outerNode);return outerNode}(data,holeIndices,outerNode,dim)),data.length>80*dim){minX=1/0,minY=1/0;let maxX=-1/0,maxY=-1/0;for(let i=dim;i<outerLen;i+=dim){const x=data[i],y=data[i+1];x<minX&&(minX=x),y<minY&&(minY=y),x>maxX&&(maxX=x),y>maxY&&(maxY=y)}invSize=Math.max(maxX-minX,maxY-minY),invSize=0!==invSize?32767/invSize:0}return earcutLinked(outerNode,triangles,dim,minX,minY,invSize,0),triangles}function linkedList(data,start,end,dim,clockwise){let last;if(clockwise===function signedArea(data,start,end,dim){let sum=0;for(let i=start,j=end-dim;i<end;i+=dim)sum+=(data[j]-data[i])*(data[i+1]+data[j+1]),j=i;return sum}(data,start,end,dim)>0)for(let i=start;i<end;i+=dim)last=insertNode(i/dim|0,data[i],data[i+1],last);else for(let i=end-dim;i>=start;i-=dim)last=insertNode(i/dim|0,data[i],data[i+1],last);return last&&equals(last,last.next)&&(removeNode(last),last=last.next),last}function filterPoints(start,end){if(!start)return start;end||(end=start);let again,p=start;do{if(again=!1,p.steiner||!equals(p,p.next)&&0!==area(p.prev,p,p.next))p=p.next;else{if(removeNode(p),p=end=p.prev,p===p.next)break;again=!0}}while(again||p!==end);return end}function earcutLinked(ear,triangles,dim,minX,minY,invSize,pass){if(!ear)return;!pass&&invSize&&function indexCurve(start,minX,minY,invSize){let p=start;do{0===p.z&&(p.z=zOrder(p.x,p.y,minX,minY,invSize)),p.prevZ=p.prev,p.nextZ=p.next,p=p.next}while(p!==start);p.prevZ.nextZ=null,p.prevZ=null,function sortLinked(list){let numMerges,inSize=1;do{let e,p=list;list=null;let tail=null;for(numMerges=0;p;){numMerges++;let q=p,pSize=0;for(let i=0;i<inSize&&(pSize++,q=q.nextZ,q);i++);let qSize=inSize;for(;pSize>0||qSize>0&&q;)0!==pSize&&(0===qSize||!q||p.z<=q.z)?(e=p,p=p.nextZ,pSize--):(e=q,q=q.nextZ,qSize--),tail?tail.nextZ=e:list=e,e.prevZ=tail,tail=e;p=q}tail.nextZ=null,inSize*=2}while(numMerges>1);return list}(p)}(ear,minX,minY,invSize);let stop=ear;for(;ear.prev!==ear.next;){const prev=ear.prev,next=ear.next;if(invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear))triangles.push(prev.i,ear.i,next.i),removeNode(ear),ear=next.next,stop=next.next;else if((ear=next)===stop){pass?1===pass?earcutLinked(ear=cureLocalIntersections(filterPoints(ear),triangles),triangles,dim,minX,minY,invSize,2):2===pass&&splitEarcut(ear,triangles,dim,minX,minY,invSize):earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);break}}}function isEar(ear){const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const ax=a.x,bx=b.x,cx=c.x,ay=a.y,by=b.y,cy=c.y,x0=Math.min(ax,bx,cx),y0=Math.min(ay,by,cy),x1=Math.max(ax,bx,cx),y1=Math.max(ay,by,cy);let p=c.next;for(;p!==a;){if(p.x>=x0&&p.x<=x1&&p.y>=y0&&p.y<=y1&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.next}return!0}function isEarHashed(ear,minX,minY,invSize){const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const ax=a.x,bx=b.x,cx=c.x,ay=a.y,by=b.y,cy=c.y,x0=Math.min(ax,bx,cx),y0=Math.min(ay,by,cy),x1=Math.max(ax,bx,cx),y1=Math.max(ay,by,cy),minZ=zOrder(x0,y0,minX,minY,invSize),maxZ=zOrder(x1,y1,minX,minY,invSize);let p=ear.prevZ,n=ear.nextZ;for(;p&&p.z>=minZ&&n&&n.z<=maxZ;){if(p.x>=x0&&p.x<=x1&&p.y>=y0&&p.y<=y1&&p!==a&&p!==c&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,n.x>=x0&&n.x<=x1&&n.y>=y0&&n.y<=y1&&n!==a&&n!==c&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}for(;p&&p.z>=minZ;){if(p.x>=x0&&p.x<=x1&&p.y>=y0&&p.y<=y1&&p!==a&&p!==c&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;n&&n.z<=maxZ;){if(n.x>=x0&&n.x<=x1&&n.y>=y0&&n.y<=y1&&n!==a&&n!==c&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}return!0}function cureLocalIntersections(start,triangles){let p=start;do{const a=p.prev,b=p.next.next;!equals(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)&&(triangles.push(a.i,p.i,b.i),removeNode(p),removeNode(p.next),p=start=b),p=p.next}while(p!==start);return filterPoints(p)}function splitEarcut(start,triangles,dim,minX,minY,invSize){let a=start;do{let b=a.next.next;for(;b!==a.prev;){if(a.i!==b.i&&isValidDiagonal(a,b)){let c=splitPolygon(a,b);return a=filterPoints(a,a.next),c=filterPoints(c,c.next),earcutLinked(a,triangles,dim,minX,minY,invSize,0),void earcutLinked(c,triangles,dim,minX,minY,invSize,0)}b=b.next}a=a.next}while(a!==start)}function compareXYSlope(a,b){let result=a.x-b.x;if(0===result&&(result=a.y-b.y,0===result)){result=(a.next.y-a.y)/(a.next.x-a.x)-(b.next.y-b.y)/(b.next.x-b.x)}return result}function eliminateHole(hole,outerNode){const bridge=function findHoleBridge(hole,outerNode){let p=outerNode;const hx=hole.x,hy=hole.y;let m,qx=-1/0;if(equals(hole,p))return p;do{if(equals(hole,p.next))return p.next;if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){const x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx&&(qx=x,m=p.x<p.next.x?p:p.next,x===hx))return m}p=p.next}while(p!==outerNode);if(!m)return null;const stop=m,mx=m.x,my=m.y;let tanMin=1/0;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){const tan=Math.abs(hy-p.y)/(hx-p.x);locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&&sectorContainsSector(m,p)))&&(m=p,tanMin=tan)}p=p.next}while(p!==stop);return m}(hole,outerNode);if(!bridge)return outerNode;const bridgeReverse=splitPolygon(bridge,hole);return filterPoints(bridgeReverse,bridgeReverse.next),filterPoints(bridge,bridge.next)}function sectorContainsSector(m,p){return area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0}function zOrder(x,y,minX,minY,invSize){return(x=1431655765&((x=858993459&((x=252645135&((x=16711935&((x=(x-minX)*invSize|0)|x<<8))|x<<4))|x<<2))|x<<1))|(y=1431655765&((y=858993459&((y=252645135&((y=16711935&((y=(y-minY)*invSize|0)|y<<8))|y<<4))|y<<2))|y<<1))<<1}function getLeftmost(start){let p=start,leftmost=start;do{(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)&&(leftmost=p),p=p.next}while(p!==start);return leftmost}function pointInTriangle(ax,ay,bx,by,cx,cy,px,py){return(cx-px)*(ay-py)>=(ax-px)*(cy-py)&&(ax-px)*(by-py)>=(bx-px)*(ay-py)&&(bx-px)*(cy-py)>=(cx-px)*(by-py)}function pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,px,py){return!(ax===px&&ay===py)&&pointInTriangle(ax,ay,bx,by,cx,cy,px,py)}function isValidDiagonal(a,b){return a.next.i!==b.i&&a.prev.i!==b.i&&!function intersectsPolygon(a,b){let p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return!0;p=p.next}while(p!==a);return!1}(a,b)&&(locallyInside(a,b)&&locallyInside(b,a)&&function middleInside(a,b){let p=a,inside=!1;const px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{p.y>py!=p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x&&(inside=!inside),p=p.next}while(p!==a);return inside}(a,b)&&(area(a.prev,a,b.prev)||area(a,b.prev,b))||equals(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0)}function area(p,q,r){return(q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y)}function equals(p1,p2){return p1.x===p2.x&&p1.y===p2.y}function intersects(p1,q1,p2,q2){const o1=sign(area(p1,q1,p2)),o2=sign(area(p1,q1,q2)),o3=sign(area(p2,q2,p1)),o4=sign(area(p2,q2,q1));return o1!==o2&&o3!==o4||(!(0!==o1||!onSegment(p1,p2,q1))||(!(0!==o2||!onSegment(p1,q2,q1))||(!(0!==o3||!onSegment(p2,p1,q2))||!(0!==o4||!onSegment(p2,q1,q2)))))}function onSegment(p,q,r){return q.x<=Math.max(p.x,r.x)&&q.x>=Math.min(p.x,r.x)&&q.y<=Math.max(p.y,r.y)&&q.y>=Math.min(p.y,r.y)}function sign(num){return num>0?1:num<0?-1:0}function locallyInside(a,b){return area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0}function splitPolygon(a,b){const a2=createNode(a.i,a.x,a.y),b2=createNode(b.i,b.x,b.y),an=a.next,bp=b.prev;return a.next=b,b.prev=a,a2.next=an,an.prev=a2,b2.next=a2,a2.prev=b2,bp.next=b2,b2.prev=bp,b2}function insertNode(i,x,y,last){const p=createNode(i,x,y);return last?(p.next=last.next,p.prev=last,last.next.prev=p,last.next=p):(p.prev=p,p.next=p),p}function removeNode(p){p.next.prev=p.prev,p.prev.next=p.next,p.prevZ&&(p.prevZ.nextZ=p.nextZ),p.nextZ&&(p.nextZ.prevZ=p.prevZ)}function createNode(i,x,y){return{i:i,x:x,y:y,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function unifyVertices(vertices,uvs,indices){const vertMap=new Map,verticesOut=[],uvsOut=[],indicesOut=[];for(let i=0;i<indices.length;i++){const idx=indices[i],vx=vertices[3*idx+0],vy=vertices[3*idx+1],vz=vertices[3*idx+2],ux=uvs[2*idx+0],uy=uvs[2*idx+1],key=`${vx},${vy},${vz}|${ux},${uy}`;if(vertMap.has(key))indicesOut.push(vertMap.get(key));else{const newIndex=verticesOut.length/3;vertMap.set(key,newIndex),verticesOut.push(vx,vy,vz),uvsOut.push(ux,uy),indicesOut.push(newIndex)}}return{vertices:verticesOut,uvs:uvsOut,indices:indicesOut}}function infoestrudi(shape,hshape,pts,options,sh){options||(options={}),pts||(pts=[]);let p0=options.p0||0,coeffbase1=Math.tan(options.coeffbase1*PIF||0),coeffbase2=Math.tan(options.coeffbase2*PIF||0),p1=hshape||options.p1||20,coefftop1=Math.tan(options.coefftop1*PIF||0),coefftop2=Math.tan(options.coefftop2*PIF||0),{mi:mi,ma:ma}=shape.pt.reduce(((t,e)=>(t.mi.x=Math.min(t.mi.x,e.x),t.mi.y=Math.min(t.mi.y,e.y),t.ma.x=Math.max(t.ma.x,e.x),t.ma.y=Math.max(t.ma.y,e.y),t)),{mi:{x:1e9,y:1e9},ma:{x:-1e9,y:-1e9}}),lmax=0,lmin=1e9;function getpars(p){p.z1=getzeta(p.x,p.y,p0,coeffbase1,coeffbase2,sh),p.z2=getzeta(p.x,p.y,p1,coefftop1,coefftop2,sh),p.l=Math.abs(p.z2-p.z1)}for(let p of pts)getpars(p);getpars(mi),getpars(ma);let rect=[{x:mi.x,y:mi.y},{x:ma.x,y:mi.y},{x:ma.x,y:ma.y},{x:mi.x,y:ma.y}];for(let r of rect)getpars(r),r.l>lmax&&(lmax=r.l),r.l<lmin&&(lmin=r.l);return{aini:options.coeffbase1||0,aini2:options.coeffbase2||0,afin:options.coefftop1||0,afin2:options.coefftop2||0,pts:pts,mi:mi,ma:ma,rect:rect,dimx:ma.x-mi.x,dimy:ma.y-mi.y,lnom:p1-p0,lmax:lmax,lmin:lmin,lmed:(lmax+lmin)/2}}function getzeta(x,y,zbase,cx,cy,sh,invert=!1){let z=x*cx+y*cy+zbase;if(sh){let t=sh.xfromy(-y,0,!0);invert?z-=t:z=t}return z}function sidegeomfromshapes(gcad,ky,s1,s2,invert=!1,stonda=!1){if(s1&&s2){if(s1.length!==s2.length)throw new Error("shapes with different length");if(s1.length<2)throw new Error("I percorsi devono contenere almeno due punti ciascuno.");if(!gcad.geo[ky]){const vertices=[],uvs=[],indices=[],np=s1.length,addpts=ss=>{for(const s of ss)vertices.push(s.x,s.y,s.z),uvs.push(s.u,s.v)},equalpos=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y&&p1.z===p2.z,addindexquad=(i1,i2,i3,i4)=>{invert?indices.push(i1,i3,i2,i3,i4,i2):indices.push(i1,i2,i3,i3,i2,i4)};addpts(s1),addpts(s2);for(let i=0;i<np-1;i++){const j=i+1;equalpos(s1[i],s1[j])||addindexquad(i,j,i+np,j+np)}const geometry=new THREE.BufferGeometry;if(stonda){let tm=unifyVertices(vertices,uvs,indices);geometry.setAttribute("position",new THREE.Float32BufferAttribute(tm.vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(tm.uvs,2)),geometry.setIndex(tm.indices)}else geometry.setAttribute("position",new THREE.Float32BufferAttribute(vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(uvs,2)),geometry.setIndex(indices);geometry.computeVertexNormals(),gcad.geo[ky]=geometry}return gcad.geo[ky]}}function bottomgeomfromshape(gcad,inverti,outer,holes,c=0,a=0,b=0,shape=null,stonda=!1){let ky=`bg:${c}|${a}${b}|${outer.key}|${inverti}|${shape?.key||""}`;for(let h of holes)ky=`${ky}|${h.key}`;if(ky=hash(ky),!gcad.geo[ky]){let triangles,pos=[],hl=[],cc=outer.pt.length;pos=outer.vec;const geometry=new THREE.BufferGeometry,vertices=[],uvs=[],indices=[];function addvertexes(triangles,pos){let i0=vertices.length/3;for(let i=0;i<triangles.length;i++){const index=triangles[i],x=pos[2*index],y=-pos[2*index+1],z=getzeta(x,y,c,a,b,shape,inverti);vertices.push(x,y,z),uvs.push(y,x)}for(let i=0;i<triangles.length;i+=3)inverti?indices.push(i+i0,i+i0+2,i+i0+1):indices.push(i+i0,i+i0+1,i+i0+2)}if(shape){let cl2=outer.sliceony(shape);for(let c of cl2){let x=c.flatMap((p=>[p.x,p.y]));addvertexes(earcut(x,[]),x)}}else if(Array.isArray(holes)&&holes.length){for(let h of holes)hl.push(cc),cc+=h.pt.length,pos=[...pos,...h.vec];triangles=earcut(pos,hl),addvertexes(triangles,pos)}else triangles=earcut(pos),addvertexes(triangles,pos);if(stonda){let tm=unifyVertices(vertices,uvs,indices);geometry.setAttribute("position",new THREE.Float32BufferAttribute(tm.vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(tm.uvs,2)),geometry.setIndex(tm.indices)}else geometry.setAttribute("position",new THREE.Float32BufferAttribute(vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(uvs,2)),geometry.setIndex(indices);geometry.computeVertexNormals(),gcad.geo[ky]=geometry}return gcad.geo[ky]}function estrusorotate(orientamento,mesh,z=0){switch(orientamento.trim().toUpperCase().slice(0,1)){case"A":mesh.rotation.x=-Math.PI/2;break;case"L":mesh.rotation.y=Math.PI/2,mesh.rotation.z=Math.PI;break;case"P":mesh.rotation.z=Math.PI/2}return mesh}
644
+ function toTrianglesDrawMode(geometry,drawMode){if(drawMode===TrianglesDrawMode)return console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles."),geometry;if(drawMode===TriangleFanDrawMode||drawMode===TriangleStripDrawMode){let index=geometry.getIndex();if(null===index){const indices=[],position=geometry.getAttribute("position");if(void 0===position)return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible."),geometry;for(let i=0;i<position.count;i++)indices.push(i);geometry.setIndex(indices),index=geometry.getIndex()}const numberOfTriangles=index.count-2,newIndices=[];if(drawMode===TriangleFanDrawMode)for(let i=1;i<=numberOfTriangles;i++)newIndices.push(index.getX(0)),newIndices.push(index.getX(i)),newIndices.push(index.getX(i+1));else for(let i=0;i<numberOfTriangles;i++)i%2==0?(newIndices.push(index.getX(i)),newIndices.push(index.getX(i+1)),newIndices.push(index.getX(i+2))):(newIndices.push(index.getX(i+2)),newIndices.push(index.getX(i+1)),newIndices.push(index.getX(i)));newIndices.length/3!==numberOfTriangles&&console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.");const newGeometry=geometry.clone();return newGeometry.setIndex(newIndices),newGeometry.clearGroups(),newGeometry}return console.error("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:",drawMode),geometry}function pannellogeometry(gcad,l,a,p,r1=0,r2=0,r3=0,r4=0,b=0,npt=2,fluvswap=!1){let ky=hash(`pg--${l}|${a}|${p}|${r1}|${r2}|${r3}|${r4}|${b}|${npt}|${fluvswap?1:0}`);if(l-=.01,a-=.01,p-=.01,!gcad.geo[ky]){l-=2*b,a-=2*b,p-=2*b;let tm=getshape();const vv=[{x:r4,y:0},{x:a-r1,y:0},{x:a,y:r1},{x:a,y:p-r2},{x:a-r2,y:p},{x:r3,y:p},{x:0,y:p-r3},{x:0,y:r4}];tm.addpt(vv[0]),tm.addpt(vv[1]),r1&&tm.addpt(raccordabezier(vv[0],vv[1],vv[2],vv[3],npt)),tm.addpt(vv[2]),tm.addpt(vv[3]),r2&&tm.addpt(raccordabezier(vv[2],vv[3],vv[4],vv[5],npt)),tm.addpt(vv[4]),tm.addpt(vv[5]),r3&&tm.addpt(raccordabezier(vv[4],vv[5],vv[6],vv[7],npt)),tm.addpt(vv[6]),tm.addpt(vv[7]),r2&&tm.addpt(raccordabezier(vv[6],vv[7],vv[0],vv[1],npt)),tm.removeduplicate(.01);let pts=tm.pt;const shape=new THREE.Shape;shape.moveTo(pts[0].x,pts[0].y);for(let i=1;i<pts.length;i++)shape.lineTo(pts[i].x,pts[i].y);shape.lineTo(pts[0].x,pts[0].y);const extrudeSettings={depth:l,bevelEnabled:b>0,bevelThickness:b,bevelSize:b,bevelSegments:1};let xgeo=new THREE.ExtrudeGeometry(shape,extrudeSettings);xgeo=function mergeVertices(geometry,tolerance=1e-4){tolerance=Math.max(tolerance,Number.EPSILON);const hashToIndex={},indices=geometry.getIndex(),positions=geometry.getAttribute("position"),vertexCount=indices?indices.count:positions.count;let nextIndex=0;const attributeNames=Object.keys(geometry.attributes),tmpAttributes={},tmpMorphAttributes={},newIndices=[],getters=["getX","getY","getZ","getW"],setters=["setX","setY","setZ","setW"];for(let i=0,l=attributeNames.length;i<l;i++){const name=attributeNames[i],attr=geometry.attributes[name];tmpAttributes[name]=new attr.constructor(new attr.array.constructor(attr.count*attr.itemSize),attr.itemSize,attr.normalized);const morphAttributes=geometry.morphAttributes[name];morphAttributes&&(tmpMorphAttributes[name]||(tmpMorphAttributes[name]=[]),morphAttributes.forEach(((morphAttr,i)=>{const array=new morphAttr.array.constructor(morphAttr.count*morphAttr.itemSize);tmpMorphAttributes[name][i]=new morphAttr.constructor(array,morphAttr.itemSize,morphAttr.normalized)})))}const halfTolerance=.5*tolerance,exponent=Math.log10(1/tolerance),hashMultiplier=Math.pow(10,exponent),hashAdditive=halfTolerance*hashMultiplier;for(let i=0;i<vertexCount;i++){const index=indices?indices.getX(i):i;let hash="";for(let j=0,l=attributeNames.length;j<l;j++){const name=attributeNames[j],attribute=geometry.getAttribute(name),itemSize=attribute.itemSize;for(let k=0;k<itemSize;k++)hash+=~~(attribute[getters[k]](index)*hashMultiplier+hashAdditive)+","}if(hash in hashToIndex)newIndices.push(hashToIndex[hash]);else{for(let j=0,l=attributeNames.length;j<l;j++){const name=attributeNames[j],attribute=geometry.getAttribute(name),morphAttributes=geometry.morphAttributes[name],itemSize=attribute.itemSize,newArray=tmpAttributes[name],newMorphArrays=tmpMorphAttributes[name];for(let k=0;k<itemSize;k++){const getterFunc=getters[k],setterFunc=setters[k];if(newArray[setterFunc](nextIndex,attribute[getterFunc](index)),morphAttributes)for(let m=0,ml=morphAttributes.length;m<ml;m++)newMorphArrays[m][setterFunc](nextIndex,morphAttributes[m][getterFunc](index))}}hashToIndex[hash]=nextIndex,newIndices.push(nextIndex),nextIndex++}}const result=geometry.clone();for(const name in geometry.attributes){const tmpAttribute=tmpAttributes[name];if(result.setAttribute(name,new tmpAttribute.constructor(tmpAttribute.array.slice(0,nextIndex*tmpAttribute.itemSize),tmpAttribute.itemSize,tmpAttribute.normalized)),name in tmpMorphAttributes)for(let j=0;j<tmpMorphAttributes[name].length;j++){const tmpMorphAttribute=tmpMorphAttributes[name][j];result.morphAttributes[name][j]=new tmpMorphAttribute.constructor(tmpMorphAttribute.array.slice(0,nextIndex*tmpMorphAttribute.itemSize),tmpMorphAttribute.itemSize,tmpMorphAttribute.normalized)}}return result.setIndex(newIndices),result}(xgeo),xgeo.computeVertexNormals();const uv=xgeo.attributes.uv;let x1=Math.random()*l,y1=Math.random()*(a+p);fluvswap&&uvswap(xgeo);for(let i=0;i<uv.count;i++)uv.setXY(i,uv.getY(i)+y1,uv.getX(i)+x1);uv.needsUpdate=!0,gcad.geo[ky]=xgeo}return gcad.geo[ky]}function getpannello(gcad,orientamento,x,y,z,mat1,mat2,options){options||(options={});let l,a,p,{r:r,r1:r1,r2:r2,r3:r3,r4:r4,b:b,npt:npt}=options;r1=r1||r||0,r2=r2||r||0,r3=r3||r||0,r4=r4||r||0,npt=npt||2,b=b||0,(b>=x/2||b>=y/2||b>=z/2)&&(b=0),l="L"==(orientamento=orientamento.trim().toUpperCase())[0]?x:"A"==orientamento[0]?y:z,a="L"==orientamento[1]?x:"A"==orientamento[1]?y:z,p="L"==orientamento[2]?x:"A"==orientamento[2]?y:z;let grp=new THREE.Group;if(!options.nolines){let segments=edgesfromgeometry(new THREE.BoxGeometry(x,y,z));segments.position.set(x/2,y/2,z/2),grp.add(segments)}let mesh=getmesh(pannellogeometry(gcad,l,a,p,r1,r2,r3,r4,b,npt,options.uvswap),[mat2||mat1||mgreen,mat1||mred]);mesh.name="pannello",mesh.layers.set(1);let m2=mesh;return b&&(mesh.position.set(b,b,b),m2=new THREE.Group,m2.add(mesh)),mesh=function meshrotate(orientamento,mesh,x=0,y=0,z=0){switch(orientamento.trim().toUpperCase()){case"LPA":mesh.rotation.y=Math.PI/2,mesh.rotation.x=Math.PI,mesh.position.set(0,z,0);break;case"ALP":mesh.rotation.x=Math.PI/2,mesh.position.set(0,x,0);break;case"APL":mesh.rotation.x=-Math.PI/2,mesh.rotation.z=-Math.PI/2;break;case"PLA":break;case"PAL":mesh.rotation.z=Math.PI/2,mesh.position.set(z,0,0);break;case"LAP":mesh.rotation.y=Math.PI/2,mesh.rotation.z=Math.PI/2}return mesh}(orientamento,m2,l,a,p),grp.add(mesh),grp}async function getpannello2(gcad,orientamento,l,a,p,mat,round=0){let bb;switch((round<0||round>Math.max(l,a,p)/3)&&(round=0),orientamento){case"lap":bb=getextrude(gcad,getshape().fromrect(l-2*round,a-2*round).pt,p-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=p-round,bb.position.y=a-round,bb.rotation.x=Math.PI;break;case"alp":bb=getextrude(gcad,getshape().fromrect(a-2*round,l-2*round).pt,p-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=round,bb.position.y=a-round,bb.rotation.z=-Math.PI/2;break;case"apl":bb=getextrude(gcad,getshape().fromrect(a-2*round,p-2*round).pt,l-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=round,bb.position.y=round,bb.rotation.y=Math.PI/2,bb.rotation.z=Math.PI/2;break;case"pal":bb=getextrude(gcad,getshape().fromrect(p-2*round,a-2*round).pt,l-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=p-round,bb.position.y=round,bb.rotation.y=Math.PI/2;break;case"pla":bb=getextrude(gcad,getshape().fromrect(p-2*round,l-2*round).pt,a-2*round,[],mat,{round:round,stonda:round}),bb.rotation.z=-Math.PI/2,bb.rotation.x=-Math.PI/2,bb.position.x=round,bb.position.z=round,bb.position.y=round;break;default:bb=getextrude(gcad,getshape().fromrect(l-2*round,p-2*round).pt,a-2*round,[],mat,{round:round,stonda:round}),bb.position.x=round,bb.position.z=round,bb.rotation.x=Math.PI/2,bb.position.y=a-round}return bb}function earcut(data,holeIndices,dim=2){const hasHoles=holeIndices&&holeIndices.length,outerLen=hasHoles?holeIndices[0]*dim:data.length;let outerNode=linkedList(data,0,outerLen,dim,!0);const triangles=[];if(!outerNode||outerNode.next===outerNode.prev)return triangles;let minX,minY,invSize;if(hasHoles&&(outerNode=function eliminateHoles(data,holeIndices,outerNode,dim){const queue=[];for(let i=0,len=holeIndices.length;i<len;i++){const list=linkedList(data,holeIndices[i]*dim,i<len-1?holeIndices[i+1]*dim:data.length,dim,!1);list===list.next&&(list.steiner=!0),queue.push(getLeftmost(list))}queue.sort(compareXYSlope);for(let i=0;i<queue.length;i++)outerNode=eliminateHole(queue[i],outerNode);return outerNode}(data,holeIndices,outerNode,dim)),data.length>80*dim){minX=1/0,minY=1/0;let maxX=-1/0,maxY=-1/0;for(let i=dim;i<outerLen;i+=dim){const x=data[i],y=data[i+1];x<minX&&(minX=x),y<minY&&(minY=y),x>maxX&&(maxX=x),y>maxY&&(maxY=y)}invSize=Math.max(maxX-minX,maxY-minY),invSize=0!==invSize?32767/invSize:0}return earcutLinked(outerNode,triangles,dim,minX,minY,invSize,0),triangles}function linkedList(data,start,end,dim,clockwise){let last;if(clockwise===function signedArea(data,start,end,dim){let sum=0;for(let i=start,j=end-dim;i<end;i+=dim)sum+=(data[j]-data[i])*(data[i+1]+data[j+1]),j=i;return sum}(data,start,end,dim)>0)for(let i=start;i<end;i+=dim)last=insertNode(i/dim|0,data[i],data[i+1],last);else for(let i=end-dim;i>=start;i-=dim)last=insertNode(i/dim|0,data[i],data[i+1],last);return last&&equals(last,last.next)&&(removeNode(last),last=last.next),last}function filterPoints(start,end){if(!start)return start;end||(end=start);let again,p=start;do{if(again=!1,p.steiner||!equals(p,p.next)&&0!==area(p.prev,p,p.next))p=p.next;else{if(removeNode(p),p=end=p.prev,p===p.next)break;again=!0}}while(again||p!==end);return end}function earcutLinked(ear,triangles,dim,minX,minY,invSize,pass){if(!ear)return;!pass&&invSize&&function indexCurve(start,minX,minY,invSize){let p=start;do{0===p.z&&(p.z=zOrder(p.x,p.y,minX,minY,invSize)),p.prevZ=p.prev,p.nextZ=p.next,p=p.next}while(p!==start);p.prevZ.nextZ=null,p.prevZ=null,function sortLinked(list){let numMerges,inSize=1;do{let e,p=list;list=null;let tail=null;for(numMerges=0;p;){numMerges++;let q=p,pSize=0;for(let i=0;i<inSize&&(pSize++,q=q.nextZ,q);i++);let qSize=inSize;for(;pSize>0||qSize>0&&q;)0!==pSize&&(0===qSize||!q||p.z<=q.z)?(e=p,p=p.nextZ,pSize--):(e=q,q=q.nextZ,qSize--),tail?tail.nextZ=e:list=e,e.prevZ=tail,tail=e;p=q}tail.nextZ=null,inSize*=2}while(numMerges>1);return list}(p)}(ear,minX,minY,invSize);let stop=ear;for(;ear.prev!==ear.next;){const prev=ear.prev,next=ear.next;if(invSize?isEarHashed(ear,minX,minY,invSize):isEar(ear))triangles.push(prev.i,ear.i,next.i),removeNode(ear),ear=next.next,stop=next.next;else if((ear=next)===stop){pass?1===pass?earcutLinked(ear=cureLocalIntersections(filterPoints(ear),triangles),triangles,dim,minX,minY,invSize,2):2===pass&&splitEarcut(ear,triangles,dim,minX,minY,invSize):earcutLinked(filterPoints(ear),triangles,dim,minX,minY,invSize,1);break}}}function isEar(ear){const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const ax=a.x,bx=b.x,cx=c.x,ay=a.y,by=b.y,cy=c.y,x0=Math.min(ax,bx,cx),y0=Math.min(ay,by,cy),x1=Math.max(ax,bx,cx),y1=Math.max(ay,by,cy);let p=c.next;for(;p!==a;){if(p.x>=x0&&p.x<=x1&&p.y>=y0&&p.y<=y1&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.next}return!0}function isEarHashed(ear,minX,minY,invSize){const a=ear.prev,b=ear,c=ear.next;if(area(a,b,c)>=0)return!1;const ax=a.x,bx=b.x,cx=c.x,ay=a.y,by=b.y,cy=c.y,x0=Math.min(ax,bx,cx),y0=Math.min(ay,by,cy),x1=Math.max(ax,bx,cx),y1=Math.max(ay,by,cy),minZ=zOrder(x0,y0,minX,minY,invSize),maxZ=zOrder(x1,y1,minX,minY,invSize);let p=ear.prevZ,n=ear.nextZ;for(;p&&p.z>=minZ&&n&&n.z<=maxZ;){if(p.x>=x0&&p.x<=x1&&p.y>=y0&&p.y<=y1&&p!==a&&p!==c&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;if(p=p.prevZ,n.x>=x0&&n.x<=x1&&n.y>=y0&&n.y<=y1&&n!==a&&n!==c&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}for(;p&&p.z>=minZ;){if(p.x>=x0&&p.x<=x1&&p.y>=y0&&p.y<=y1&&p!==a&&p!==c&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,p.x,p.y)&&area(p.prev,p,p.next)>=0)return!1;p=p.prevZ}for(;n&&n.z<=maxZ;){if(n.x>=x0&&n.x<=x1&&n.y>=y0&&n.y<=y1&&n!==a&&n!==c&&pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,n.x,n.y)&&area(n.prev,n,n.next)>=0)return!1;n=n.nextZ}return!0}function cureLocalIntersections(start,triangles){let p=start;do{const a=p.prev,b=p.next.next;!equals(a,b)&&intersects(a,p,p.next,b)&&locallyInside(a,b)&&locallyInside(b,a)&&(triangles.push(a.i,p.i,b.i),removeNode(p),removeNode(p.next),p=start=b),p=p.next}while(p!==start);return filterPoints(p)}function splitEarcut(start,triangles,dim,minX,minY,invSize){let a=start;do{let b=a.next.next;for(;b!==a.prev;){if(a.i!==b.i&&isValidDiagonal(a,b)){let c=splitPolygon(a,b);return a=filterPoints(a,a.next),c=filterPoints(c,c.next),earcutLinked(a,triangles,dim,minX,minY,invSize,0),void earcutLinked(c,triangles,dim,minX,minY,invSize,0)}b=b.next}a=a.next}while(a!==start)}function compareXYSlope(a,b){let result=a.x-b.x;if(0===result&&(result=a.y-b.y,0===result)){result=(a.next.y-a.y)/(a.next.x-a.x)-(b.next.y-b.y)/(b.next.x-b.x)}return result}function eliminateHole(hole,outerNode){const bridge=function findHoleBridge(hole,outerNode){let p=outerNode;const hx=hole.x,hy=hole.y;let m,qx=-1/0;if(equals(hole,p))return p;do{if(equals(hole,p.next))return p.next;if(hy<=p.y&&hy>=p.next.y&&p.next.y!==p.y){const x=p.x+(hy-p.y)*(p.next.x-p.x)/(p.next.y-p.y);if(x<=hx&&x>qx&&(qx=x,m=p.x<p.next.x?p:p.next,x===hx))return m}p=p.next}while(p!==outerNode);if(!m)return null;const stop=m,mx=m.x,my=m.y;let tanMin=1/0;p=m;do{if(hx>=p.x&&p.x>=mx&&hx!==p.x&&pointInTriangle(hy<my?hx:qx,hy,mx,my,hy<my?qx:hx,hy,p.x,p.y)){const tan=Math.abs(hy-p.y)/(hx-p.x);locallyInside(p,hole)&&(tan<tanMin||tan===tanMin&&(p.x>m.x||p.x===m.x&&sectorContainsSector(m,p)))&&(m=p,tanMin=tan)}p=p.next}while(p!==stop);return m}(hole,outerNode);if(!bridge)return outerNode;const bridgeReverse=splitPolygon(bridge,hole);return filterPoints(bridgeReverse,bridgeReverse.next),filterPoints(bridge,bridge.next)}function sectorContainsSector(m,p){return area(m.prev,m,p.prev)<0&&area(p.next,m,m.next)<0}function zOrder(x,y,minX,minY,invSize){return(x=1431655765&((x=858993459&((x=252645135&((x=16711935&((x=(x-minX)*invSize|0)|x<<8))|x<<4))|x<<2))|x<<1))|(y=1431655765&((y=858993459&((y=252645135&((y=16711935&((y=(y-minY)*invSize|0)|y<<8))|y<<4))|y<<2))|y<<1))<<1}function getLeftmost(start){let p=start,leftmost=start;do{(p.x<leftmost.x||p.x===leftmost.x&&p.y<leftmost.y)&&(leftmost=p),p=p.next}while(p!==start);return leftmost}function pointInTriangle(ax,ay,bx,by,cx,cy,px,py){return(cx-px)*(ay-py)>=(ax-px)*(cy-py)&&(ax-px)*(by-py)>=(bx-px)*(ay-py)&&(bx-px)*(cy-py)>=(cx-px)*(by-py)}function pointInTriangleExceptFirst(ax,ay,bx,by,cx,cy,px,py){return!(ax===px&&ay===py)&&pointInTriangle(ax,ay,bx,by,cx,cy,px,py)}function isValidDiagonal(a,b){return a.next.i!==b.i&&a.prev.i!==b.i&&!function intersectsPolygon(a,b){let p=a;do{if(p.i!==a.i&&p.next.i!==a.i&&p.i!==b.i&&p.next.i!==b.i&&intersects(p,p.next,a,b))return!0;p=p.next}while(p!==a);return!1}(a,b)&&(locallyInside(a,b)&&locallyInside(b,a)&&function middleInside(a,b){let p=a,inside=!1;const px=(a.x+b.x)/2,py=(a.y+b.y)/2;do{p.y>py!=p.next.y>py&&p.next.y!==p.y&&px<(p.next.x-p.x)*(py-p.y)/(p.next.y-p.y)+p.x&&(inside=!inside),p=p.next}while(p!==a);return inside}(a,b)&&(area(a.prev,a,b.prev)||area(a,b.prev,b))||equals(a,b)&&area(a.prev,a,a.next)>0&&area(b.prev,b,b.next)>0)}function area(p,q,r){return(q.y-p.y)*(r.x-q.x)-(q.x-p.x)*(r.y-q.y)}function equals(p1,p2){return p1.x===p2.x&&p1.y===p2.y}function intersects(p1,q1,p2,q2){const o1=sign(area(p1,q1,p2)),o2=sign(area(p1,q1,q2)),o3=sign(area(p2,q2,p1)),o4=sign(area(p2,q2,q1));return o1!==o2&&o3!==o4||(!(0!==o1||!onSegment(p1,p2,q1))||(!(0!==o2||!onSegment(p1,q2,q1))||(!(0!==o3||!onSegment(p2,p1,q2))||!(0!==o4||!onSegment(p2,q1,q2)))))}function onSegment(p,q,r){return q.x<=Math.max(p.x,r.x)&&q.x>=Math.min(p.x,r.x)&&q.y<=Math.max(p.y,r.y)&&q.y>=Math.min(p.y,r.y)}function sign(num){return num>0?1:num<0?-1:0}function locallyInside(a,b){return area(a.prev,a,a.next)<0?area(a,b,a.next)>=0&&area(a,a.prev,b)>=0:area(a,b,a.prev)<0||area(a,a.next,b)<0}function splitPolygon(a,b){const a2=createNode(a.i,a.x,a.y),b2=createNode(b.i,b.x,b.y),an=a.next,bp=b.prev;return a.next=b,b.prev=a,a2.next=an,an.prev=a2,b2.next=a2,a2.prev=b2,bp.next=b2,b2.prev=bp,b2}function insertNode(i,x,y,last){const p=createNode(i,x,y);return last?(p.next=last.next,p.prev=last,last.next.prev=p,last.next=p):(p.prev=p,p.next=p),p}function removeNode(p){p.next.prev=p.prev,p.prev.next=p.next,p.prevZ&&(p.prevZ.nextZ=p.nextZ),p.nextZ&&(p.nextZ.prevZ=p.prevZ)}function createNode(i,x,y){return{i:i,x:x,y:y,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function unifyVertices(vertices,uvs,indices){const vertMap=new Map,verticesOut=[],uvsOut=[],indicesOut=[];for(let i=0;i<indices.length;i++){const idx=indices[i],vx=vertices[3*idx+0],vy=vertices[3*idx+1],vz=vertices[3*idx+2],ux=uvs[2*idx+0],uy=uvs[2*idx+1],key=`${vx},${vy},${vz}|${ux},${uy}`;if(vertMap.has(key))indicesOut.push(vertMap.get(key));else{const newIndex=verticesOut.length/3;vertMap.set(key,newIndex),verticesOut.push(vx,vy,vz),uvsOut.push(ux,uy),indicesOut.push(newIndex)}}return{vertices:verticesOut,uvs:uvsOut,indices:indicesOut}}function infoestrudi(shape,hshape,pts,options,sh){options||(options={}),pts||(pts=[]);let p0=options.p0||0,coeffbase1=Math.tan(options.coeffbase1*PIF||0),coeffbase2=Math.tan(options.coeffbase2*PIF||0),p1=hshape||options.p1||20,coefftop1=Math.tan(options.coefftop1*PIF||0),coefftop2=Math.tan(options.coefftop2*PIF||0),{mi:mi,ma:ma}=shape.pt.reduce(((t,e)=>(t.mi.x=Math.min(t.mi.x,e.x),t.mi.y=Math.min(t.mi.y,e.y),t.ma.x=Math.max(t.ma.x,e.x),t.ma.y=Math.max(t.ma.y,e.y),t)),{mi:{x:1e9,y:1e9},ma:{x:-1e9,y:-1e9}}),lmax=0,lmin=1e9;function getpars(p){p.z1=getzeta(p.x,p.y,p0,coeffbase1,coeffbase2,sh),p.z2=getzeta(p.x,p.y,p1,coefftop1,coefftop2,sh),p.l=Math.abs(p.z2-p.z1)}for(let p of pts)getpars(p);getpars(mi),getpars(ma);let rect=[{x:mi.x,y:mi.y},{x:ma.x,y:mi.y},{x:ma.x,y:ma.y},{x:mi.x,y:ma.y}];for(let r of rect)getpars(r),r.l>lmax&&(lmax=r.l),r.l<lmin&&(lmin=r.l);return{aini:options.coeffbase1||0,aini2:options.coeffbase2||0,afin:options.coefftop1||0,afin2:options.coefftop2||0,pts:pts,mi:mi,ma:ma,rect:rect,dimx:ma.x-mi.x,dimy:ma.y-mi.y,lnom:p1-p0,lmax:lmax,lmin:lmin,lmed:(lmax+lmin)/2}}function getzeta(x,y,zbase,cx,cy,sh,invert=!1){let z=x*cx+y*cy+zbase;if(sh){let t=sh.xfromy(-y,0,!0);invert?z-=t:z=t}return z}function sidegeomfromshapes(gcad,ky,s1,s2,invert=!1,stonda=!1,fuvswap=!1){if(s1&&s2){if(s1.length!==s2.length)throw new Error("shapes with different length");if(s1.length<2)throw new Error("I percorsi devono contenere almeno due punti ciascuno.");if(!gcad.geo[ky]){const vertices=[],uvs=[],indices=[],np=s1.length,addpts=ss=>{for(const s of ss)vertices.push(s.x,s.y,s.z),fuvswap?uvs.push(s.v,s.u):uvs.push(s.u,s.v)},equalpos=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y&&p1.z===p2.z,addindexquad=(i1,i2,i3,i4)=>{invert?indices.push(i1,i3,i2,i3,i4,i2):indices.push(i1,i2,i3,i3,i2,i4)};addpts(s1),addpts(s2);for(let i=0;i<np-1;i++){const j=i+1;equalpos(s1[i],s1[j])||addindexquad(i,j,i+np,j+np)}const geometry=new THREE.BufferGeometry;if(stonda){let tm=unifyVertices(vertices,uvs,indices);geometry.setAttribute("position",new THREE.Float32BufferAttribute(tm.vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(tm.uvs,2)),geometry.setIndex(tm.indices)}else geometry.setAttribute("position",new THREE.Float32BufferAttribute(vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(uvs,2)),geometry.setIndex(indices);geometry.computeVertexNormals(),gcad.geo[ky]=geometry}return gcad.geo[ky]}}function bottomgeomfromshape(gcad,inverti,outer,holes,c=0,a=0,b=0,shape=null,stonda=!1,fuvswap=!1){let ky=`bg:${c}|${a}${b}|${outer.key}|${inverti}|${shape?.key||""}|${fuvswap?1:0}`;for(let h of holes)ky=`${ky}|${h.key}`;if(ky=hash(ky),!gcad.geo[ky]){let triangles,pos=[],hl=[],cc=outer.pt.length;pos=outer.vec;const geometry=new THREE.BufferGeometry,vertices=[],uvs=[],indices=[];function addvertexes(triangles,pos){let i0=vertices.length/3;for(let i=0;i<triangles.length;i++){const index=triangles[i],x=pos[2*index],y=-pos[2*index+1],z=getzeta(x,y,c,a,b,shape,inverti);vertices.push(x,y,z),fuvswap?uvs.push(x,y):uvs.push(y,x)}for(let i=0;i<triangles.length;i+=3)inverti?indices.push(i+i0,i+i0+2,i+i0+1):indices.push(i+i0,i+i0+1,i+i0+2)}if(shape){let cl2=outer.sliceony(shape);for(let c of cl2){let x=c.flatMap((p=>[p.x,p.y]));addvertexes(earcut(x,[]),x)}}else if(Array.isArray(holes)&&holes.length){for(let h of holes)hl.push(cc),cc+=h.pt.length,pos=[...pos,...h.vec];triangles=earcut(pos,hl),addvertexes(triangles,pos)}else triangles=earcut(pos),addvertexes(triangles,pos);if(stonda){let tm=unifyVertices(vertices,uvs,indices);geometry.setAttribute("position",new THREE.Float32BufferAttribute(tm.vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(tm.uvs,2)),geometry.setIndex(tm.indices)}else geometry.setAttribute("position",new THREE.Float32BufferAttribute(vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(uvs,2)),geometry.setIndex(indices);geometry.computeVertexNormals(),gcad.geo[ky]=geometry}return gcad.geo[ky]}function estrusorotate(orientamento,mesh,z=0){switch(orientamento.trim().toUpperCase().slice(0,1)){case"A":mesh.rotation.x=-Math.PI/2;break;case"L":mesh.rotation.y=Math.PI/2,mesh.rotation.z=Math.PI;break;case"P":mesh.rotation.z=Math.PI/2}return mesh}
645
645
  /**
646
646
  * Crea una geometria estrusa con opzioni avanzate
647
647
  * @param {string} orient - Orientamento dell'estrusione
@@ -651,7 +651,7 @@ function toTrianglesDrawMode(geometry,drawMode){if(drawMode===TrianglesDrawMode)
651
651
  * @param {Array} mats - Array di materiali
652
652
  * @param {Object} options - Opzioni di configurazione
653
653
  * @returns {THREE.Group} Gruppo contenente la geometria estrusa
654
- */function estruso(gcad,orient,hshape,shape,holes,mats,options){options||(options={}),mats||(mats=[]),Array.isArray(mats)||(mats=[mats,mats,mats]);let p0=options.p0||0,coeffbase1=Math.tan(options.coeffbase1*PIF||0),coeffbase2=Math.tan(options.coeffbase2*PIF||0),p1=hshape||options.p1||20,coefftop1=Math.tan(options.coefftop1*PIF||0),coefftop2=Math.tan(options.coefftop2*PIF||0),shapetop=options.shapetop,shapebase=options.shapebase||options.shapebottom;shapetop&&(coefftop2=0),shapebase&&(coefftop2=0);let shb=shapebase?shapebase.key:"",sht=shapetop?shapetop.key:"",notopholes=options.notopholes||!1,nobottomholes=options.nobottomholes||options.nobaseholes||!1,opinvert=options.invert||!1,open=options.open||!1,grp=new THREE.Group;if(shape){if(!options.nobase){let h1=holes;nobottomholes&&(h1=Array.isArray(nobottomholes)?h1.filter(((_,i)=>!nobottomholes[i])):[]);let g1=bottomgeomfromshape(gcad,!1,shape,open?[]:h1,p0,coeffbase1,coeffbase2,shapebase);options.nolines||grp.add(edgesfromgeometry(g1)),grp.add(getmesh(g1,mats[0]||mwhite))}if(!options.notop){let h1=holes;notopholes&&(h1=Array.isArray(notopholes)?h1.filter(((_,i)=>!notopholes[i])):[]);let g3=bottomgeomfromshape(gcad,!0,shape,open?[]:h1,p1,coefftop1,coefftop2,shapetop);grp.add(getmesh(g3,mats[1]||mats[0]||mwhite)),options.nolines||grp.add(edgesfromgeometry(g3))}if(!options.nosides){let pat1=shape.to3d(0,p0,coeffbase1,-coeffbase2,open,shapebase,!opinvert),pat2=shape.to3d(1,p1,coefftop1,-coefftop2,open,shapetop,opinvert),ky=`${shape.key}${opinvert?1:0}|${p0}|${p1}|${coeffbase1}|${coeffbase2||shb}|${coefftop1}|${coefftop2||sht}|${open}`,geo1=sidegeomfromshapes(gcad,ky,pat1,pat2,!1);if(options.nolines||options.nosidelines||grp.add(edgesfromgeometry(geo1)),grp.add(getmesh(geo1,mats[2]||mats[0]||mwhite)),holes&&!open)for(let i=0;i<holes.length;i++){let h=holes[i];if(Array.isArray(notopholes)){if(notopholes[i])continue}else if(notopholes)continue;if(Array.isArray(nobottomholes)){if(nobottomholes[i])continue}else if(nobottomholes)continue;pat1=h.to3d(0,p0,coeffbase1,coeffbase2),pat2=h.to3d(0,p1,coefftop1,coefftop2),ky=`${h.key}|${p0}|${p1}|${coeffbase1}|${coeffbase2}|${coefftop1}|${coefftop2}`;let geo2=sidegeomfromshapes(gcad,ky,pat1,pat2,!0);options.nolines||options.nosidelines||grp.add(edgesfromgeometry(geo2)),grp.add(getmesh(geo2,mats[3]||mats[0]||mwhite))}}return estrusorotate(orient,grp,hshape)}return grp}function revolve(gcad,shape,orient,mat,options){options||(options={});let segmenti=options.segmenti??12,ky=hash(`rev|${shape.key}|${orient}|${segmenti}`),geometria=gcad.geo[ky],grp=new THREE.Group;if(!geometria){const punti3D=shape.pt.map((p=>new THREE.Vector3(p.x,p.y,0)));geometria=new THREE.LatheGeometry(punti3D,segmenti,0,2*Math.PI),gcad.geo[ky]=geometria}const mesh=new THREE.Mesh(geometria,mat);return grp.add(mesh),options.nolines||options.nosidelines||grp.add(edgesfromgeometry(geometria)),grp}function estrusopat(gcad,orient,pat,plink,shape,mats,options){options||(options={});let invert=options.invert;mats||(mats=[]);let open=options.open,closepat=options.closepat;if(!pat.pt?.length)return;let pbase=shape.to3d(0,0,0,0,open),grp=new THREE.Group;if(!options.nobase&&!options.open&&!closepat){let gb=new THREE.Group,angolo=angle3point(plink[0],pat.pt[0],pat.pt[1])+Math.PI/2,g1=bottomgeomfromshape(gcad,!1,shape,[],0,-Math.tan(angolo));gb.add(getmesh(g1,mats[0]||mwhite)),gb.add(edgesfromgeometry(g1));let seg1=pat.infosegmento(0,!0);grp.add(posiziona(gb,{sl:seg1.x,sp:seg1.y,sa:0,ay:90-seg1.ang}))}if(!options.notop&&!options.open&&!closepat){let gt=new THREE.Group,angolo=-(angle3point(pat.pt[pat.npt-2],pat.pt[pat.npt-1],plink[pat.npt-1])+Math.PI/2),g2=bottomgeomfromshape(gcad,!0,shape,[],0,-Math.tan(angolo),0);gt.add(getmesh(g2,mats[1]||mats[0]||mwhite)),gt.add(edgesfromgeometry(g2));let seg1=pat.infosegmento(pat.pt.length-1,!0);grp.add(posiziona(gt,{sl:seg1.x,sp:seg1.y,sa:0,ay:90-seg1.ang}))}const geo1=function sidegeomfrompat(gcad,pbase,pat,plink,closepat,invert){let ky=`bsg:${pbase.key}|${pat.key}|${closepat}|${invert}`;if(pat.npt==plink.length){if(ky=hash(ky),!gcad.geo[ky]){const vertices=[],uvs=[],indices=[],np=pbase.length,equalpos=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y&&p1.z===p2.z;let l0=0,pt=pat.pt,ptl=pat.npt;const addpts=(ss,mat,deltav,coeffz)=>{for(const s of ss){let p=new THREE.Vector3(s.x,s.y,s.x*coeffz);p.applyMatrix4(mat),vertices.push(p.x,p.y,p.z),uvs.push(s.u,s.v+deltav)}};let lp=ptl;for(let ii=0;ii<ptl;ii++){let angolo;angolo=ii<ptl-1?angle3point(plink[ii],pt[ii],pt[ii+1])+Math.PI/2:-(angle3point(pt[ii-1],pt[ii],plink[ii])+Math.PI/2);let coefficente=-Math.tan(angolo),seg1=pat.infosegmento(ii,!0),obj=new THREE.Object3D;obj.position.set(seg1.x,0,seg1.y),obj.rotation.set(0,(90-seg1.ang)*PIF,0),obj.updateMatrix(),addpts(pbase,obj.matrix,l0,coefficente),l0+=seg1.l}if(closepat){let seg1=pat.infosegmento(0,!0),obj=new THREE.Object3D;obj.position.set(seg1.x,0,seg1.y),obj.rotation.set(0,(90-seg1.ang)*PIF,0);let angolo=angle3point(pt[ptl-1],pt[0],plink[0])+Math.PI/2,coefficente=-Math.tan(angolo);obj.updateMatrix(),addpts(pbase,obj.matrix,l0,coefficente),l0+=seg1.l,lp++}for(let li=0;li<lp-1;li++)for(let i=0;i<np-1;i++){const addindexquad=(i1,i2,i3,i4)=>{invert?indices.push(i1,i3,i2,i3,i4,i2):indices.push(i1,i2,i3,i3,i2,i4)},j=i+1;equalpos(pbase[i],pbase[j])||addindexquad(i+li*np,j+li*np,i+(li+1)*np,j+(li+1)*np)}const geometry=new THREE.BufferGeometry;geometry.setAttribute("position",new THREE.Float32BufferAttribute(vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(uvs,2)),geometry.setIndex(indices),geometry.computeVertexNormals(),gcad[ky]=geometry}return gcad[ky]}}(gcad,pbase,pat,plink,closepat?1:0,invert?1:0);return geo1&&(options.nolines||options.nosidelines||grp.add(edgesfromgeometry(geo1)),grp.add(getmesh(geo1,mats[2]||mats[0]||mwhite))),estrusorotate(orient,grp,0)}async function spritemat(gcad,file){try{let tm={transparent:!0,depthTest:!1,depthWrite:!1,fog:!1,toneMapped:!1};if(file.startsWith("#"))tm.color=file;else{let tx=await gcad.tex(file,1e3,1e3);tx?tm.map=tx:tm.color="black"}return new THREE.SpriteMaterial(tm)}catch(error){return mwhite}}function getsprite0(ispunto,x,y,z,mat,options={}){options||(options={});let{size:size=50,pick:pick=!1,screen:screen=!1,sizex:sizex,sizey:sizey}=options;const sprite=new THREE.Sprite(mat);sprite.position.set(0,0,0),sprite.userData.issprite=!0,sprite.userData.ispunto=ispunto,sprite.userData.ispick=pick,sprite.userData.isScreen=screen,sprite.renderOrder=999,sprite.layers.set(29),sprite.name=ispunto?"_punto":"_sprite";let gr=new THREE.Group;return gr.position.set(x,y,z),gr.scale.set(sizex||size,sizey||sizex||size,1),gr.add(sprite),gr.traverse((obj=>{obj.material&&(obj.material.depthTest=!1,obj.material.depthWrite=!1)})),gr.renderOrder=999,gr}async function getpunto(gcad,x,y,z,color="yellow",options){options||(options={size:20}),options.screen=!0;const texture=await function createCircleTexture(gcad,size=64,color="rgba(255,0,0,1)"){const ky=`ct|${size}|${color}`;if(!gcad.textures[ky]){const canvas=document.createElement("canvas");canvas.width=canvas.height=size;const ctx=canvas.getContext("2d"),radius=size/2;ctx.clearRect(0,0,size,size),ctx.fillStyle=color,ctx.beginPath(),ctx.arc(radius,radius,radius,0,2*Math.PI),ctx.fill();const texture=new THREE.CanvasTexture(canvas);texture.needsUpdate=!0,gcad.textures[ky]=texture}return gcad.textures[ky]}(gcad,64,color);return getsprite0(!0,x,y,z,new THREE.SpriteMaterial({map:texture,transparent:!0,fog:!1,toneMapped:!1}),options)}function getsprite(gcad,x,y,z,mat,options={}){return getsprite0(!1,x,y,z,mat,options)}class GLTFLoader extends Loader{constructor(manager){super(manager),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register((function(parser){return new GLTFMaterialsClearcoatExtension(parser)})),this.register((function(parser){return new GLTFMaterialsDispersionExtension(parser)})),this.register((function(parser){return new GLTFTextureBasisUExtension(parser)})),this.register((function(parser){return new GLTFTextureWebPExtension(parser)})),this.register((function(parser){return new GLTFTextureAVIFExtension(parser)})),this.register((function(parser){return new GLTFMaterialsSheenExtension(parser)})),this.register((function(parser){return new GLTFMaterialsTransmissionExtension(parser)})),this.register((function(parser){return new GLTFMaterialsVolumeExtension(parser)})),this.register((function(parser){return new GLTFMaterialsIorExtension(parser)})),this.register((function(parser){return new GLTFMaterialsEmissiveStrengthExtension(parser)})),this.register((function(parser){return new GLTFMaterialsSpecularExtension(parser)})),this.register((function(parser){return new GLTFMaterialsIridescenceExtension(parser)})),this.register((function(parser){return new GLTFMaterialsAnisotropyExtension(parser)})),this.register((function(parser){return new GLTFMaterialsBumpExtension(parser)})),this.register((function(parser){return new GLTFLightsExtension(parser)})),this.register((function(parser){return new GLTFMeshoptCompression(parser)})),this.register((function(parser){return new GLTFMeshGpuInstancing(parser)}))}load(url,onLoad,onProgress,onError){const scope=this;let resourcePath;if(""!==this.resourcePath)resourcePath=this.resourcePath;else if(""!==this.path){const relativeUrl=LoaderUtils.extractUrlBase(url);resourcePath=LoaderUtils.resolveURL(relativeUrl,this.path)}else resourcePath=LoaderUtils.extractUrlBase(url);this.manager.itemStart(url);const _onError=function(e){onError?onError(e):console.error(e),scope.manager.itemError(url),scope.manager.itemEnd(url)},loader=new FileLoader(this.manager);loader.setPath(this.path),loader.setResponseType("arraybuffer"),loader.setRequestHeader(this.requestHeader),loader.setWithCredentials(this.withCredentials),loader.load(url,(function(data){try{scope.parse(data,resourcePath,(function(gltf){onLoad(gltf),scope.manager.itemEnd(url)}),_onError)}catch(e){_onError(e)}}),onProgress,_onError)}setDRACOLoader(dracoLoader){return this.dracoLoader=dracoLoader,this}setDDSLoader(){throw new Error('THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".')}setKTX2Loader(ktx2Loader){return this.ktx2Loader=ktx2Loader,this}setMeshoptDecoder(meshoptDecoder){return this.meshoptDecoder=meshoptDecoder,this}register(callback){return-1===this.pluginCallbacks.indexOf(callback)&&this.pluginCallbacks.push(callback),this}unregister(callback){return-1!==this.pluginCallbacks.indexOf(callback)&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(callback),1),this}parse(data,path,onLoad,onError){let json;const extensions={},plugins={},textDecoder=new TextDecoder;if("string"==typeof data)json=JSON.parse(data);else if(data instanceof ArrayBuffer){if(textDecoder.decode(new Uint8Array(data,0,4))===BINARY_EXTENSION_HEADER_MAGIC){try{extensions[EXTENSIONS.KHR_BINARY_GLTF]=new GLTFBinaryExtension(data)}catch(error){return void(onError&&onError(error))}json=JSON.parse(extensions[EXTENSIONS.KHR_BINARY_GLTF].content)}else json=JSON.parse(textDecoder.decode(data))}else json=data;if(void 0===json.asset||json.asset.version[0]<2)return void(onError&&onError(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.")));const parser=new GLTFParser(json,{path:path||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});parser.fileLoader.setRequestHeader(this.requestHeader);for(let i=0;i<this.pluginCallbacks.length;i++){const plugin=this.pluginCallbacks[i](parser);plugin.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),plugins[plugin.name]=plugin,extensions[plugin.name]=!0}if(json.extensionsUsed)for(let i=0;i<json.extensionsUsed.length;++i){const extensionName=json.extensionsUsed[i],extensionsRequired=json.extensionsRequired||[];switch(extensionName){case EXTENSIONS.KHR_MATERIALS_UNLIT:extensions[extensionName]=new GLTFMaterialsUnlitExtension;break;case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:extensions[extensionName]=new GLTFDracoMeshCompressionExtension(json,this.dracoLoader);break;case EXTENSIONS.KHR_TEXTURE_TRANSFORM:extensions[extensionName]=new GLTFTextureTransformExtension;break;case EXTENSIONS.KHR_MESH_QUANTIZATION:extensions[extensionName]=new GLTFMeshQuantizationExtension;break;default:extensionsRequired.indexOf(extensionName)>=0&&void 0===plugins[extensionName]&&console.warn('THREE.GLTFLoader: Unknown extension "'+extensionName+'".')}}parser.setExtensions(extensions),parser.setPlugins(plugins),parser.parse(onLoad,onError)}parseAsync(data,path){const scope=this;return new Promise((function(resolve,reject){scope.parse(data,path,resolve,reject)}))}}function GLTFRegistry(){let objects={};return{get:function(key){return objects[key]},add:function(key,object){objects[key]=object},remove:function(key){delete objects[key]},removeAll:function(){objects={}}}}
654
+ */function estruso(gcad,orient,hshape,shape,holes,mats,options){options||(options={}),mats||(mats=[]),Array.isArray(mats)||(mats=[mats,mats,mats]);let p0=options.p0||0,coeffbase1=Math.tan(options.coeffbase1*PIF||0),coeffbase2=Math.tan(options.coeffbase2*PIF||0),p1=hshape||options.p1||20,coefftop1=Math.tan(options.coefftop1*PIF||0),coefftop2=Math.tan(options.coefftop2*PIF||0),shapetop=options.shapetop,shapebase=options.shapebase||options.shapebottom;shapetop&&(coefftop2=0),shapebase&&(coefftop2=0);let shb=shapebase?shapebase.key:"",sht=shapetop?shapetop.key:"",notopholes=options.notopholes||!1,nobottomholes=options.nobottomholes||options.nobaseholes||!1,opinvert=options.invert||!1,open=options.open||!1,grp=new THREE.Group;if(shape){if(!options.nobase){let h1=holes;nobottomholes&&(h1=Array.isArray(nobottomholes)?h1.filter(((_,i)=>!nobottomholes[i])):[]);let g1=bottomgeomfromshape(gcad,!1,shape,open?[]:h1,p0,coeffbase1,coeffbase2,shapebase,!1,options.uvswap);options.nolines||grp.add(edgesfromgeometry(g1)),grp.add(getmesh(g1,mats[0]||mwhite))}if(!options.notop){let h1=holes;notopholes&&(h1=Array.isArray(notopholes)?h1.filter(((_,i)=>!notopholes[i])):[]);let g3=bottomgeomfromshape(gcad,!0,shape,open?[]:h1,p1,coefftop1,coefftop2,shapetop,!1,options.uvswap);grp.add(getmesh(g3,mats[1]||mats[0]||mwhite)),options.nolines||grp.add(edgesfromgeometry(g3))}if(!options.nosides){let pat1=shape.to3d(0,p0,coeffbase1,-coeffbase2,open,shapebase,!opinvert),pat2=shape.to3d(1,p1,coefftop1,-coefftop2,open,shapetop,opinvert),ky=`${shape.key}${opinvert?1:0}|${p0}|${p1}|${coeffbase1}|${coeffbase2||shb}|${coefftop1}|${coefftop2||sht}|${open}|${options.wvswap?1:0}`,geo1=sidegeomfromshapes(gcad,ky,pat1,pat2,!1,!1,options.uvswap);if(options.nolines||options.nosidelines||grp.add(edgesfromgeometry(geo1)),grp.add(getmesh(geo1,mats[2]||mats[0]||mwhite)),holes&&!open)for(let i=0;i<holes.length;i++){let h=holes[i];if(Array.isArray(notopholes)){if(notopholes[i])continue}else if(notopholes)continue;if(Array.isArray(nobottomholes)){if(nobottomholes[i])continue}else if(nobottomholes)continue;pat1=h.to3d(0,p0,coeffbase1,coeffbase2),pat2=h.to3d(0,p1,coefftop1,coefftop2),ky=`${h.key}|${p0}|${p1}|${coeffbase1}|${coeffbase2}|${coefftop1}|${coefftop2}`;let geo2=sidegeomfromshapes(gcad,ky,pat1,pat2,!0);options.nolines||options.nosidelines||grp.add(edgesfromgeometry(geo2)),grp.add(getmesh(geo2,mats[3]||mats[0]||mwhite))}}return estrusorotate(orient,grp,hshape)}return grp}function revolve(gcad,shape,orient,mat,options){options||(options={});let segmenti=options.segmenti??12,ky=hash(`rev|${shape.key}|${orient}|${segmenti}`),geometria=gcad.geo[ky],grp=new THREE.Group;if(!geometria){const punti3D=shape.pt.map((p=>new THREE.Vector3(p.x,p.y,0)));geometria=new THREE.LatheGeometry(punti3D,segmenti,0,2*Math.PI),gcad.geo[ky]=geometria}options.uvswap&&uvswap(geometria);const mesh=new THREE.Mesh(geometria,mat);return grp.add(mesh),options.nolines||options.nosidelines||grp.add(edgesfromgeometry(geometria)),grp}function estrusopat(gcad,orient,pat,plink,shape,mats,options){options||(options={});let invert=options.invert;mats||(mats=[]);let open=options.open,closepat=options.closepat;if(!pat.pt?.length)return;let pbase=shape.to3d(0,0,0,0,open),grp=new THREE.Group;if(!options.nobase&&!options.open&&!closepat){let gb=new THREE.Group,angolo=angle3point(plink[0],pat.pt[0],pat.pt[1])+Math.PI/2,g1=bottomgeomfromshape(gcad,!1,shape,[],0,-Math.tan(angolo),0,null,!1,options.uvswap);gb.add(getmesh(g1,mats[0]||mwhite)),gb.add(edgesfromgeometry(g1));let seg1=pat.infosegmento(0,!0);grp.add(posiziona(gb,{sl:seg1.x,sp:seg1.y,sa:0,ay:90-seg1.ang}))}if(!options.notop&&!options.open&&!closepat){let gt=new THREE.Group,angolo=-(angle3point(pat.pt[pat.npt-2],pat.pt[pat.npt-1],plink[pat.npt-1])+Math.PI/2),g2=bottomgeomfromshape(gcad,!0,shape,[],0,-Math.tan(angolo),0,null,!1,options.uvswap);gt.add(getmesh(g2,mats[1]||mats[0]||mwhite)),gt.add(edgesfromgeometry(g2));let seg1=pat.infosegmento(pat.pt.length-1,!0);grp.add(posiziona(gt,{sl:seg1.x,sp:seg1.y,sa:0,ay:90-seg1.ang}))}const geo1=function sidegeomfrompat(gcad,pbase,pat,plink,closepat,invert){let ky=`bsg:${pbase.key}|${pat.key}|${closepat}|${invert}`;if(pat.npt==plink.length){if(ky=hash(ky),!gcad.geo[ky]){const vertices=[],uvs=[],indices=[],np=pbase.length,equalpos=(p1,p2)=>p1.x===p2.x&&p1.y===p2.y&&p1.z===p2.z;let l0=0,pt=pat.pt,ptl=pat.npt;const addpts=(ss,mat,deltav,coeffz)=>{for(const s of ss){let p=new THREE.Vector3(s.x,s.y,s.x*coeffz);p.applyMatrix4(mat),vertices.push(p.x,p.y,p.z),uvs.push(s.u,s.v+deltav)}};let lp=ptl;for(let ii=0;ii<ptl;ii++){let angolo;angolo=ii<ptl-1?angle3point(plink[ii],pt[ii],pt[ii+1])+Math.PI/2:-(angle3point(pt[ii-1],pt[ii],plink[ii])+Math.PI/2);let coefficente=-Math.tan(angolo),seg1=pat.infosegmento(ii,!0),obj=new THREE.Object3D;obj.position.set(seg1.x,0,seg1.y),obj.rotation.set(0,(90-seg1.ang)*PIF,0),obj.updateMatrix(),addpts(pbase,obj.matrix,l0,coefficente),l0+=seg1.l}if(closepat){let seg1=pat.infosegmento(0,!0),obj=new THREE.Object3D;obj.position.set(seg1.x,0,seg1.y),obj.rotation.set(0,(90-seg1.ang)*PIF,0);let angolo=angle3point(pt[ptl-1],pt[0],plink[0])+Math.PI/2,coefficente=-Math.tan(angolo);obj.updateMatrix(),addpts(pbase,obj.matrix,l0,coefficente),l0+=seg1.l,lp++}for(let li=0;li<lp-1;li++)for(let i=0;i<np-1;i++){const addindexquad=(i1,i2,i3,i4)=>{invert?indices.push(i1,i3,i2,i3,i4,i2):indices.push(i1,i2,i3,i3,i2,i4)},j=i+1;equalpos(pbase[i],pbase[j])||addindexquad(i+li*np,j+li*np,i+(li+1)*np,j+(li+1)*np)}const geometry=new THREE.BufferGeometry;geometry.setAttribute("position",new THREE.Float32BufferAttribute(vertices,3)),geometry.setAttribute("uv",new THREE.Float32BufferAttribute(uvs,2)),geometry.setIndex(indices),geometry.computeVertexNormals(),gcad[ky]=geometry}return gcad[ky]}}(gcad,pbase,pat,plink,closepat?1:0,invert?1:0,options.uvswap);return geo1&&(options.nolines||options.nosidelines||grp.add(edgesfromgeometry(geo1)),grp.add(getmesh(geo1,mats[2]||mats[0]||mwhite))),estrusorotate(orient,grp,0)}async function spritemat(gcad,file){try{let tm={transparent:!0,depthTest:!1,depthWrite:!1,fog:!1,toneMapped:!1};if(file.startsWith("#"))tm.color=file;else{let tx=await gcad.tex(file,1e3,1e3);tx?tm.map=tx:tm.color="black"}return new THREE.SpriteMaterial(tm)}catch(error){return mwhite}}function getsprite0(ispunto,x,y,z,mat,options={}){options||(options={});let{size:size=50,pick:pick=!1,screen:screen=!1,sizex:sizex,sizey:sizey}=options;const sprite=new THREE.Sprite(mat);sprite.position.set(0,0,0),sprite.userData.issprite=!0,sprite.userData.ispunto=ispunto,sprite.userData.ispick=pick,sprite.userData.isScreen=screen,sprite.renderOrder=999,sprite.layers.set(29),sprite.name=ispunto?"_punto":"_sprite";let gr=new THREE.Group;return gr.position.set(x,y,z),gr.scale.set(sizex||size,sizey||sizex||size,1),gr.add(sprite),gr.traverse((obj=>{obj.material&&(obj.material.depthTest=!1,obj.material.depthWrite=!1)})),gr.renderOrder=999,gr}async function getpunto(gcad,x,y,z,color="yellow",options){options||(options={size:20}),options.screen=!0;const texture=await function createCircleTexture(gcad,size=64,color="rgba(255,0,0,1)"){const ky=`ct|${size}|${color}`;if(!gcad.textures[ky]){const canvas=document.createElement("canvas");canvas.width=canvas.height=size;const ctx=canvas.getContext("2d"),radius=size/2;ctx.clearRect(0,0,size,size),ctx.fillStyle=color,ctx.beginPath(),ctx.arc(radius,radius,radius,0,2*Math.PI),ctx.fill();const texture=new THREE.CanvasTexture(canvas);texture.needsUpdate=!0,gcad.textures[ky]=texture}return gcad.textures[ky]}(gcad,64,color);return getsprite0(!0,x,y,z,new THREE.SpriteMaterial({map:texture,transparent:!0,fog:!1,toneMapped:!1}),options)}function getsprite(gcad,x,y,z,mat,options={}){return getsprite0(!1,x,y,z,mat,options)}class GLTFLoader extends Loader{constructor(manager){super(manager),this.dracoLoader=null,this.ktx2Loader=null,this.meshoptDecoder=null,this.pluginCallbacks=[],this.register((function(parser){return new GLTFMaterialsClearcoatExtension(parser)})),this.register((function(parser){return new GLTFMaterialsDispersionExtension(parser)})),this.register((function(parser){return new GLTFTextureBasisUExtension(parser)})),this.register((function(parser){return new GLTFTextureWebPExtension(parser)})),this.register((function(parser){return new GLTFTextureAVIFExtension(parser)})),this.register((function(parser){return new GLTFMaterialsSheenExtension(parser)})),this.register((function(parser){return new GLTFMaterialsTransmissionExtension(parser)})),this.register((function(parser){return new GLTFMaterialsVolumeExtension(parser)})),this.register((function(parser){return new GLTFMaterialsIorExtension(parser)})),this.register((function(parser){return new GLTFMaterialsEmissiveStrengthExtension(parser)})),this.register((function(parser){return new GLTFMaterialsSpecularExtension(parser)})),this.register((function(parser){return new GLTFMaterialsIridescenceExtension(parser)})),this.register((function(parser){return new GLTFMaterialsAnisotropyExtension(parser)})),this.register((function(parser){return new GLTFMaterialsBumpExtension(parser)})),this.register((function(parser){return new GLTFLightsExtension(parser)})),this.register((function(parser){return new GLTFMeshoptCompression(parser)})),this.register((function(parser){return new GLTFMeshGpuInstancing(parser)}))}load(url,onLoad,onProgress,onError){const scope=this;let resourcePath;if(""!==this.resourcePath)resourcePath=this.resourcePath;else if(""!==this.path){const relativeUrl=LoaderUtils.extractUrlBase(url);resourcePath=LoaderUtils.resolveURL(relativeUrl,this.path)}else resourcePath=LoaderUtils.extractUrlBase(url);this.manager.itemStart(url);const _onError=function(e){onError?onError(e):console.error(e),scope.manager.itemError(url),scope.manager.itemEnd(url)},loader=new FileLoader(this.manager);loader.setPath(this.path),loader.setResponseType("arraybuffer"),loader.setRequestHeader(this.requestHeader),loader.setWithCredentials(this.withCredentials),loader.load(url,(function(data){try{scope.parse(data,resourcePath,(function(gltf){onLoad(gltf),scope.manager.itemEnd(url)}),_onError)}catch(e){_onError(e)}}),onProgress,_onError)}setDRACOLoader(dracoLoader){return this.dracoLoader=dracoLoader,this}setDDSLoader(){throw new Error('THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".')}setKTX2Loader(ktx2Loader){return this.ktx2Loader=ktx2Loader,this}setMeshoptDecoder(meshoptDecoder){return this.meshoptDecoder=meshoptDecoder,this}register(callback){return-1===this.pluginCallbacks.indexOf(callback)&&this.pluginCallbacks.push(callback),this}unregister(callback){return-1!==this.pluginCallbacks.indexOf(callback)&&this.pluginCallbacks.splice(this.pluginCallbacks.indexOf(callback),1),this}parse(data,path,onLoad,onError){let json;const extensions={},plugins={},textDecoder=new TextDecoder;if("string"==typeof data)json=JSON.parse(data);else if(data instanceof ArrayBuffer){if(textDecoder.decode(new Uint8Array(data,0,4))===BINARY_EXTENSION_HEADER_MAGIC){try{extensions[EXTENSIONS.KHR_BINARY_GLTF]=new GLTFBinaryExtension(data)}catch(error){return void(onError&&onError(error))}json=JSON.parse(extensions[EXTENSIONS.KHR_BINARY_GLTF].content)}else json=JSON.parse(textDecoder.decode(data))}else json=data;if(void 0===json.asset||json.asset.version[0]<2)return void(onError&&onError(new Error("THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.")));const parser=new GLTFParser(json,{path:path||this.resourcePath||"",crossOrigin:this.crossOrigin,requestHeader:this.requestHeader,manager:this.manager,ktx2Loader:this.ktx2Loader,meshoptDecoder:this.meshoptDecoder});parser.fileLoader.setRequestHeader(this.requestHeader);for(let i=0;i<this.pluginCallbacks.length;i++){const plugin=this.pluginCallbacks[i](parser);plugin.name||console.error("THREE.GLTFLoader: Invalid plugin found: missing name"),plugins[plugin.name]=plugin,extensions[plugin.name]=!0}if(json.extensionsUsed)for(let i=0;i<json.extensionsUsed.length;++i){const extensionName=json.extensionsUsed[i],extensionsRequired=json.extensionsRequired||[];switch(extensionName){case EXTENSIONS.KHR_MATERIALS_UNLIT:extensions[extensionName]=new GLTFMaterialsUnlitExtension;break;case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:extensions[extensionName]=new GLTFDracoMeshCompressionExtension(json,this.dracoLoader);break;case EXTENSIONS.KHR_TEXTURE_TRANSFORM:extensions[extensionName]=new GLTFTextureTransformExtension;break;case EXTENSIONS.KHR_MESH_QUANTIZATION:extensions[extensionName]=new GLTFMeshQuantizationExtension;break;default:extensionsRequired.indexOf(extensionName)>=0&&void 0===plugins[extensionName]&&console.warn('THREE.GLTFLoader: Unknown extension "'+extensionName+'".')}}parser.setExtensions(extensions),parser.setPlugins(plugins),parser.parse(onLoad,onError)}parseAsync(data,path){const scope=this;return new Promise((function(resolve,reject){scope.parse(data,path,resolve,reject)}))}}function GLTFRegistry(){let objects={};return{get:function(key){return objects[key]},add:function(key,object){objects[key]=object},remove:function(key){delete objects[key]},removeAll:function(){objects={}}}}
655
655
  /*********************************/
656
656
  /********** EXTENSIONS ***********/
657
657
  /*********************************/const EXTENSIONS={KHR_BINARY_GLTF:"KHR_binary_glTF",KHR_DRACO_MESH_COMPRESSION:"KHR_draco_mesh_compression",KHR_LIGHTS_PUNCTUAL:"KHR_lights_punctual",KHR_MATERIALS_CLEARCOAT:"KHR_materials_clearcoat",KHR_MATERIALS_DISPERSION:"KHR_materials_dispersion",KHR_MATERIALS_IOR:"KHR_materials_ior",KHR_MATERIALS_SHEEN:"KHR_materials_sheen",KHR_MATERIALS_SPECULAR:"KHR_materials_specular",KHR_MATERIALS_TRANSMISSION:"KHR_materials_transmission",KHR_MATERIALS_IRIDESCENCE:"KHR_materials_iridescence",KHR_MATERIALS_ANISOTROPY:"KHR_materials_anisotropy",KHR_MATERIALS_UNLIT:"KHR_materials_unlit",KHR_MATERIALS_VOLUME:"KHR_materials_volume",KHR_TEXTURE_BASISU:"KHR_texture_basisu",KHR_TEXTURE_TRANSFORM:"KHR_texture_transform",KHR_MESH_QUANTIZATION:"KHR_mesh_quantization",KHR_MATERIALS_EMISSIVE_STRENGTH:"KHR_materials_emissive_strength",EXT_MATERIALS_BUMP:"EXT_materials_bump",EXT_TEXTURE_WEBP:"EXT_texture_webp",EXT_TEXTURE_AVIF:"EXT_texture_avif",EXT_MESHOPT_COMPRESSION:"EXT_meshopt_compression",EXT_MESH_GPU_INSTANCING:"EXT_mesh_gpu_instancing"};
@@ -1095,7 +1095,7 @@ constructor(data,position,debugMessage){this.data=data,this.offset=position,this
1095
1095
  /**
1096
1096
  * Libera tutte le risorse caricate
1097
1097
  */
1098
- async function clearmat(){for(const key in _textures)if(_textures[key]){const texture=await _textures[key];texture?.dispose()}for(const key in _smats)_smats[key]&&_smats[key]?.dispose();for(const[key,texOrPromise]of textureCache.entries()){const texture=texOrPromise instanceof Promise?await texOrPromise:texOrPromise;texture?.dispose&&texture.dispose()}textureCache.clear(),_textures={},_smats={}}return{clearmatricole:()=>{_gmatricole={}},islog:islog,clear:async function clear(){function destroymesh(mesh){function disposeMaterial(material){material.map&&material.map.dispose(),material.lightMap&&material.lightMap.dispose(),material.bumpMap&&material.bumpMap.dispose(),material.normalMap&&material.normalMap.dispose(),material.specularMap&&material.specularMap.dispose(),material.dispose()}mesh&&mesh.traverse((child=>{child.isMesh&&(child.geometry.dispose(),child.material&&(Array.isArray(child.material)?child.material.forEach(disposeMaterial):disposeMaterial(child.material)))}))}_gmatricole={},_cachefn={},THREE.Cache.clear();for(const c in _geometries)_geometries[c]?.dispose();for(const key in _meshes)if(_meshes[key]){destroymesh(await _meshes[key])}await clearmat(),_movs={},_textures={},_meshes={},_geometries={},_smats={},_scripts={}},clearmat:clearmat,getScript:async function getScript(file){file.endsWith(".custom")?file=file.slice(0,-7):file.endsWith(".js")&&(file=file.slice(0,-3));let key=hash(`${getcat()}|${file}`);if(!_scripts[key]){let script;try{script=await P.fetch("mufiles/customfn",{id:getcat(),name:file,ispar:1})}catch(error){script=`log('undefined ${getcat()}/${file}: ${error.message}');`}_scripts[key]=script}return _scripts[key]},checkScripts:async function checkScripts(files){let cl=[];if(!files||!Array.isArray(files))return;let ct=getcat();files=[...files,"_ricalcolatop","_ricalcolaaltri","_ricalcolalinee"];for(let f of files){let key=hash(`${ct}|${f}`);_scripts[key]||cl.push(f)}if(cl?.length){let scripts=await P.fetch("mufiles/customfn",{id:ct,name:cl,ispar:1});if(scripts)for(let s of scripts){let key=hash(`${ct}|${s.n}`);_scripts[key]=s.v}}},get loaderGLTF(){return _loaderGLTF},get gmats(){return _gmatricole},scripts:()=>Object.keys(_scripts),get geo(){return _geometries},get movs(){return _movs},get textures(){return _textures},get smats(){return _smats},get meshes(){return _meshes},get cacheFns(){return _cachefn},dump(){console.log(`SMATS:\n${Object.keys(_smats).join(" - ")};\nGEOMS:\n${Object.keys(_geometries).join(" - ")};\nTEX:\n${Object.keys(_textures).join(" - ")};\nMESH:\n${Object.keys(_meshes).join(" - ")};\n`)},get cat(){return getcat()},pushcat(cat){cats.push(cat)},popcat:()=>(cats.length>1&&cats.length--,getcat()),async tex(file,sx=1,sy,rot){let key;return sy||(sy=sx),rot||(rot=0),"__alpha"==file?(key=file,_textures[key]||(_textures[key]=function getfortransparent(){const texture=new THREE.CanvasTexture(function generateTexture(){const canvas=document.createElement("canvas");canvas.width=2,canvas.height=2;const context=canvas.getContext("2d");return context.fillStyle="white",context.fillRect(0,1,2,1),canvas}());return texture.magFilter=THREE.NearestFilter,texture.wrapT=THREE.RepeatWrapping,texture.wrapS=THREE.RepeatWrapping,texture.repeat.set(1,3.5),texture}()),_textures[key]):(key=hash(`${getcat()}|${file}|${sx}|${sy}|${rot}`),_textures[key]||(_textures[key]=new Promise(((resolve,reject)=>{let url;if(file.startsWith("https://"))url=file;else if(P._cdn)if(file.includes("/")){let v=file.split("/");url=`${P._cdn}${v[0]}/textures/${v[1]}`}else url=`${P._cdn}${getcat()}/textures/${file}`;else url=P.fullget("mufiles/getfile",{id:getcat(),subfolder:"textures",name:file,force:1});if(textureCache.has(url)){const tex=textureCache.get(url).clone();return tex.wrapS=THREE.RepeatWrapping,tex.wrapT=THREE.RepeatWrapping,tex.repeat.set(.001*sx,.001*sy),tex.rotation=rot,tex.colorSpace=THREE.SRGBColorSpace,void resolve(tex)}_loadertex.load(url,(tex=>{textureCache.set(url,tex),tex.wrapS=THREE.RepeatWrapping,tex.wrapT=THREE.RepeatWrapping,tex.repeat.set(.001*sx,.001*sy),tex.rotation=rot,resolve(tex)}),void 0,(error=>{console.log(`Manca Texture ${file}!. questo rallenta molto il processo`),delete _textures[key],resolve(void 0)}))}))),_textures[key])},async get3ds(file){file.endsWith(".3ds")&&(file=file.slice(0,-4));const key=hash(`${getcat()}|${file}.3ds`);return _meshes[key]||(_meshes[key]=await new Promise(((resolve,reject)=>{let url,urlt="";file.startsWith("https://")?(url=`${file}.3ds`,urlt=url):P._cdn?(url=`${P._cdn}${getcat()}/3d/${file}.3ds`,urlt=`${P._cdn}${getcat()}/3d/${file}/`):(url=P.fullget("mufiles/getfile",{id:getcat(),subfolder:"3d",name:file,ext:".3ds"}),urlt=url+"&tex="),_loader3DS.setResourcePath(urlt),_loader3DS.load(url,(object=>{const cache=new WeakMap;object.traverse((n=>{n.isMesh&&n.material&&(n.material=Array.isArray(n.material)?n.material.map((e=>to_std(e,cache))):to_std(n.material,cache))})),object.userData||(object.userData={}),object.userData._ky=key,resolve(object)}),void 0,(error=>{console.log(error),delete _meshes[key],resolve(void 0)}))}))),_meshes[key]},async getglb(file){const ext=".glb";file.endsWith(ext)&&(file=file.slice(0,-4)),file.startsWith("https://")||(file=file.replace(/\//g,"+"));let elemento=(file=file.split("+"))[1];file=file[0];const key=hash(`${getcat()}|${file}${ext}`);_meshes[key]||(_meshes[key]=await new Promise(((resolve,reject)=>{let url;url=file.startsWith("https://")?`${file}.glb`:P._cdn?`${P._cdn}${getcat()}/3d/${file}.glb`:P.fullget("mufiles/getfile",{id:getcat(),subfolder:"3d",name:file,ext:ext}),_loaderGLTF.setPath(""),_loaderGLTF.setResourcePath((resource=>(console.log("risorsa",resource),`${url}&tex=${resource}`))),_loaderGLTF.load(url,(async gltf=>{const object=gltf.scene;object.userData||(object.userData={}),object.userData._ky=key,resolve(object)}),void 0,(error=>{console.log(error),delete _meshes[key],resolve(void 0)}))})));let tm=_meshes[key];if(elemento){let n=tm?.getObjectByName(elemento);n&&(tm=n)}return tm},replacemats(bb,mats,callback){if(!Array.isArray(mats)||0==mats.length)return bb;const leggi_slot=mat=>{if(!mat)return-1;let s=(mat?.map?.name||mat?.name||mat?.map?.userData?.name||"").toString().trim();if(callback){const s1=callback(s);void 0!==s1&&(s=s1)}if(s.includes("_")&&(s=s.split("_").pop()),!s)return-1;const n=parseInt(s,10);return n>=1&&n<=9?n:-1};let serve_clone=!1,ky=String(bb.userData?._ky||"");if(bb.traverse((n=>{if(!n.isMesh)return;const ms=Array.isArray(n.material)?n.material:[n.material];for(const m of ms){const k=leggi_slot(m);k>0&&mats[k-1]&&(serve_clone=!0,ky+="|"+(mats[k-1].name||mats[k-1].uuid))}})),serve_clone){if(ky=hash(ky),_meshes[ky])return _meshes[ky];const cc=bb.clone(!0);cc.traverse((n=>{if(n.isMesh)if(Array.isArray(n.material))n.material=n.material.map((m=>{if(!m)return m;const k=leggi_slot(m);if(k>0&&mats[k-1]){const t=mats[k-1];return t.needsUpdate=!0,t}return m}));else{const m=n.material,k=leggi_slot(m);n.material=k>0&&mats[k-1]?(mats[k-1].needsUpdate=!0,mats[k-1]):m}})),cc.userData=cc.userData||{},cc.userData._ky=ky,_meshes[ky]=cc,bb=cc}return bb}}}const originalMaterials=new Map;
1098
+ async function clearmat(){for(const key in _textures)if(_textures[key]){const texture=await _textures[key];texture?.dispose()}for(const key in _smats)_smats[key]&&_smats[key]?.dispose();for(const[key,texOrPromise]of textureCache.entries()){const texture=texOrPromise instanceof Promise?await texOrPromise:texOrPromise;texture?.dispose&&texture.dispose()}textureCache.clear(),_textures={},_smats={}}return{clearmatricole:()=>{_gmatricole={}},islog:islog,clear:async function clear(){function destroymesh(mesh){function disposeMaterial(material){material.map&&material.map.dispose(),material.lightMap&&material.lightMap.dispose(),material.bumpMap&&material.bumpMap.dispose(),material.normalMap&&material.normalMap.dispose(),material.specularMap&&material.specularMap.dispose(),material.dispose()}mesh&&mesh.traverse((child=>{child.isMesh&&(child.geometry.dispose(),child.material&&(Array.isArray(child.material)?child.material.forEach(disposeMaterial):disposeMaterial(child.material)))}))}_gmatricole={},_cachefn={},THREE.Cache.clear();for(const c in _geometries)_geometries[c]?.dispose();for(const key in _meshes)if(_meshes[key]){destroymesh(await _meshes[key])}await clearmat(),_movs={},_textures={},_meshes={},_geometries={},_smats={},_scripts={}},clearmat:clearmat,getScript:async function getScript(file){file.endsWith(".custom")?file=file.slice(0,-7):file.endsWith(".js")&&(file=file.slice(0,-3));let key=hash(`${getcat()}|${file}`);if(!_scripts[key]){let script;try{script=await P.fetch("mufiles/customfn",{id:getcat(),name:file,ispar:1})}catch(error){script=`log('undefined ${getcat()}/${file}: ${error.message}');`}_scripts[key]=script}return _scripts[key]},checkScripts:async function checkScripts(files){let cl=[];if(!files||!Array.isArray(files))return;let ct=getcat();files=[...files,"_ricalcolatop","_ricalcolaaltri","_ricalcolalinee"];for(let f of files){let key=hash(`${ct}|${f}`);_scripts[key]||cl.push(f)}if(cl?.length){let scripts=await P.fetch("mufiles/customfn",{id:ct,name:cl,ispar:1});if(scripts)for(let s of scripts){let key=hash(`${ct}|${s.n}`);_scripts[key]=s.v}}},get loaderGLTF(){return _loaderGLTF},get gmats(){return _gmatricole},scripts:()=>Object.keys(_scripts),get geo(){return _geometries},get movs(){return _movs},get textures(){return _textures},get smats(){return _smats},get meshes(){return _meshes},get cacheFns(){return _cachefn},dump(){console.log(`SMATS:\n${Object.keys(_smats).join(" - ")};\nGEOMS:\n${Object.keys(_geometries).join(" - ")};\nTEX:\n${Object.keys(_textures).join(" - ")};\nMESH:\n${Object.keys(_meshes).join(" - ")};\n`)},get cat(){return getcat()},pushcat(cat){cats.push(cat)},popcat:()=>(cats.length>1&&cats.length--,getcat()),async tex(file,sx=1,sy,rot){let key;return sy||(sy=sx),rot||(rot=0),"__alpha"==file?(key=file,_textures[key]||(_textures[key]=function getfortransparent(){const texture=new THREE.CanvasTexture(function generateTexture(){const canvas=document.createElement("canvas");canvas.width=2,canvas.height=2;const context=canvas.getContext("2d");return context.fillStyle="white",context.fillRect(0,1,2,1),canvas}());return texture.magFilter=THREE.NearestFilter,texture.wrapT=THREE.RepeatWrapping,texture.wrapS=THREE.RepeatWrapping,texture.repeat.set(1,3.5),texture}()),_textures[key]):(key=hash(`${getcat()}|${file}|${sx}|${sy}|${rot}`),_textures[key]||(_textures[key]=new Promise(((resolve,reject)=>{let url;if(file.startsWith("https://"))url=file;else if(P._cdn)if(file.includes("/")){let v=file.split("/");url=`${P._cdn}${v[0]}/textures/${v[1]}`}else url=`${P._cdn}${getcat()}/textures/${file}`;else url=P.fullget("mufiles/getfile",{id:getcat(),subfolder:"textures",name:file,force:1});if(textureCache.has(url)){const tex=textureCache.get(url).clone();return tex.wrapS=THREE.RepeatWrapping,tex.wrapT=THREE.RepeatWrapping,tex.center.set(.5,.5),tex.repeat.set(.001*sx,.001*sy),tex.rotation=rot,void resolve(tex)}_loadertex.load(url,(tex=>{textureCache.set(url,tex),tex.wrapS=THREE.RepeatWrapping,tex.wrapT=THREE.RepeatWrapping,tex.repeat.set(.001*sx,.001*sy),tex.center.set(.5,.5),tex.rotation=rot,resolve(tex)}),void 0,(error=>{console.log(`Manca Texture ${file}!. questo rallenta molto il processo`),delete _textures[key],resolve(void 0)}))}))),_textures[key])},async get3ds(file){file.endsWith(".3ds")&&(file=file.slice(0,-4));const key=hash(`${getcat()}|${file}.3ds`);return _meshes[key]||(_meshes[key]=await new Promise(((resolve,reject)=>{let url,urlt="";file.startsWith("https://")?(url=`${file}.3ds`,urlt=url):P._cdn?(url=`${P._cdn}${getcat()}/3d/${file}.3ds`,urlt=`${P._cdn}${getcat()}/3d/${file}/`):(url=P.fullget("mufiles/getfile",{id:getcat(),subfolder:"3d",name:file,ext:".3ds"}),urlt=url+"&tex="),_loader3DS.setResourcePath(urlt),_loader3DS.load(url,(object=>{const cache=new WeakMap;object.traverse((n=>{n.isMesh&&n.material&&(n.material=Array.isArray(n.material)?n.material.map((e=>to_std(e,cache))):to_std(n.material,cache))})),object.userData||(object.userData={}),object.userData._ky=key,resolve(object)}),void 0,(error=>{console.log(error),delete _meshes[key],resolve(void 0)}))}))),_meshes[key]},async getglb(file){const ext=".glb";file.endsWith(ext)&&(file=file.slice(0,-4)),file.startsWith("https://")||(file=file.replace(/\//g,"+"));let elemento=(file=file.split("+"))[1];file=file[0];const key=hash(`${getcat()}|${file}${ext}`);_meshes[key]||(_meshes[key]=await new Promise(((resolve,reject)=>{let url;url=file.startsWith("https://")?`${file}.glb`:P._cdn?`${P._cdn}${getcat()}/3d/${file}.glb`:P.fullget("mufiles/getfile",{id:getcat(),subfolder:"3d",name:file,ext:ext}),_loaderGLTF.setPath(""),_loaderGLTF.setResourcePath((resource=>(console.log("risorsa",resource),`${url}&tex=${resource}`))),_loaderGLTF.load(url,(async gltf=>{const object=gltf.scene;object.userData||(object.userData={}),object.userData._ky=key,resolve(object)}),void 0,(error=>{console.log(error),delete _meshes[key],resolve(void 0)}))})));let tm=_meshes[key];if(elemento){let n=tm?.getObjectByName(elemento);n&&(tm=n)}return tm},replacemats(bb,mats,callback){if(!Array.isArray(mats)||0==mats.length)return bb;const leggi_slot=mat=>{if(!mat)return-1;let s=(mat?.map?.name||mat?.name||mat?.map?.userData?.name||"").toString().trim();if(callback){const s1=callback(s);void 0!==s1&&(s=s1)}if(s.includes("_")&&(s=s.split("_").pop()),!s)return-1;const n=parseInt(s,10);return n>=1&&n<=9?n:-1};let serve_clone=!1,ky=String(bb.userData?._ky||"");if(bb.traverse((n=>{if(!n.isMesh)return;const ms=Array.isArray(n.material)?n.material:[n.material];for(const m of ms){const k=leggi_slot(m);k>0&&mats[k-1]&&(serve_clone=!0,ky+="|"+(mats[k-1].name||mats[k-1].uuid))}})),serve_clone){if(ky=hash(ky),_meshes[ky])return _meshes[ky];const cc=bb.clone(!0);cc.traverse((n=>{if(n.isMesh)if(Array.isArray(n.material))n.material=n.material.map((m=>{if(!m)return m;const k=leggi_slot(m);if(k>0&&mats[k-1]){const t=mats[k-1];return t.needsUpdate=!0,t}return m}));else{const m=n.material,k=leggi_slot(m);n.material=k>0&&mats[k-1]?(mats[k-1].needsUpdate=!0,mats[k-1]):m}})),cc.userData=cc.userData||{},cc.userData._ky=ky,_meshes[ky]=cc,bb=cc}return bb}}}const originalMaterials=new Map;
1099
1099
  /**
1100
1100
  * Salva i materiali originali di tutti i mesh nel gruppo (solo layer <= 20)
1101
1101
  * @param {THREE.Object3D} gruppo
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markuno_lib",
3
- "version": "1.2.62",
3
+ "version": "1.2.63",
4
4
  "description": "Croswil Markuno Language Lib",
5
5
  "author": "Croswil SRL",
6
6
  "license": "SEE LICENSE IN LICENSE.txt",
@@ -195,6 +195,7 @@ export class Punto2 {
195
195
  * Restituisce il vettore normalizzato (lunghezza unitaria)
196
196
  * @returns {Punto2} Nuovo punto con le coordinate normalizzate
197
197
  */ dir(): Punto2;
198
+ distanza(p1: any): number;
198
199
  }
199
200
  export const SIDE: any;
200
201
  export var SP: Readonly<{