// Do not edit this file; automatically generated by blockscad_build.py. "use strict"; var Blockscad=Blockscad||{},CSG=CSG||{},CAG=CAG||{}; Blockscad.Viewer=function(g,l,p,k){var c=GL.create();this.gl=c;this.angleX=-60;this.angleY=0;this.angleZ=-45;this.viewpointX=0;this.viewpointY=-5;this.viewpointZ=k;this.defaultColor=[1,.5,1,1];this.touch={lastX:0,lastY:0,scale:0,ctrl:0,shiftTimer:null,shiftControl:null,cur:null};this.lineOverlay=this.drawLines=!1;c.canvas.width=l;c.canvas.height=p;c.viewport(0,0,l,p);c.matrixMode(c.PROJECTION);c.loadIdentity();c.perspective(45,l/p,1,3E3);c.matrixMode(c.MODELVIEW);c.blendFunc(c.SRC_ALPHA,c.ONE_MINUS_SRC_ALPHA); c.clearColor(1,1,1,1);c.enable(c.DEPTH_TEST);c.enable(c.CULL_FACE);c.polygonOffset(1,1);this.blackShader=new GL.Shader("void main() {gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;}","void main() {gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);}");this.lightingShader=new GL.Shader("varying vec3 color;varying float alpha;varying vec3 normal;varying vec3 light;void main() {const vec3 lightDir = vec3(1.0, 2.0, 3.0) / 3.741657386773941;light = lightDir;color = gl_Color.rgb;alpha = gl_Color.a;normal = gl_NormalMatrix * gl_Normal;gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;}", "varying vec3 color;varying float alpha;varying vec3 normal;varying vec3 light;void main() {vec3 n = normalize(normal);float diffuse = max(0.0, dot(light, n));float specular = pow(max(0.0, -reflect(light, n).z), 18.0) * sqrt(diffuse);gl_FragColor = vec4(mix(color * (0.3 + 0.7 * diffuse), vec3(1.0), specular), alpha);}");var n=this,a=$('
'); this.touch.shiftControl=a;$(g).append(c.canvas).append(a).hammer({drag_lock_to_axis:!0}).on("transform",function(a){2<=a.gesture.touches.length&&(n.clearShift(),n.onTransform(a),a.preventDefault())}).on("touch",function(b){if("touch"!=b.gesture.pointerType)b.preventDefault();else if(1==b.gesture.touches.length){var d=b.gesture.center;n.touch.shiftTimer=setTimeout(function(){a.addClass("active").css({left:d.pageX+"px",top:d.pageY+"px"});n.touch.shiftTimer=null;n.touch.cur="shifting"},500)}else n.clearShift()}).on("drag", function(a){if("touch"!=a.gesture.pointerType)a.preventDefault();else if(!n.touch.cur||"dragging"==n.touch.cur)n.clearShift(),n.onPanTilt(a);else if("shifting"==n.touch.cur)n.onShift(a)}).on("touchend",function(b){n.clearShift();n.touch.cur&&a.removeClass("active shift-horizontal shift-vertical")}).on("transformend dragstart dragend",function(a){if("transformend"==a.type&&"transforming"==n.touch.cur||"dragend"==a.type&&"shifting"==n.touch.cur||"dragend"==a.type&&"dragging"==n.touch.cur)n.touch.cur= null;n.touch.lastX=0;n.touch.lastY=0;n.touch.scale=0});c.onmousemove=function(a){n.onMouseMove(a)};c.ondraw=function(){n.onDraw()};c.onmousewheel=function(a){var b=0;a.wheelDelta?b=a.wheelDelta:a.detail&&(b=-40*a.detail);b&&(a=Math.pow(1.003,-(b/2)),b=n.getZoom(),n.setZoom(b*a))};this.clear()}; Blockscad.Viewer.prototype={setCsg:function(g){this.gl.makeCurrent();this.meshes=Blockscad.Viewer.csgToMeshes(g,this.defaultColor);this.onDraw()},rendered_resize:function(g,l){this.gl.canvas.width=g;this.gl.canvas.height=l;this.gl.viewport(0,0,g,l);this.gl.matrixMode(this.gl.PROJECTION);this.gl.loadIdentity();this.gl.perspective(45,g/l,1,3E3);this.gl.matrixMode(this.gl.MODELVIEW);this.onDraw()},viewReset:function(g){g=g?g:document.getElementById("viewMenu").value;"diagonal"==g?(this.angleX=-60,this.angleY= 0,this.angleZ=-45,this.viewpointX=0,this.viewpointY=-5,this.viewpointZ=100):"top"==g?(this.viewpointY=this.viewpointX=this.angleZ=this.angleY=this.angleX=0,this.viewpointZ=100):"bottom"==g?(this.angleX=180,this.viewpointY=this.viewpointX=this.angleZ=this.angleY=0,this.viewpointZ=100):"right"==g?(this.angleX=-90,this.viewpointY=this.viewpointX=this.angleZ=this.angleY=0,this.viewpointZ=100):"front"==g?(this.angleX=-90,this.angleY=0,this.angleZ=-90,this.viewpointY=this.viewpointX=0,this.viewpointZ=100): "left"==g?(this.angleX=-90,this.angleY=0,this.angleZ=180,this.viewpointY=this.viewpointX=0,this.viewpointZ=100):"back"==g&&(this.angleX=-90,this.angleY=0,this.angleZ=90,this.viewpointY=this.viewpointX=0,this.viewpointZ=100);this.onDraw()},clear:function(){this.meshes=[];this.onDraw()},supported:function(){return!!this.gl},ZOOM_MAX:1500,ZOOM_MIN:5,onZoomChanged:null,plate:!0,setZoom:function(g){g=Math.max(g,0);g=Math.min(g,1);this.viewpointZ=this.ZOOM_MIN+g*(this.ZOOM_MAX-this.ZOOM_MIN);if(this.onZoomChanged)this.onZoomChanged(); this.onDraw()},getZoom:function(){return(this.viewpointZ-this.ZOOM_MIN)/(this.ZOOM_MAX-this.ZOOM_MIN)},zoomOut:function(){var g=this.getZoom();this.setZoom(1.15*g)},zoomIn:function(){var g=this.getZoom();this.setZoom(.85*g)},onMouseMove:function(g){if(g.dragging){var l=g.button;g.which&&(l=g.which);g.preventDefault();g.altKey||3==l?(this.angleY+=g.deltaX,this.angleX+=g.deltaY):g.shiftKey||2==l?(l=.005,this.viewpointX+=l*g.deltaX*this.viewpointZ,this.viewpointY-=l*g.deltaY*this.viewpointZ):g.ctrlKey? (l=Math.pow(1.006,g.deltaX+g.deltaY),g=this.getZoom(),this.setZoom(g*l)):(this.angleZ+=g.deltaX,this.angleX+=g.deltaY);this.onDraw()}},clearShift:function(){this.touch.shiftTimer&&(clearTimeout(this.touch.shiftTimer),this.touch.shiftTimer=null);return this},onPanTilt:function(g){this.touch.cur="dragging";var l=0;!this.touch.lastY||"up"!=g.gesture.direction&&"down"!=g.gesture.direction?!this.touch.lastX||"left"!=g.gesture.direction&&"right"!=g.gesture.direction||(l=g.gesture.deltaX-this.touch.lastX, this.angleZ+=l):(l=g.gesture.deltaY-this.touch.lastY,this.angleX+=l);if(l)this.onDraw();this.touch.lastX=g.gesture.deltaX;this.touch.lastY=g.gesture.deltaY},onShift:function(g){this.touch.cur="shifting";var l=0;!this.touch.lastY||"up"!=g.gesture.direction&&"down"!=g.gesture.direction||(this.touch.shiftControl.removeClass("shift-horizontal").addClass("shift-vertical").css("top",g.gesture.center.pageY+"px"),l=g.gesture.deltaY-this.touch.lastY,this.viewpointY-=.005*l*this.viewpointZ,this.angleX+=l); !this.touch.lastX||"left"!=g.gesture.direction&&"right"!=g.gesture.direction||(this.touch.shiftControl.removeClass("shift-vertical").addClass("shift-horizontal").css("left",g.gesture.center.pageX+"px"),l=g.gesture.deltaX-this.touch.lastX,this.viewpointX+=.005*l*this.viewpointZ,this.angleZ+=l);if(l)this.onDraw();this.touch.lastX=g.gesture.deltaX;this.touch.lastY=g.gesture.deltaY},onTransform:function(g){this.touch.cur="transforming";if(this.touch.scale){var l=1/(1+g.gesture.scale-this.touch.scale), p=this.getZoom();this.setZoom(p*l)}this.touch.scale=g.gesture.scale;return this},onDraw:function(g,l,p){var k=this.gl;k.makeCurrent();g&&k.clearColor(1,1,1,1);if(g&&this.meshes[0]){l+=3*Math.PI/4;var c=this.bsph,n=this.bbox,n=1.3-(n[1].z-n[0].z)/(2*c.radius),a=2.6*c.radius;k.matrixMode(k.PROJECTION);k.loadIdentity();k.perspective(45,k.canvas.width/k.canvas.height,1,3E3);k.matrixMode(k.MODELVIEW);k.loadIdentity();k.lookAt(c.center.x+a*Math.sin(l),c.center.y+a*Math.cos(l),c.center.z+n*a/2,c.center.x, c.center.y,c.center.z,0,0,1)}else k.matrixMode(k.PROJECTION),k.loadIdentity(),k.perspective(45,k.canvas.width/k.canvas.height,1,3E3),k.matrixMode(k.MODELVIEW),k.loadIdentity(),k.translate(this.viewpointX,this.viewpointY,-this.viewpointZ),k.rotate(this.angleX,1,0,0),k.rotate(this.angleY,0,1,0),k.rotate(this.angleZ,0,0,1);k.clear(k.COLOR_BUFFER_BIT|k.DEPTH_BUFFER_BIT);k.enable(k.BLEND);this.lineOverlay||k.enable(k.POLYGON_OFFSET_FILL);for(l=0;l=l;l++)l%10&&0!==l&&(k.vertex(-100,l,0),k.vertex(100,l,0),k.vertex(l,-100,0),k.vertex(l,100,0),l<200/2.8&&l>-200/2.8&&(k.vertex(-.5,0,l),k.vertex(.5,0,l),k.vertex(0,-.5,l),k.vertex(0,.5,l)));k.color(.5,.5,.5,.5);for(l=10;100>=l;l+=10)0!==l&&(k.vertex(-100,l,0),k.vertex(100,l,0),k.vertex(l,-100,0),k.vertex(l,100,0),k.vertex(-100,-l,0),k.vertex(100,-l,0),k.vertex(-l,-100,0),k.vertex(-l,100,0),l<200/2.8&&(k.vertex(-1,0,l),k.vertex(1,0,l),k.vertex(0,-1,l),k.vertex(0,1,l),k.vertex(-1,0,-l),k.vertex(1, 0,-l),k.vertex(0,-1,-l),k.vertex(0,1,-l)))}k.color(1,0,0,1);k.vertex(0,0,0);k.vertex(100,0,0);for(l=-100;0>l;l++)l%2&&(k.vertex(l,0,0),k.vertex(l+1,0,0));k.color(0,.7,0,1);k.vertex(0,0,0);k.vertex(0,100,0);for(l=-100;0>l;l++)l%2&&(k.vertex(0,l,0),k.vertex(0,l+1,0));k.color(.1,.1,.4,1);k.vertex(0,0,0);k.vertex(0,0,200/2.8);for(l=Math.floor(-200/2.8);0>l;l++)l%2&&(k.vertex(0,0,l),k.vertex(0,0,l+1));k.color(0,0,0,1);k.vertex(102.5,-2.5,0);k.vertex(107.5,2.5,0);k.vertex(102.5,2.5,0);k.vertex(107.5,-2.5, 0);k.vertex(-2.5,110,0);k.vertex(0,107.5,0);k.vertex(0,107.5,0);k.vertex(2.5,110,0);k.vertex(0,102.5,0);k.vertex(0,107.5,0);k.vertex(-2.5,0,200/2.8+7.5);k.vertex(2.5,0,200/2.8+7.5);k.vertex(-2.5,0,200/2.8+2.5);k.vertex(2.5,0,200/2.8+2.5);k.vertex(-2.5,0,200/2.8+2.5);k.vertex(2.5,0,200/2.8+7.5);k.end();k.disable(k.BLEND)}if(g)return p=[],p[0]=this.gl.canvas.toDataURL("image/jpeg",g),k=document.createElement("canvas"),l=k.getContext("2d"),k.height=.5*this.gl.canvas.height,k.width=.5*this.gl.canvas.height, l.drawImage(this.gl.canvas,0,0,k.width,k.height),l=document.createElement("canvas"),c=l.getContext("2d"),l.height=.5*k.height,l.width=.5*k.width,c.drawImage(k,0,0,.5*k.width,.5*k.height),p[1]=l.toDataURL("image/jpeg",g),p;if(p)return this.gl.canvas.toDataURL("image/jpeg",p)},takePic:function(g,l){return this.onDraw(g,l)},takeCameraPic:function(g){return this.onDraw(0,0,g)}}; Blockscad.Viewer.csgToMeshes=function(g,l){for(var p=g.canonicalized(),k=new GL.Mesh({normals:!0,colors:!0}),c=[k],n=[],a=[],b=[],p=p.toPolygons(),d=p.length,e=0;eh.length&&h.push(1);for(var f=f.vertices.map(function(b){b.getTag();var d;d=n.length;n.push([b.pos.x,b.pos.y,b.pos.z]);a.push(h);return d}),m=2;m'):"log"==a.data.cmd&&console.log(a.data.txt)};k.onerror=function(a){l("Error in line "+a.lineno+": "+a.message,null)};var p=[],c=[],n;for(n in Blockscad.fonts)p.push(n),c.push(Blockscad.fonts[n]);k.postMessage({cmd:"render",data:g,fontkeys:p,fontdata:c,csg_filename:Blockscad.csg_filename,csg_commands:Blockscad.csg_commands});return k}; Blockscad.getWindowURL=function(){if(window.URL)return window.URL;if(window.webkitURL)return window.webkitURL;throw Error("Your browser doesn't support window.URL");};Blockscad.textToBlobUrl=function(g){var l=Blockscad.getWindowURL();g=new Blob([g]);l=l.createObjectURL(g);if(!l)throw Error("createObjectURL() failed");return l}; Blockscad.revokeBlobUrl=function(g){if(window.URL)window.URL.revokeObjectURL(g);else if(window.webkitURL)window.webkitURL.revokeObjectURL(g);else throw Error("Your browser doesn't support window.URL");};Blockscad.AlertUserOfUncaughtExceptions=function(){window.onerror=function(g,l,p){g=g.replace(/^Uncaught /i,"");alert(g+"\n\n("+l+" line "+p+")")}}; Blockscad.Processor=function(g,l){this.containerdiv=g;this.onchange=l;this.rpicviewer=this.picviewer=this.viewer=this.picdiv=this.viewerdiv=null;this.initialViewerDistance=100;this.processing=!1;this.currentObject=null;this.hasOutputFile=this.hasValidCurrentObject=!1;this.worker=null;this.paramDefinitions=[];this.paramControls=[];this.script=null;this.debugging=this.hasError=!1;this.img=this.imgStrip=this.thumbnail="none";this.createElements()}; Blockscad.Processor.convertToSolid=function(g){if("object"!=typeof g||!(g instanceof CAG||g instanceof CSG))throw Error("Cannot convert to solid");return g}; Blockscad.Processor.prototype={createElements:function(){for(var g=this;7

BlocksCAD currently requires Google Chrome or Firefox with WebGL enabled"}$("#picdiv").addClass("hidden");try{this.rpicviewer=new Blockscad.Viewer(this.rpicdiv,k.offsetWidth,k.offsetHeight,this.initialViewerDistance)}catch(c){this.rpicdiv.innerHTML="

Error: "+c.toString()+"


BlocksCAD currently requires Google Chrome or Firefox with WebGL enabled"}$("#rpicdiv").addClass("hidden"); try{this.viewer=new Blockscad.Viewer(this.viewerdiv,l.offsetWidth,l.offsetHeight,this.initialViewerDistance)}catch(c){this.viewerdiv.innerHTML="

Error: "+c.toString()+"


BlocksCAD currently requires Google Chrome or Firefox with WebGL enabled"}this.abortbutton=document.getElementById("abortButton");this.renderbutton=document.getElementById("renderButton");this.ongoingrender=document.getElementById("render-ongoing");this.abortbutton.onclick=function(c){g.abort()};this.formatDropdown= document.getElementById("render-type");this.formatDropdown.onchange=function(c){g.currentFormat=g.formatDropdown.options[g.formatDropdown.selectedIndex].value;g.updateDownloadLink()};this.generateOutputFileButton=document.getElementById("stlButton");this.generateOutputFileButton.onclick=function(c){g.generateOutputFile()};this.enableItems()},setCurrentObject:function(g,l){var p=Blockscad.Processor.convertToSolid(g);this.currentObject=p;this.hasValidCurrentObject=!0;this.viewer&&this.viewer.setCsg(p); this.picviewer&&(this.picviewer.bbox=p.getBounds(),this.picviewer.bsph=p.getBoundingSphere(),this.picviewer.setCsg(p));this.rpicviewer&&(this.rpicviewer.bbox=p.getBounds(),this.rpicviewer.bsph=p.getBoundingSphere(),this.rpicviewer.setCsg(p));if(l){for($("#stl_buttons").removeClass("hidden");0'),this.processing=!1,this.worker.terminate(),this.enableItems(),this.onchange))this.onchange()},enableItems:function(){this.abortbutton.style.display=this.processing?"inline-block": "none";this.renderbutton.style.display=this.processing?"none":"inline-block";this.ongoingrender.style.display=this.processing?"inline-block":"none"},setError:function(g){this.hasError=""!=g;$("#error-message").text(g);this.enableItems()},setDebugging:function(g){this.debugging=g},setBlockscad:function(g){this.script=g;this.rebuildSolid()},rebuildSolid:function(){this.abort();this.setError("");this.clearViewer();this.processing=!0;$("#renderButton").html(Blockscad.Msg.RENDER_BUTTON);$("#renderButton").prop("disabled", !1);this.enableItems();var g=this,l=this.debugging;if(!l)try{this.worker=Blockscad.parseBlockscadScriptASync(this.script,function(k,c){if(k&&"finalMesh"==k){$("#render-ongoing").html(Blockscad.Msg.PARSE_IN_PROGRESS+'');g.processing=!1;g.setCurrentObject(c,!0);var l=g.picviewer.takePic(Blockscad.picQuality,0,1);g.img=l[0];g.thumbnail=l[1];g.imgStrip=g.takeRotatingPic(1,Blockscad.numRotPics);g.processing=!1;g.worker=null}else k&&"rendered"==k?($("#render-ongoing").html('Prepare for Download...'), g.setCurrentObject(c,!1),l=g.picviewer.takePic(Blockscad.picQuality,0,1),g.img=l[0],g.thumbnail=l[1],g.imgStrip=g.takeRotatingPic(1,Blockscad.numRotPics)):(console.log("what is going on?"),console.log("error in proc"+k),g.processing=!1,g.worker=null,g.setError(k));if(g.onchange)g.onchange();g.enableItems()})}catch(k){console.log("async failed, try sync compute, error: "+k.message),l=!0}if(l){try{var p=Blockscad.parseBlockscadScriptSync(this.script,this.debugging);g.setCurrentObject(p);g.processing= !1}catch(k){g.processing=!1,(l=k.stack)||(l=k.toString()),g.setError(l)}g.enableItems();if(g.onchange)g.onchange()}},hasSolid:function(){return this.hasValidCurrentObject},isProcessing:function(){return this.processing},clearOutputFile:function(){if(this.hasOutputFile&&(this.outputFileBlobUrl&&(Blockscad.revokeBlobUrl(this.outputFileBlobUrl),this.outputFileBlobUrl=null),this.enableItems(),this.onchange))this.onchange()},generateOutputFile:function(){this.clearOutputFile();this.hasValidCurrentObject&& this.generateAndSaveRenderedFile()},currentObjectToBlob:function(){var g=this.selectedFormat();if("stla"==g)g=this.currentObject.toStlString(),g=new Blob([g],{type:"text/plain; charset=utf-8"});else if("stlb"==g)g=this.currentObject.toStlBinary({webBlob:!0});else if("amf"==g)g=this.currentObject.toAMFString({producer:"BlocksCAD "+Blockscad.version,date:new Date}),g=new Blob([g],{type:"text/plain; charset=utf-8"});else if("x3d"==g)g=this.currentObject.toX3D(),g=new Blob([g],{type:"text/plain; charset=utf-8"}); else if("dxf"==g)g=this.currentObject.toDxf(),g=new Blob([g],{type:"text/plain; charset=utf-8"});else if("obj"==g)g=this.currentObject.toObj(),g=new Blob([g],{type:"text/plain; charset=utf-8"});else throw Error("Not supported");return g},supportedFormatsForCurrentObject:function(){if(this.currentObject instanceof CSG)return-1!=navigator.userAgent.indexOf("Safari")&&-1==navigator.userAgent.indexOf("Chrome")?["stla","amf","x3d"]:["stlb","stla","x3d","obj","amf"];if(this.currentObject instanceof CAG)return["dxf"]; throw Error("Not supported");},formatInfo:function(g){return{stla:{displayName:"STL (ASCII)",extension:"stl",mimetype:"application/sla"},obj:{displayName:"OBJ (ASCII)",extension:"obj",mimetype:"application/sla"},stlb:{displayName:"STL (Binary)",extension:"stl",mimetype:"application/sla"},amf:{displayName:"AMF",extension:"amf",mimetype:"application/amf+xml"},x3d:{displayName:"X3D",extension:"x3d",mimetype:"model/x3d+xml"},dxf:{displayName:"DXF",extension:"dxf",mimetype:"application/dxf"}}[g]},generateAndSaveRenderedFile:function(){var g= this.currentObjectToBlob(),l=this.selectedFormatInfo().extension,p=$("#project-name").val();p?saveAs(g,p+"."+l):($("#message-text").html("

"+Blockscad.Msg.SAVE_FAILED+" "+Blockscad.Msg.SAVE_FAILED_PROJECT_NAME+".

"),$("#message-modal").modal())},takeRotatingPic:function(g,l){var p=[],k=[],c=document.createElement("canvas");c.width=Blockscad.rpicSize[0]*l;c.height=Blockscad.rpicSize[0];for(var n=c.getContext("2d"),a=0;ap.length&&(p=[]);return[p,k]};(function(g){function l(a,b){return a-b}function p(a,b,d){for(var c=0,f=a.length;f>c;){var h=Math.floor((c+f)/2);0=b&&(b=1E-4);var d=this.getBounds(),e=0,f=0;a[0]?(e=d[1].x-d[0].x,f=d[0].x):a[1]?(e=d[1].y-d[0].y,f=d[0].y):a[2]&& (e=d[1].z-d[0].z,f=d[0].z);for(var d=[],h,m,q=0;qA&&(A+=2*Math.PI);p.push(A);A=Math.atan2(-t,-y);0>A&&(A+=2*Math.PI);p.push(A)}var p=p.sort(l),q=p.length,w,x,B=[],v=[],z=[];for(d=-1;dd?d+q:d],t=Math.sin(A),y=Math.cos(A),y=k.times(y*a).plus(n.times(t*a)),t=u.plus(y),y=g.plus(y),A=!1,0<=d&&1E-5> t.distanceTo(w)&&(A=!0),A||(0<=d&&(B.push(new c.Vertex(t)),v.push(new c.Vertex(y)),w=[new c.Vertex(x),new c.Vertex(y),new c.Vertex(t),new c.Vertex(w)],w=new c.Polygon(w),z.push(w)),w=t,x=y);v.reverse();z.push(new c.Polygon(B));z.push(new c.Polygon(v));d=c.fromPolygons(z);f=f.unionSub(d,!1,!1)}var D={};e.polygons.map(function(a){a.vertices.map(function(b){var d=b.getTag();d in D?b=D[d]:(b={pos:b.pos,normals:[]},D[d]=b);b.normals.push(a.plane.normal)})});for(var C in D){e=D[C];m=e.normals[0].unit(); u=null;g=0;for(d=1;dg&&(g=w,u=k);u||(u=m.randomNonParallelVector());d=m.cross(u).unit();u=d.cross(m);d=c.sphere({center:e.pos,radius:a,resolution:b,axes:[m,d,u]});f=f.unionSub(d,!1,!1)}return f},canonicalized:function(){if(this.isCanonicalized)return this;var a=(new c.fuzzyCSGFactory).getCSG(this);a.isCanonicalized=!0;a.isRetesselated=this.isRetesselated;a.properties=this.properties;return a},reTesselated:function(){if(this.isRetesselated)return this; var a={},b=this.isCanonicalized,d=new c.fuzzyCSGFactory;this.polygons.map(function(c){var e=c.plane,f=c.shared;b||(e=d.getPlane(e),f=d.getPolygonShared(f));e=e.getTag()+"/"+f.getTag();e in a?a[e].push(c):a[e]=[c]});var e=[],f;for(f in a){var h=a[f];if(2>h.length)e=e.concat(h);else{var m=[];c.reTesselateCoplanarPolygons(h,m);e=e.concat(m)}}e=c.fromPolygons(e);e.isRetesselated=!0;e.properties=this.properties;return e},getBounds:function(){if(!this.cachedBoundingBox){for(var a=new c.Vector3D(0,0,0), b=new c.Vector3D(0,0,0),d=this.polygons,e=d.length,f=0;fa[1].x||b[1].ya[1].y||b[1].za[1].z?!1:!0},cutByPlane:function(a){if(0===this.polygons.length)return new c;var b=a.normal.times(a.w), d=0;this.polygons.map(function(a){a.vertices.map(function(a){a=a.pos.distanceToSquared(b);a>d&&(d=a)})});var d=Math.sqrt(d),d=1.01*d,e=[],f=new c.OrthoNormalBasis(a);e.push(new c.Vertex(f.to3D(new c.Vector2D(d,-d))));e.push(new c.Vertex(f.to3D(new c.Vector2D(-d,-d))));e.push(new c.Vertex(f.to3D(new c.Vector2D(-d,d))));e.push(new c.Vertex(f.to3D(new c.Vector2D(d,d))));a=(new c.Polygon(e,null,a.flipped())).extrude(a.normal.times(-d));a=this.intersect(a);a.properties=this.properties;return a},connectTo:function(a, b,d,c){a=a.getTransformationTo(b,d,c);return this.transform(a)},setShared:function(a){var b=this.polygons.map(function(b){return new c.Polygon(b.vertices,a,b.plane)}),b=c.fromPolygons(b);b.properties=this.properties;b.isRetesselated=this.isRetesselated;b.isCanonicalized=this.isCanonicalized;return b},sC:function(a){var b=c.Polygon.Shared.fromColor.apply(this,arguments);return this.setShared(b)},toCompactBinary:function(){var a=this.canonicalized(),b=a.polygons.length,d=0,c=0,f={},h=[],m=0,q={},u= 0,g=[],k=[],l={},n=0;a.polygons.map(function(a){a.vertices.map(function(a){++d;var b=a.getTag();b in f||(f[b]=c++,h.push(a))});var b=a.plane.getTag();b in q||(q[b]=m++,g.push(a.plane));b=a.shared.getTag();b in l||(l[b]=n++,k.push(a.shared))});for(var p=new Uint32Array(b),v=new Uint32Array(b),t=new Uint32Array(d),y=new Uint32Array(b),A=new Float64Array(3*c),w=new Float64Array(4*m),x=0,u=0;uy?(t=new c.Connector(v,p.normal,d),v=t.getTransformationTo(h,!1,0),t=h.getTransformationTo(t,!1,0)):(t=new c.Connector(v,p.normal,e),v=t.getTransformationTo(m,!1,0),t=m.getTransformationTo(t,!1,0));var y=a.transform(v),p=-p.normal.dot(f),A=y.getBounds(),y=A[1].z-A[0].z;q||(yg&&(q=!0));q&&(u=new c.Vector3D([-.5*(A[1].x+A[0].x),-.5*(A[1].y+A[0].y),-A[0].z]),v=v.multiply(c.Matrix4x4.translation(u)), t=c.Matrix4x4.translation(u.negated()).multiply(t),u=y,g=p,k=v,l=t);q=!1}return[k,l]},getTransformationToFlatLying:function(){return this.getTransformationAndInverseTransformationToFlatLying()[0]},lieFlat:function(){var a=this.getTransformationToFlatLying();return this.transform(a)},projectToOrthoNormalBasis:function(a){var b=[];this.polygons.filter(function(b){return b.plane.normal.minus(a.plane.normal).lengthSquared()<1E-5*1E-5}).map(function(d){d=d.projectToOrthoNormalBasis(a);0d.x||0>d.y||0>d.z)throw Error("Dimension should be positive");if(5E-4>d.x||5E-4>d.y||5E-4>d.z)return console.log("Throwing out a zero-length cube."), new c;a=c.fromPolygons([[[0,4,6,2],[-1,0,0]],[[1,3,7,5],[1,0,0]],[[0,1,5,4],[0,-1,0]],[[2,6,7,3],[0,1,0]],[[0,2,3,1],[0,0,-1]],[[4,5,7,6],[0,0,1]]].map(function(a){a=a[0].map(function(a){a=new c.Vector3D(b.x+d.x*(2*!!(a&1)-1),b.y+d.y*(2*!!(a&2)-1),b.z+d.z*(2*!!(a&4)-1));return new c.Vertex(a)});return new c.Polygon(a,null)}));a.properties.cube=new c.Properties;a.properties.cube.center=new c.Vector3D(b);a.properties.cube.facecenters=[new c.Connector((new c.Vector3D([d.x,0,0])).plus(b),[1,0,0],[0,0, 1]),new c.Connector((new c.Vector3D([-d.x,0,0])).plus(b),[-1,0,0],[0,0,1]),new c.Connector((new c.Vector3D([0,d.y,0])).plus(b),[0,1,0],[0,0,1]),new c.Connector((new c.Vector3D([0,-d.y,0])).plus(b),[0,-1,0],[0,0,1]),new c.Connector((new c.Vector3D([0,0,d.z])).plus(b),[0,0,1],[1,0,0]),new c.Connector((new c.Vector3D([0,0,-d.z])).plus(b),[0,0,-1],[1,0,0])];return a};c.sphere=function(a){a=a||{};var b=c.parseOptionAs3DVector(a,"center",[0,0,0]),d=c.parseOptionAsFloat(a,"radius",1),e=c.parseOptionAsInt(a, "res",c.defaultResolution3D),f,h;if(0>d)throw Error("Radius should be positive");if(1E-6>d)return console.log("Throwing out a zero-radius sphere."),new c;"axes"in a?(f=a.axes[0].unit().times(d),h=a.axes[1].unit().times(d),a=a.axes[2].unit().times(d)):(f=(new c.Vector3D([1,0,0])).times(d),h=(new c.Vector3D([0,-1,0])).times(d),a=(new c.Vector3D([0,0,1])).times(d));4>e&&(e=4);for(var d=Math.round(e/4),m,q=[],u=0;u<=e;u++){var g=2*Math.PI*u/e,g=f.times(Math.cos(g)).plus(h.times(Math.sin(g)));if(0h||0>f)throw Error("Radius should be non-negative");if(5E-4>Math.abs(e.z-d.z)||5E-4>h&&5E-4>f)return console.log("throwing out a zero-height cylinder or a cylinder with both ends < 0.0005"),new c;var q=c.parseOptionAsInt(a,"res",c.defaultResolution2D),u=e.minus(d);a=u.unit();var k=a.randomNonParallelVector().unit(), g=k.cross(a).unit(),l=new c.Vertex(d),p=new c.Vertex(e),n=[];if(0m&&(n.push(new c.Polygon([l, p,b(0,0,f)])),n.push(new c.Polygon([b(0,0,f),p,b(1,0,h)])),n.push(new c.Polygon([l,b(0,1,f),p])),n.push(new c.Polygon([b(0,1,f),b(1,1,h),p])))}q=c.fromPolygons(n);q.properties.cylinder=new c.Properties;q.properties.cylinder.start=new c.Connector(d,a.negated(),k);q.properties.cylinder.end=new c.Connector(e,a,k);e=d.plus(u.times(.5));h=k.rotate(d,a,-m/2).times((f+h)/2);f=h.cross(a);q.properties.cylinder.facepointH=new c.Connector(e.plus(h),h,a);q.properties.cylinder.facepointH90=new c.Connector(e.plus(f), f,a);return q};c.roundedCylinder=function(a){var b=c.parseOptionAs3DVector(a,"start",[0,-1,0]),d=c.parseOptionAs3DVector(a,"end",[0,1,0]),e=c.parseOptionAsFloat(a,"radius",1),f=d.minus(b),h;h=Math.abs(f.x)>Math.abs(f.y)?new c.Vector3D(0,1,0):new c.Vector3D(1,0,0);var m=c.parseOptionAs3DVector(a,"normal",h);a=c.parseOptionAsInt(a,"resolution",c.defaultResolution3D);4>a&&(a=4);h=[];var q=Math.floor(.25*a);if(1E-10>f.length())return c.sphere({center:b,radius:e,resolution:a});for(var k=f.unit().times(e), f=k.cross(m).unit().times(e),e=f.cross(k).unit().times(e),g,m=0;m<=a;m++){var l=2*Math.PI*m/a,l=f.times(Math.cos(l)).plus(e.times(Math.sin(l)));if(0e&&(e=4);1==e%2&&8>e&&(e=8);a=c.parseOptionAs3DVector(a,"roundradius",[.2,.2,.2]);a=c.Vector3D.Create(Math.max(a.x,.01),Math.max(a.y,.01),Math.max(a.z,.01));var f=d.minus(a);if(0>f.x||0>f.y||0>f.z)throw"roundradius <= radius!";e=c.sphere({radius:1, resolution:e});e=e.scale(a);1E-5a.length||3b)a=Math.sqrt(a),this._x/=a,this._y/=a,this._z/=a},set:function(a,b,d){this._x=a;this._y=b;this._z=d}};c.Vertex=function(a){this.pos=a};c.Vertex.fromObject=function(a){a=new c.Vector3D(a.pos);return new c.Vertex(a)};c.Vertex.prototype={flipped:function(){return this},getTag:function(){var a=this.tag;a||(this.tag=a=c.getTag());return a},interpolate:function(a,b){var d=this.pos.lerp(a.pos,b);return new c.Vertex(d)},transform:function(a){a=this.pos.multiply4x4(a); return new c.Vertex(a)},toString:function(){return this.pos.toString()}};c.hVertex=function(a,b,d,e){this.pnt=new c.Vector3D(a,b,d);4==arguments.length&&(this.index=e);this.face=this.prev=this.next=null};c.hVertex.prototype={clone:function(){return new c.hVertex(this._x,this._y,this._z,this.index)}};c.hVertexList=function(){this.tail=this.head=null};c.hVertexList.prototype={clear:function(){this.tail=this.head=null},add:function(a){null==this.head?this.head=a:this.tail.next=a;a.prev=this.tail;a.next= null;this.tail=a},addAll:function(a){null==this.head?this.head=a:this.tail.next=a;for(a.prev=this.tail;null!=a.next;)a=a.next;this.tail=a},"delete":function(a,b){1==arguments.length?(null==a.prev?this.head=a.next:a.prev.next=a.next,null==a.next?this.tail=a.prev:a.next.prev=a.prev):2==arguments.length&&(null==a.prev?this.head=b.next:a.prev.next=b.next,null==b.next?this.tail=a.prev:b.next.prev=a.prev)},insertBefore:function(a,b){a.prev=b.prev;null==b.prev?this.head=a:b.prev.next=a;a.next=b;b.prev=a}, first:function(){return this.head},isEmpty:function(){return null==this.head}};c.HalfEdge=function(a,b){2==arguments.length?(this.vertex=a,this.face=b):this.face=this.vertex=null;this.opposite=this.next=this.prev=null};c.HalfEdge.prototype={setNext:function(a){this.next=a},getNext:function(){return this.next},setPrev:function(a){this.prev=a},getPrev:function(){return this.prev},getFace:function(){return this.face},getOpposite:function(){return this.opposite},setOpposite:function(a){this.opposite= a;a.opposite=this},head:function(){return this.vertex},tail:function(){return null!=this.prev?this.prev.vertex:null},oppositeFace:function(){return null!=this.opposite?this.opposite.face:null},getVertexString:function(){return null!=this.tail()?""+this.tail().index+"-"+this.head().index:"? -"+this.head().index},length:function(){return null!=this.tail()?this.head().pnt.distanceTo(this.tail().pnt):-1},lengthSquared:function(){return null!=this.tail()?this.head().pnt.distanceToSquared(this.tail().pnt): -1}};c.Face=function(){this.normal=new c.Vector3D(0,0,0);this.centroid=new c.Vector3D(0,0,0);this.mark=1;this.he0=null;this.numVerts=this.index=this.planeOffset=this.area=-1;this.outside=this.next=null};c.Face.prototype={computeCentroid:function(a){a.setZero();var b=this.he0;do a.hAdd(a,b.head().pnt),b=b.next;while(b!=this.he0);a.hTimes(a,1/this.numVerts)},computeNormal:function(a,b){var d=this.he0.next,c=d.next,f=this.he0.head().pnt,d=d.head().pnt,h=d._x-f._x,m=d._y-f._y,d=d._z-f._z;this.normal.setZero(); for(this.numVerts=2;c!=this.he0;){var q=h,k=m,g=d,d=c.head().pnt,h=d._x-f._x,m=d._y-f._y,d=d._z-f._z;this.normal._x+=k*d-g*m;this.normal._y+=g*h-q*d;this.normal._z+=q*m-k*h;c=c.next;this.numVerts++}this.area=this.normal.length();this.normal.hTimes(this.normal,1/this.area);if(2==arguments.length&&this.areaf&&(c=d,f=h);while(d!=this.he0);d=c.head().pnt;p1=c.tail().pnt;h=Math.sqrt(f);c=(d._x-p1._x)/h;f=(d._y-p1._y)/h;d=(d._z-p1._z)/h;h=this.normal._x* c+this.normal._y*f+this.normal._z*d;this.normal._x-=h*c;this.normal._y-=h*f;this.normal._z-=h*d;this.normal.normalize()}},computeNormalAndCentroid:function(a){1==arguments.length?this.computeNormal(this.normal,a):this.computeNormal(this.normal);this.computeCentroid(this.centroid);this.planeOffset=this.normal.dot(this.centroid)},createTriangle:function(a,b,d,e){var f=new c.Face;a=new c.HalfEdge(a,f);b=new c.HalfEdge(b,f);d=new c.HalfEdge(d,f);a.prev=d;a.next=b;b.prev=a;b.next=d;d.prev=b;d.next=a;f.he0= a;e?f.computeNormalAndCentroid(e):f.computeNormalAndCentroid(0);return f},create:function(a,b){for(var d=new c.Face,e=null,f=0;fa;)b=b.prev,a++;return b},getFirstEdge:function(){return this.he0},findEdge:function(a,b){var d=this.he0;do{if(d.head()==b&&d.tail()==a)return d; d=d.next}while(d!=this.he0);return null},distanceToPlane:function(a){return this.normal._x*a._x+this.normal._y*a._y+this.normal._z*a._z-this.planeOffset},getNormal:function(){return this.normal},getCentroid:function(){return this.centroid},numVertices:function(){return this.numVerts},getVertexString:function(){var a="",b=this.he0;do a=0==a.length?a+b.head().index:a+(" "+b.head().index),b=b.next;while(b!=this.he0);return a},getVertexIndices:function(a){var b=this.he0,d=0;do a[d++]=b.head().index,b= b.next;while(b!=this.he0)},connectHalfEdges:function(a,b){var d=null;if(a.oppositeFace()==b.oppositeFace()){var c=b.oppositeFace(),f;a==this.he0&&(this.he0=b);3==c.numVertices()?(f=b.getOpposite().prev.getOpposite(),c.mark=3,d=c):(f=b.getOpposite().next,c.he0==f.prev&&(c.he0=f),f.prev=f.prev.prev,f.prev.next=f);b.prev=a.prev;b.prev.next=b;b.opposite=f;f.opposite=b;c.computeNormalAndCentroid()}else a.next=b,b.prev=a;return d},checkConsistency:function(){var a=this.he0,b=0,d=0;if(3>this.numVerts)throw"face"+ this.getVertexString()+": unreflected half edge "+a.getVertexString();do{var c=a.getOpposite();if(null==c)throw"face "+this.getVertexString()+": unreflected half edge "+a.getVertexString();if(c.getOpposite()!=a)throw"face "+this.getVertexString()+": opposite half edge "+c.getVertexString()+" has opposite "+c.getOpposite().getVertexString();if(c.head()!=a.tail()||a.head()!=c.tail())throw"face "+this.getVertexString()+": half edge "+a.getVertexString()+" reflected by "+c.getVertexString();var f=c.face; if(null==f)throw"face "+this.getVertexString()+": no face on half edge "+c.getVertexString();if(3==f.mark)throw"face "+this.getVertexString()+": opposite face "+f.getVertexString()+" not on hull";c=Math.abs(this.distanceToPlane(a.head().pnt));c>b&&(b=c);d++;a=a.next}while(a!=this.he0);if(d!=this.numVerts)throw"face "+this.getVertexString()+" numVerts="+this.numVerts+" should be "+d;},mergeAdjacentFace:function(a,b){var d=a.oppositeFace(),c=0;b[c++]=d;d.mark=3;for(var f=a.getOpposite(),h=a.prev,m= a.next,q=f.prev,f=f.next;h.oppositeFace()==d;)h=h.prev,f=f.next;for(;m.oppositeFace()==d;)q=q.prev,m=m.next;for(d=f;d!=q.next;d=d.next)d.face=this;a==this.he0&&(this.he0=m);m=this.connectHalfEdges(q,m);null!=m&&(b[c++]=m);m=this.connectHalfEdges(h,f);null!=m&&(b[c++]=m);this.computeNormalAndCentroid();this.checkConsistency();return c},areaSquared:function(a,b){var d=a.tail().pnt,c=a.head().pnt,f=b.head().pnt,h=c._x-d._x,m=c._y-d._y,q=c._z-d._z,c=f._x-d._x,k=f._y-d._y,f=f._z-d._z,d=m*f-q*k,q=q*c-h* f,h=h*k-m*c;return d*d+q*q+h*h},triangulate:function(a,b){var d;if(!(4>this.numVertices)){var e=this.he0.head();d=this.he0.next;var f=d.opposite,h=null;for(d=d.next;d!=this.he0.prev;d=d.next){var m=createTriangle(e,d.prev.head(),d.head(),b);m.he0.next.setOpposite(f);m.he0.prev.setOpposite(d.opposite);f=m.he0;a.add(m);null==h&&(h=m)}d=new c.HalfEdge(this.he0.prev.prev.head(),this);d.setOpposite(f);d.prev=this.he0;d.prev.next=d;d.next=this.he0.prev;d.next.prev=d;computeNormalAndCentroid(b);checkConsistency(); for(m=h;null!=m;m=m.next)m.checkConsistency()}}};c.FaceList=function(){this.tail=this.head=null};c.FaceList.prototype={clear:function(){this.tail=this.head=null},add:function(a){null==this.head?this.head=a:this.tail.next=a;a.next=null;this.tail=a},first:function(){return this.head},isEmpty:function(){return null==this.head}};c.quickHull3D=function(){this.AUTOMATIC_TOLERANCE=-1;this.DOUBLE_PREC=2.220446049250313E-16;this.findIndex=-1;this.debug=!0;this.charLength=0;this.pointBuffer=[];this.vertexPointIndices= [];this.discardedFaces=[];this.maxVtxs=[];this.minVtxs=[];for(var a=0;3>a;a++)this.maxVtxs.push(new c.hVertex(0,0,0,a)),this.minVtxs.push(new c.hVertex(0,0,0,a)),this.discardedFaces.push(new c.Face);this.faces=[];this.horizon=[];this.newFaces=new c.FaceList;this.unclaimed=new c.hVertexList;this.claimed=new c.hVertexList;this.numPoints=this.numFaces=this.numVertices=0;this.explicitTolerance=this.AUTOMATIC_TOLERANCE;this.tolerance=0};c.quickHull3D.prototype={build:function(a){if(4>a.length)return console.log("cannot build hull - fewer than four points"), null;this.initBuffers(a,a.length);return this.buildHull()},initBuffers:function(a,b){this.pointBuffer=[];for(var d=0;db;b++)this.maxVtxs[b]=this.pointBuffer[0],this.minVtxs[b]=this.pointBuffer[0];for(var d=[a.pnt._x,a.pnt._y,a.pnt._z],a=[a.pnt._x,a.pnt._y,a.pnt._z],b=0;bd[0]?(d[0]=c._x,this.maxVtxs[0]=this.pointBuffer[b]):c._xd[1]?(d[1]=c._y,this.maxVtxs[1]=this.pointBuffer[b]):c._yd[2]?(d[2]=c._z,this.maxVtxs[2]=this.pointBuffer[b]):c._za&&(a=d,b=0);e>a&&(a=e,b=1);f>a&&(a=f,b=2);if(a<=this.tolerance)throw"hull points are all coincident - fail!";a=[];a[0]=this.maxVtxs[b];a[1]=this.minVtxs[b];e=new c.Vector3D(a[1].pnt._x,a[1].pnt._y,a[1].pnt._z);e=e.minus(a[0].pnt);e.normalize();d=new c.Vector3D(0,0,0);for(b=f=0;bf&&this.pointBuffer[b]!=a[0]&&this.pointBuffer[b]!=a[1]&&(f=m,a[2]=this.pointBuffer[b],d.set(h._x,h._y,h._z))}if(Math.sqrt(f)<=100*this.tolerance)throw"Input points to hull appear to be co-linear";d.normalize();e=0;m=a[2].pnt.dot(d);for(b=0;be&&this.pointBuffer[b]!=a[0]&&this.pointBuffer[b]!=a[1]&&this.pointBuffer[b]!=a[2]&&(e=f,a[3]=this.pointBuffer[b]);if(Math.abs(e)<=100*this.tolerance)throw"Input points appear to be coplanar"; h=[new c.Face,new c.Face,new c.Face,new c.Face];if(0>a[3].pnt.dot(d)-m)for(h[0]=h[0].createTriangle(a[0],a[1],a[2]),h[1]=h[1].createTriangle(a[3],a[1],a[0]),h[2]=h[2].createTriangle(a[3],a[2],a[1]),h[3]=h[3].createTriangle(a[3],a[0],a[2]),b=0;3>b;b++)d=(b+1)%3,h[b+1].getEdge(1).setOpposite(h[d+1].getEdge(0)),h[b+1].getEdge(2).setOpposite(h[0].getEdge(d));else for(h[0]=h[0].createTriangle(a[0],a[2],a[1]),h[1]=h[1].createTriangle(a[3],a[0],a[1]),h[2]=h[2].createTriangle(a[3],a[1],a[2]),h[3]=h[3].createTriangle(a[3], a[2],a[0]),b=0;3>b;b++)d=(b+1)%3,h[b+1].getEdge(0).setOpposite(h[d+1].getEdge(1)),h[b+1].getEdge(2).setOpposite(h[0].getEdge((3-b)%3));for(b=0;4>b;b++)this.faces.push(h[b]);for(b=0;bd;d++)f=h[d].distanceToPlane(m.pnt),f>e&&(q=h[d],e=f);null!=q&&this.addPointToFace(m,q)}},addPointToFace:function(a,b){a.face=b;null==b.outside?this.claimed.add(a):this.claimed.insertBefore(a,b.outside); b.outside=a},nextPointToAdd:function(){if(this.claimed.isEmpty())return null;for(var a=this.claimed.first().face,b=null,d=0,c=a.outside;null!=c&&c.face==a;c=c.next){var f=a.distanceToPlane(c.pnt);f>d&&(d=f,b=c)}return b},addPointToHull:function(a){this.horizon=[];this.unclaimed.clear();this.removePointFromFace(a,a.face);this.calculateHorizon(a.pnt,null,a.face,this.horizon);this.newFaces.clear();this.addNewFaces(this.newFaces,a,this.horizon);for(a=this.newFaces.first();null!=a;a=a.next)if(1==a.mark)for(;this.doAdjacentMerge(a, 1););for(a=this.newFaces.first();null!=a;a=a.next)if(2==a.mark)for(a.mark=1;this.doAdjacentMerge(a,2););this.resolveUnclaimedPoints(this.newFaces)},removePointFromFace:function(a,b){a==b.outside&&(b.outside=null!=a.next&&a.next.face==b?a.next:null);this.claimed["delete"](a)},calculateHorizon:function(a,b,d,c){this.deleteFacePoints(d,null);d.mark=3;d=null==b?b=d.getEdge(0):b.getNext();do{var e=d.oppositeFace();1==e.mark&&(e.distanceToPlane(a)>this.tolerance?this.calculateHorizon(a,d.getOpposite(), e,c):c.push(d));d=d.getNext()}while(d!=b)},oppFaceDistance:function(a){return a.face.distanceToPlane(a.opposite.face.getCentroid())},doAdjacentMerge:function(a,b){var d=a.he0,c=!0;do{var f=d.oppositeFace(),h=!1;if(2==b){if(this.oppFaceDistance(d)>-1*this.tolerance||this.oppFaceDistance(d.opposite)>-1*this.tolerance)h=!0}else a.area>f.area?this.oppFaceDistance(d)>-this.tolerance?h=!0:this.oppFaceDistance(d.opposite)>-this.tolerance&&(c=!1):this.oppFaceDistance(d.opposite)>-this.tolerance?h=!0:this.oppFaceDistance(d)> -this.tolerance&&(c=!1);if(h){d=a.mergeAdjacentFace(d,this.discardedFaces);for(c=0;cthis.tolerance?this.addPointToFace(c,b):this.unclaimed.add(c)},removeAllPointsFromFace:function(a){if(null!=a.outside){for(var b= a.outside;null!=b.next&&b.next.face==a;)b=b.next;this.claimed["delete"](a.outside,b);b.next=null;return a.outside}return null},addNewFaces:function(a,b,d){a.clear();for(var c=null,f=null,h=0;hc&&(c=m,f=h);if(c>1E3*this.tolerance)break}null!=f&&this.addPointToFace(d,f)}},reindexFacesAndVertices:function(){for(var a=0;ab.length()&&(b=d.randomNonParallelVector());1E-5>d.length()&&(d=b.randomNonParallelVector());d=b.cross(d);1E-5>d.length()&&(d=b.randomNonParallelVector(),d=b.cross(d));d=d.unit();return new c.Plane(d,d.dot(a))};c.Plane.fromPoints=function(a,b,d){a=new c.Vector3D(a);b=new c.Vector3D(b);d=new c.Vector3D(d);return c.Plane.fromVector3Ds(a,b,d)};c.Plane.fromNormalAndPoint=function(a,b){a=new c.Vector3D(a); b=new c.Vector3D(b);a=a.unit();var d=b.dot(a);return new c.Plane(a,d)};c.Plane.prototype={flipped:function(){return new c.Plane(this.normal.negated(),-this.w)},getTag:function(){var a=this.tag;a||(this.tag=a=c.getTag());return a},equals:function(a){return this.normal.equals(a.normal)&&this.w==a.w},transform:function(a){var b=a.isMirroring(),d=this.normal.randomNonParallelVector(),e=this.normal.cross(d),f=this.normal.cross(e),d=this.normal.times(this.w),e=d.plus(e),f=d.plus(f),d=d.multiply4x4(a),e= e.multiply4x4(a),f=f.multiply4x4(a);a=c.Plane.fromVector3Ds(d,e,f);b&&(a=a.flipped());return a},splitPolygon:function(a){var b={type:null,front:null,back:null},d=this.normal,e=a.vertices,f=e.length;if(a.plane.equals(this))b.type=0;else{for(var h=c.Plane.EPSILON,m=this.w,q=!1,k=!1,g=[],l=-h,n=0;np;g.push(B);p>h&&(q=!0);p=f&&(l=0),k=g[l],B==k?B?h.push(q):d.push(q):(l=this.splitLineBetweenPoints(q.pos, e[l].pos),l=new c.Vertex(l),B?(h.push(q),h.push(l),d.push(l)):(d.push(q),d.push(l),h.push(l))),B=k;e=c.Plane.EPSILON*c.Plane.EPSILON;if(3<=h.length)for(f=h[h.length-1],m=0;mc&&(c=0);return a.plus(d.times(c))},intersectWithLine:function(a){return a.intersectWithPlane(this)},intersectWithPlane:function(a){return c.Line3D.fromPlanes(this,a)},signedDistanceToPoint:function(a){return this.normal.dot(a)-this.w},toString:function(){return"[normal: "+this.normal.toString()+", w: "+this.w+ "]"},mirrorPoint:function(a){var b=this.signedDistanceToPoint(a);return a.minus(this.normal.times(2*b))}};c.Polygon=function(a,b,d){this.vertices=a;b||(b=c.Polygon.defaultShared);this.shared=b;this.plane=3<=arguments.length?d:c.Plane.fromVector3Ds(a[0].pos,a[1].pos,a[2].pos)};c.Polygon.fromObject=function(a){var b=a.vertices.map(function(a){return c.Vertex.fromObject(a)}),d=c.Polygon.Shared.fromObject(a.shared);a=c.Plane.fromObject(a.plane);return new c.Polygon(b,d,a)};c.Polygon.prototype={checkIfConvex:function(){if(!c.Polygon.verticesConvex(this.vertices, this.plane.normal))throw c.Polygon.verticesConvex(this.vertices,this.plane.normal),Error("Not convex!");},sC:function(a){this.shared=c.Polygon.Shared.fromColor.apply(this,arguments);return this},getSignedVolume:function(){for(var a=0,b=0;bMath.abs(d)?b=new n:0>d&&(b=b.flipped());return b},solidFromSlices:function(a){var b=[],d=null,e=null,f=null,h=null,m=2,q=!1,k,g=null;a&&(q=!!a.loop,a.numslices&&(m=a.numslices),a.callback&&(k=a.callback));if(!k){var l=new c.Polygon.createFromPoints([[0,0,0],[1,0,0],[1,1,0],[0,1,0]]);k=function(a,b){return 0==a||1==a?l.tr([0,0, a]):null}}a=0;for(--m;a<=m;a++)if(d=k.call(this,a/m,a)){if(!(d instanceof c.Polygon))throw Error("CSG.Polygon.solidFromSlices callback error: CSG.Polygon expected");d.checkIfConvex();e?(null===g&&(g=0>e.plane.signedDistanceToPoint(d.vertices[0].pos)),this._addWalls(b,e,d,g)):f=d;e=d}h=d;q?f.vertices.length==h.vertices.length&&f.vertices.every(function(a,b){return a.pos.equals(h.vertices[b].pos)})||this._addWalls(b,h,f,g):(b.unshift(g?f:f.flipped()),b.push(g?h.flipped():h));return c.fromPolygons(b)}, _addWalls:function(a,b,d,e){b=b.vertices.slice(0);var f=d.vertices.slice(0);d=d.shared||null;b[0].pos.equals(b[b.length-1].pos)||b.push(b[0]);f[0].pos.equals(f[f.length-1].pos)||f.push(f[0]);e&&(b=b.reverse(),f=f.reverse());e=f.length-1;for(var h=b.length-1,m=e-h,q=0m,l=[],m=Math.abs(m);0n){l[p].len=n;l.index=p;break}}else if(q)for(m=0;mn){l[p].len=n;l.index=p;break}l.sort(k);m=b[0];n=f[0];for(var r,B,v=p=0,t=e+h;p+varguments.length&&new c.Vector3D(0,0,0);var e=[];a.map(function(a){a=new c.Vector3D(a);a=new c.Vertex(a);e.push(a)});return 3>arguments.length?new c.Polygon(e,b):new c.Polygon(e,b,d)};c.Polygon.isConvexPoint= function(a,b,d,c){return 0<=b.minus(a).cross(d.minus(b)).dot(c)};c.Polygon.isStrictlyConvexPoint=function(a,b,d,c){return 1E-5<=b.minus(a).cross(d.minus(b)).dot(c)};c.Polygon.Shared=function(a){if(null!==a&&4!=a.length)throw Error("Expecting 4 element array");this.color=a};c.Polygon.Shared.fromObject=function(a){return new c.Polygon.Shared(a.color)};c.Polygon.Shared.fromColor=function(a){var b;if(1==arguments.length)b=arguments[0].slice();else{b=[];for(var d=0;db)throw Error("Assertion failed");a.splice(b,1);this.parent.recursivelyInvalidatePolygon()}},isRemoved:function(){return this.removed},isRootNode:function(){return!this.parent},invert:function(){if(!this.isRootNode())throw Error("Assertion failed");this.invertSub()},getPolygon:function(){if(!this.polygon)throw Error("Assertion failed"); return this.polygon},getPolygons:function(a){var b=[this],d=[b],c,f,h,m;for(c=0;cq)e.push(this);else if(m<-q)f.push(this);else switch(a=a.splitPolygon(d),a.type){case 0:b.push(this);break;case 1:c.push(this);break;case 2:e.push(this);break;case 3:f.push(this);break;case 4:a.front&&(b=this.addChild(a.front),e.push(b)),a.back&&(e=this.addChild(a.back),f.push(e))}}},addChild:function(a){var b=new c.PolygonTreeNode;b.parent=this;b.polygon=a;this.children.push(b);return b},invertSub:function(){var a=[this],b=[a],c,e,f,h; for(c=0;cd;d++)b[d]=this.elements[d]+a.elements[d];return new c.Matrix4x4(b)},minus:function(a){for(var b=[],d=0;16>d;d++)b[d]=this.elements[d]- a.elements[d];return new c.Matrix4x4(b)},multiply:function(a){var b=this.elements[0],d=this.elements[1],e=this.elements[2],f=this.elements[3],h=this.elements[4],m=this.elements[5],q=this.elements[6],g=this.elements[7],k=this.elements[8],l=this.elements[9],n=this.elements[10],p=this.elements[11],B=this.elements[12],v=this.elements[13],t=this.elements[14],y=this.elements[15],A=a.elements[0],w=a.elements[1],x=a.elements[2],z=a.elements[3],D=a.elements[4],C=a.elements[5],F=a.elements[6],H=a.elements[7], K=a.elements[8],L=a.elements[9],N=a.elements[10],M=a.elements[11],O=a.elements[12],P=a.elements[13],Q=a.elements[14];a=a.elements[15];var I=[];I[0]=b*A+d*D+e*K+f*O;I[1]=b*w+d*C+e*L+f*P;I[2]=b*x+d*F+e*N+f*Q;I[3]=b*z+d*H+e*M+f*a;I[4]=h*A+m*D+q*K+g*O;I[5]=h*w+m*C+q*L+g*P;I[6]=h*x+m*F+q*N+g*Q;I[7]=h*z+m*H+q*M+g*a;I[8]=k*A+l*D+n*K+p*O;I[9]=k*w+l*C+n*L+p*P;I[10]=k*x+l*F+n*N+p*Q;I[11]=k*z+l*H+n*M+p*a;I[12]=B*A+v*D+t*K+y*O;I[13]=B*w+v*C+t*L+y*P;I[14]=B*x+v*F+t*N+y*Q;I[15]=B*z+v*H+t*M+y*a;return new c.Matrix4x4(I)}, clone:function(){var a=this.elements.map(function(a){return a});return new c.Matrix4x4(a)},rightMultiply1x3Vector:function(a){var b=a._x,d=a._y,e=a._z;a=b*this.elements[0]+d*this.elements[1]+e*this.elements[2]+1*this.elements[3];var f=b*this.elements[4]+d*this.elements[5]+e*this.elements[6]+1*this.elements[7],h=b*this.elements[8]+d*this.elements[9]+e*this.elements[10]+1*this.elements[11],b=b*this.elements[12]+d*this.elements[13]+e*this.elements[14]+1*this.elements[15];1!=b&&(b=1/b,a*=b,f*=b,h*=b); return new c.Vector3D(a,f,h)},leftMultiply1x3Vector:function(a){var b=a._x,d=a._y,e=a._z;a=b*this.elements[0]+d*this.elements[4]+e*this.elements[8]+1*this.elements[12];var f=b*this.elements[1]+d*this.elements[5]+e*this.elements[9]+1*this.elements[13],h=b*this.elements[2]+d*this.elements[6]+e*this.elements[10]+1*this.elements[14],b=b*this.elements[3]+d*this.elements[7]+e*this.elements[11]+1*this.elements[15];1!=b&&(b=1/b,a*=b,f*=b,h*=b);return new c.Vector3D(a,f,h)},rightMultiply1x2Vector:function(a){var b= a.x,d=a.y;a=b*this.elements[0]+d*this.elements[1]+0*this.elements[2]+1*this.elements[3];var e=b*this.elements[4]+d*this.elements[5]+0*this.elements[6]+1*this.elements[7],b=b*this.elements[12]+d*this.elements[13]+0*this.elements[14]+1*this.elements[15];1!=b&&(b=1/b,a*=b,e*=b);return new c.Vector2D(a,e)},leftMultiply1x2Vector:function(a){var b=a.x,d=a.y;a=b*this.elements[0]+d*this.elements[4]+0*this.elements[8]+1*this.elements[12];var e=b*this.elements[1]+d*this.elements[5]+0*this.elements[9]+1*this.elements[13], b=b*this.elements[3]+d*this.elements[7]+0*this.elements[11]+1*this.elements[15];1!=b&&(b=1/b,a*=b,e*=b);return new c.Vector2D(a,e)},isMirroring:function(){var a=new c.Vector3D(this.elements[0],this.elements[4],this.elements[8]),b=new c.Vector3D(this.elements[1],this.elements[5],this.elements[9]),d=new c.Vector3D(this.elements[2],this.elements[6],this.elements[10]);return 0>a.cross(b).dot(d)}};c.Matrix4x4.unity=function(){return new c.Matrix4x4};c.Matrix4x4.rotationX=function(a){var b=1/180*Math.PI* a;a=Math.cos(b);b=Math.sin(b);return new c.Matrix4x4([1,0,0,0,0,a,b,0,0,-b,a,0,0,0,0,1])};c.Matrix4x4.rotationY=function(a){var b=1/180*Math.PI*a;a=Math.cos(b);b=Math.sin(b);return new c.Matrix4x4([a,0,-b,0,0,1,0,0,b,0,a,0,0,0,0,1])};c.Matrix4x4.rotationZ=function(a){var b=1/180*Math.PI*a;a=Math.cos(b);b=Math.sin(b);return new c.Matrix4x4([a,b,0,0,-b,a,0,0,0,0,1,0,0,0,0,1])};c.Matrix4x4.rotation=function(a,b,d){a=new c.Vector3D(a);b=new c.Vector3D(b);b=c.Plane.fromNormalAndPoint(b,a);b=new c.OrthoNormalBasis(b); var e=c.Matrix4x4.translation(a.negated()),e=e.multiply(b.getProjectionMatrix()),e=e.multiply(c.Matrix4x4.rotationZ(d)),e=e.multiply(b.getInverseProjectionMatrix());return e=e.multiply(c.Matrix4x4.translation(a))};c.Matrix4x4.translation=function(a){a=new c.Vector3D(a);return new c.Matrix4x4([1,0,0,0,0,1,0,0,0,0,1,0,a.x,a.y,a.z,1])};c.Matrix4x4.mirroring=function(a){var b=a.normal.x,d=a.normal.y,e=a.normal.z;a=a.w;return new c.Matrix4x4([1-2*b*b,-2*d*b,-2*e*b,0,-2*b*d,1-2*d*d,-2*e*d,0,-2*b*e,-2*d* e,1-2*e*e,0,-2*b*a,-2*d*a,-2*e*a,1])};c.Matrix4x4.scaling=function(a){a=new c.Vector3D(a);return new c.Matrix4x4([a.x,0,0,0,0,a.y,0,0,0,0,a.z,0,0,0,0,1])};c.Vector2D=function(a,b){if(2==arguments.length)this._x=parseFloat(a),this._y=parseFloat(b);else{var d=!0;if(1==arguments.length)if("object"==typeof a)a instanceof c.Vector2D?(this._x=a._x,this._y=a._y):a instanceof Array?(this._x=parseFloat(a[0]),this._y=parseFloat(a[1])):"x"in a&&"y"in a?(this._x=parseFloat(a.x),this._y=parseFloat(a.y)):d=!1; else{var e=parseFloat(a);this._y=this._x=e}else d=!1;d&&(c.IsFloat(this._x)&&c.IsFloat(this._y)||(d=!1));if(!d)throw Error("wrong arguments");}};c.Vector2D.fromAngle=function(a){return c.Vector2D.fromAngleRadians(a)};c.Vector2D.fromAngleDegrees=function(a){return c.Vector2D.fromAngleRadians(Math.PI*a/180)};c.Vector2D.fromAngleRadians=function(a){return c.Vector2D.Create(Math.cos(a),Math.sin(a))};c.Vector2D.Create=function(a,b){var d=Object.create(c.Vector2D.prototype);d._x=a;d._y=b;return d};c.Vector2D.prototype= {get x(){return this._x},get y(){return this._y},set x(a){throw Error("Vector2D is immutable");},set y(a){throw Error("Vector2D is immutable");},toVector3D:function(a){return new c.Vector3D(this._x,this._y,a)},equals:function(a){return this._x==a._x&&this._y==a._y},clone:function(){return c.Vector2D.Create(this._x,this._y)},negated:function(){return c.Vector2D.Create(-this._x,-this._y)},plus:function(a){return c.Vector2D.Create(this._x+a._x,this._y+a._y)},minus:function(a){return c.Vector2D.Create(this._x- a._x,this._y-a._y)},times:function(a){return c.Vector2D.Create(this._x*a,this._y*a)},dividedBy:function(a){return c.Vector2D.Create(this._x/a,this._y/a)},dot:function(a){return this._x*a._x+this._y*a._y},lerp:function(a,b){return this.plus(a.minus(this).times(b))},length:function(){return Math.sqrt(this.dot(this))},distanceTo:function(a){return this.minus(a).length()},distanceToSquared:function(a){return this.minus(a).lengthSquared()},lengthSquared:function(){return this.dot(this)},unit:function(){return this.dividedBy(this.length())}, cross:function(a){return this._x*a._y-this._y*a._x},normal:function(){return c.Vector2D.Create(this._y,-this._x)},multiply4x4:function(a){return a.leftMultiply1x2Vector(this)},transform:function(a){return a.leftMultiply1x2Vector(this)},angle:function(){return this.angleRadians()},angleDegrees:function(){return 180*this.angleRadians()/Math.PI},angleRadians:function(){return Math.atan2(this._y,this._x)},min:function(a){return c.Vector2D.Create(Math.min(this._x,a._x),Math.min(this._y,a._y))},max:function(a){return c.Vector2D.Create(Math.max(this._x, a._x),Math.max(this._y,a._y))},toString:function(){return"("+this._x.toFixed(2)+", "+this._y.toFixed(2)+")"},abs:function(){return c.Vector2D.Create(Math.abs(this._x),Math.abs(this._y))}};c.Line2D=function(a,b){a=new c.Vector2D(a);b=parseFloat(b);var d=a.length();b*=d;this.normal=a=a.times(1/d);this.w=b};c.Line2D.fromPoints=function(a,b){a=new c.Vector2D(a);b=new c.Vector2D(b);var d=b.minus(a).normal().negated().unit(),e=a.dot(d);return new c.Line2D(d,e)};c.Line2D.prototype={reverse:function(){return new c.Line2D(this.normal.negated(), -this.w)},equals:function(a){return a.normal.equals(this.normal)&&a.w==this.w},origin:function(){return this.normal.times(this.w)},direction:function(){return this.normal.normal()},xAtY:function(a){return(this.w-this.normal._y*a)/this.normal.x},absDistanceToPoint:function(a){a=new c.Vector2D(a);a=a.dot(this.normal);return Math.abs(a-this.w)},intersectWithLine:function(a){a=c.solve2Linear(this.normal.x,this.normal.y,a.normal.x,a.normal.y,this.w,a.w);return a=new c.Vector2D(a)},transform:function(a){var b= new c.Vector2D(0,0),d=this.normal.times(this.w),b=b.multiply4x4(a),b=this.normal.multiply4x4(a).minus(b);a=d.multiply4x4(a);a=b.dot(a);return new c.Line2D(b,a)}};c.Line3D=function(a,b){a=new c.Vector3D(a);b=new c.Vector3D(b);this.point=a;this.direction=b.unit()};c.Line3D.fromPoints=function(a,b){a=new c.Vector3D(a);b=new c.Vector3D(b);var d=b.minus(a);return new c.Line3D(a,d)};c.Line3D.fromPlanes=function(a,b){var d=a.normal.cross(b.normal),e=d.length();if(1E-10>e)throw Error("Parallel planes");var d= d.times(1/e),e=Math.abs(d.x),f=Math.abs(d.y),h=Math.abs(d.z);e>=f&&e>=h?(e=c.solve2Linear(a.normal.y,a.normal.z,b.normal.y,b.normal.z,a.w,b.w),e=new c.Vector3D(0,e[0],e[1])):f>=e&&f>=h?(e=c.solve2Linear(a.normal.x,a.normal.z,b.normal.x,b.normal.z,a.w,b.w),e=new c.Vector3D(e[0],0,e[1])):(e=c.solve2Linear(a.normal.x,a.normal.y,b.normal.x,b.normal.y,a.w,b.w),e=new c.Vector3D(e[0],e[1],0));return new c.Line3D(e,d)};c.Line3D.prototype={intersectWithPlane:function(a){a=(a.w-a.normal.dot(this.point))/a.normal.dot(this.direction); return this.point.plus(this.direction.times(a))},clone:function(a){return new c.Line3D(this.point.clone(),this.direction.clone())},reverse:function(){return new c.Line3D(this.point.clone(),this.direction.negated())},transform:function(a){var b=this.point.multiply4x4(a);a=this.point.plus(this.direction).multiply4x4(a).minus(b);return new c.Line3D(b,a)},closestPointOnLine:function(a){a=new c.Vector3D(a);a=a.minus(this.point).dot(this.direction)/this.direction.dot(this.direction);return this.point.plus(this.direction.times(a))}, distanceToPoint:function(a){a=new c.Vector3D(a);var b=this.closestPointOnLine(a);return a.minus(b).length()},equals:function(a){return!this.direction.equals(a.direction)||1E-8arguments.length?a.normal.randomNonParallelVector():new c.Vector3D(b);this.v=a.normal.cross(b).unit();this.u=this.v.cross(a.normal);this.plane=a;this.planeorigin=a.normal.times(a.w)};c.OrthoNormalBasis.GetCartesian=function(a,b){var d=a+"/"+b,e;if("X/Y"== d)d=[0,0,1],e=[1,0,0];else if("Y/-X"==d)d=[0,0,1],e=[0,1,0];else if("-X/-Y"==d)d=[0,0,1],e=[-1,0,0];else if("-Y/X"==d)d=[0,0,1],e=[0,-1,0];else if("-X/Y"==d)d=[0,0,-1],e=[-1,0,0];else if("-Y/-X"==d)d=[0,0,-1],e=[0,-1,0];else if("X/-Y"==d)d=[0,0,-1],e=[1,0,0];else if("Y/X"==d)d=[0,0,-1],e=[0,1,0];else if("X/Z"==d)d=[0,-1,0],e=[1,0,0];else if("Z/-X"==d)d=[0,-1,0],e=[0,0,1];else if("-X/-Z"==d)d=[0,-1,0],e=[-1,0,0];else if("-Z/X"==d)d=[0,-1,0],e=[0,0,-1];else if("-X/Z"==d)d=[0,1,0],e=[-1,0,0];else if("-Z/-X"== d)d=[0,1,0],e=[0,0,-1];else if("X/-Z"==d)d=[0,1,0],e=[1,0,0];else if("Z/X"==d)d=[0,1,0],e=[0,0,1];else if("Y/Z"==d)d=[1,0,0],e=[0,1,0];else if("Z/-Y"==d)d=[1,0,0],e=[0,0,1];else if("-Y/-Z"==d)d=[1,0,0],e=[0,-1,0];else if("-Z/Y"==d)d=[1,0,0],e=[0,0,-1];else if("-Y/Z"==d)d=[-1,0,0],e=[0,-1,0];else if("-Z/-Y"==d)d=[-1,0,0],e=[0,0,-1];else if("Y/-Z"==d)d=[-1,0,0],e=[0,1,0];else if("Z/Y"==d)d=[-1,0,0],e=[0,0,1];else throw Error("CSG.OrthoNormalBasis.GetCartesian: invalid combination of axis identifiers. Should pass two string arguments from [X,Y,Z,-X,-Y,-Z], being two different axes."); return new c.OrthoNormalBasis(new c.Plane(new c.Vector3D(d),0),new c.Vector3D(e))};c.OrthoNormalBasis.Z0Plane=function(){var a=new c.Plane(new c.Vector3D([0,0,1]),0);return new c.OrthoNormalBasis(a,new c.Vector3D([1,0,0]))};c.OrthoNormalBasis.prototype={getProjectionMatrix:function(){return new c.Matrix4x4([this.u.x,this.v.x,this.plane.normal.x,0,this.u.y,this.v.y,this.plane.normal.y,0,this.u.z,this.v.z,this.plane.normal.z,0,0,0,-this.plane.w,1])},getInverseProjectionMatrix:function(){var a=this.plane.normal.times(this.plane.w); return new c.Matrix4x4([this.u.x,this.u.y,this.u.z,0,this.v.x,this.v.y,this.v.z,0,this.plane.normal.x,this.plane.normal.y,this.plane.normal.z,0,a.x,a.y,a.z,1])},to2D:function(a){return new c.Vector2D(a.dot(this.u),a.dot(this.v))},to3D:function(a){return this.planeorigin.plus(this.u.times(a.x)).plus(this.v.times(a.y))},line3Dto2D:function(a){var b=a.point;a=a.direction.plus(b);b=this.to2D(b);a=this.to2D(a);return c.Line2D.fromPoints(b,a)},line2Dto3D:function(a){var b=a.origin();a=a.direction().plus(b); b=this.to3D(b);a=this.to3D(a);return c.Line3D.fromPoints(b,a)},transform:function(a){var b=this.plane.transform(a),d=this.u.transform(a);a=(new c.Vector3D(0,0,0)).transform(a);d=d.minus(a);return new c.OrthoNormalBasis(b,d)}};c.interpolateBetween2DPointsForY=function(a,b,c){c-=a.y;var d=b.y-a.y;0>d&&(c=-c,d=-d);return a.x+(0>=c?0:c>=d?1:1E-10>d?.5:c/d)*(b.x-a.x)};c.reTesselateCoplanarPolygons=function(a,b){var d=a.length;if(0w)w=z;z in k||(k[z]={});k[z][r]=!0}A>=w?(v=[],t=0,y=-1):(A in g||(g[A]=[]),g[A].push(r))}v.reverse();y=t-y-1;m.push(v);q.push(y)}var d=[],F;for(F in k)d.push(F);d.sort(l);n=[];E=[];for(B= 0;B=t&&(w=0);if(v[w].y!=F)break;r=w}z=H-1;0>z&&(z=t-1);v[z].y==F&&(H=z);r!=x.leftvertexindex&&r==H?(n.splice(C,1),--C):(x.leftvertexindex=r,x.rightvertexindex=H,x.topleft=v[r],x.topright=v[H],w=r+1,w>=t&&(w=0),x.bottomleft=v[w],z=H-1,0>z&&(z=t-1),x.bottomright=v[z])}if(B>=d.length-1)n=[],A=null;else{A=Number(d[B+1]);var K= .5*(F+A),D=g[D],L;for(L in D){r=D[L];v=m[r];t=v.length;for(C=w=q[r];;){x=C+1;x>=t&&(x=0);if(v[x].y!=F)break;if(x==w)break;C=x}for(H=w;;){x=H-1;0>x&&(x=t-1);if(v[x].y!=F)break;if(x==C)break;H=x}w=C+1;w>=t&&(w=0);z=H-1;0>z&&(z=t-1);p(n,{polygonindex:r,leftvertexindex:C,rightvertexindex:H,topleft:v[C],topright:v[H],bottomleft:v[w],bottomright:v[z]},function(a,b){var d=c.interpolateBetween2DPointsForY(a.topleft,a.bottomleft,K),e=c.interpolateBetween2DPointsForY(b.topleft,b.bottomleft,K);return d>e?1: dv&&1E-5>t&&(x.topleft=r.topleft,x.leftline=r.leftline,x.bottomleft=r.bottomleft,y.splice(y.length-1,1))),y.push(x);if(0z.bottomleft.distanceTo(w.topleft)&&1E-5>z.bottomright.distanceTo(w.topright))){A[r]=!0;v=w.leftline.direction().x-z.leftline.direction().x;t=w.rightline.direction().x- z.rightline.direction().x;D=1E-5>Math.abs(v);t=(C=1E-5>Math.abs(t))||0<=t;(D||0<=v)&&t&&(w.outpolygon=z.outpolygon,w.leftlinecontinues=D,w.rightlinecontinues=C,F[r]=!0);break}for(r=0;r>=1});this.lookuptable[c]=f}return f}};c.fuzzyCSGFactory=function(){this.vertexfactory=new c.fuzzyFactory(3,1E-5);this.planefactory=new c.fuzzyFactory(4,1E-5);this.polygonsharedfactory={}};c.fuzzyCSGFactory.prototype={getPolygonShared:function(a){var b= a.getHash();return b in this.polygonsharedfactory?this.polygonsharedfactory[b]:this.polygonsharedfactory[b]=a},getVertex:function(a){return this.vertexfactory.lookupOrCreate([a.pos._x,a.pos._y,a.pos._z],function(b){return a})},getPlane:function(a){return this.planefactory.lookupOrCreate([a.normal._x,a.normal._y,a.normal._z,a.w],function(b){return a})},getPolygon:function(a){var b=this.getPlane(a.plane),d=this.getPolygonShared(a.shared),e=this;a=a.vertices.map(function(a){return e.getVertex(a)});var f= [];if(0f.length&&(f=[]);return new c.Polygon(f,d,b)},getCSG:function(a){var b=this,d=[];a.polygons.forEach(function(a){a=b.getPolygon(a);3<=a.vertices.length&&d.push(a)});return c.fromPolygons(d)}};c.staticTag=1;c.getTag=function(){return c.staticTag++};c.Properties=function(){};c.Properties.prototype={_transform:function(a){var b=new c.Properties;c.Properties.transformObj(this,b,a);return b},_merge:function(a){var b= new c.Properties;c.Properties.cloneObj(this,b);c.Properties.addFrom(b,a);return b}};c.Properties.transformObj=function(a,b,d){for(var e in a)if("_transform"!=e&&"_merge"!=e){var f=a[e],h=f;"object"==typeof f&&("transform"in f&&"function"==typeof f.transform?h=f.transform(d):f instanceof Array?(h=[],c.Properties.transformObj(f,h,d)):f instanceof c.Properties&&(h=new c.Properties,c.Properties.transformObj(f,h,d)));b[e]=h}};c.Properties.cloneObj=function(a,b){for(var d in a)if("_transform"!=d&&"_merge"!= d){var e=a[d],f=e;if("object"==typeof e)if(e instanceof Array)for(var f=[],h=0;h=b.point.minus(a.point).dot(a.axisvector))throw"Invalid ConnectorList. Each connectors position needs to be within a <90deg range of previous connectors axisvector"; if(0>=a.axisvector.dot(b.axisvector))throw"invalid ConnectorList. No neighboring connectors axisvectors may span a >=90deg angle";}}};c.Path2D=function(a,b){b=!!b;a=a||[];var d=null;b&&0a.distanceTo(d));b||e.push(a);d=a});this.points=e;this.closed=b};c.Path2D.arc=function(a){var b=c.parseOptionAs2DVector(a,"center",0),d=c.parseOptionAsFloat(a,"radius",1),e=c.parseOptionAsFloat(a, "startangle",0),f=c.parseOptionAsFloat(a,"endangle",360),h=c.parseOptionAsInt(a,"resolution",c.defaultResolution2D);for(a=c.parseOptionAsBool(a,"maketangent",!1);720<=f-e;)f-=360;for(;-720>=f-e;)f+=360;var m=[],g,k=Math.abs(f-e);if(1E-5>k)g=c.Vector2D.fromAngle(e/180*Math.PI).times(d),m.push(g.plus(b));else{h=Math.floor(h*k/360)+1;k=.5*h/k;.25g&&(g=0),g>h&&(g=h)),g=c.Vector2D.fromAngle((e+g*(f-e)/h)/180*Math.PI).times(d),m.push(g.plus(b))}return new c.Path2D(m, !1)};c.Path2D.prototype={concat:function(a){if(this.closed||a.closed)throw Error("Paths must not be closed");a=this.points.concat(a.points);return new c.Path2D(a)},appendPoint:function(a){if(this.closed)throw Error("Path must not be closed");a=new c.Vector2D(a);a=this.points.concat([a]);return new c.Path2D(a)},appendPoints:function(a){if(this.closed)throw Error("Path must not be closed");var b=this.points;a.forEach(function(a){b.push(new c.Vector2D(a))});return new c.Path2D(b)},close:function(){return new c.Path2D(this.points, !0)},rectangularExtrude:function(a,b,c){return this.expandToCAG(a/2,c).extrude({offset:[0,0,b]})},expandToCAG:function(a,b){var c=[],e=this.points.length,f=0;this.closed&&2g&&(g=e-1);g=new n.Vertex(this.points[g]);m>f&&(h=new n.Side(h,g),c.push(h));h=g}return n.fromSides(c).expandedShell(a,b)},innerToCAG:function(){if(!this.closed)throw Error("The path should be closed!");return n.fromPoints(this.points)},transform:function(a){var b=this.points.map(function(b){return b.multiply4x4(a)}); return new c.Path2D(b,this.closed)},appendBezier:function(a,b){2>arguments.length&&(b={});if(this.closed)throw Error("Path must not be closed");if(!(a instanceof Array))throw Error("appendBezier: should pass an array of control points");if(1>a.length)throw Error("appendBezier: need at least 1 control point");if(1>this.points.length)throw Error("appendBezier: path must already contain a point (the endpoint of the path is used as the starting point for the bezier curve)");var d=c.parseOptionAsInt(b, "resolution",c.defaultResolution2D);4>d&&(d=4);var e=[],f=[];f.push(this.points[this.points.length-1]);for(var h=0;ha.length)throw Error("appendBezier: null can only be passed if there is at least one more control point");if("lastBezierControlPoint"in this)m=this.lastBezierControlPoint;else{if(2>this.points.length)throw Error("appendBezier: null is passed as a control point but this requires a previous bezier curve or at least two points in the existing path"); m=this.points[this.points.length-2]}m=this.points[this.points.length-1].times(2).minus(m)}else m=new c.Vector2D(m);f.push(m)}for(var g=f.length-1,m=1,h=0;h<=g;++h)0d){var p=l[h-1],r=l[h+1],n=p+1*(r-p)/3,p=p+2*(r-p)/3,r=e(n),B=e(p);m.splice(h,1,r,B);l.splice(h,1,n,p);h--;1>h&&(h=1)}else++h;m=this.points.concat(m.slice(1));e=new c.Path2D(m);e.lastBezierControlPoint=f[f.length-2];return e},appendArc:function(a,b){2>arguments.length&&(b={});if(this.closed)throw Error("Path must not be closed");if(1>this.points.length)throw Error("appendArc: path must already contain a point (the endpoint of the path is used as the starting point for the arc)"); var d=c.parseOptionAsInt(b,"resolution",c.defaultResolution2D);4>d&&(d=4);var e,f;if("xradius"in b||"yradius"in b){if("radius"in b)throw Error("Should either give an xradius and yradius parameter, or a radius parameter");e=c.parseOptionAsFloat(b,"xradius",0);f=c.parseOptionAsFloat(b,"yradius",0)}else f=e=c.parseOptionAsFloat(b,"radius",0);var h=c.parseOptionAsFloat(b,"xaxisrotation",0),m=c.parseOptionAsBool(b,"clockwise",!1),g=c.parseOptionAsBool(b,"large",!1),k=this.points[this.points.length-1]; a=new c.Vector2D(a);var l=!m,m=[];if(0==e||0==f)m.push(a);else{e=Math.abs(e);f=Math.abs(f);var n=h*Math.PI/180,h=Math.cos(n),n=Math.sin(n),p=k.minus(a).times(.5),p=new c.Vector2D(h*p.x+n*p.y,-n*p.x+h*p.y),r=p.x*p.x/(e*e)+p.y*p.y/(f*f);1p&&(p+=2*Math.PI);d=Math.ceil(Math.abs(p)/(2*Math.PI)*d)+1;1>d&&(d=1);for(l=1;l<=d;l++){var B=g+l/d*p,r=Math.cos(B),B=Math.sin(B),r=(new c.Vector2D(h*e*r-n*f*B,n*e*r+h*f*B)).plus(k);m.push(r)}}m=this.points.concat(m);return new c.Path2D(m)}};c.addTransformationMethodsToPrototype=function(a){a.mirrored=function(a){return this.transform(c.Matrix4x4.mirroring(a))};a.mirroredX= function(){var a=new c.Plane(c.Vector3D.Create(1,0,0),0);return this.mirrored(a)};a.mirroredY=function(){var a=new c.Plane(c.Vector3D.Create(0,1,0),0);return this.mirrored(a)};a.mirroredZ=function(){var a=new c.Plane(c.Vector3D.Create(0,0,1),0);return this.mirrored(a)};a.tr=function(a){return this.transform(c.Matrix4x4.translation(a))};a.scale=function(a){return this.transform(c.Matrix4x4.scaling(a))};a.rX=function(a){return this.transform(c.Matrix4x4.rotationX(a))};a.rY=function(a){return this.transform(c.Matrix4x4.rotationY(a))}; a.rZ=function(a){return this.transform(c.Matrix4x4.rotationZ(a))};a.rotate=function(a,d,e){return this.transform(c.Matrix4x4.rotation(a,d,e))}};c.addCenteringToPrototype=function(a,b){a.center=function(a){a=Array.prototype.map.call(arguments,function(a){return a});a.length||(a=b.slice());var c=this.getBounds();return this.tr(b.map(function(b){return-1b)throw Error("CAG shape needs at least 3 points");var d=[],b=new c.Vector2D(a[b-1]),e=new n.Vertex(b);a.map(function(a){a=new c.Vector2D(a);a=new n.Vertex(a);var b=new n.Side(e,a);d.push(b);e=a});a=n.fromSides(d);if(a.isSelfIntersecting())throw Error("Polygon is self intersecting!");b=a.area();if(1E-5>Math.abs(b))throw Error("Degenerate polygon!");0>b&&(a=a.flipped());return a=a.canonicalized()};n.fromPointsNoCheck=function(a){var b=[],d=new c.Vector2D(a[a.length-1]),e=new n.Vertex(d); a.map(function(a){a=new c.Vector2D(a);a=new n.Vertex(a);var d=new n.Side(e,a);b.push(d);e=a});return n.fromSides(b)};n.fromFakeCSG=function(a){a=a.polygons.map(function(a){return n.Side._fromFakePolygon(a)}).filter(function(a){return null!==a});return n.fromSides(a)};n.linesIntersect=function(a,b,d,e){if(b.equals(d)||e.equals(a)){if(1E-5>e.minus(d).unit().plus(b.minus(a).unit()).length())return!0}else{b=b.minus(a);e=e.minus(d);if(1E-9>Math.abs(b.cross(e)))return!1;a=c.solve2Linear(-b.x,e.x,-b.y,e.y, a.x-d.x,a.y-d.y);if(1E-6a[0]&&1E-5a[1])return!0}return!1};n.circle=function(a){a=a||{};var b=c.parseOptionAs2DVector(a,"center",[0,0]),d=c.parseOptionAsFloat(a,"radius",1);a=c.parseOptionAsInt(a,"resolution",c.defaultResolution2D);var e=[],f;if(0>d)throw Error("Radius should be positive.");if(5E-4>d)return new n;for(var h=0;h<=a;h++){var m=c.Vector2D.fromAngleRadians(2*Math.PI*h/a).times(d).plus(b),m=new n.Vertex(m);0a.x||0>a.y)throw Error("Dimension should be positive."); if(5E-4>a.x||5E-4>a.y)return console.log("Throwing out a zero-length rectangle."),new n;var d=new c.Vector2D(a.x,-a.y);b=[b.plus(a),b.plus(d),b.minus(a),b.minus(d)];return n.fromPoints(b)};n.roundedRectangle=function(a){a=a||{};var b,d;if("corner1"in a||"corner2"in a){if("center"in a||"radius"in a)throw Error("roundedRectangle: should either give a radius and center parameter, or a corner1 and corner2 parameter");corner1=c.parseOptionAs2DVector(a,"corner1",[0,0]);corner2=c.parseOptionAs2DVector(a, "corner2",[1,1]);b=corner1.plus(corner2).times(.5);d=corner2.minus(corner1).times(.5)}else b=c.parseOptionAs2DVector(a,"center",[0,0]),d=c.parseOptionAs2DVector(a,"radius",[1,1]);d=d.abs();var e=c.parseOptionAsFloat(a,"roundradius",.2);a=c.parseOptionAsInt(a,"resolution",c.defaultResolution2D);e=Math.min(e,Math.min(d.x,d.y)-.1);e=Math.max(0,e);d=new c.Vector2D(d.x-e,d.y-e);b=n.rectangle({center:b,radius:d});0=b&&(b=1E-4); var d=this.getBounds(),e;a[0]?(e=d[1].x-d[0].x,d=d[0].x):(e=d[1].y-d[0].y,d=d[0].y);for(var f=[],h=[],m=0;mb&&(b=4);var d=[],e={};this.canonicalized().sides.map(function(b){var c=b.vertex1.pos.minus(b.vertex0.pos),f=c.length();if(1E-5c;c++){var f=0===c?b.vertex0.pos:b.vertex1.pos,h=0===c?b.vertex1.pos:b.vertex0.pos,g=f.x+" "+f.y;g in e||(e[g]=[]);e[g].push({p1:f,p2:h})}});for(var f in e){var h=e[f],g,k=h[0].p1;if(2==h.length){g=h[1].p2;h=h[0].p2.minus(k).angleDegrees();g=g.minus(k).angleDegrees();g=h+360&&(g-=360);if(gh+359.999)h=0,g=360;if(g>h+1E-5){var p=[];l||p.push(k);var G=Math.round(b*(g- h)/360);1>G&&(G=1);for(var E=0;E<=G;E++){var r=h+E/G*(g-h);E==G&&(r=g);r=k.plus(c.Vector2D.fromAngleDegrees(r).times(a));(!l||0a&&(a=1E-4);1E-4>f&&(f=1E-4); if(0==b.z)throw"offset cannot be orthogonal to Z axis";if(0==d||1>e)e=1;for(var h=c.Vector3D.Create(0,1,0),g=[],g=g.concat(this._toPlanePolygons({translation:[0,0,0],normalVector:h,flipped:!(0>b.z)})),g=g.concat(this._toPlanePolygons({translation:b,normalVector:h.rZ(d),flipped:0>b.z})),k=0;kb)var k=new c.Connector(a, e.rZ(-b),f),h=h.concat(this._toPlanePolygons({toConnector:g,flipped:!0})),h=h.concat(this._toPlanePolygons({toConnector:k}));for(var l=k=b/d;l<=b+1E-5;l+=k)d=new c.Connector(a,e.rZ(-l),f),h=h.concat(this._toWallPolygons({toConnector1:g,toConnector2:d})),g=d;return c.fromPolygons(h).reTesselated()},rotate_extrude:function(a){if(0==this.sides.length)return new c;var b=c.parseOptionAsInt(a,"faces",10),d=c.parseOptionAsInt(a,"twist",0),e=Math.abs(c.parseOptionAsInt(a,"radius",0));a=c.parseOptionAsInt(a, "tsteps",0);3>b&&(b=3);a=Math.ceil(a/b);1>a&&(a=1);for(var f=n.fromPoints([[-.001,1E5],[2E5,1E5],[2E5,-1E5],[-.001,-1E5]]),h=n.fromPoints([[.001,1E5],[-2E5,1E5],[-2E5,-1E5],[.001,-1E5]]),g=this.tr([e,0,0]),f=g.subtract(f),h=g.subtract(h),h=0!=f.sides.length?f.mirroredX().union(h):h,h=h.tr([-e,0,0]),g=[],f=0;fa.angle?1:this.distancea.distance?1:0}};n.ConvexHull=function(){this.indices=this.points=null;this.getIndices=function(){return this.indices};this.clear= function(){this.points=this.indices=null};this.ccw=function(a,b,c){a=(this.points[b].x-this.points[a].x)*(this.points[c].y-this.points[a].y)-(this.points[b].y-this.points[a].y)*(this.points[c].x-this.points[a].x);return 1E-5>a?0:a};this.angle=function(a,b){return Math.atan2(this.points[b].y-this.points[a].y,this.points[b].x-this.points[a].x)};this.distance=function(a,b){return(this.points[b].x-this.points[a].x)*(this.points[b].x-this.points[a].x)+(this.points[b].y-this.points[a].y)*(this.points[b].y- this.points[a].y)};this.compute=function(a){this.indices=null;if(!(3>a.length)){this.points=a;var b=0;for(a=1;ad&&(d+=Math.PI),e=this.distance(b,a),c.push(new n.ConvexHullPoint(a,d,e)));c.sort(function(a,b){return a.compare(b)});d=Array(this.points.length+1);e=2;for(a=0;a=this.ccw(d[c-1],d[c],d[a]);)c--;c++;b=d[a];d[a]=d[c];d[c]=b}this.indices=Array(c);for(a=0;ar&&(r+=360);180<=r&&(r-=360);if(0>p||r>n)p=E,n=r}n=l[p];l.splice(p,1);0===l.length&&delete b[k];g=a[n]}h=new c.Path2D(h,!0);d.push(h)}return d},overCutInsideCorners:function(a){var b=this.canonicalized(),d={};b.sides.map(function(a){a.vertex0.getTag()in d||(d[a.vertex0.getTag()]={pos:a.vertex0.pos,from:[],to:[]}); d[a.vertex0.getTag()].to.push(a.vertex1.pos);a.vertex1.getTag()in d||(d[a.vertex1.getTag()]={pos:a.vertex1.pos,from:[],to:[]});d[a.vertex1.getTag()].from.push(a.vertex0.pos)});var e=[],f;for(f in d){var h=d[f];if(1==h.from.length&&1==h.to.length){var g=h.pos,k=h.to[0],h=g.minus(h.from[0]).unit(),k=k.minus(g).unit();if(.001>h.cross(k)){var l=k.angleRadians()-h.angleRadians()+Math.PI;0>l?l+=2*Math.PI:l>=2*Math.PI&&(l-=2*Math.PI);for(var k=k.minus(h).unit(),p=30/180*Math.PI,h=a/Math.cos(p/2),g=g.plus(k.times(h)), k=l+k.angleRadians(),l=2*(Math.PI-l),p=2*Math.ceil(l/p/2),G=[g],E=0;E<=p;E++){var r=c.Vector2D.fromAngleRadians(k+E/p*l).times(h).plus(g);G.push(r)}e.push(n.fromPoints(G))}}}return b.subtract(e)}};n.Vertex=function(a){this.pos=a};n.Vertex.prototype={toString:function(){return"("+this.pos.x.toFixed(2)+","+this.pos.y.toFixed(2)+")"},getTag:function(){var a=this.tag;a||(this.tag=a=c.getTag());return a}};n.Side=function(a,b){if(!(a instanceof n.Vertex))throw Error("Assertion failed");if(!(b instanceof n.Vertex))throw Error("Assertion failed");this.vertex0=a;this.vertex1=b};n.Side._fromFakePolygon=function(a){a.vertices.forEach(function(a){if(!(-1.001<=a.pos.z&&-.999>a.pos.z||.999<=a.pos.z&&1.001>a.pos.z))throw"Assertion failed: _fromFakePolygon expects abs z values of 1";});if(4>a.vertices.length)return null;var b=[];a=a.vertices.filter(function(a,c){if(0 "+this.vertex1},toPolygon3D:function(a,b){var d=[new c.Vertex(this.vertex0.pos.toVector3D(a)),new c.Vertex(this.vertex1.pos.toVector3D(a)),new c.Vertex(this.vertex1.pos.toVector3D(b)),new c.Vertex(this.vertex0.pos.toVector3D(b))];return new c.Polygon(d)},transform:function(a){var b= this.vertex0.pos.transform(a);a=this.vertex1.pos.transform(a);return new n.Side(new n.Vertex(b),new n.Vertex(a))},flipped:function(){return new n.Side(this.vertex1,this.vertex0)},direction:function(){return this.vertex1.pos.minus(this.vertex0.pos)},getTag:function(){var a=this.tag;a||(this.tag=a=c.getTag());return a},lengthSquared:function(){var a=this.vertex1.pos.x-this.vertex0.pos.x,b=this.vertex1.pos.y-this.vertex0.pos.y;return a*a+b*b},length:function(){return Math.sqrt(this.lengthSquared())}}; n.fuzzyCAGFactory=function(){this.vertexfactory=new c.fuzzyFactory(2,1E-5)};n.fuzzyCAGFactory.prototype={getVertex:function(a){return this.vertexfactory.lookupOrCreate([a.pos._x,a.pos._y],function(b){return a})},getSide:function(a){var b=this.getVertex(a.vertex0);a=this.getVertex(a.vertex1);return new n.Side(b,a)},getCAG:function(a){var b=this;a=a.sides.map(function(a){return b.getSide(a)}).filter(function(a){return 1E-5g;g++)p[g]=65;g=new Uint32Array(1);g[0]=k;var c=new ArrayBuffer(50*k),n=new Int8Array(c),a=new ArrayBuffer(50),b=new Int8Array(a),d=new Float32Array(a,0,12),e=new Uint16Array(a,48,1),f=0;this.polygons.map(function(a){for(var c=a.vertices.length,h=0;hk;k++){var l=a.vertices[k+(0=g.points.length&&(a-=g.points.length);a=g.points[a];l+=" 10\n"+a.x+"\n 20\n"+a.y+"\n 30\n0.0\n"}});l+=" 0\nENDSEC\n 0\nEOF\n";return new Blob([l],{type:"application/dxf"})};CAG.prototype.toDxf=function(){var g=this.getOutlinePaths();return CAG.PathsToDxf(g)};CSG.prototype.toAMFString=function(g){var l='\n\n",k;for(k in g)l+=''+g[k]+ "\n";l+='\n\n\n';this.polygons.map(function(c){for(var a=0;a\n",c=0;this.polygons.map(function(g){l+="\n";if(!(3>g.vertices.length)){var a=1,b=.4,d=1,e=1;g.shared&&g.shared.color?(a=g.shared.color[0],b=g.shared.color[1],d=g.shared.color[2],e=g.shared.color[3]):g.color&&(a=g.color[0],b=g.color[1],d=g.color[2],3"+a+""+b+ ""+d+""+(void 0!==e?""+e+"":"")+"";for(a=0;a",l+=""+c+"",l+=""+(c+a+1)+"",l+=""+(c+a+2)+"",l+="\n";c+=g.vertices.length;l+="\n"}});l+="\n\n";l+="\n";return new Blob([l],{type:"application/amf+xml"})};CSG.Vector3D.prototype.toAMFString=function(){return""+this._x+""+this._y+""+this._z+""};CSG.Vertex.prototype.toAMFString=function(){return""+ this.pos.toAMFString()+"\n"};g.CSG=CSG;g.CAG=CAG})(this);