markuno_lib 1.2.6 → 1.2.7
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 +2 -2
- package/package.json +1 -1
package/bin/markcad.js
CHANGED
|
@@ -286,7 +286,7 @@ function sharpCorners(path,thresholdDeg=45){const result=[],n=path.length;if(n<3
|
|
|
286
286
|
* @param {number} thresholdDeg - Angolo in gradi.
|
|
287
287
|
* @returns {Array<{ index: number, point: {x:number,y:number}, angle: number }>}
|
|
288
288
|
*/
|
|
289
|
-
segment(i,inverse=!1){let n=pt.length;return i<0&&(i+=n),new Linea2(pt[i%n],pt[(i+(inverse?-1:1))%n])},lineoffset(i1,i2,offset){if((i1=(i1||0)%pt.length)!=(i2=(i2||0)%pt.length)){let l2=new Linea2(pt[i1],pt[i2]);if(l2){return l2=l2.offsetline(-offset),this.intersectline(l2)}}},orientasplitter(){-1!=orientation()&&pt.reverse();let np=pt.length;for(let i=0;i<np;i++){let lt=new Linea2(pt[(np+i-1)%np],pt[i]);if(Math.abs(Math.abs(lt.angle)-Math.PI)<.001){i&&selezionaprimo(i);break}}return this},move(x=0,y=0){"object"==typeof x&&x.x&&(y=x.y||0,x=x.x);for(let p of pt)p.x+=x,p.y+=y;return this},mirrorx(value=0){for(let p of pt)p.x=2*value-p.x;return this},mirrory(value=0){for(let p of pt)p.y=2*value-p.y;return this},simplify(tolerance,hq){return pt=function simplify(points,tolerance,highestQuality){if(points.length<=2)return points;var sqTolerance=void 0!==tolerance?tolerance*tolerance:1;return simplifyDouglasPeucker(points=highestQuality?points:function simplifyRadialDist(points,sqTolerance){for(var point,p1,p2,dx,dy,prevPoint=points[0],newPoints=[prevPoint],i=1,len=points.length;i<len;i++)p2=prevPoint,dx=void 0,dy=void 0,(dx=(p1=point=points[i]).x-p2.x)*dx+(dy=p1.y-p2.y)*dy>sqTolerance&&(newPoints.push(point),prevPoint=point);return prevPoint!==point&&newPoints.push(point),newPoints}(points,sqTolerance),sqTolerance)}(pt,tolerance,hq),this},fromclip(vv){pt=[];for(let p of vv)pt.push({x:p.x/1e3,y:p.y/1e3});return this},infosegmento(i,open=!1){const n=pt.length;function clampIndex(idx){return(idx+n)%n}function angle(p1,p2){return Math.atan2(p2.y-p1.y,p2.x-p1.x)}function angleDiff(a,b){let diff=a-b;for(;diff>Math.PI;)diff-=2*Math.PI;for(;diff<-Math.PI;)diff+=2*Math.PI;return diff}const p1=pt[i];let p0,p2,p3;if(open)if(0===i){const dx=pt[1].x-pt[0].x,dy=pt[1].y-pt[0].y;p0={x:pt[0].x-dx,y:pt[0].y-dy},p2=pt[1],p3=pt[2]}else if(i===n-1){const dx=pt[n-1].x-pt[n-2].x,dy=pt[n-1].y-pt[n-2].y;p0=pt[n-2],p2={x:pt[n-1].x+dx,y:pt[n-1].y+dy},p3={x:p2.x+dx,y:p2.y+dy}}else p0=pt[i-1],p2=pt[i+1],p3=i+2<n?pt[i+2]:{x:pt[i+1].x+(pt[i+1].x-pt[i].x),y:pt[i+1].y+(pt[i+1].y-pt[i].y)};else{const i0=clampIndex(i-1),i2=clampIndex(i+1),i3=clampIndex(i+2);p0=pt[i0],p2=pt[i2],p3=pt[i3]}const ang12=angle(p1,p2),ang01=angle(p0,p1),ang23=angle(p2,p3);return{x:p1.x,y:p1.y,l:function length(p1,p2){const dx=p2.x-p1.x,dy=p2.y-p1.y;return Math.sqrt(dx*dx+dy*dy)}(p1,p2),ang:ang12/PIF,a1:angleDiff(ang12,ang01)/PIF,a2:angleDiff(ang23,ang12)/PIF}},swapxy(){for(let i=0;i<pt.length;i++){let q=pt[i].x;pt[i].x=-pt[i].y,pt[i].y=-q}return this},fromvec(aa){return pt=[],_addvec(aa),this},addvec(vec){return _addvec(vec),this},frompt(pts){return pt=[...pts],pt=removeduplicate(pt),this},fromdxfvec(verts){let points=[];if(verts&&verts.length)for(let i=0;i<verts.length;i++){let{x:x,y:y,bulge:bulge}=verts[i];if(points.push({x:x,y:y}),bulge){const step=1;let p1={x:x,y:y},p2=verts[(i+1)%verts.length],dx=p2.x-p1.x,dy=p2.y-p1.y,dist=Math.hypot(dx,dy);dist>step&&points.push(...dxfbulge(p1,p2,bulge,Math.floor((dist-step)/step)+1))}}return pt=points.map((e=>({x:Math.round(10*e.x)/10,y:Math.round(10*e.y)/10}))),pt=removeduplicate(pt),this},fromstr(str){return pt=removeduplicate(function processTokens(tokens){const points=[];for(let i=0;i<tokens.length;i++){const token=tokens[i];if("point"===token.type)points.push(token.point);else if("command"===token.type)switch(token.cmd){case"x":{const p1=points[points.length-1],p2="point"===tokens[i+1]?.type?tokens[i+1].point:points[0],bulge=parseFloat(token.params[0])||5;{const STEP=1;let dx=p2.x-p1.x,dy=p2.y-p1.y,dist=Math.hypot(dx,dy);dist>1&&points.push(...dxfbulge(p1,p2,bulge,Math.floor((dist-STEP)/(STEP+2))+1))}break}case"b":{if(points.length<2)continue;const npt=parseInt(token.params[0])||5,p1=points[points.length-2],p2=points[points.length-1];let p3="point"===tokens[i+1]?.type?tokens[i+1].point:void 0,p4="point"===tokens[i+2]?.type?tokens[i+2].point:void 0;p3?p4||(p4=points[0]):(p3=points[0],p4=points[1]);const raccordo=raccordabezier(p1,p2,p3,p4,npt);points.push(...raccordo),i+=1;break}case"r":{if(points.length<1)continue;const dist=parseFloat(token.params[0])||5,npt=parseInt(token.params[1])||10,p1=points[points.length-1];let p2="point"===tokens[i+1]?.type?tokens[i+1].point:void 0,p3="point"===tokens[i+2]?.type?tokens[i+2].point:"point"===tokens[i+3]?.type?tokens[i+3].point:void 0;p2?p3||(p3=points[0]):(p2=points[0],p3=points[1],points.splice(0,1));const raccordo=raccordabezier3(p1,p2,p3,dist,npt);points.push(...raccordo),i+=1;break}case"c":{const radius=parseFloat(token.params[0])||50,segments=parseInt(token.params[1])||12,center="point"===tokens[i+1]?.type?tokens[i+1].point:new Punto2(0,0);for(let j=0;j<segments;j++)points.push(new Punto2(center.x+radius*Math.cos(j/segments*Math.PI*2),center.y+radius*Math.sin(j/segments*Math.PI*2)));i+=1;break}case"a":{let npt,p1="point"===tokens[i+1]?.type?tokens[i+1].point:void 0,p2="point"===tokens[i+2]?.type?tokens[i+2].point:void 0,p3="point"===tokens[i+3]?.type?tokens[i+3].point:void 0;if(!p1||!p3)continue;if(p2)if(token.params[0])npt=clamp(parseInt(token.params[0]),1,24);else{const chord=Math.hypot(p3.x-p1.x,p3.y-p1.y),sagitta=Math.abs((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))/(2*chord);npt=Math.round(chord*Math.sqrt(sagitta/(chord+.1))*10),npt=clamp(npt,1,24),npt=1}else p2=p3,npt=0;const arcoPoints=arcfrom3point(npt,p1,p2,p3);points.push(...arcoPoints),i+=3;break}}}return points}(function tokenize(str){const tokens=[],values=str.replace(/[\n\r,;]/g," ").replace(/\s+/g," ").toLowerCase().trim().split(" ").filter((s=>s.length>0));let i=0;for(;i<values.length;){const val=values[i];/^[brcax]/.test(val)?(tokens.push({type:"command",cmd:val[0],params:val.slice(1).split(":")}),i++):i<values.length-1&&/^-?\d+(\.\d+)?$/.test(values[i])&&/^-?\d+(\.\d+)?$/.test(values[i+1])?(tokens.push({type:"point",point:new Punto2(parseFloat(values[i]),parseFloat(values[i+1]))}),i+=2):i++}return tokens}(str))),this},monotona(vert=!0){let pp=[...pt];vert?(pp[0].x==pp[1].x&&(pp=pp.slice(1)),pp[pp.length-2].x==pp[pp.length-1].x&&(pp=pp.slice(0,-1))):(pp[0].y==pp[1].y&&(pp=pp.slice(1)),pp[pp.length-2].y==pp[pp.length-1].y&&(pp=pp.slice(0,-1)));const vv=i=>vert?pt[i].y:pt[i].x,crescente=vv(0)<vv(pt.length-1),newpt=[];let lastv=vv(0);newpt.push(pp[0]);for(let i=1;i<pp.length;i++)if(crescente){if(vv(i)>lastv+1e-4)newpt.push(pp[i]),lastv=vv(i);else if(Math.abs(vv(i)-lastv)<1e-4){const newv=lastv+1e-4;newpt.push(vert?{x:pp[i].x,y:newv}:{x:newv,y:pp[i].y}),lastv=newv}}else if(vv(i)<lastv-1e-4)newpt.push(pp[i]),lastv=vv(i);else if(Math.abs(vv(i)-lastv)<1e-4){const newv=lastv-1e-4;newpt.push(vert?{x:pp[i].x,y:newv}:{x:newv,y:pp[i].y}),lastv=newv}return getshape().frompt(newpt)},splitshape(p,verticale=!0){const p1=verticale?{x:p.x,y:p.y-100}:{x:p.x-100,y:p.y},p2=verticale?{x:p.x,y:p.y+100}:{x:p.x+100,y:p.y},linea=this.intersectline(new Linea2(p1,p2));if(!linea)return null;const pstart=linea.p1,pend=linea.p2,findIndex=pt=>this.pt.findIndex(((v,i)=>new Linea2(v,this.pt[(i+1)%this.pt.length]).onsegment(pt))),i1=findIndex(pstart),i2=findIndex(pend);if(i1<0||i2<0)return null;const n=this.pt.length,loop=(a,b,p0,p1)=>{const res=[p0];for(let i=a;i!==b;i=(i+1)%n)res.push(this.pt[(i+1)%n]);return res.push(p1),res},sx=getshape().frompt(loop(i1,i2,pstart,pend)),dx=getshape().frompt(loop(i2,i1,pend,pstart)),unique=new Set,arr=[...sx.pt,...dx.pt];for(const p of arr)unique.add(verticale?p.y:p.x);return{sx:sx,dx:dx,linea:linea,valori:Array.from(unique).sort(((a,b)=>a-b)),valore0:verticale?p.y:p.x}},xfromy(y,valore0,maggiore=!0){const res=[],n=this.pt.length;for(let i=0;i<n-1;i++){const p1=this.pt[i],p2=this.pt[i+1];if(p1.y<=y&&p2.y>=y||p2.y<=y&&p1.y>=y){const dy=p2.y-p1.y,t=dy?(y-p1.y)/dy:0,x=p1.x+t*(p2.x-p1.x);res.push(x)}else p1.y===y&&p2.y===y&&res.push(maggiore?Math.max(p1.x,p2.x):Math.min(p1.x,p2.x))}return res.length?maggiore?Math.max(...res):Math.min(...res):valore0},yfromx(x,valore0,maggiore=!0){const res=[],n=this.pt.length;for(let i=0;i<n-1;i++){const p1=this.pt[i],p2=this.pt[i+1];if(p1.x<=x&&p2.x>=x||p2.x<=x&&p1.x>=x){const dx=p2.x-p1.x,t=dx?(x-p1.x)/dx:0,y=p1.y+t*(p2.y-p1.y);res.push(y)}else p1.x===x&&p2.x===x&&res.push(maggiore?Math.max(p1.y,p2.y):Math.min(p1.y,p2.y))}return res.length?maggiore?Math.max(...res):Math.min(...res):valore0},forcevalues(shape,verticale=!0,delta=1e-6){const sorted=[...new Set(shape.pt.map((e=>verticale?e.y:e.x)))].sort(((a,b)=>a-b)),newpt=[],n=pt.length;for(let i=0;i<n;i++){const p1=pt[i],p2=pt[(i+1)%n];newpt.push({...p1});let v1=verticale?p1.y:p1.x,v2=verticale?p2.y:p2.x;if(v1===v2)continue;const range=v2>v1?sorted.filter((v=>v>v1+delta&&v<v2-delta)):sorted.filter((v=>v<v1-delta&&v>v2+delta)).reverse();for(const v of range){const t=(v-v1)/(v2-v1),q={x:p1.x+t*(p2.x-p1.x),y:p1.y+t*(p2.y-p1.y)};newpt.push(q)}}return pt=newpt,this},fromrect(w,h,sx,sy,bordo){w||(w=10),h||(h=10),bordo||(bordo=0),bordo=Math.min(Math.abs(bordo),Math.abs(.4*w),Math.abs(.4*h));let b1=w>0?bordo:-bordo,b2=h>0?bordo:-bordo;return pt=bordo?[{x:b1,y:0},{x:w-b1,y:0},{x:w,y:b2},{x:w,y:h-b2},{x:w-b1,y:h},{x:b1,y:h},{x:0,y:h-b2},{x:0,y:b2}]:[{x:0,y:0},{x:w,y:0},{x:w,y:h},{x:0,y:h}],this},intersectline:l=>function _intersectline(shape,p3,p4){let n=shape.length,l=new Linea2(p3,p4);const intersezioni=[];for(let i=0;i<shape.length;i++){let l2=new Linea2(shape[i],shape[(i+1)%n]),p=l2.interseca(l);p&&l2.onsegment(p)&&intersezioni.push(p)}if(intersezioni.length<2)return null;const{dx:dx,dy:dy}=l;intersezioni.sort(((a,b)=>(a.x-p3.x)*dx+(a.y-p3.y)*dy-((b.x-p3.x)*dx+(b.y-p3.y)*dy)));let pstart=new Punto2(intersezioni[0].x,intersezioni[0].y),pend=new Punto2(intersezioni[intersezioni.length-1].x,intersezioni[intersezioni.length-1].y);const vx1=pend.x-pstart.x,vy1=pend.y-pstart.y;return vx1*dx+vy1*dy<0&&([pstart,pend]=[pend,pstart]),new Linea2(pstart,pend)}(pt,l.p1,l.p2),tostr(dec=2){let dd=10**dec,pstr=x=>String(Math.round(x*dd)/dd),cl=pt.map((e=>`${pstr(e.x)};${pstr(e.y)};`)).join("");return cl&&cl.length?cl.slice(0,-1).match(/.{1,80}(;|$)/g).map((s=>s.trim())).join("\n"):""},addpt(pts){return pts?(Array.isArray(pts)||(pts=[pts]),pt=removeduplicate([...pt,...pts]),this):this},addracc(v1,v2,suddivisioni=2,addv1v2=!0){if(Array.isArray(v1)&&(v2={x:v1[2]||0,y:v1[3]||0},v1={x:v1[0]||0,y:v1[1]||0}),pt.length>=2){let tm=raccordabezier(pt[pt.length-2],pt[pt.length-1],v1,v2,suddivisioni);pt=[...pt,...tm],addv1v2&&(pt.push(v1),pt.push(v2))}return pt=removeduplicate(pt),this},setorient(mode){let p=orientation();return(1==p&&-1==mode||-1==p&&1==mode)&&pt.reverse(),this},reverse(){return pt.reverse(),this},pointinshape:p=>function isPointInPolygon(P){let x=P.x,y=P.y,inside=!1;for(let i=0,j=pt.length-1;i<pt.length;j=i++){let xi=pt[i].x,yi=pt[i].y,xj=pt[j].x,yj=pt[j].y;yi>y!=yj>y&&x<(xj-xi)*(y-yi)/(yj-yi)+xi&&(inside=!inside)}return inside}(p),azzera(){return pt=[],this},removeduplicate(delta=.005){return pt=removeduplicate(pt,delta),this},to3d(u0,alt=0,coeffa=0,coeffb=0,open=!1,sh=null,invert=!1){let tm=function to3dcoor(path,options){let{currentU:currentU=0,c:c=0,a:a=0,b:b=0,anglemin:anglemin=30,open:open=!1,sh:sh=null}=options;const pointsWithNormals=[];sh&&sh.pt.length;const n=path.length;for(let i=0;i<n;i++){const prev=path[(i-1+n)%n],current=path[i],next=path[(i+1)%n],vPrev={x:current.x-prev.x,y:current.y-prev.y},vNext={x:next.x-current.x,y:next.y-current.y},normalPrev=normal2(prev,current),normalNext=normal2(current,next),angle=angle2vec(vPrev,vNext);let z=a*current.x+b*current.y+c;if(sh){let t=sh.xfromy(current.y,0,!0);console.log("y",current.y,t),z+=t}Math.abs(angle-180)<=anglemin?(normalPrev.nx,normalNext.nx,normalPrev.ny,normalNext.ny,pointsWithNormals.push({x:current.x,y:-current.y,z:z,u:currentU,v:z})):(pointsWithNormals.push({x:current.x,y:-current.y,z:z,u:currentU,v:z}),pointsWithNormals.push({x:current.x,y:-current.y,z:z,u:currentU,v:z}));const dx=next.x-current.x,dy=next.y-current.y;currentU+=Math.sqrt(dx*dx+dy*dy)}if(!open){let p=pointsWithNormals[0],pf=pointsWithNormals[pointsWithNormals.length-1];p.x==pf.x&&p.y==pf.y||pointsWithNormals.push({x:p.x,y:p.y,z:p.z,nx:p.nx,ny:p.ny,nz:p.nz,u:currentU,v:p.z})}return pointsWithNormals}(pt,{open:open,currentU:u0,c:alt,a:coeffa,b:coeffb,anglemin:30,sh:sh});return tm},getboundbox:()=>pt.length?pt.reduce(((box,p)=>(box.p1.x=Math.min(box.p1.x,p.x),box.p1.y=Math.min(box.p1.y,p.y),box.p2.x=Math.max(box.p2.x,p.x),box.p2.y=Math.max(box.p2.y,p.y),box)),{p1:new Punto2(1/0,1/0),p2:new Punto2(-1/0,-1/0)}):{p1:new Punto2(0,0),p2:new Punto2(0,0)},fittobox(p1,p2){if(!pt.length)return this;const currentBox=this.getboundbox(),currentWidth=currentBox.p2.x-currentBox.p1.x,currentHeight=currentBox.p2.y-currentBox.p1.y,targetWidth=p2.x-p1.x,targetHeight=p2.y-p1.y,scale=Math.min(targetWidth/(currentWidth||1),targetHeight/(currentHeight||1));for(let p of pt)p.x=(p.x-currentBox.p1.x)*scale,p.y=(p.y-currentBox.p1.y)*scale,p.x+=p1.x,p.y+=p1.y;return this}}}
|
|
289
|
+
segment(i,inverse=!1){let n=pt.length;return i<0&&(i+=n),new Linea2(pt[i%n],pt[(i+(inverse?-1:1))%n])},lineoffset(i1,i2,offset){if((i1=(i1||0)%pt.length)!=(i2=(i2||0)%pt.length)){let l2=new Linea2(pt[i1],pt[i2]);if(l2){return l2=l2.offsetline(-offset),this.intersectline(l2)}}},orientasplitter(){-1!=orientation()&&pt.reverse();let np=pt.length;for(let i=0;i<np;i++){let lt=new Linea2(pt[(np+i-1)%np],pt[i]);if(Math.abs(Math.abs(lt.angle)-Math.PI)<.001){i&&selezionaprimo(i);break}}return this},move(x=0,y=0){"object"==typeof x&&x.x&&(y=x.y||0,x=x.x);for(let p of pt)p.x+=x,p.y+=y;return this},mirrorx(value=0){for(let p of pt)p.x=2*value-p.x;return this},mirrory(value=0){for(let p of pt)p.y=2*value-p.y;return this},simplify(tolerance,hq){return pt=function simplify(points,tolerance,highestQuality){if(points.length<=2)return points;var sqTolerance=void 0!==tolerance?tolerance*tolerance:1;return simplifyDouglasPeucker(points=highestQuality?points:function simplifyRadialDist(points,sqTolerance){for(var point,p1,p2,dx,dy,prevPoint=points[0],newPoints=[prevPoint],i=1,len=points.length;i<len;i++)p2=prevPoint,dx=void 0,dy=void 0,(dx=(p1=point=points[i]).x-p2.x)*dx+(dy=p1.y-p2.y)*dy>sqTolerance&&(newPoints.push(point),prevPoint=point);return prevPoint!==point&&newPoints.push(point),newPoints}(points,sqTolerance),sqTolerance)}(pt,tolerance,hq),this},fromclip(vv){pt=[];for(let p of vv)pt.push({x:p.x/1e3,y:p.y/1e3});return this},infosegmento(i,open=!1){const n=pt.length;function clampIndex(idx){return(idx+n)%n}function angle(p1,p2){return Math.atan2(p2.y-p1.y,p2.x-p1.x)}function angleDiff(a,b){let diff=a-b;for(;diff>Math.PI;)diff-=2*Math.PI;for(;diff<-Math.PI;)diff+=2*Math.PI;return diff}const p1=pt[i];let p0,p2,p3;if(open)if(0===i){const dx=pt[1].x-pt[0].x,dy=pt[1].y-pt[0].y;p0={x:pt[0].x-dx,y:pt[0].y-dy},p2=pt[1],p3=pt[2]}else if(i===n-1){const dx=pt[n-1].x-pt[n-2].x,dy=pt[n-1].y-pt[n-2].y;p0=pt[n-2],p2={x:pt[n-1].x+dx,y:pt[n-1].y+dy},p3={x:p2.x+dx,y:p2.y+dy}}else p0=pt[i-1],p2=pt[i+1],p3=i+2<n?pt[i+2]:{x:pt[i+1].x+(pt[i+1].x-pt[i].x),y:pt[i+1].y+(pt[i+1].y-pt[i].y)};else{const i0=clampIndex(i-1),i2=clampIndex(i+1),i3=clampIndex(i+2);p0=pt[i0],p2=pt[i2],p3=pt[i3]}const ang12=angle(p1,p2),ang01=angle(p0,p1),ang23=angle(p2,p3);return{x:p1.x,y:p1.y,l:function length(p1,p2){const dx=p2.x-p1.x,dy=p2.y-p1.y;return Math.sqrt(dx*dx+dy*dy)}(p1,p2),ang:ang12/PIF,a1:angleDiff(ang12,ang01)/PIF,a2:angleDiff(ang23,ang12)/PIF}},swapxy(){for(let i=0;i<pt.length;i++){let q=pt[i].x;pt[i].x=-pt[i].y,pt[i].y=-q}return this},fromvec(aa){return pt=[],_addvec(aa),this},addvec(vec){return _addvec(vec),this},frompt(pts){return pt=[...pts],pt=removeduplicate(pt),this},fromdxfvec(verts){let points=[];if(verts&&verts.length)for(let i=0;i<verts.length;i++){let{x:x,y:y,bulge:bulge}=verts[i];if(points.push({x:x,y:y}),bulge){const step=1;let p1={x:x,y:y},p2=verts[(i+1)%verts.length],dx=p2.x-p1.x,dy=p2.y-p1.y,dist=Math.hypot(dx,dy);dist>step&&points.push(...dxfbulge(p1,p2,bulge,Math.floor((dist-step)/step)+1))}}return pt=points.map((e=>({x:Math.round(10*e.x)/10,y:Math.round(10*e.y)/10}))),pt=removeduplicate(pt),this},fromstr(str){return pt=removeduplicate(function processTokens(tokens){const points=[];for(let i=0;i<tokens.length;i++){const token=tokens[i];if("point"===token.type)points.push(token.point);else if("command"===token.type)switch(token.cmd){case"x":{const p1=points[points.length-1],p2="point"===tokens[i+1]?.type?tokens[i+1].point:points[0],bulge=parseFloat(token.params[0])||5;{const STEP=1;let dx=p2.x-p1.x,dy=p2.y-p1.y,dist=Math.hypot(dx,dy);dist>1&&points.push(...dxfbulge(p1,p2,bulge,Math.floor((dist-STEP)/(STEP+2))+1))}break}case"b":{if(points.length<2)continue;const npt=parseInt(token.params[0])||5,p1=points[points.length-2],p2=points[points.length-1];let p3="point"===tokens[i+1]?.type?tokens[i+1].point:void 0,p4="point"===tokens[i+2]?.type?tokens[i+2].point:void 0;p3?p4||(p4=points[0]):(p3=points[0],p4=points[1]);const raccordo=raccordabezier(p1,p2,p3,p4,npt);points.push(...raccordo),i+=1;break}case"r":{if(points.length<1)continue;const dist=parseFloat(token.params[0])||5,npt=parseInt(token.params[1])||10,p1=points[points.length-1];let p2="point"===tokens[i+1]?.type?tokens[i+1].point:void 0,p3="point"===tokens[i+2]?.type?tokens[i+2].point:"point"===tokens[i+3]?.type?tokens[i+3].point:void 0;p2?p3||(p3=points[0]):(p2=points[0],p3=points[1],points.splice(0,1));const raccordo=raccordabezier3(p1,p2,p3,dist,npt);points.push(...raccordo),i+=1;break}case"c":{const radius=parseFloat(token.params[0])||50,segments=parseInt(token.params[1])||12,center="point"===tokens[i+1]?.type?tokens[i+1].point:new Punto2(0,0);for(let j=0;j<segments;j++)points.push(new Punto2(center.x+radius*Math.cos(j/segments*Math.PI*2),center.y+radius*Math.sin(j/segments*Math.PI*2)));i+=1;break}case"a":{let npt,p1="point"===tokens[i+1]?.type?tokens[i+1].point:void 0,p2="point"===tokens[i+2]?.type?tokens[i+2].point:void 0,p3="point"===tokens[i+3]?.type?tokens[i+3].point:void 0;if(!p1||!p3)continue;if(p2)if(token.params[0])npt=clamp(parseInt(token.params[0]),1,24);else{const chord=Math.hypot(p3.x-p1.x,p3.y-p1.y),sagitta=Math.abs((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))/(2*chord);npt=Math.round(chord*Math.sqrt(sagitta/(chord+.1))*10),npt=clamp(npt,1,24),npt=1}else p2=p3,npt=0;const arcoPoints=arcfrom3point(npt,p1,p2,p3);points.push(...arcoPoints),i+=3;break}}}return points}(function tokenize(str){const tokens=[],values=str.replace(/[\n\r,;]/g," ").replace(/\s+/g," ").toLowerCase().trim().split(" ").filter((s=>s.length>0));let i=0;for(;i<values.length;){const val=values[i];/^[brcax]/.test(val)?(tokens.push({type:"command",cmd:val[0],params:val.slice(1).split(":")}),i++):i<values.length-1&&/^-?\d+(\.\d+)?$/.test(values[i])&&/^-?\d+(\.\d+)?$/.test(values[i+1])?(tokens.push({type:"point",point:new Punto2(parseFloat(values[i]),parseFloat(values[i+1]))}),i+=2):i++}return tokens}(str))),this},monotona(){let dxd=dims(pt),pp=pt.map((e=>({x:e.x-dxd.p2.x,y:e.y}))),xp=[];xp.push(pp[0]);let lastv=pp[0].y;for(let i=1;i<pp.length;i++)if(pp[i].y>lastv+1e-4||i==pp.length-1)xp.push(pp[i]),lastv=pp[i].y;else{const newv=lastv+1e-4;xp.push({x:pp[i].x,y:newv}),lastv=newv}return{sh:getshape().frompt(xp),...dxd}},splitshape(p,verticale=!0){const p1=verticale?{x:p.x,y:p.y-100}:{x:p.x-100,y:p.y},p2=verticale?{x:p.x,y:p.y+100}:{x:p.x+100,y:p.y},linea=this.intersectline(new Linea2(p1,p2));if(!linea)return null;const pstart=linea.p1,pend=linea.p2,findIndex=pt=>this.pt.findIndex(((v,i)=>new Linea2(v,this.pt[(i+1)%this.pt.length]).onsegment(pt))),i1=findIndex(pstart),i2=findIndex(pend);if(i1<0||i2<0)return null;const n=this.pt.length,loop=(a,b,p0,p1)=>{const res=[];for(let i=a;i!==b;i=(i+1)%n)res.push(this.pt[(i+1)%n]);return res},dx=getshape().frompt(loop(i1,i2));return{sx:getshape().frompt(loop(i2,i1)),dx:dx,linea:linea}},xfromy(y,valore0=0,maggiore=!0){const res=[],n=this.pt.length;for(let i=0;i<n-1;i++){const p1=this.pt[i],p2=this.pt[i+1];if(p1.y<=y&&p2.y>=y||p2.y<=y&&p1.y>=y){const dy=p2.y-p1.y,t=dy?(y-p1.y)/dy:0,x=p1.x+t*(p2.x-p1.x);res.push(x)}else p1.y===y&&p2.y===y&&res.push(maggiore?Math.max(p1.x,p2.x):Math.min(p1.x,p2.x))}return res.length?maggiore?Math.max(...res):Math.min(...res):valore0},yfromx(x,valore0=0,maggiore=!0){const res=[],n=this.pt.length;for(let i=0;i<n-1;i++){const p1=this.pt[i],p2=this.pt[i+1];if(p1.x<=x&&p2.x>=x||p2.x<=x&&p1.x>=x){const dx=p2.x-p1.x,t=dx?(x-p1.x)/dx:0,y=p1.y+t*(p2.y-p1.y);res.push(y)}else p1.x===x&&p2.x===x&&res.push(maggiore?Math.max(p1.y,p2.y):Math.min(p1.y,p2.y))}return res.length?maggiore?Math.max(...res):Math.min(...res):valore0},forcevalues(shape,verticale=!0,delta=1e-6){const sorted=[...new Set(shape.pt.map((e=>verticale?e.y:e.x)))].sort(((a,b)=>a-b)),newpt=[],n=pt.length;for(let i=0;i<n;i++){const p1=pt[i],p2=pt[(i+1)%n];newpt.push({...p1});let v1=verticale?p1.y:p1.x,v2=verticale?p2.y:p2.x;if(v1===v2)continue;const range=v2>v1?sorted.filter((v=>v>v1+delta&&v<v2-delta)):sorted.filter((v=>v<v1-delta&&v>v2+delta)).reverse();for(const v of range){const t=(v-v1)/(v2-v1),q={x:p1.x+t*(p2.x-p1.x),y:p1.y+t*(p2.y-p1.y)};newpt.push(q)}}return pt=newpt,this},fromrect(w,h,sx,sy,bordo){w||(w=10),h||(h=10),bordo||(bordo=0),bordo=Math.min(Math.abs(bordo),Math.abs(.4*w),Math.abs(.4*h));let b1=w>0?bordo:-bordo,b2=h>0?bordo:-bordo;return pt=bordo?[{x:b1,y:0},{x:w-b1,y:0},{x:w,y:b2},{x:w,y:h-b2},{x:w-b1,y:h},{x:b1,y:h},{x:0,y:h-b2},{x:0,y:b2}]:[{x:0,y:0},{x:w,y:0},{x:w,y:h},{x:0,y:h}],this},intersectline:l=>function _intersectline(shape,p3,p4){let n=shape.length,l=new Linea2(p3,p4);const intersezioni=[];for(let i=0;i<shape.length;i++){let l2=new Linea2(shape[i],shape[(i+1)%n]),p=l2.interseca(l);p&&l2.onsegment(p)&&intersezioni.push(p)}if(intersezioni.length<2)return null;const{dx:dx,dy:dy}=l;intersezioni.sort(((a,b)=>(a.x-p3.x)*dx+(a.y-p3.y)*dy-((b.x-p3.x)*dx+(b.y-p3.y)*dy)));let pstart=new Punto2(intersezioni[0].x,intersezioni[0].y),pend=new Punto2(intersezioni[intersezioni.length-1].x,intersezioni[intersezioni.length-1].y);const vx1=pend.x-pstart.x,vy1=pend.y-pstart.y;return vx1*dx+vy1*dy<0&&([pstart,pend]=[pend,pstart]),new Linea2(pstart,pend)}(pt,l.p1,l.p2),tostr(dec=2){let dd=10**dec,pstr=x=>String(Math.round(x*dd)/dd),cl=pt.map((e=>`${pstr(e.x)};${pstr(e.y)};`)).join("");return cl&&cl.length?cl.slice(0,-1).match(/.{1,80}(;|$)/g).map((s=>s.trim())).join("\n"):""},addpt(pts){return pts?(Array.isArray(pts)||(pts=[pts]),pt=removeduplicate([...pt,...pts]),this):this},addracc(v1,v2,suddivisioni=2,addv1v2=!0){if(Array.isArray(v1)&&(v2={x:v1[2]||0,y:v1[3]||0},v1={x:v1[0]||0,y:v1[1]||0}),pt.length>=2){let tm=raccordabezier(pt[pt.length-2],pt[pt.length-1],v1,v2,suddivisioni);pt=[...pt,...tm],addv1v2&&(pt.push(v1),pt.push(v2))}return pt=removeduplicate(pt),this},setorient(mode){let p=orientation();return(1==p&&-1==mode||-1==p&&1==mode)&&pt.reverse(),this},reverse(){return pt.reverse(),this},pointinshape:p=>function isPointInPolygon(P){let x=P.x,y=P.y,inside=!1;for(let i=0,j=pt.length-1;i<pt.length;j=i++){let xi=pt[i].x,yi=pt[i].y,xj=pt[j].x,yj=pt[j].y;yi>y!=yj>y&&x<(xj-xi)*(y-yi)/(yj-yi)+xi&&(inside=!inside)}return inside}(p),azzera(){return pt=[],this},removeduplicate(delta=.005){return pt=removeduplicate(pt,delta),this},to3d(u0,alt=0,coeffa=0,coeffb=0,open=!1,sh=null,invert=!1){let tm=function to3dcoor(path,options){let{currentU:currentU=0,c:c=0,a:a=0,b:b=0,anglemin:anglemin=30,open:open=!1,sh:sh=null,invert:invert=!1}=options;const pointsWithNormals=[],n=path.length;for(let i=0;i<n;i++){const prev=path[(i-1+n)%n],current=path[i],next=path[(i+1)%n],vPrev={x:current.x-prev.x,y:current.y-prev.y},vNext={x:next.x-current.x,y:next.y-current.y},normalPrev=normal2(prev,current),normalNext=normal2(current,next),angle=angle2vec(vPrev,vNext);let z=a*current.x+b*current.y+c;if(sh){let t=sh.xfromy(current.y,0,!0);invert?z+=t:z-=t}Math.abs(angle-180)<=anglemin?(normalPrev.nx,normalNext.nx,normalPrev.ny,normalNext.ny,pointsWithNormals.push({x:current.x,y:-current.y,z:z,u:currentU,v:z})):(pointsWithNormals.push({x:current.x,y:-current.y,z:z,u:currentU,v:z}),pointsWithNormals.push({x:current.x,y:-current.y,z:z,u:currentU,v:z}));const dx=next.x-current.x,dy=next.y-current.y;currentU+=Math.sqrt(dx*dx+dy*dy)}if(!open){let p=pointsWithNormals[0],pf=pointsWithNormals[pointsWithNormals.length-1];p.x==pf.x&&p.y==pf.y||pointsWithNormals.push({x:p.x,y:p.y,z:p.z,nx:p.nx,ny:p.ny,nz:p.nz,u:currentU,v:p.z})}return pointsWithNormals}(pt,{open:open,currentU:u0,c:alt,a:coeffa,b:coeffb,anglemin:30,sh:sh,invert:invert});return tm},getboundbox:()=>pt.length?pt.reduce(((box,p)=>(box.p1.x=Math.min(box.p1.x,p.x),box.p1.y=Math.min(box.p1.y,p.y),box.p2.x=Math.max(box.p2.x,p.x),box.p2.y=Math.max(box.p2.y,p.y),box)),{p1:new Punto2(1/0,1/0),p2:new Punto2(-1/0,-1/0)}):{p1:new Punto2(0,0),p2:new Punto2(0,0)},fittobox(p1,p2){if(!pt.length)return this;const currentBox=this.getboundbox(),currentWidth=currentBox.p2.x-currentBox.p1.x,currentHeight=currentBox.p2.y-currentBox.p1.y,targetWidth=p2.x-p1.x,targetHeight=p2.y-p1.y,scale=Math.min(targetWidth/(currentWidth||1),targetHeight/(currentHeight||1));for(let p of pt)p.x=(p.x-currentBox.p1.x)*scale,p.y=(p.y-currentBox.p1.y)*scale,p.x+=p1.x,p.y+=p1.y;return this}}}
|
|
290
290
|
/**
|
|
291
291
|
* Calcola i punti di un arco passante per tre punti
|
|
292
292
|
* @param {number} segments - Numero di segmenti (punti-1)
|
|
@@ -631,7 +631,7 @@ function toTrianglesDrawMode(geometry,drawMode){if(drawMode===TrianglesDrawMode)
|
|
|
631
631
|
* @param {Array} mats - Array di materiali
|
|
632
632
|
* @param {Object} options - Opzioni di configurazione
|
|
633
633
|
* @returns {THREE.Group} Gruppo contenente la geometria estrusa
|
|
634
|
-
*/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:"",opinvert=options.invert||!1,open=options.open||!1,grp=new THREE.Group;if(shape){if(!options.nobase){let g1=bottomgeomfromshape(gcad,!1,shape,open?[]:holes,p0,coeffbase1,coeffbase2,shapebase);options.nolines||grp.add(edgesfromgeometry(g1)),grp.add(getmesh(g1,mats[0]||mwhite))}if(!options.notop){let g3=bottomgeomfromshape(gcad,!0,shape,open?[]:holes,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(var h of holes){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}
|
|
634
|
+
*/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:"",opinvert=options.invert||!1,open=options.open||!1,grp=new THREE.Group;if(shape){if(!options.nobase&&!shapebase){let g1=bottomgeomfromshape(gcad,!1,shape,open?[]:holes,p0,coeffbase1,coeffbase2,shapebase);options.nolines||grp.add(edgesfromgeometry(g1)),grp.add(getmesh(g1,mats[0]||mwhite))}if(!options.notop&&!shapetop){let g3=bottomgeomfromshape(gcad,!0,shape,open?[]:holes,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(var h of holes){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}
|
|
635
635
|
/**
|
|
636
636
|
* Crea una geometria estrusa con opzioni avanzate
|
|
637
637
|
* @param {string} orient - Orientamento dell'estrusione
|