// 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=$('
d?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;f a[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);0 d.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(0 m&&(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(0 e&&(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-5 a.length||3 b)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;f a;)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;b d[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;b f&&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;b e&&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;b d;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;c this.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;h c&&(c=m,f=h);if(c>1E3*this.tolerance)break}null!=f&&this.addPointToFace(d,f)}},reindexFacesAndVertices:function(){for(var a=0;a b.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;n p;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;m c&&(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;b Math.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=0 m,l=[],m=Math.abs(m);0 n){l[p].len=n;l.index=p;break}}else if(q)for(m=0;m n){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+v arguments.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;d b)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;c q)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;c d;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-8 arguments.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(0 w)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: d v&&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(0 f.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&&0 a.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;.25 g&&(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&&2 g&&(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;h a.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)0 d){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);1 p&&(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-1 b)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);0 a.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;m b&&(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-5 c;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(g h+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||0 a&&(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;k b)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.distance a.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;a d&&(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;a r&&(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-5 g;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;h k;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+=' \n";return new Blob([l],{type:"application/amf+xml"})};CSG.Vector3D.prototype.toAMFString=function(){return"'+g[k]+ " \n";l+='\n";l+=""+this._x+" "+this._y+" "+this._z+" "};CSG.Vertex.prototype.toAMFString=function(){return"\n"};g.CSG=CSG;g.CAG=CAG})(this); "+ this.pos.toAMFString()+"