markuno_lib 1.1.51 → 1.1.52
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 +6 -6
- package/bin/markcad3d.js +1 -1
- package/package.json +1 -1
- package/types/markcad.d.ts +18 -9
package/bin/markcad.js
CHANGED
|
@@ -276,7 +276,7 @@ function getshape(){let pt=[];
|
|
|
276
276
|
* Verifica se un punto è interno al poligono usando ray casting
|
|
277
277
|
* @param {Object} P - Punto da verificare {x,y}
|
|
278
278
|
* @returns {boolean} true se il punto è interno
|
|
279
|
-
*/
|
|
279
|
+
*/function selezionaprimo(idprimopunto){return(idprimopunto%=pt.length)>0&&(pt=[...pt.slice(idprimopunto),...pt.slice(0,idprimopunto)]),this}
|
|
280
280
|
/**
|
|
281
281
|
* Aggiunge punti da array di coordinate
|
|
282
282
|
* @param {Array<number>} aa - Array [x1,y1,x2,y2,...]
|
|
@@ -289,7 +289,7 @@ function _addvec(aa){for(let i=0;i<aa.length;i+=2)pt.push({x:aa[i],y:aa[i+1]})}f
|
|
|
289
289
|
* @param {number} thresholdDeg - Angolo in gradi.
|
|
290
290
|
* @returns {Array<{ index: number, point: {x:number,y:number}, angle: number }>}
|
|
291
291
|
*/
|
|
292
|
-
function sharpCorners(path,thresholdDeg=45){const result=[],n=path.length;if(n<3)return result;for(let i=0;i<n;i++){const prev=path[(i-1+n)%n],curr=path[i],next=path[(i+1)%n],ux=curr.x-prev.x,uy=curr.y-prev.y,vx=next.x-curr.x,vy=next.y-curr.y,magU=Math.hypot(ux,uy),magV=Math.hypot(vx,vy);if(0===magU||0===magV)continue;let cosTheta=(ux*vx+uy*vy)/(magU*magV);cosTheta=Math.max(-1,Math.min(1,cosTheta));const angleDeg=180*Math.acos(cosTheta)/Math.PI;angleDeg>thresholdDeg&&result.push({i:i,x:curr.x,y:curr.y,a:angleDeg})}return result}(pt,45),clone:()=>getshape().frompt(pt),dims:()=>dims(pt),alignline(p1,p2){return pt=function stretchShapeToLine(shapePts,p1,p2){if(!shapePts?.length||!p1||!p2)return[];const first=shapePts[0],last=shapePts[shapePts.length-1],dx=last.x-first.x,dy=last.y-first.y,ang=Math.atan2(dy,dx);let pts1=shapePts.map((p=>({x:p.x-first.x,y:p.y-first.y}))).map((p=>({x:p.x*Math.cos(-ang)-p.y*Math.sin(-ang),y:p.x*Math.sin(-ang)+p.y*Math.cos(-ang)})));const linea={dx:p2.x-p1.x,dy:p2.y-p1.y},scaleX=Math.sqrt(linea.dx*linea.dx+linea.dy*linea.dy)/(pts1[pts1.length-1].x||1e-8);let pts2=pts1.map((p=>({x:p.x*scaleX,y:p.y})));const angDest=Math.atan2(linea.dy,linea.dx);return pts2.map((p=>({x:p.x*Math.cos(angDest)-p.y*Math.sin(angDest),y:p.x*Math.sin(angDest)+p.y*Math.cos(angDest)}))).map((p=>({x:p.x+p1.x,y:p.y+p1.y})))}(pt,p1,p2),this},rotate(deg){if(!deg)return this;const r=deg*Math.PI/180,cosTheta=Math.cos(r),sinTheta=Math.sin(r);for(let p of pt){const xNew=p.x*cosTheta-p.y*sinTheta,yNew=p.x*sinTheta+p.y*cosTheta;p.x=xNew,p.y=yNew}return this},selezionaprimo:
|
|
292
|
+
function sharpCorners(path,thresholdDeg=45){const result=[],n=path.length;if(n<3)return result;for(let i=0;i<n;i++){const prev=path[(i-1+n)%n],curr=path[i],next=path[(i+1)%n],ux=curr.x-prev.x,uy=curr.y-prev.y,vx=next.x-curr.x,vy=next.y-curr.y,magU=Math.hypot(ux,uy),magV=Math.hypot(vx,vy);if(0===magU||0===magV)continue;let cosTheta=(ux*vx+uy*vy)/(magU*magV);cosTheta=Math.max(-1,Math.min(1,cosTheta));const angleDeg=180*Math.acos(cosTheta)/Math.PI;angleDeg>thresholdDeg&&result.push({i:i,x:curr.x,y:curr.y,a:angleDeg})}return result}(pt,45),clone:()=>getshape().frompt(pt),dims:()=>dims(pt),alignline(p1,p2){return pt=function stretchShapeToLine(shapePts,p1,p2){if(!shapePts?.length||!p1||!p2)return[];const first=shapePts[0],last=shapePts[shapePts.length-1],dx=last.x-first.x,dy=last.y-first.y,ang=Math.atan2(dy,dx);let pts1=shapePts.map((p=>({x:p.x-first.x,y:p.y-first.y}))).map((p=>({x:p.x*Math.cos(-ang)-p.y*Math.sin(-ang),y:p.x*Math.sin(-ang)+p.y*Math.cos(-ang)})));const linea={dx:p2.x-p1.x,dy:p2.y-p1.y},scaleX=Math.sqrt(linea.dx*linea.dx+linea.dy*linea.dy)/(pts1[pts1.length-1].x||1e-8);let pts2=pts1.map((p=>({x:p.x*scaleX,y:p.y})));const angDest=Math.atan2(linea.dy,linea.dx);return pts2.map((p=>({x:p.x*Math.cos(angDest)-p.y*Math.sin(angDest),y:p.x*Math.sin(angDest)+p.y*Math.cos(angDest)}))).map((p=>({x:p.x+p1.x,y:p.y+p1.y})))}(pt,p1,p2),this},rotate(deg){if(!deg)return this;const r=deg*Math.PI/180,cosTheta=Math.cos(r),sinTheta=Math.sin(r);for(let p of pt){const xNew=p.x*cosTheta-p.y*sinTheta,yNew=p.x*sinTheta+p.y*cosTheta;p.x=xNew,p.y=yNew}return this},selezionaprimo:selezionaprimo,
|
|
293
293
|
/**
|
|
294
294
|
* Trova i punti in cui l’angolo interno è maggiore di `thresholdDeg`.
|
|
295
295
|
*
|
|
@@ -297,7 +297,7 @@ function sharpCorners(path,thresholdDeg=45){const result=[],n=path.length;if(n<3
|
|
|
297
297
|
* @param {number} thresholdDeg - Angolo in gradi.
|
|
298
298
|
* @returns {Array<{ index: number, point: {x:number,y:number}, angle: number }>}
|
|
299
299
|
*/
|
|
300
|
-
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)}}},move(x=0,y=0){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}},fromvec(aa){return pt=[],_addvec(aa),this},addvec(vec){return _addvec(vec),this},frompt(pts){return pt=[...pts],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"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.toLowerCase().replace(/[\n\s]+/gm," ").split(/[,;]/).map((s=>s.trim()));for(let i=0;i<values.length;){const current=values[i];["b","r","c","a"].includes(current[0])?(tokens.push({type:"command",cmd:current[0],params:current.slice(1).split(":")}),i++):/[a-zA-Z]/.test(current[0])||(i<values.length-1?(tokens.push({type:"point",point:new Punto2(parseFloat(values[i]),parseFloat(values[i+1]))}),i+=2):i++)}return tokens}(str))),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);return pt.map((e=>pstr(e.x)+";"+pstr(e.y))).join(";")},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){pt=removeduplicate(pt);let tm=function genuvnormal(path,options){let{currentU:currentU=0,c:c=0,a:a=0,b:b=0,anglemin:anglemin=30,open:open=!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;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});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}}}
|
|
300
|
+
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},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"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.toLowerCase().replace(/[\n\s]+/gm," ").split(/[,;]/).map((s=>s.trim()));for(let i=0;i<values.length;){const current=values[i];["b","r","c","a"].includes(current[0])?(tokens.push({type:"command",cmd:current[0],params:current.slice(1).split(":")}),i++):/[a-zA-Z]/.test(current[0])||(i<values.length-1?(tokens.push({type:"point",point:new Punto2(parseFloat(values[i]),parseFloat(values[i+1]))}),i+=2):i++)}return tokens}(str))),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);return pt.map((e=>pstr(e.x)+";"+pstr(e.y))).join(";")},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){pt=removeduplicate(pt);let tm=function genuvnormal(path,options){let{currentU:currentU=0,c:c=0,a:a=0,b:b=0,anglemin:anglemin=30,open:open=!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;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});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}}}
|
|
301
301
|
/**
|
|
302
302
|
* Calcola i punti di un arco passante per tre punti
|
|
303
303
|
* @param {number} segments - Numero di segmenti (punti-1)
|
|
@@ -515,7 +515,7 @@ ClipperLib.ExPolygon=function(){this.outer=null,this.holes=null},ClipperLib.JS.A
|
|
|
515
515
|
* @property {Function} inflate - Espande o contrae una forma
|
|
516
516
|
* @property {Function} unisci - Unisce più forme con gestione di fori e tagli
|
|
517
517
|
*/
|
|
518
|
-
function shapeclip(){function toclipformat(pts){let tm=pts.map((e=>({X:Math.round(1e4*e.x),Y:Math.round(1e4*e.y)})));return ensureOrientation(tm)}function fromclipformat(pts){return pts.map((e=>({x:e.X/1e4,y:e.Y/1e4})))}const ensureOrientation=poly=>ClipperLib.Clipper.Orientation(poly)?poly:poly.slice().reverse();function orientation(pt){if(!pt.length)return 0;let area=0;const n=pt.length;for(let i=0;i<n;i++){const current=pt[i],next=pt[(i+1)%n];area+=current.X*next.Y-next.X*current.Y}return area>0?1:area<0?-1:0}const _inflate=(pt,delta,cut=!1)=>{const co=new ClipperLib.ClipperOffset;co.MiterLimit=4,co.AddPath(pt,ClipperLib.JoinType.jtMiter,cut||2==pt.length?ClipperLib.EndType.etOpenButt:ClipperLib.EndType.etClosedPolygon);const solution=new ClipperLib.Paths;return co.Execute(solution,delta),solution};return{offset(shape,delta,full=!1){const co=new ClipperLib.ClipperOffset;co.MiterLimit=4,co.ArcTolerance=.25;const DD=1e4*Math.abs(delta),pshape=toclipformat(shape.pt);co.AddPath(pshape,ClipperLib.JoinType.jtMiter,ClipperLib.EndType.etOpenButt);const solution=new ClipperLib.Paths;co.Execute(solution,DD);let tm=fromclipformat(solution[0]);return full?getshape().frompt(tm):getshape().frompt(getptsoffset(shape.pt,tm,delta))},inflate(shape,delta=2,mantainorder=!1,isopen=0){let pshape=toclipformat(shape.pt),tm=_inflate(pshape,1e4*delta);let p2=getshape().frompt(fromclipformat(tm[0]));if(mantainorder&&shape.pt.length==p2.pt.length){p2.orient!=shape.orient&&p2.reverse();let p3=function alignByMinDist(sag1,sag2){const N=sag1.length;let bestOffset=0,minSum=1/0;for(let k=0;k<N;k++){let sum=0;for(let i=0;i<N;i++){const p=sag1[i],q=sag2[(i+k)%N],dx=p.x-q.x,dy=p.y-q.y;sum+=dx*dx+dy*dy}sum<minSum&&(minSum=sum,bestOffset=k)}return[...sag2.slice(bestOffset),...sag2.slice(0,bestOffset)]}(shape.pt,p2.pt);if(p2.frompt(p3),isopen>0&&shape.pt.length>=3){function estendi1(sh1,sh2){let l1=sh1.segment(0).ruotata(-Math.PI/2,200,!0),l2=sh1.segment(-2).ruotata(-Math.PI/2,200),p2=sh2.segment(-2).interseca(l2),p1=sh2.segment(0).interseca(l1);p1&&(sh2.pt[0]=p1),p2&&(sh2.pt[sh2.pt.length-1]=p2)}function estendi2(sh1,sh2){let lfin=sh1.segment(-1),l2=sh2.segment(0),p1=lfin.interseca(l2);p1&&(sh2.pt[0]=p1),l2=sh2.segment(-2);let p2=lfin.interseca(l2);p2&&(sh2.pt[sh2.pt.length-1]=p2)}1==isopen?estendi1(shape,p2):estendi2(shape,p2)}}return p2},intersecasplitter(areabase,forma1){const clipper=new ClipperLib.Clipper,pt1=[toclipformat(forma1.pt)],pt2=[toclipformat(areabase.pt)];clipper.AddPaths(pt1,ClipperLib.PolyType.ptSubject,!0),clipper.AddPaths(pt2,ClipperLib.PolyType.ptClip,!0);const solution=new ClipperLib.Paths;let res;if(clipper.Execute(ClipperLib.ClipType.ctIntersection,solution,ClipperLib.PolyFillType.pftNonZero,ClipperLib.PolyFillType.pftNonZero)&&solution.length>0){const path=solution[0];if(1===orientation(path)){res=getshape().frompt(fromclipformat(path)),res.orient!=forma1.orient&&res.reverse();for(let iu=0;iu<forma1.pt.length;iu++){let p2=forma1.pt[iu],id=res.pt.findIndex((p=>Math.abs(p.x-p2.x)<.01&&Math.abs(p.y-p2.y)<.01));if(id>0){id-=iu,0!=id&&res.selezionaprimo(id);break}}}}return res},offsetpts(pts,delta=.01){const DELTA=1e4*delta;let tm=_inflate(toclipformat(pts),DELTA);if(tm&&tm.length)return fromclipformat(tm[0])},areesplitter(shapept,clipspt,useInflatedClipping=!0){if(!Array.isArray(shapept)||shapept.length<3)return;if(!clipspt||0==clipspt.length)return[shapept];const subj=new ClipperLib.Paths,clip=new ClipperLib.Paths;let shape_in=useInflatedClipping?_inflate(toclipformat(shapept),-100):[toclipformat(shapept)],clips_in=useInflatedClipping?clipspt.flatMap((c=>_inflate(toclipformat(c),100))):clipspt.map((c=>toclipformat(c)));for(let s of shape_in)subj.push(s);for(let c of clips_in)clip.push(c);const clipper=new ClipperLib.Clipper;clipper.AddPaths(subj,ClipperLib.PolyType.ptSubject,!0),clipper.AddPaths(clip,ClipperLib.PolyType.ptClip,!0);const solution=new ClipperLib.Paths;if(!clipper.Execute(ClipperLib.ClipType.ctDifference,solution,ClipperLib.PolyFillType.pftNonZero,ClipperLib.PolyFillType.pftNonZero))return;let res=[];for(let x of solution)if(useInflatedClipping){const restored=_inflate(x,100);for(const r of restored)1===orientation(r)&&res.push(fromclipformat(r))}else if(x.length>4&&1==orientation(x)){const cleaned=_inflate(x,-100);if(cleaned.length>0)for(let cc of cleaned){const restored=_inflate(cc,100);for(const rr of restored)1===orientation(rr)&&res.push(fromclipformat(rr))}}else 1==orientation(x)&&res.push(fromclipformat(x));return res},unisci(shapes,holes,cuts){const subj=new ClipperLib.Paths,clip=new ClipperLib.Paths;for(let hh of shapes){let h2=[toclipformat(hh.pt)];for(let h of h2)subj.push(h)}if(holes&&holes.length)for(let hh of holes){let h1=toclipformat(hh.pt);clip.push(h1)}if(cuts&&cuts.length)for(let hh of cuts){let h1=toclipformat(hh.pt),h2=_inflate(h1,1,!0);for(let h of h2)clip.push(h)}const clipper=new ClipperLib.Clipper;clipper.AddPaths(subj,ClipperLib.PolyType.ptSubject,!0),clipper.AddPaths(clip,ClipperLib.PolyType.ptClip,!0);const solution=new ClipperLib.Paths;if(clipper.Execute(ClipperLib.ClipType.ctDifference,solution,ClipperLib.PolyFillType.pftNonZero,ClipperLib.PolyFillType.pftNonZero)){let res=[],holes=[];for(let x of solution)if(1==orientation(x)){let yy=[x];for(let y of yy)res.push({shape:getshape().frompt(fromclipformat(y)),holes:[]})}else holes.push(getshape().frompt(fromclipformat(x)));for(let h of holes)for(let s of res)if(s.shape.pointinshape(h.pt[0])){s.holes.push(h);break}return res}return[]}}}class Vis2d{constructor(name,scalalinea=1){this.name=name,this.clear(scalalinea)}clear(scalalinea=1){return this.vec=[],this._sl=scalalinea,this}push(x,y,rot=0){this.vec.push({type:"push",x:x,y:y,rot:rot})}pop(){this.vec.push({type:"pop"})}randomcolor(transp="100%"){return`hsl(${Math.floor(360*Math.random())}, 50%, 40%,${transp})`}addpoint(p,id=-1,color="red",spessore=8){return p&&this.vec.push({type:"point",p:p,id:id,color:color,spessore:spessore*this._sl}),this}addline(l,id=-1,color=void 0,spessore=1){return l&&this.vec.push({type:"line",l:l,id:id,color:color,spessore:spessore*this._sl}),this}addrect(l,id=-1,color=void 0,spessore=1){return l&&this.vec.push({type:"rect",l:l,id:id,color:color,spessore:spessore*this._sl}),this}addrecta(l,id=-1,color=void 0){return l&&this.vec.push({type:"recta",l:l,id:id,color:color,spessore:0}),this}addshape(s,color=void 0,spessore=1){return s&&this.vec.push({type:"shape",s:s,color:color||this.randomcolor(),spessore:spessore*this._sl}),this}addshapelin(s,color=void 0,spessore=1){return s&&this.vec.push({type:"shapelin",s:s,color:color||this.randomcolor(),spessore:spessore*this._sl}),this}addarea(s,color=void 0){return s&&this.vec.push({type:"area",s:s,color:color||this.randomcolor()}),this}addoffset(x,y){return this.vec.push({type:"offset",x:x||0,y:y||0}),this}}function checkoggetto(oggetti,tipo,cod){"h"==tipo&&(tipo="o"),oggetti||(oggetti=[]);let bb=oggetti.find((e=>e.tipo.includes(tipo)&&e.cod==cod));return bb||(bb={cod:"__",macro:"",sps:0}),"a"!=tipo&&"as"!=tipo||"__"==bb.cod||bb.color||(bb.color=`hsl(${function stringToHue(str){let hash=0;for(let i=0;i<str.length;i++)hash=31*hash+str.charCodeAt(i)>>>0;return Math.floor(.6180339887*hash%1*360)}(bb.cod)}, 95%, 97%`),bb}function getbordi(oggetti,bordo){let bordi,uguali=!1;if(Array.isArray(bordo)){bordo.length=4;let b0=bordo[0]||"";bordi=bordo.map((b=>checkoggetto(oggetti,"b",b||b0))),uguali=bordi.every((b=>b.cod===bordi[0].cod))}else{"number"==typeof bordo&&(bordo=String(bordo));let tm=checkoggetto(oggetti,"b","string"==typeof bordo?bordo:"");bordi=[tm,tm,tm,tm],uguali=!0}return{bordi:bordi,uguali:uguali,senza:!(bordi[0].sps||bordi[1].sps||bordi[2].sps||bordi[3].sps),bl:bordi[0].sps,bt:bordi[1].sps,br:bordi[2].sps,bb:bordi[3].sps}}function creaprofiloesterno(ff,oggetti){let dati=[],draws=[];function newcount(){return ff.countid++,ff.countid}function eseguipezzo(l1,l2,bordo,shape){let info=l1.infoquad(l2);if(info&&info.distanza){let s0=getshape().frompt(shape||[l1.p1,l1.p2,l2.p2,l2.p1]),s1=s0.clone();(info.sx||info.sy)&&s1.move(-info.sx||0,-info.sy||0),info.angle&&s1.rotate(-info.angle||0);let tm={id:newcount,type:`b${bordo}`,info:info};shape&&(tm.shape=s1.pt),draws.push({type:`b${bordo}`,pt:s0.pt}),dati.push(tm)}}ff.countid=ff.countid||0;let sh1,sh2,sh3,p1h,p2h,p3h,p4h,p1v,p2v,p3v,p4v,p1s,p2s,line1,line2,i1,i2,{x:x,y:y,tipo:tipo,bordo:bordo,taglio:taglio,h1:h1,h2:h2,l1:l1,l2:l2,forma:forma}=ff;x=x<50?50:x,y=y<50?50:y,l1=l1||0,l2=l2||0,h1=h1||0,h2=h2||0;let idr=0,pts=[0,0];switch(tipo){case"i":case"d":pts.push(l1>0&&l1<x?l1:0,h1>0&&h1<y?y-h1:y),pts.push(l2>0&&l2<x-l1?x-l2:x,h2>0&&h2<y&&h2!=h1?y-h2:y);break;case"a":if(forma){let tm=getshape().fromstr(forma);tm.alignline({x:l1,y:y-h1},{x:x-l2,y:y-h2}),pts.push(...tm.vec)}else if((h1||h2)&&h1>=0&&h1<Math.min(y,x/2)&&h2>=0&&h2<Math.min(y,x/2)){let tm=getshape().fromstr(`a30;${l1||0};${y-h1};${x/2};${y};${x-l2};${y-h2}`);pts.push(...tm.vec)}else pts.push(0,y,x,y);break;case"s":l1>0&&h1>0?pts.push(0,y-h1,l1,y):pts.push(0,y),l2&&l2<x-l1&&h2>0&&h2<y?pts.push(x-l2,y,x,y-h2):pts.push(x,y);break;default:pts.push(0,y,x,y)}idr=pts.length/2,pts.push(x,0),sh1=getshape().fromvec(pts);let np=sh1.pt.length,{bordi:bordi,uguali:uguali,senza:senza}=getbordi(oggetti,bordo);if(uguali)if(senza||!bordi[0].sps)sh2=sh1.clone();else{let b=bordi[0].sps;sh2=shapeclip().inflate(sh1,-b,!0)}else{let b,ll=[],pp=[];for(let i=0;i<np;i++){b=0==i?bordi[0].sps:i==idr-1?bordi[2].sps:i==idr?bordi[3].sps:bordi[1].sps,"number"!=typeof b&&(b=0);let l=sh1.segment(i).offset(-b);ll.push(l)}for(let i=0;i<np;i++){let p=ll[i].interseca(ll[(i-1+np)%np]);pp.push(p)}sh2=getshape().frompt(pp)}if(!senza){p1h=sh2.segment(idr).interseca(sh1.segment(0)),p2h=sh2.segment(1).interseca(sh1.segment(0)),p3h=sh1.segment(idr-1).interseca(sh2.segment(idr-2)),p4h=sh1.segment(idr-1).interseca(sh2.segment(idr)),p1v=sh1.segment(idr).interseca(sh2.segment(0)),p2v=sh1.segment(1).interseca(sh2.segment(0)),p3v=sh1.segment(idr-2).interseca(sh2.segment(idr-1)),p4v=sh1.segment(idr).interseca(sh2.segment(idr-1)),i1=1,i2=idr-2,line1=sh2.segment(0),line2=sh2.segment(idr-1);for(let i=1;i<idr-1;i++){let l=sh1.segment(i),p=l.interseca(line1);p&&l.onsegment(p)&&(i1=i,p2v=p),p=l.interseca(line2),p&&l.onsegment(p)&&(i2=i,p3v=p)}i1-=1,i2=idr-2-i2;let p1=sh1.pt[0],p2=sh2.pt[0],p3=sh2.pt[idr],p4=sh1.pt[idr];switch(taglio[0]){case"v":eseguipezzo(new Linea2(p4v,p1v),sh2.segment(idr),3),p2=p1v,p3=p4v;break;case"o":eseguipezzo(sh1.segment(idr),new Linea2(p4h,p1h),3),p1=p1h,p4=p4h;break;default:eseguipezzo(sh1.segment(idr),sh2.segment(idr),3)}switch(p1s=sh1.pt.slice(1,idr),p2s=sh2.pt.slice(1,idr),taglio[1]){case"v":eseguipezzo(new Linea2(p1,sh1.pt[1]),new Linea2(p2,p2v),0),eseguipezzo(new Linea2(sh1.pt[idr-1],p4),new Linea2(p3v,p3),2),i1&&(p1s=p1s.slice(i1)),i2&&(p1s=p1s.slice(0,-i2)),p1s[0]=p2v,p1s[p1s.length-1]=p3v;break;case"o":eseguipezzo(new Linea2(p1,p2h),new Linea2(p2,sh2.pt[1]),0),eseguipezzo(new Linea2(p3h,p4),new Linea2(sh2.pt[idr-1],p3),2),p2s[0]=p2h,p2s[p2s.length-1]=p3h;break;default:eseguipezzo(new Linea2(p1,sh1.pt[1]),new Linea2(p2,sh2.pt[1]),0),eseguipezzo(new Linea2(sh1.pt[idr-1],p4),new Linea2(sh2.pt[idr-1],p3),2)}if(sh3=getshape().frompt(p2s),p1s.length<8&&p1s.length==p2s.length)for(let i=0;i<p1s.length-1;i++)eseguipezzo(new Linea2(p1s[i],p1s[i+1]),new Linea2(p2s[i],p2s[i+1]),1);else{let sh3=getshape().frompt([...p1s,...p2s.reverse()]),l3=new Linea2(p1s[0],p1s[p1s.length-1]),l4=l3.offset(-bordo[1]);eseguipezzo(l3,l4,1,sh3.pt)}}return{shape:sh1,internalshape:sh2,shape2:sh2,shapetop:sh3,bordi:bordi,dati:dati,draws:draws}}
|
|
518
|
+
function shapeclip(){function toclipformat(pts){let tm=pts.map((e=>({X:Math.round(1e4*e.x),Y:Math.round(1e4*e.y)})));return ensureOrientation(tm)}function fromclipformat(pts){return pts.map((e=>({x:e.X/1e4,y:e.Y/1e4})))}const ensureOrientation=poly=>ClipperLib.Clipper.Orientation(poly)?poly:poly.slice().reverse();function orientation(pt){if(!pt.length)return 0;let area=0;const n=pt.length;for(let i=0;i<n;i++){const current=pt[i],next=pt[(i+1)%n];area+=current.X*next.Y-next.X*current.Y}return area>0?1:area<0?-1:0}const _inflate=(pt,delta,cut=!1)=>{const co=new ClipperLib.ClipperOffset;co.MiterLimit=4,co.AddPath(pt,ClipperLib.JoinType.jtMiter,cut||2==pt.length?ClipperLib.EndType.etOpenButt:ClipperLib.EndType.etClosedPolygon);const solution=new ClipperLib.Paths;return co.Execute(solution,delta),solution};return{offset(shape,delta,full=!1){const co=new ClipperLib.ClipperOffset;co.MiterLimit=4,co.ArcTolerance=.25;const DD=1e4*Math.abs(delta),pshape=toclipformat(shape.pt);co.AddPath(pshape,ClipperLib.JoinType.jtMiter,ClipperLib.EndType.etOpenButt);const solution=new ClipperLib.Paths;co.Execute(solution,DD);let tm=fromclipformat(solution[0]);return full?getshape().frompt(tm):getshape().frompt(getptsoffset(shape.pt,tm,delta))},inflate(shape,delta=2,mantainorder=!1,isopen=0){let pshape=toclipformat(shape.pt),tm=_inflate(pshape,1e4*delta);let p2=getshape().frompt(fromclipformat(tm[0]));if(mantainorder&&shape.pt.length==p2.pt.length){p2.orient!=shape.orient&&p2.reverse();let p3=function alignByMinDist(sag1,sag2){const N=sag1.length;let bestOffset=0,minSum=1/0;for(let k=0;k<N;k++){let sum=0;for(let i=0;i<N;i++){const p=sag1[i],q=sag2[(i+k)%N],dx=p.x-q.x,dy=p.y-q.y;sum+=dx*dx+dy*dy}sum<minSum&&(minSum=sum,bestOffset=k)}return[...sag2.slice(bestOffset),...sag2.slice(0,bestOffset)]}(shape.pt,p2.pt);if(p2.frompt(p3),isopen>0&&shape.pt.length>=3){function estendi1(sh1,sh2){let l1=sh1.segment(0).ruotata(-Math.PI/2,200,!0),l2=sh1.segment(-2).ruotata(-Math.PI/2,200),p2=sh2.segment(-2).interseca(l2),p1=sh2.segment(0).interseca(l1);p1&&(sh2.pt[0]=p1),p2&&(sh2.pt[sh2.pt.length-1]=p2)}function estendi2(sh1,sh2){let lfin=sh1.segment(-1),l2=sh2.segment(0),p1=lfin.interseca(l2);p1&&(sh2.pt[0]=p1),l2=sh2.segment(-2);let p2=lfin.interseca(l2);p2&&(sh2.pt[sh2.pt.length-1]=p2)}1==isopen?estendi1(shape,p2):estendi2(shape,p2)}}return p2},intersecasplitter(areabase,forma1){const clipper=new ClipperLib.Clipper,pt1=[toclipformat(forma1.pt)],pt2=[toclipformat(areabase.pt)];clipper.AddPaths(pt1,ClipperLib.PolyType.ptSubject,!0),clipper.AddPaths(pt2,ClipperLib.PolyType.ptClip,!0);const solution=new ClipperLib.Paths;let res;if(clipper.Execute(ClipperLib.ClipType.ctIntersection,solution,ClipperLib.PolyFillType.pftNonZero,ClipperLib.PolyFillType.pftNonZero)&&solution.length>0){const path=solution[0];if(1===orientation(path)){res=getshape().frompt(fromclipformat(path)),res.orient!=forma1.orient&&res.reverse();for(let iu=0;iu<forma1.pt.length;iu++){let p2=forma1.pt[iu],id=res.pt.findIndex((p=>Math.abs(p.x-p2.x)<.01&&Math.abs(p.y-p2.y)<.01));if(id>0){id-=iu,0!=id&&res.selezionaprimo(id);break}}}}return res},offsetpts(pts,delta=.01){const DELTA=1e4*delta;let tm=_inflate(toclipformat(pts),DELTA);if(tm&&tm.length)return fromclipformat(tm[0])},areesplitter(shapept,clipspt,useInflatedClipping=!0){if(!Array.isArray(shapept)||shapept.length<3)return;if(!clipspt||0==clipspt.length)return[shapept];const subj=new ClipperLib.Paths,clip=new ClipperLib.Paths;let shape_in=useInflatedClipping?_inflate(toclipformat(shapept),-100):[toclipformat(shapept)],clips_in=useInflatedClipping?clipspt.flatMap((c=>_inflate(toclipformat(c),100))):clipspt.map((c=>toclipformat(c)));for(let s of shape_in)subj.push(s);for(let c of clips_in)clip.push(c);const clipper=new ClipperLib.Clipper;clipper.AddPaths(subj,ClipperLib.PolyType.ptSubject,!0),clipper.AddPaths(clip,ClipperLib.PolyType.ptClip,!0);const solution=new ClipperLib.Paths;if(!clipper.Execute(ClipperLib.ClipType.ctDifference,solution,ClipperLib.PolyFillType.pftNonZero,ClipperLib.PolyFillType.pftNonZero))return;let res=[];for(let x of solution)if(useInflatedClipping){const restored=_inflate(x,100);for(const r of restored)1===orientation(r)&&res.push(fromclipformat(r))}else if(x.length>4&&1==orientation(x)){const cleaned=_inflate(x,-100);if(cleaned.length>0)for(let cc of cleaned){const restored=_inflate(cc,100);for(const rr of restored)1===orientation(rr)&&res.push(fromclipformat(rr))}}else 1==orientation(x)&&res.push(fromclipformat(x));return res},unisci(shapes,holes,cuts){const subj=new ClipperLib.Paths,clip=new ClipperLib.Paths;for(let hh of shapes){let h2=[toclipformat(hh.pt)];for(let h of h2)subj.push(h)}if(holes&&holes.length)for(let hh of holes){let h1=toclipformat(hh.pt);clip.push(h1)}if(cuts&&cuts.length)for(let hh of cuts){let h1=toclipformat(hh.pt),h2=_inflate(h1,1,!0);for(let h of h2)clip.push(h)}const clipper=new ClipperLib.Clipper;clipper.AddPaths(subj,ClipperLib.PolyType.ptSubject,!0),clipper.AddPaths(clip,ClipperLib.PolyType.ptClip,!0);const solution=new ClipperLib.Paths;if(clipper.Execute(ClipperLib.ClipType.ctDifference,solution,ClipperLib.PolyFillType.pftNonZero,ClipperLib.PolyFillType.pftNonZero)){let res=[],holes=[];for(let x of solution)if(1==orientation(x)){let yy=[x];for(let y of yy)res.push({shape:getshape().frompt(fromclipformat(y)),holes:[]})}else holes.push(getshape().frompt(fromclipformat(x)));for(let h of holes)for(let s of res)if(s.shape.pointinshape(h.pt[0])){s.holes.push(h);break}return res}return[]}}}class Vis2d{constructor(name,scalalinea=1){this.name=name,this.clear(scalalinea)}clear(scalalinea=1){return this.vec=[],this._sl=scalalinea,this}push(x,y,rot=0){this.vec.push({type:"push",x:x,y:y,rot:rot})}pop(){this.vec.push({type:"pop"})}randomcolor(transp="100%"){return`hsl(${Math.floor(360*Math.random())}, 50%, 40%,${transp})`}addpoint(p,id=-1,color="red",spessore=8){return p&&this.vec.push({type:"point",p:p,id:id,color:color,spessore:spessore*this._sl}),this}addline(l,id=-1,color=void 0,spessore=1){return l&&this.vec.push({type:"line",l:l,id:id,color:color,spessore:spessore*this._sl}),this}addrect(l,id=-1,color=void 0,spessore=1){return l&&this.vec.push({type:"rect",l:l,id:id,color:color,spessore:spessore*this._sl}),this}addrecta(l,id=-1,color=void 0){return l&&this.vec.push({type:"recta",l:l,id:id,color:color,spessore:0}),this}addshape(s,color=void 0,spessore=1){return s&&this.vec.push({type:"shape",s:s,color:color||this.randomcolor(),spessore:spessore*this._sl}),this}addshapelin(s,color=void 0,spessore=1){return s&&this.vec.push({type:"shapelin",s:s,color:color||this.randomcolor(),spessore:spessore*this._sl}),this}addarea(s,color=void 0){return s&&this.vec.push({type:"area",s:s,color:color||this.randomcolor()}),this}addoffset(x,y){return this.vec.push({type:"offset",x:x||0,y:y||0}),this}}function checkoggetto(oggetti,tipo,cod){if("h"==tipo&&(tipo="o"),oggetti||(oggetti=[]),"number"==typeof cod&&!["a","as"].includes(tipo))return{cod:"__",macro:"",sps:cod};let bb=oggetti.find((e=>e.tipo.includes(tipo)&&e.cod==cod));return bb||(bb={cod:"__",macro:"",sps:0}),"a"!=tipo&&"as"!=tipo||"__"==bb.cod||bb.color||(bb.color=`hsl(${function stringToHue(str){let hash=0;for(let i=0;i<str.length;i++)hash=31*hash+str.charCodeAt(i)>>>0;return Math.floor(.6180339887*hash%1*360)}(bb.cod)}, 95%, 97%`),bb}function getbordi(oggetti,bordo){let bordi,uguali=!1;if(Array.isArray(bordo)){bordo.length=4;let b0=bordo[0]||"";bordi=bordo.map((b=>checkoggetto(oggetti,"b",b||b0))),uguali=bordi.every((b=>b.sps===bordi[0].sps))}else{let tm=checkoggetto(oggetti,"b",bordo);bordi=[tm,tm,tm,tm],uguali=!0}return{bordi:bordi,uguali:uguali,senza:!(bordi[0].sps||bordi[1].sps||bordi[2].sps||bordi[3].sps),bl:bordi[0].sps,bt:bordi[1].sps,br:bordi[2].sps,bb:bordi[3].sps}}function elaborapercorso(sh1,bordo,taglio,oggetti,countid=0){let sh2,sh3,p1h,p2h,p3h,p4h,p1v,p2v,p3v,p4v,p1s,p2s,line1,line2,i1,i2,dati=[],draws=[];function eseguipezzo(l1,l2,bordo,shape){let info=l1.infoquad(l2);if(info&&info.distanza){let s0=getshape().frompt(shape||[l1.p1,l1.p2,l2.p2,l2.p1]),s1=s0.clone();(info.sx||info.sy)&&s1.move(-info.sx||0,-info.sy||0),info.angle&&s1.rotate(-info.angle||0);let tm={id:++countid,type:`b${bordo}`,info:info};shape&&(tm.shape=s1.pt),draws.push({type:`b${bordo}`,pt:s0.pt}),dati.push(tm)}}countid=countid||0;let np=sh1.pt.length,idr=np-1;oggetti||(oggetti=[]);let{bordi:bordi,uguali:uguali,senza:senza}=getbordi(oggetti,bordo);if(uguali)if(senza||!bordi[0].sps)sh2=sh1.clone();else{let b=bordi[0].sps;sh2=shapeclip().inflate(sh1,-b,!0)}else{let b,ll=[],pp=[];for(let i=0;i<np;i++){b=0==i?bordi[0].sps:i==idr-1?bordi[2].sps:i==idr?bordi[3].sps:bordi[1].sps,"number"!=typeof b&&(b=0);let l=sh1.segment(i).offset(-b);ll.push(l)}for(let i=0;i<np;i++){let p=ll[i].interseca(ll[(i-1+np)%np]);pp.push(p)}sh2=getshape().frompt(pp)}if(!senza){p1h=sh2.segment(idr).interseca(sh1.segment(0)),p2h=sh2.segment(1).interseca(sh1.segment(0)),p3h=sh1.segment(idr-1).interseca(sh2.segment(idr-2)),p4h=sh1.segment(idr-1).interseca(sh2.segment(idr)),p1v=sh1.segment(idr).interseca(sh2.segment(0)),p2v=sh1.segment(1).interseca(sh2.segment(0)),p3v=sh1.segment(idr-2).interseca(sh2.segment(idr-1)),p4v=sh1.segment(idr).interseca(sh2.segment(idr-1)),i1=1,i2=idr-2,line1=sh2.segment(0),line2=sh2.segment(idr-1);for(let i=1;i<idr-1;i++){let l=sh1.segment(i),p=l.interseca(line1);p&&l.onsegment(p)&&(i1=i,p2v=p),p=l.interseca(line2),p&&l.onsegment(p)&&(i2=i,p3v=p)}i1-=1,i2=idr-2-i2;let p1=sh1.pt[0],p2=sh2.pt[0],p3=sh2.pt[idr],p4=sh1.pt[idr];switch(taglio[0]){case"v":eseguipezzo(new Linea2(p4v,p1v),sh2.segment(idr),3),p2=p1v,p3=p4v;break;case"o":eseguipezzo(sh1.segment(idr),new Linea2(p4h,p1h),3),p1=p1h,p4=p4h;break;default:eseguipezzo(sh1.segment(idr),sh2.segment(idr),3)}switch(p1s=sh1.pt.slice(1,idr),p2s=sh2.pt.slice(1,idr),taglio[1]){case"v":eseguipezzo(new Linea2(p1,sh1.pt[1]),new Linea2(p2,p2v),0),eseguipezzo(new Linea2(sh1.pt[idr-1],p4),new Linea2(p3v,p3),2),i1&&(p1s=p1s.slice(i1)),i2&&(p1s=p1s.slice(0,-i2)),p1s[0]=p2v,p1s[p1s.length-1]=p3v;break;case"o":eseguipezzo(new Linea2(p1,p2h),new Linea2(p2,sh2.pt[1]),0),eseguipezzo(new Linea2(p3h,p4),new Linea2(sh2.pt[idr-1],p3),2),p2s[0]=p2h,p2s[p2s.length-1]=p3h;break;default:eseguipezzo(new Linea2(p1,sh1.pt[1]),new Linea2(p2,sh2.pt[1]),0),eseguipezzo(new Linea2(sh1.pt[idr-1],p4),new Linea2(sh2.pt[idr-1],p3),2)}if(sh3=getshape().frompt(p2s),p1s.length<8&&p1s.length==p2s.length)for(let i=0;i<p1s.length-1;i++)eseguipezzo(new Linea2(p1s[i],p1s[i+1]),new Linea2(p2s[i],p2s[i+1]),1);else{let sh3=getshape().frompt([...p1s,...p2s.reverse()]),l3=new Linea2(p1s[0],p1s[p1s.length-1]),l4=l3.offset(-bordo[1]);eseguipezzo(l3,l4,1,sh3.pt)}}return{countid:countid,shape2:sh2,shapetop:sh3,bordi:bordi,dati:dati,draws:draws}}function creaprofiloesterno(ff,oggetti){let sh1,{x:x,y:y,tipo:tipo,bordo:bordo,taglio:taglio,h1:h1,h2:h2,l1:l1,l2:l2,forma:forma}=ff;x=x<50?50:x,y=y<50?50:y,l1=l1||0,l2=l2||0,h1=h1||0,h2=h2||0;let pts=[0,0];switch(tipo){case"i":case"d":pts.push(l1>0&&l1<x?l1:0,h1>0&&h1<y?y-h1:y),pts.push(l2>0&&l2<x-l1?x-l2:x,h2>0&&h2<y&&h2!=h1?y-h2:y);break;case"a":if(forma){let tm=getshape().fromstr(forma);tm.alignline({x:l1,y:y-h1},{x:x-l2,y:y-h2}),pts.push(...tm.vec)}else if((h1||h2)&&h1>=0&&h1<Math.min(y,x/2)&&h2>=0&&h2<Math.min(y,x/2)){let tm=getshape().fromstr(`a30;${l1||0};${y-h1};${x/2};${y};${x-l2};${y-h2}`);pts.push(...tm.vec)}else pts.push(0,y,x,y);break;case"s":l1>0&&h1>0?pts.push(0,y-h1,l1,y):pts.push(0,y),l2&&l2<x-l1&&h2>0&&h2<y?pts.push(x-l2,y,x,y-h2):pts.push(x,y);break;default:pts.push(0,y,x,y)}pts.push(x,0),sh1=getshape().fromvec(pts);let{countid:countid,shape2:shape2,shapetop:shapetop,bordi:bordi,dati:dati,draws:draws}=elaborapercorso(sh1,bordo,taglio,oggetti,ff.countid);return ff.countid=countid,{shape:sh1,internalshape:shape2,shape2:shape2,shapetop:shapetop,bordi:bordi,dati:dati,draws:draws}}
|
|
519
519
|
/**
|
|
520
520
|
* Genera segmenti basati su intervalli e punti di interruzione
|
|
521
521
|
* @param {Array<{a: number, b: number}>} t1 - Array di oggetti che rappresentano intervalli con coordinate a e b
|
|
@@ -534,7 +534,7 @@ function shapeclip(){function toclipformat(pts){let tm=pts.map((e=>({X:Math.roun
|
|
|
534
534
|
* - dati: Array di oggetti con le posizioni elaborate dei tagli
|
|
535
535
|
* - punti: Array di oggetti {a,b} che definiscono inizio e fine di ogni segmento
|
|
536
536
|
*/
|
|
537
|
-
function calcoladivisioni(ff,notused,shape2,oggetti){return makedivisions(ff,shape2,oggetti)},check:check,checkoggetto:checkoggetto,creaprofiloesterno:creaprofiloesterno,create:function create(x,y,bordo,options){options||(options={});let{minvano:minvano,priority:priority,taglio:taglio,tipo:tipo,h1:h1,h2:h2,d1:d1,d2:d2,l1:l1,l2:l2,x1:x1,x2:x2,y1:y1,y2:y2,gvert:gvert,goriz:goriz,forma:forma,area:area}=options,ff=check({x:x,y:y,area:area,bordo:bordo,gvert:gvert,goriz:goriz,priority:priority,minvano:minvano,taglio:taglio,tipo:tipo,h1:h1,h2:h2,l1:l1,l2:l2,d1:d1,x1:x1,y1:y1,d2:d2,x2:x2,y2:y2});return ff.forma=forma,ff},getbordi:getbordi,makedivisions:makedivisions,makeshape:function makeshape(ff,oggetti){return creaprofiloesterno(ff,oggetti)},priorita:{v:"verticale",h:"orizzontale"},tagli:tagli,tipi:tipi,tipoalign:tipoalign,tipocut:tipocut});async function valutagrafica(amb,startmacro,rulespec,progetto,fnreload){let{getcolonne:getcolonne,muCalc:muCalc,muEval:muEval,tipifree:tipifree}=amb.muvalutatore;rulespec||(rulespec={});for(let x of["l","a","p"]){!amb.vari.var(x)&&startmacro.dims&&amb.vari.add(x,String(startmacro.dims[x].val||100))}let fnlist=new Set;const PARSGLOBAL=["sl","sa","sp","ul","ua","up","ax","ay","az","scx","scy","scz","scale"];let isdimreload,isfnreload=!1,oo=await muEval(amb,startmacro,startmacro.codice,{leveleval:0,checkheader:op=>{let{variante:variante}=op;if(Array.isArray(startmacro.head)){let ff=startmacro.head.find((e=>e.cod==variante));isfnreload=!!ff}},grafica:async _op=>{let p2,cadv,iscad,des,fatti,{id:id,pars:pars,parametri:parametri,macro:macro,options:options,vari:vari}=_op,isheader=!!(macro&¯o.head&¯o.head.length),sv={l:amb.vari.var("l"),a:amb.vari.var("a"),p:amb.vari.var("p")};const varcad=["l","a","p","#d",...PARSGLOBAL];for(let x of varcad){let tm=amb.vari.dictionary[x];tm&&(sv[x]=tm)}async function _parsepars(x,head){let k,v,r9=/^#(d|des|descrizione)\s*=\s*(.*)\s*$/im.exec(x);if(r9)k="#d",v=await amb.vari.valuta(r9[2]);else{let result=await vari.parametrokeyval(x);k=result.k,v=result.v}k&&!fatti[k]&&(fatti[k]=!0,varcad.includes(k)?"#d"==k?des=v:("string"==typeof v&&(v=muCalc(v)),["l","a","p"].includes(k)&&amb.vari.add(k,String(v)),cadv[k]=v,iscad=!0):"string"==typeof v?p2.push(`${k}=${v}`):amb.vari.add(k,v))}if(p2=[],cadv={},iscad=!1,des="",fatti={},progetto&&progetto.keys&&progetto.keys[id]){let px=progetto.keys[id].pars;if(px)for(let t in px){let t1=amb.vari.dictionary[t];t1&&(sv[t]=t1),await _parsepars(`${t}=${px[t]}`)}}if(pars&&pars.length)for(const par of pars)await _parsepars(par);if(parametri&¶metri.length)for(const param of parametri)await _parsepars(param);if(macro&¯o.head&¯o.head.length){let tm=macro.head.filter((e=>!["g"].includes(e.t)));for(const h of tm)await _parsepars(h.cod)}let out={iscad:iscad,isheader:isheader,name:macro.name,des:des,leveleval:options.leveleval};isheader&&id&&(out.id=id),iscad&&(cadv.l?amb.vari.add("l",String(cadv.l)):cadv.l=muCalc(amb.vari.var("l")),cadv.a?amb.vari.add("a",String(cadv.a)):cadv.a=muCalc(amb.vari.var("a")),cadv.p?amb.vari.add("p",String(cadv.p)):cadv.p=muCalc(amb.vari.var("p")),out.cadv=cadv),await macro.impostaparametri(parametri,p2,!0);let ruleid=rulespec[id];if(id&&isheader&&ruleid&&ruleid.pars&&(out.pars=ruleid.pars,options.leveleval++,await macro.setparametri(ruleid.pars)),out.rows=await muEval(amb,macro,macro.codice,options),id&&isheader&&(out.spars=macro.getparametri()),iscad)for(let x in sv)amb.vari.dictionary[x]=sv[x];return out},parsefnpunto:async _op=>{let{dati:dati,vari:vari,id:id,output:output}=_op;dati=dati.trim();let q=dati.indexOf(" "),q2=dati.indexOf(",");q2>0&&q>0&&q2<q&&(q=q2);let fn,pp,pars={},p2={};q>1?(fn=dati.slice(1,q),pp=getcolonne(dati.slice(q+1))):(fn=dati.slice(1),pp=[]),fnlist.has(fn)||fnlist.add(fn);for(let p of pp){let{k:k,v:v}=await vari.parametrokeyval(p);k&&/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(k)&&(pars[k]=v||"")}for(let l of["l","a","p"])pars[l]||(pars[l]=vari.var(l));let tm=Object.keys(pars);for(let l of PARSGLOBAL)tm.includes(l)&&(p2[l]=muCalc(pars[l]),delete pars[l]);output.push({t:"fn",fn:fn,id:id,pars:pars,p2:p2})}});for(let x of["l","a","p"])if(startmacro.dims&&startmacro.dims[x].val!=parseFloat(amb.vari.var(x))){isdimreload=!0;break}return(isfnreload||isdimreload&&"function"==typeof fnreload)&&await fnreload(isdimreload,isfnreload),{oo:oo,vari:amb.vari.dump(!0),fnlist:[...fnlist]}}function ismacro(row){return"object"==typeof row&&row?.name&&row.rows}function isfn(row){return"object"==typeof row&&"fn"==row?.t}function getnodebyid(id,nodocorrente){let res;return nodocorrente&&nodocorrente.rows&&function _getnode(rows){for(let x of rows){if(ismacro(x)){if(x.id==id)return void(res=x);x.rows&&_getnode(x.rows)}if(res)return}}(nodocorrente.rows),res}function getsubrules(nodocorrente){let res=[];return res.push({id:"",level:0,name:"home"}),function _xfiltrati(rr,level){if(rr.rows&&rr.rows.length)for(let x of rr.rows)ismacro(x)&&(x.id&&x.isheader?(res.push({id:x.id,name:x.name,des:x.des||"",spec:x.pars?1:0,level:level}),_xfiltrati(x,level+1)):_xfiltrati(x,level))}(nodocorrente,1),res}function getprojectkeys(project){return project.keys={},function _getkeys(node){if(node.rows&&node.rows.length)for(let x of node.rows)ismacro(x)&&(x.id&&x.isheader&&x.pars&&(project.keys[x.id]={name:x.name,des:x.des||"",pars:x.pars}),_getkeys(x))}(project),project}function getdumpmacro(nodo){let cl=[];return function _dumpnodo(node){if(node.rows&&node.rows.length)for(let x of node.rows)if(ismacro(x)){x.name;let c=[];if(x.iscad&&x.cadv)for(let k in x.cadv){let t=x.cadv[k];"number"==typeof t&&t&&c.push(`${k}=${t}`)}if(x.pars)for(let k in x.pars){let t=x.pars[k];c.push(`${k}=${t}`)}c.length&&cl.push(`--\x3e ${x.name} ${c.join(",")}`),_dumpnodo(x),c.length&&cl.push("<--")}else isfn(x)?cl.push(`FN: ${x.fn} ${JSON.stringify(x.pars)}`):"string"==typeof x&&x.length&&cl.push(x)}(nodo),cl.join("\n")}function clean(k,locase=!1){return locase?(k||"").trim().toLowerCase():(k||"").trim()}function TODEG(a,dec=1){let C=10**dec;return Math.round(180*a*C/Math.PI)/C}function TORAD(a,dec=3){let C=10**dec;return Math.round(a*PIF*C)/C}const blocked={window:void 0,self:void 0,globalThis:void 0,document:void 0,Function:void 0,eval:void 0,fetch:void 0,XMLHttpRequest:void 0};function getOggetto(obj,exclude=[]){if(Array.isArray(obj))return obj.map((item=>getOggetto(item,exclude)));if(obj&&"object"==typeof obj){const result={};for(const[key,value]of Object.entries(obj))"function"==typeof value||exclude&&exclude.includes(key)||(result[key]=getOggetto(value,exclude));return result}return obj}async function evalcustomfunction(amb,code,values,objects){try{values||(values={}),objects||(objects={});const params={GCAD:!1,...values,A:amb,V:amb.vari,amb:amb,log:function addlog(...pars){const sanitized=pars.map((p=>getOggetto(p)));console.log(...sanitized)},Math:Math,clean:clean,SP:SP,Punto2:Punto2,Linea2:Linea2,clamp:clamp,hash:hash,PIF:PIF,getshape:getshape,shapeclip:shapeclip,...objects},paramNames=[...Object.keys(params),...Object.keys(blocked)],paramValues=[...Object.values(params),...Object.values(blocked)],fn=new Function(...paramNames,`\n try {\n return (async () => {\n ${code}\n })();\n } catch (err) {\n err.stack = '[SCRIPT] ' + err.stack;\n throw err;\n }`);return await fn(...paramValues)}catch(error){throw console.error("Errore durante l'esecuzione:",error),error}}
|
|
537
|
+
function calcoladivisioni(ff,notused,shape2,oggetti){return makedivisions(ff,shape2,oggetti)},check:check,checkoggetto:checkoggetto,creaprofiloesterno:creaprofiloesterno,create:function create(x,y,bordo,options){options||(options={});let{minvano:minvano,priority:priority,taglio:taglio,tipo:tipo,h1:h1,h2:h2,d1:d1,d2:d2,l1:l1,l2:l2,x1:x1,x2:x2,y1:y1,y2:y2,gvert:gvert,goriz:goriz,forma:forma,area:area}=options,ff=check({x:x,y:y,area:area,bordo:bordo,gvert:gvert,goriz:goriz,priority:priority,minvano:minvano,taglio:taglio,tipo:tipo,h1:h1,h2:h2,l1:l1,l2:l2,d1:d1,x1:x1,y1:y1,d2:d2,x2:x2,y2:y2});return ff.forma=forma,ff},elaborapercorso:elaborapercorso,getbordi:getbordi,makedivisions:makedivisions,makeshape:function makeshape(ff,oggetti){return creaprofiloesterno(ff,oggetti)},priorita:{v:"verticale",h:"orizzontale"},tagli:tagli,tipi:tipi,tipoalign:tipoalign,tipocut:tipocut});async function valutagrafica(amb,startmacro,rulespec,progetto,fnreload){let{getcolonne:getcolonne,muCalc:muCalc,muEval:muEval,tipifree:tipifree}=amb.muvalutatore;rulespec||(rulespec={});for(let x of["l","a","p"]){!amb.vari.var(x)&&startmacro.dims&&amb.vari.add(x,String(startmacro.dims[x].val||100))}let fnlist=new Set;const PARSGLOBAL=["sl","sa","sp","ul","ua","up","ax","ay","az","scx","scy","scz","scale"];let isdimreload,isfnreload=!1,oo=await muEval(amb,startmacro,startmacro.codice,{leveleval:0,checkheader:op=>{let{variante:variante}=op;if(Array.isArray(startmacro.head)){let ff=startmacro.head.find((e=>e.cod==variante));isfnreload=!!ff}},grafica:async _op=>{let p2,cadv,iscad,des,fatti,{id:id,pars:pars,parametri:parametri,macro:macro,options:options,vari:vari}=_op,isheader=!!(macro&¯o.head&¯o.head.length),sv={l:amb.vari.var("l"),a:amb.vari.var("a"),p:amb.vari.var("p")};const varcad=["l","a","p","#d",...PARSGLOBAL];for(let x of varcad){let tm=amb.vari.dictionary[x];tm&&(sv[x]=tm)}async function _parsepars(x,head){let k,v,r9=/^#(d|des|descrizione)\s*=\s*(.*)\s*$/im.exec(x);if(r9)k="#d",v=await amb.vari.valuta(r9[2]);else{let result=await vari.parametrokeyval(x);k=result.k,v=result.v}k&&!fatti[k]&&(fatti[k]=!0,varcad.includes(k)?"#d"==k?des=v:("string"==typeof v&&(v=muCalc(v)),["l","a","p"].includes(k)&&amb.vari.add(k,String(v)),cadv[k]=v,iscad=!0):"string"==typeof v?p2.push(`${k}=${v}`):amb.vari.add(k,v))}if(p2=[],cadv={},iscad=!1,des="",fatti={},progetto&&progetto.keys&&progetto.keys[id]){let px=progetto.keys[id].pars;if(px)for(let t in px){let t1=amb.vari.dictionary[t];t1&&(sv[t]=t1),await _parsepars(`${t}=${px[t]}`)}}if(pars&&pars.length)for(const par of pars)await _parsepars(par);if(parametri&¶metri.length)for(const param of parametri)await _parsepars(param);if(macro&¯o.head&¯o.head.length){let tm=macro.head.filter((e=>!["g"].includes(e.t)));for(const h of tm)await _parsepars(h.cod)}let out={iscad:iscad,isheader:isheader,name:macro.name,des:des,leveleval:options.leveleval};isheader&&id&&(out.id=id),iscad&&(cadv.l?amb.vari.add("l",String(cadv.l)):cadv.l=muCalc(amb.vari.var("l")),cadv.a?amb.vari.add("a",String(cadv.a)):cadv.a=muCalc(amb.vari.var("a")),cadv.p?amb.vari.add("p",String(cadv.p)):cadv.p=muCalc(amb.vari.var("p")),out.cadv=cadv),await macro.impostaparametri(parametri,p2,!0);let ruleid=rulespec[id];if(id&&isheader&&ruleid&&ruleid.pars&&(out.pars=ruleid.pars,options.leveleval++,await macro.setparametri(ruleid.pars)),out.rows=await muEval(amb,macro,macro.codice,options),id&&isheader&&(out.spars=macro.getparametri()),iscad)for(let x in sv)amb.vari.dictionary[x]=sv[x];return out},parsefnpunto:async _op=>{let{dati:dati,vari:vari,id:id,output:output}=_op;dati=dati.trim();let q=dati.indexOf(" "),q2=dati.indexOf(",");q2>0&&q>0&&q2<q&&(q=q2);let fn,pp,pars={},p2={};q>1?(fn=dati.slice(1,q),pp=getcolonne(dati.slice(q+1))):(fn=dati.slice(1),pp=[]),fnlist.has(fn)||fnlist.add(fn);for(let p of pp){let{k:k,v:v}=await vari.parametrokeyval(p);k&&/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(k)&&(pars[k]=v||"")}for(let l of["l","a","p"])pars[l]||(pars[l]=vari.var(l));let tm=Object.keys(pars);for(let l of PARSGLOBAL)tm.includes(l)&&(p2[l]=muCalc(pars[l]),delete pars[l]);output.push({t:"fn",fn:fn,id:id,pars:pars,p2:p2})}});for(let x of["l","a","p"])if(startmacro.dims&&startmacro.dims[x].val!=parseFloat(amb.vari.var(x))){isdimreload=!0;break}return(isfnreload||isdimreload&&"function"==typeof fnreload)&&await fnreload(isdimreload,isfnreload),{oo:oo,vari:amb.vari.dump(!0),fnlist:[...fnlist]}}function ismacro(row){return"object"==typeof row&&row?.name&&row.rows}function isfn(row){return"object"==typeof row&&"fn"==row?.t}function getnodebyid(id,nodocorrente){let res;return nodocorrente&&nodocorrente.rows&&function _getnode(rows){for(let x of rows){if(ismacro(x)){if(x.id==id)return void(res=x);x.rows&&_getnode(x.rows)}if(res)return}}(nodocorrente.rows),res}function getsubrules(nodocorrente){let res=[];return res.push({id:"",level:0,name:"home"}),function _xfiltrati(rr,level){if(rr.rows&&rr.rows.length)for(let x of rr.rows)ismacro(x)&&(x.id&&x.isheader?(res.push({id:x.id,name:x.name,des:x.des||"",spec:x.pars?1:0,level:level}),_xfiltrati(x,level+1)):_xfiltrati(x,level))}(nodocorrente,1),res}function getprojectkeys(project){return project.keys={},function _getkeys(node){if(node.rows&&node.rows.length)for(let x of node.rows)ismacro(x)&&(x.id&&x.isheader&&x.pars&&(project.keys[x.id]={name:x.name,des:x.des||"",pars:x.pars}),_getkeys(x))}(project),project}function getdumpmacro(nodo){let cl=[];return function _dumpnodo(node){if(node.rows&&node.rows.length)for(let x of node.rows)if(ismacro(x)){x.name;let c=[];if(x.iscad&&x.cadv)for(let k in x.cadv){let t=x.cadv[k];"number"==typeof t&&t&&c.push(`${k}=${t}`)}if(x.pars)for(let k in x.pars){let t=x.pars[k];c.push(`${k}=${t}`)}c.length&&cl.push(`--\x3e ${x.name} ${c.join(",")}`),_dumpnodo(x),c.length&&cl.push("<--")}else isfn(x)?cl.push(`FN: ${x.fn} ${JSON.stringify(x.pars)}`):"string"==typeof x&&x.length&&cl.push(x)}(nodo),cl.join("\n")}function clean(k,locase=!1){return locase?(k||"").trim().toLowerCase():(k||"").trim()}function TODEG(a,dec=1){let C=10**dec;return Math.round(180*a*C/Math.PI)/C}function TORAD(a,dec=3){let C=10**dec;return Math.round(a*PIF*C)/C}const blocked={window:void 0,self:void 0,globalThis:void 0,document:void 0,Function:void 0,eval:void 0,fetch:void 0,XMLHttpRequest:void 0};function getOggetto(obj,exclude=[]){if(Array.isArray(obj))return obj.map((item=>getOggetto(item,exclude)));if(obj&&"object"==typeof obj){const result={};for(const[key,value]of Object.entries(obj))"function"==typeof value||exclude&&exclude.includes(key)||(result[key]=getOggetto(value,exclude));return result}return obj}async function evalcustomfunction(amb,code,values,objects){try{values||(values={}),objects||(objects={});const params={GCAD:!1,...values,A:amb,V:amb.vari,amb:amb,log:function addlog(...pars){const sanitized=pars.map((p=>getOggetto(p)));console.log(...sanitized)},Math:Math,clean:clean,SP:SP,Punto2:Punto2,Linea2:Linea2,clamp:clamp,hash:hash,PIF:PIF,getshape:getshape,shapeclip:shapeclip,...objects},paramNames=[...Object.keys(params),...Object.keys(blocked)],paramValues=[...Object.values(params),...Object.values(blocked)],fn=new Function(...paramNames,`\n try {\n return (async () => {\n ${code}\n })();\n } catch (err) {\n err.stack = '[SCRIPT] ' + err.stack;\n throw err;\n }`);return await fn(...paramValues)}catch(error){throw console.error("Errore durante l'esecuzione:",error),error}}
|
|
538
538
|
/**
|
|
539
539
|
* Crea un MeshStandardMaterial da una stringa compatta tipo:
|
|
540
540
|
* "wood(nr)[s=2,a=45,r=0.7]"
|
|
@@ -542,4 +542,4 @@ function calcoladivisioni(ff,notused,shape2,oggetti){return makedivisions(ff,sha
|
|
|
542
542
|
* @param {string} file - es: "nome(aehr)[s=2,a=30]"
|
|
543
543
|
* @param {object} op - opzioni aggiuntive, scalatura/rotazione incluse
|
|
544
544
|
* @returns {Promise<THREE.MeshStandardMaterial>}
|
|
545
|
-
*/export{Linea2,Matrix3D,PIF,Punto2,SP,TODEG,TORAD,Vis2d,angle2vec,angle3point,blocked,clamp,clean,evalcustomfunction,getOggetto,getdumpmacro,getnodebyid,getprojectkeys,getptsoffset,getshape,getsubrules,hash,isfn,ismacro,normal2,raccordabezier,shapeclip,valutagrafica};
|
|
545
|
+
*/export{Linea2,Matrix3D,PIF,Punto2,SP,TODEG,TORAD,Vis2d,angle2vec,angle3point,blocked,clamp,clean,elaborapercorso,evalcustomfunction,getOggetto,getbordi,getdumpmacro,getnodebyid,getprojectkeys,getptsoffset,getshape,getsubrules,hash,isfn,ismacro,normal2,raccordabezier,shapeclip,valutagrafica};
|
package/bin/markcad3d.js
CHANGED
|
@@ -100,7 +100,7 @@ function getcilindro(gcad,ori,h,r1,r2,mats=mwhite,options){options||(options={})
|
|
|
100
100
|
* @param {Array} mats - Array di materiali
|
|
101
101
|
* @param {Object} options - Opzioni di configurazione
|
|
102
102
|
* @returns {THREE.Group} Gruppo contenente la geometria estrusa
|
|
103
|
-
*/function estruso(gcad,orient,hshape,shape,holes,mats,options){options||(options={}),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),open=options.open||!1,grp=new THREE.Group;if(shape){if(!options.nobase){let g1=bottomgeomfromshape(gcad,!1,shape,open?[]:holes,p0,coeffbase1,coeffbase2);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);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),pat2=shape.to3d(1,p1,coefftop1,-coefftop2,open),ky=`${shape.key}|${p0}|${p1}|${coeffbase1}|${coeffbase2}|${coefftop1}|${coefftop2}|${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}
|
|
103
|
+
*/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),open=options.open||!1,grp=new THREE.Group;if(shape){if(!options.nobase){let g1=bottomgeomfromshape(gcad,!1,shape,open?[]:holes,p0,coeffbase1,coeffbase2);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);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),pat2=shape.to3d(1,p1,coefftop1,-coefftop2,open),ky=`${shape.key}|${p0}|${p1}|${coeffbase1}|${coeffbase2}|${coefftop1}|${coefftop2}|${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}
|
|
104
104
|
/**
|
|
105
105
|
* Crea una geometria estrusa con opzioni avanzate
|
|
106
106
|
* @param {string} orient - Orientamento dell'estrusione
|
package/package.json
CHANGED
package/types/markcad.d.ts
CHANGED
|
@@ -203,6 +203,7 @@ export var SP: Readonly<{
|
|
|
203
203
|
aree: any;
|
|
204
204
|
countid: any;
|
|
205
205
|
};
|
|
206
|
+
elaborapercorso: typeof elaborapercorso;
|
|
206
207
|
getbordi: typeof getbordi;
|
|
207
208
|
makedivisions: typeof makedivisions;
|
|
208
209
|
makeshape: (ff: any, oggetti: any) => {
|
|
@@ -293,8 +294,25 @@ export namespace blocked {
|
|
|
293
294
|
* Classe per la gestione degli errori con funzionalità di accumulo e formattazione
|
|
294
295
|
*/ export function clamp(n: any, min?: number, max?: number): any;
|
|
295
296
|
export function clean(k: any, locase?: boolean): any;
|
|
297
|
+
export function elaborapercorso(sh1: any, bordo: any, taglio: any, oggetti: any, countid?: number): {
|
|
298
|
+
countid: number;
|
|
299
|
+
shape2: any;
|
|
300
|
+
shapetop: any;
|
|
301
|
+
bordi: any[];
|
|
302
|
+
dati: any[];
|
|
303
|
+
draws: any[];
|
|
304
|
+
};
|
|
296
305
|
export function evalcustomfunction(amb: any, code: any, values: any, objects: any): Promise<any>;
|
|
297
306
|
export function getOggetto(obj: any, exclude?: any[]): any;
|
|
307
|
+
export function getbordi(oggetti: any, bordo: any): {
|
|
308
|
+
bordi: any[];
|
|
309
|
+
uguali: boolean;
|
|
310
|
+
senza: boolean;
|
|
311
|
+
bl: any;
|
|
312
|
+
bt: any;
|
|
313
|
+
br: any;
|
|
314
|
+
bb: any;
|
|
315
|
+
};
|
|
298
316
|
export function getdumpmacro(nodo: any): string;
|
|
299
317
|
export function getnodebyid(id: any, nodocorrente: any): any;
|
|
300
318
|
export function getprojectkeys(project: any): any;
|
|
@@ -429,15 +447,6 @@ declare function creaprofiloesterno(ff: any, oggetti: any): {
|
|
|
429
447
|
dati: any[];
|
|
430
448
|
draws: any[];
|
|
431
449
|
};
|
|
432
|
-
declare function getbordi(oggetti: any, bordo: any): {
|
|
433
|
-
bordi: any[];
|
|
434
|
-
uguali: boolean;
|
|
435
|
-
senza: boolean;
|
|
436
|
-
bl: any;
|
|
437
|
-
bt: any;
|
|
438
|
-
br: any;
|
|
439
|
-
bb: any;
|
|
440
|
-
};
|
|
441
450
|
declare function makedivisions(ff: any, shape2: any, oggetti: any): {
|
|
442
451
|
ff: any;
|
|
443
452
|
h1: {
|