From b1c4df3d994f369cac3f573147c7dfd9e203f74c Mon Sep 17 00:00:00 2001 From: pboyer Date: Mon, 27 Oct 2014 09:29:22 -0400 Subject: [PATCH] Add additional comments and unit tests for curve_knot_insert --- build/verb.js | 39 +-- build/verb.min.js | 4 +- build/verbEval.js | 39 +-- build/verbEval.min.js | 6 +- docs/verb.html | 562 +++++++++++++++++++++++------------------- src/eval/eval.js | 39 +-- test/test.js | 149 ++++++++--- 7 files changed, 499 insertions(+), 339 deletions(-) diff --git a/build/verb.js b/build/verb.js index 7ea4c9f5..096cd3c0 100644 --- a/build/verb.js +++ b/build/verb.js @@ -4270,24 +4270,27 @@ verb.eval.nurbs.rational_surface_curvature = function( degree_u, knots_u, degree // // ####curve_knot_insert( degree, knots, control_points, u, s, r ) // -// Insert a knot along a rational curve +// Insert a knot along a rational curve. Note that this algorithm only works +// for r + s <= degree, where s is the initial multiplicity (number of duplicates) of the knot. +// +// Corresponds to algorithm A5.1 (Piegl & Tiller) +// +// Use the curve_knot_refine for applications like curve splitting. // // **params** // + *Number*, integer degree // + *Array*, array of nondecreasing knot values // + *Array*, array of control points // + *Number*, parameter at which to insert the knot -// + *Number*, initial multiplicity of the knot // + *Number*, number of times to insert the knot // // **returns** -// + *Object* the new curve, defined by degree, knots, and control_points +// + *Object* the new curve, defined by knots and control_points // verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, r ) { // num_pts is num control points for the initial curve - // nq is num control points for the output curve with knots inserted // k is the span on which the knots are inserted // s is the initial multiplicity of the knot // r is the number of times to insert the knot @@ -4295,13 +4298,10 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, var s = 0; // assume original multiplicity is 0 - TODO add check for multiplicity in knots - var dim = control_points[0].length - , num_pts = control_points.length + var num_pts = control_points.length , k = verb.eval.nurbs.knot_span( degree, u, knots ) // the span in which the knot will be inserted - , mp = knots.length - , nq = num_pts + r , num_pts_post = num_pts + r // a new control pt for every new knot - , Rw = new Array( degree - s ) + , control_points_temp = new Array( degree - s ) , knots_post = new Array( knots.length + r ) // r new knots , control_points_post = new Array( num_pts_post ) , i = 0; @@ -4337,7 +4337,7 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, // collect the affected control points in this temporary array for (i = 0; i <= degree-s; i++) { - Rw[i] = control_points[k-degree+i]; + control_points_temp[i] = control_points[k-degree+i]; } var L = 0 @@ -4351,27 +4351,30 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, for (i = 0; i <= degree-j-s; i++) { alpha = ( u - knots[L+i] ) / ( knots[i+k+1] - knots[L+i] ); - Rw[i] = numeric.add( numeric.mul( alpha, Rw[i+1] ), numeric.mul( (1.0 - alpha), Rw[i]) ); + + control_points_temp[i] = + numeric.add( + numeric.mul( alpha, control_points_temp[i+1] ), + numeric.mul( (1.0 - alpha), control_points_temp[i]) + ); + } - control_points_post[ L ] = Rw[0]; - control_points_post[k+r-j-s] = Rw[degree-j-s]; + control_points_post[ L ] = control_points_temp[0]; + control_points_post[k+r-j-s] = control_points_temp[degree-j-s]; } // not so confident about this part - for (i = L+1; i < k-s; i++) // set remaining control points - { - control_points_post[i] = Rw[ i - L ]; + for (i = L+1; i < k-s; i++) { + control_points_post[i] = control_points_temp[ i - L ]; } return { knots: knots_post, control_points: control_points_post }; } -// knot refinement - // // ####rational_surface_derivs( degree_u, knots_u, degree_v, knots_v, homo_control_points, num_derivs, u, v) diff --git a/build/verb.min.js b/build/verb.min.js index e28b2473..746b9fac 100644 --- a/build/verb.min.js +++ b/build/verb.min.js @@ -1,3 +1,3 @@ -/*! verb 2014-02-01 */ +/*! verb 2014-10-27 */ function getEastNeighbor(e,r,t,n,i,s){return t===i-1?null:s[e+1]}function getNorthNeighbor(e,r,t,n,i,s){return 0===r?null:s[e-i]}function getSouthNeighbor(e,r,t,n,i,s){return r===n-1?null:s[e+i]}function getWestNeighbor(e,r,t,n,i,s){return 0===t?null:s[e-1]}function crossprod(e,r){return[e[1]*r[2]-e[2]*r[1],e[2]*r[0]-e[0]*r[2],e[0]*r[1]-e[1]*r[0]]}if("object"!=typeof exports||void 0===exports)var verb={},numeric=window.numeric,binomial=window.binomial,labor=window.labor;else var verb=module.exports={},numeric=require("numeric"),binomial=require("binomial"),labor=require("labor");verb.geom=verb.geom||{},verb.core=verb.core||{},verb.eval=verb.eval||{},verb.intersect=verb.intersect||{},verb.eval.nurbs=verb.eval.nurbs||{},verb.eval.geom=verb.eval.geom||{},verb.eval.mesh=verb.eval.mesh||{},verb.EPSILON=1e-8,verb.TOLERANCE=.001,verb.init=function(){verb.nurbsEngine=new verb.core.Engine(verb.eval.nurbs),verb.geom.NurbsGeometry.prototype.nurbsEngine=verb.nurbsEngine},Function.prototype.method=function(e,r){return this.prototype[e]=r,this},Function.method("inherits",function(e){return this.prototype=new e,this.prototype,this.prototype.constructor=e,this}),Array.prototype.flatten=function(){if(0==this.length)return[];for(var e=[],r=0;this.length>r;r++)e=this[r]instanceof Array?e.concat(this[r].flatten()):e.concat(this[r]);return e},numeric.normalized=function(e){return numeric.div(e,numeric.norm2(e))},numeric.cross=function(e,r){return[e[1]*r[2]-e[2]*r[1],e[2]*r[0]-e[0]*r[2],e[0]*r[1]-e[1]*r[0]]},verb.left=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(0,r)},verb.right=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(r)},verb.rightWithPivot=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(r-1)},verb.unique=function(e,r){if(0===e.length)return[];for(var t=[e.pop()],n=0;e.length>n;n++){for(var i=e.pop(),s=!0,a=0;t.length>a;a++)if(r(i,t[n])){s=!1;break}s&&t.push(i)}return t},verb.range=function(e,r,t){1>=arguments.length&&(r=e||0,e=0),t=arguments[2]||1;for(var n=Math.max(Math.ceil((r-e)/t),0),i=0,s=Array(n);n>i;)s[i++]=e,e+=t;return s},verb.core.Engine=function(e){var r="function"==typeof Worker&&(e.use_pool||void 0===e.use_pool),t=e.num_workers||2,n=e.tolerance||1e-4,i=e.url||"js/verbEval.js",s=e.library||verb.eval.nurbs,a=e.error_handler||function(e){console.warn(e)},o=void 0,u=function(){try{o=new labor.Pool(i,t),o.start()}catch(e){return a("Failed to initialize labor.Pool: "+e),!1}return!0},v=function(e,r){return s[e].apply(null,r)};this.start=function(){r&&u()},this.eval=function(e,t,n){return n?(r&&(o||void 0===o&&u())?o.addWork(e,t,n):setTimeout(function(){n(v(e,t))},0),void 0):v(e,t)},this.setTolerance=function(e){n=e},this.setUsePool=function(e){return e&&void 0===o&&u()?(r=e,!0):e?!1:(o=null,delete o,!0)},this.setErrorHandler=function(e){a=e},this.setNumThreads=function(e){t=e}},verb.core.WatchObject=function(){var e={change:{}},r={},t=0,i=this,s=function(r,t){if("string"==typeof r){for(ele in e[r])e[r][ele](t);for(ele in e.change)e.change[ele](t)}else for(n in r)s(n,t)};this.get=function(e){return r[e]},this.set=function(t,n){var a=r[t];r[t]=n,e[t]=e[t]||{},s(t,{name:t,old:a,"new":n,target:i,type:"full"})},this.setAll=function(t){var n={};for(propName in t)n[propName]=r[propName],r[propName]=t[propName],e[propName]=e[propName]||{};s(t,{old:n,"new":t,target:i,type:"multi"})},this.setAt=function(e,t,n){var a=r[e];if(!(void 0===a||a.length>=t||0>t)){var o=r[e][t];r[e][t]=n,s(e,{name:e,index:t,old:o,"new":n,target:i,type:"index"})}},this.watch=function(n,i){return void 0!==r[n]&&i?(t++,e[n][t]=i,t++):void 0},this.watchAll=function(e,r){for(var t=[],n=0;e.length>n;n++)t.push(this.watch(e[n],r));return t},this.ignore=function(r,t){void 0!==e[r]&&void 0!==e[r][t]&&(e[r][t]=void 0)}},verb.core.uid=function(){var e=0;return function(){return e++}}(),verb.geom.Geometry=function(){verb.core.WatchObject.call(this);var e=verb.core.uid();this.uniqueId=function(){return e}}.inherits(verb.core.WatchObject),verb.geom.NurbsGeometry=function(){verb.geom.Geometry.call(this)}.inherits(verb.geom.Geometry),verb.geom.NurbsCurve=function(e,r,t,n){verb.geom.NurbsGeometry.call(this),this.setAll({controlPoints:r,weights:t,knots:n?n.slice(0):[],degree:e})}.inherits(verb.geom.NurbsGeometry),verb.geom.NurbsCurve.prototype.point=function(e,r){return this.nurbsEngine.eval("rational_curve_point",[this.get("degree"),this.get("knots"),this.homogenize(),e],r)},verb.geom.NurbsCurve.prototype.derivatives=function(e,r,t){return this.nurbsEngine.eval("rational_curve_derivs",[this.get("degree"),this.get("knots"),this.homogenize(),e,r],t)},verb.geom.NurbsCurve.prototype.tesselate=function(e,r){var e=e||{};return e.tolerance=e.tolerance||verb.EPSILON,this.nurbsEngine.eval("rational_curve_adaptive_sample",[this.get("degree"),this.get("knots"),this.homogenize(),e.tolerance],r)},verb.geom.NurbsCurve.prototype.transform=function(e){for(var r=this.get("controlPoints"),t=0;r.length>t;t++){var n=r[1].push(1);r[t]=numeric.mul(e,n).slice(0,n.length-2)}return this.set("controlPoints",r),this},verb.geom.NurbsCurve.prototype.clone=function(){for(var e=this.get("controlPoints"),r=[],t=0;e.length>t;t++)r.push(e[t].slice(0));return new verb.geom.NurbsCurve(this.get("degree"),r,this.get("weights").slice(0),this.get("knots").slice)},verb.geom.NurbsCurve.prototype.homogenize=function(){return verb.eval.nurbs.homogenize_1d(this.get("controlPoints"),this.get("weights"))},verb.geom.NurbsCurve.prototype.update=function(){if(this.nurbsRep){var e=this.nurbsRep();this.setAll({controlPoints:e.control_points,weights:e.weights,knots:e.knots,degree:e.degree})}},verb.geom.NurbsSurface=function(e,r,t,n,i,s){verb.geom.NurbsGeometry.call(this),this.setAll({controlPoints:i,weights:s,knotsU:r?r.slice(0):[],knotsV:n?n.slice(0):[],degreeU:e,degreeV:t})}.inherits(verb.geom.NurbsGeometry),verb.geom.NurbsSurface.prototype.point=function(e,r,t){return this.nurbsEngine.eval("rational_surface_point",[this.get("degreeU"),this.get("knotsU"),this.get("degreeV"),this.get("knotsV"),this.homogenize(),e,r],t)},verb.geom.NurbsSurface.prototype.derivatives=function(e,r,t,n){return this.nurbsEngine.eval("rational_surface_derivs",[this.get("degreeU"),this.get("knotsU"),this.get("degreeV"),this.get("knotsV"),this.homogenize(),t,e,r],n)},verb.geom.NurbsSurface.prototype.tesselate=function(e,r){var t=20,n=20;return e&&(t=e.minDivsV||t,n=e.minDivsU||n),this.nurbsEngine.eval("tesselate_rational_surface_naive",[this.get("degreeU"),this.get("knotsU"),this.get("degreeV"),this.get("knotsV"),this.homogenize(),n,t],r)},verb.geom.NurbsSurface.prototype.transform=function(e){for(var r=this.get("controlPoints"),t=0;r.length>t;t++)for(var n=0;r[t].length>n;n++){var i=r[1].push(1);r[t]=numeric.mul(e,i).slice(0,i.length-2)}return this.set("controlPoints",r),this},verb.geom.NurbsSurface.prototype.clone=function(){for(var e=this.get("controlPoints"),r=[],t=0;e.length>t;t++){r.push([]);for(var n=0;e[t].length>n;n++)r[t].push(e[t][n].slice(0))}for(var i=this.get("weights"),s=[],t=0;i.length>t;t++)s.push(i[t].slice(0));return new verb.geom.NurbsSurface(this.get("degreeU"),this.get("knotsU").slice(0),this.get("degreeV"),this.get("knotsV").slice(0),r,s)},verb.geom.NurbsSurface.prototype.homogenize=function(){return verb.eval.nurbs.homogenize_2d(this.get("controlPoints"),this.get("weights"))},verb.geom.NurbsSurface.prototype.update=function(){if(this.nurbsRep){var e=this.nurbsRep();this.setAll({controlPoints:e.control_points,weights:e.weights,knotsU:e.knots_u,knotsV:e.knots_v,degreeU:e.degree_u,degreeV:e.degree_v})}},verb.geom.Arc=function(e,r,t,n,i){verb.geom.NurbsCurve.call(this),this.setAll({center:e,xaxis:r,yaxis:t,radius:n,interval:i}),this.update(),this.watchAll(["center","xaxis","yaxis","radius","interval"],this.update)}.inherits(verb.geom.NurbsCurve),verb.geom.Arc.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_arc",[this.get("center"),this.get("xaxis"),this.get("yaxis"),this.get("radius"),this.get("interval").get("min"),this.get("interval").get("max")])},verb.geom.BezierCurve=function(e,r){verb.geom.NurbsCurve.call(this),this.setAll({controlPoints:e?e.slice(0):[],weights:r?r.slice(0):void 0}),this.update()}.inherits(verb.geom.NurbsCurve),verb.geom.BezierCurve.prototype.nurbsRep=function(){for(var e=this.get("controlPoints"),r=this.get("weights"),t=e.length-1,n=[],i=0;t+1>i;i++)n.push(0);for(var i=0;t+1>i;i++)n.push(1);if(void 0===r){r=[];for(var i=0;e.length>i;i++)r.push(1)}return{degree:t,knots:n,control_points:e,weights:r}},verb.geom.BoundingBox=function(){this.initialized=!1,this.min=[0,0,0],this.max=[0,0,0];var e=Array.prototype.slice.call(arguments,0);1===e.length&&e[0]instanceof Array&&e[0][0]instanceof Array?this.add_elements_sync(e[0]):this.add_elements_sync(e)},verb.geom.BoundingBox.prototype.add_elements=function(e,r){var t=this;setTimeout(function(){e.forEach(function(e){t.add(e)}),r(t)},0)},verb.geom.BoundingBox.prototype.add_elements_sync=function(e){var r=this;return e.forEach(function(e){r.add(e)}),this},verb.geom.BoundingBox.prototype.add=function(e){return this.initialized?(e[0]>this.max[0]&&(this.max[0]=e[0]),e[1]>this.max[1]&&(this.max[1]=e[1]),e[2]>this.max[2]&&(this.max[2]=e[2]),e[0]=o&&u>=s||a>=o&&u>=a||o>=s&&a>=o||u>=s&&a>=u?!0:!1},verb.geom.BoundingBox.prototype.intersects=function(e,r){if(!this.initialized||!e.initialized)return!1;var t=this.min,n=this.max,i=e.min,s=e.max;return this.intervals_overlap(t[0],n[0],i[0],s[0],r)&&this.intervals_overlap(t[1],n[1],i[1],s[1],r)&&this.intervals_overlap(t[2],n[2],i[2],s[2],r)?!0:!1},verb.geom.BoundingBox.prototype.clear=function(){return this.initialized=!1,this},verb.geom.BoundingBox.prototype.get_longest_axis=function(){var e=[this.get_axis_length(0),this.get_axis_length(1),this.get_axis_length(2)];return e.indexOf(Math.max.apply(Math,e))},verb.geom.BoundingBox.prototype.get_axis_length=function(e){return 0>e||e>2?0:Math.abs(this.min[e]-this.max[e])},verb.geom.BoundingBox.prototype.intersect=function(e,r){if(!this.initialized)return null;var t=this.min,n=this.max,i=e.min,s=e.max;if(!this.intersects(e,r))return null;var a=Math.min(n[0],s[0]),o=Math.max(t[0],i[0]),u=Math.min(n[1],s[1]),v=Math.max(t[1],i[1]),l=Math.min(n[2],s[2]),c=Math.max(t[2],i[2]),b=[a,u,l],h=[o,v,c];return new verb.geom.BoundingBox(h,b)},verb.geom.Circle=function(e,r,t,n){verb.geom.NurbsCurve.call(this),this.setAll({center:e,xaxis:r,yaxis:t,radius:n}),this.update(),this.watchAll(["center","xaxis","yaxis","radius"],this.update)}.inherits(verb.geom.NurbsCurve),verb.geom.Circle.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_arc",[this.get("center"),this.get("xaxis"),this.get("yaxis"),this.get("radius"),0,2*Math.PI])},verb.geom.Cone=function(e,r,t,n,i){verb.geom.NurbsSurface.call(this),this.setAll({axis:e,xaxis:r,base:t,height:n,radius:i});var s=this.nurbsRep();verb.geom.NurbsSurface.call(this,s.degree_u,s.knots_u,s.degree_v,s.knots_v,s.control_points,s.weights),this.watchAll(["axis","xaxis","base","height","radius"],this.update)}.inherits(verb.geom.NurbsSurface),verb.geom.Cone.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_cone_surface",[this.get("axis"),this.get("xaxis"),this.get("base"),this.get("height"),this.get("radius")])},verb.geom.Cylinder=function(e,r,t,n,i){this.setAll({axis:e,xaxis:r,base:t,height:n,radius:i});var s=this.nurbsRep();verb.geom.NurbsSurface.call(this,s.degree_u,s.knots_u,s.degree_v,s.knots_v,s.control_points,s.weights),this.watchAll(["axis","xaxis","base","height","radius"],this.update)}.inherits(verb.geom.NurbsSurface),verb.geom.Cylinder.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_cylinder_surface",[this.get("axis"),this.get("xaxis"),this.get("base"),this.get("height"),this.get("radius")])},verb.geom.Ellipse=function(e,r,t,n,i){verb.geom.NurbsCurve.call(this),this.setAll({center:e,xaxis:r,yaxis:t,xradius:n,yradius:i}),this.update(),this.watchAll(["center","xaxis","yaxis","xradius","yradius"],this.update)}.inherits(verb.geom.NurbsCurve),verb.geom.Ellipse.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_ellipse_arc",[this.get("center"),this.get("xaxis"),this.get("yaxis"),this.get("xradius"),this.get("yradius"),0,2*Math.PI])},verb.geom.EllipseArc=function(e,r,t,n,i,s){verb.geom.NurbsCurve.call(this),this.setAll({center:e,xaxis:r,yaxis:t,xradius:n,yradius:i,interval:s}),this.update(),this.watchAll(["center","xaxis","yaxis","xradius","yradius","interval"],this.update)}.inherits(verb.geom.NurbsCurve),verb.geom.EllipseArc.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_ellipse_arc",[this.get("center"),this.get("xaxis"),this.get("yaxis"),this.get("xradius"),this.get("yradius"),this.get("interval").get("min"),this.get("interval").get("max")])},verb.geom.Extrusion=function(e,r,t){verb.geom.NurbsSurface.call(this),this.setAll({profile:e,axis:r,length:t}),this.update(),this.watchAll(["axis","length"],this.update),e.watchAll(["knots","degree","controlPoints","weights"],this.update)}.inherits(verb.geom.NurbsSurface),verb.geom.Extrusion.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_extruded_surface",[this.get("axis"),this.get("length"),this.get("profile").get("knots"),this.get("profile").get("degree"),this.get("profile").get("controlPoints"),this.get("profile").get("weights")])},verb.geom.FourPointSurface=function(e,r,t,n){verb.geom.NurbsSurface.call(this),this.setAll({p1:e,p2:r,p3:t,p4:n}),this.update(),this.watchAll(["p1","p2","p3","p4"],this.update)}.inherits(verb.geom.NurbsSurface),verb.geom.FourPointSurface.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_4pt_surface",[this.get("p1"),this.get("p2"),this.get("p3"),this.get("p4")])},verb.geom.Interval=function(e,r){verb.core.WatchObject.call(this),this.setAll({min:e,max:r})}.inherits(verb.core.WatchObject),verb.geom.Interval2=function(e,r,t,n){verb.core.WatchObject.call(this),this.setAll({uinterval:new verb.geom.Interval(e,r),vinterval:new verb.geom.Interval(t,n)})}.inherits(verb.core.WatchObject),verb.geom.Line=function(e,r){verb.geom.NurbsCurve.call(this),this.setAll({start:e,end:r}),this.update(),this.watchAll(["start","end"],this.update)}.inherits(verb.geom.NurbsCurve),verb.geom.Line.prototype.nurbsRep=function(){return{knots:[0,0,1,1],control_points:[this.get("start"),this.get("end")],weights:[1,1],degree:1}},verb.geom.PlanarSurface=function(e,r,t,n,i){verb.geom.NurbsSurface.call(this),this.setAll({base:e,uaxis:r,vaxis:t,ulength:n,vlength:i}),this.update(),this.watchAll(["base","uaxis","vaxis","ulength","vlength"],this.update)}.inherits(verb.geom.NurbsSurface),verb.geom.PlanarSurface.prototype.nurbsRep=function(){var e=this.get("base"),r=numeric.mul(this.get("uaxis"),this.get("ulength")),t=numeric.mul(this.get("vaxis"),this.get("vlength")),n=numeric.add(e,r),i=numeric.add(e,t,r),s=numeric.add(e,t);return this.nurbsEngine.eval("get_4pt_surface",[e,n,i,s])},verb.geom.PolyLine=function(e){verb.geom.NurbsCurve.call(this),this.setAll({control_points:e?e.slice(0):[]}),this.update()}.inherits(verb.geom.NurbsCurve),verb.geom.PolyLine.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_polyline_curve",[this.get("control_points")])},verb.geom.RevolvedSurface=function(e,r,t,n){verb.geom.NurbsSurface.call(this),this.setAll({center:e,axis:r,angle:t,profile:n}),this.update(),this.watchAll(["center","axis","angle","profile"],this.update)}.inherits(verb.geom.NurbsSurface),verb.geom.RevolvedSurface.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_revolved_surface",[this.get("center"),this.get("axis"),this.get("angle"),this.get("profile").get("knots"),this.get("profile").get("degree"),this.get("profile").get("controlPoints"),this.get("profile").get("weights")])},verb.geom.Sphere=function(e,r){verb.geom.NurbsSurface.call(this),this.setAll({center:e,radius:r}),this.update(),this.watchAll(["center","radius"],this.update)}.inherits(verb.geom.NurbsSurface),verb.geom.Sphere.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_sphere_surface",[this.get("center"),[0,0,1],[1,0,0],this.get("radius")])},verb.geom.SweepOneRail=function(e,r){verb.geom.NurbsSurface.call(this),this.setAll({rail:e,profile:r}),this.update(),this.watchAll(["rail","profile"],this.update)}.inherits(verb.geom.NurbsSurface),verb.geom.SweepOneRail.prototype.nurbsRep=function(){return this.nurbsEngine.eval("get_sweep1_surface",[this.get("profile").get("knots"),this.get("profile").get("degree"),this.get("profile").get("controlPoints"),this.get("profile").get("weights"),this.get("rail").get("knots"),this.get("rail").get("degree"),this.get("rail").get("controlPoints"),this.get("rail").get("weights")])},verb.intersect.curveCurve=function(e,r,t){return verb.nurbsEngine.eval("intersect_rational_curves_by_aabb_refine",[e.get("degree"),e.get("knots"),e.homogenize(),r.get("degree"),r.get("knots"),r.homogenize(),verb.TOLERANCE,verb.TOLERANCE],t)},verb.intersect.curveSurface=function(e,r,t,n){return t=t||{tolerance:verb.TOLERANCE,sampleTolerance:verb.TOLERANCE,uDivs:20,vDivs:20},verb.nurbsEngine.eval("intersect_rational_curve_surface_by_aabb_refine",[r.get("degreeU"),r.get("knotsU"),r.get("degreeV"),r.get("knotsV"),r.homogenize(),e.get("degree"),e.get("knots"),e.homogenize(),t.sampleTolerance,t.tolerance,t.uDivs,t.vDivs],n)},verb.eval.nurbs.intersect_rational_curve_surface_by_aabb_refine=function(e,r,t,n,i,s,a,o,u,v,l,c){var b=verb.eval.nurbs.intersect_rational_curve_surface_by_aabb(e,r,t,n,i,s,a,o,u,v,l,c);return b.map(function(u){var v=[u.p,u.uv[0],u.uv[1]],l=verb.eval.nurbs.refine_rational_curve_surface_intersection(e,r,t,n,i,s,a,o,v);return u.p=l[0],u.uv[0]=l[1],u.uv[1]=l[2],u.distance=l[3],delete u.face,u})},verb.eval.nurbs.refine_rational_curve_surface_intersection=function(e,r,t,n,i,s,a,o,u){var v=function(u){var v=verb.eval.nurbs.rational_curve_point(s,a,o,u[0]),l=verb.eval.nurbs.rational_surface_point(e,r,t,n,i,u[1],u[2]),c=numeric.sub(v,l);return numeric.dot(c,c)},l=numeric.uncmin(v,u);return l.solution.concat(l.f)},verb.eval.nurbs.intersect_rational_curve_surface_by_aabb=function(e,r,t,n,i,s,a,o,u,v,l,c){var b=verb.eval.nurbs.rational_curve_adaptive_sample(s,a,o,u,!0),h=verb.eval.nurbs.tesselate_rational_surface_naive(e,r,t,n,i,l,c),g=b.map(function(e){return e[0]}),_=b.map(function(e){return e.slice(1)}),m=verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(_,g,h,verb.range(h.faces.length),v);return verb.unique(m,function(e,r){return v>numeric.norm2(numeric.sub(e.point,r.point))&&v>Math.abs(e.p-r.p)&&v>numeric.norm2(numeric.sub(e.uv,r.uv))})},verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb=function(e,r,t,n,i){var s=new verb.geom.BoundingBox(e),a=verb.eval.mesh.make_mesh_aabb(t.points,t.faces,n);if(!s.intersects(a,i))return[];if(2!==e.length||1!==n.length){if(1===n.length){var o=verb.left(e),u=verb.rightWithPivot(e),v=verb.left(r),l=verb.rightWithPivot(r);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,v,t,n,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,l,t,n,i))}if(2===e.length){var c=verb.eval.mesh.sort_tris_on_longest_axis(a,t.points,t.faces,n),b=verb.left(c),h=verb.right(c);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(e,r,t,b,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(e,r,t,h,i))}var c=verb.eval.mesh.sort_tris_on_longest_axis(a,t.points,t.faces,n),b=verb.left(c),h=verb.right(c),o=verb.left(e),u=verb.rightWithPivot(e),v=verb.left(r),l=verb.rightWithPivot(r);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,v,t,b,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,v,t,h,i)).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,l,t,b,i)).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,l,t,h,i))}var g=verb.eval.geom.intersect_segment_with_tri(e[0],e[1],t.points,t.faces[n[0]]);if(null!=g){var _=g.p*(r[1]-r[0])+r[0],m=t.faces[n][0],f=t.faces[n][1],d=t.faces[n][2],p=t.uvs[m],y=t.uvs[f],x=t.uvs[d],N=numeric.sub(y,p),k=numeric.sub(x,p),w=numeric.add(p,numeric.mul(g.s,N),numeric.mul(g.t,k));return[{point:g.point,p:_,uv:w,face:n[0]}]}return[]},verb.eval.geom.intersect_segment_with_tri=function(e,r,t,n){var i=t[n[0]],s=t[n[1]],a=t[n[2]],o=numeric.sub(s,i),u=numeric.sub(a,i),v=numeric.cross(o,u),l=numeric.sub(r,e),c=numeric.sub(e,i),b=-numeric.dot(v,c),h=numeric.dot(v,l);if(Math.abs(h)g||g>1)return null;var _=numeric.add(e,numeric.mul(g,l)),m=numeric.dot(o,u),f=numeric.dot(o,o),d=numeric.dot(u,u),p=numeric.sub(_,i),y=numeric.dot(p,o),x=numeric.dot(p,u),N=m*m-f*d,k=(m*x-d*y)/N,w=(m*y-f*x)/N;return k>1+verb.EPSILON||w>1+verb.EPSILON||-verb.EPSILON>w||-verb.EPSILON>k||k+w>1+verb.EPSILON?null:{point:_,s:k,t:w,p:g}},verb.eval.geom.intersect_segment_with_plane=function(e,r,t,n){var i=numeric.dot(n,numeric.sub(e,r));if(EPSILON>abs(i))return null;var s=numeric.dot(n,numeric.sub(t,e));return{p:s/i}},verb.eval.geom.intersect_aabb_trees=function(e,r,t,n,i,s){var a=i.bounding_box.intersects(s.bounding_box);return a?0===i.children.length&&0===s.children.length?[[i.triangle,s.triangle]]:0===i.children.length&&0!=s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,t,n,i,s.children[0]).concat(verb.eval.geom.intersect_aabb_trees(e,r,t,n,i,s.children[1])):0!=i.children.length&&0===s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,t,n,i.children[0],s).concat(verb.eval.geom.intersect_aabb_trees(e,r,t,n,i.children[1],s)):0!=i.children.length&&0!=s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,t,n,i.children[0],s.children[0]).concat(verb.eval.geom.intersect_aabb_trees(e,r,t,n,i.children[0],s.children[1])).concat(verb.eval.geom.intersect_aabb_trees(e,r,t,n,i.children[1],s.children[0])).concat(verb.eval.geom.intersect_aabb_trees(e,r,t,n,i.children[1],s.children[1])):void 0:[]},verb.eval.mesh.make_mesh_aabb_tree=function(e,r,t){var n={bounding_box:verb.eval.mesh.make_mesh_aabb(e,r,t),children:[]};if(1===t.length)return n.triangle=t[0],n;var i=verb.eval.mesh.sort_tris_on_longest_axis(n.bounding_box,e,r,t),s=i.slice(0,Math.floor(i.length/2)),a=i.slice(Math.floor(i.length/2),i.length);return n.children=[verb.eval.mesh.make_mesh_aabb_tree(e,r,s),verb.eval.mesh.make_mesh_aabb_tree(e,r,a)],n},verb.eval.mesh.make_mesh_aabb=function(e,r,t){var n=new verb.geom.BoundingBox;return t.forEach(function(t){n.add(e[r[t][0]]),n.add(e[r[t][1]]),n.add(e[r[t][2]])}),n},verb.eval.mesh.sort_tris_on_longest_axis=function(e,r,t,n){for(var i=e.get_longest_axis(),s=[],a=n.length-1;a>=0;a--){var o=n[a],u=verb.eval.mesh.get_min_coordinate_on_axis(r,t[o],i);s.push([u,o])}s.sort(function(e,r){return e[0]>r[0]});for(var v=[],a=0,l=s.length;l>a;a++)v.push(s[a][1]);return v},verb.eval.mesh.get_min_coordinate_on_axis=function(e,r,t){for(var n=[],i=0;3>i;i++)n.push(e[r[i]][t]);return Math.min.apply(Math,n)},verb.eval.geom.get_tri_centroid=function(e,r){for(var t=[0,0,0],n=0;3>n;n++)for(var i=0;3>i;i++)t[i]+=e[r[n]][i];for(var n=0;3>n;n++)t[n]/=3;return t},verb.eval.geom.get_tri_norm=function(e,r){var t=e[r[0]],n=e[r[1]],i=e[r[2]],s=numeric.sub(n,t),a=numeric.sub(i,t),o=numeric.cross(s,a);return numeric.mul(1/numeric.norm2(o),o)},verb.eval.nurbs.intersect_rational_curves_by_aabb_refine=function(e,r,t,n,i,s,a,o){var u=verb.eval.nurbs.intersect_rational_curves_by_aabb(e,r,t,n,i,s,a,o);return u.map(function(a){return verb.eval.nurbs.refine_rational_curve_intersection(e,r,t,n,i,s,a)})},verb.eval.nurbs.refine_rational_curve_intersection=function(e,r,t,n,i,s,a){var o=function(a){var o=verb.eval.nurbs.rational_curve_point(e,r,t,a[0]),u=verb.eval.nurbs.rational_curve_point(n,i,s,a[1]),v=numeric.sub(o,u);return numeric.dot(v,v)},u=numeric.uncmin(o,a);return u.solution.concat(u.f)},verb.eval.nurbs.intersect_rational_curves_by_aabb=function(e,r,t,n,i,s,a,o){var u=verb.eval.nurbs.rational_curve_adaptive_sample(e,r,t,a,!0),v=verb.eval.nurbs.rational_curve_adaptive_sample(n,i,s,a,!0),l=u.map(function(e){return e[0]}),c=v.map(function(e){return e[0]}),b=u.map(function(e){return e.slice(1)}),h=v.map(function(e){return e.slice(1)});return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(b,h,l,c,o)},verb.eval.nurbs.intersect_parametric_polylines_by_aabb=function(e,r,t,n,i){var s=new verb.geom.BoundingBox(e),a=new verb.geom.BoundingBox(r);if(!s.intersects(a,i))return[];if(2!==e.length||2!==r.length){if(2===e.length){var o=Math.ceil(r.length/2),u=r.slice(0,o),v=r.slice(o-1),l=n.slice(0,o),c=n.slice(o-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(e,u,t,l,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(e,v,t,c,i))}if(2===r.length){var b=Math.ceil(e.length/2),h=e.slice(0,b),g=e.slice(b-1),_=t.slice(0,b),m=t.slice(b-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,r,_,n,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(g,r,m,n,i))}var b=Math.ceil(e.length/2),h=e.slice(0,b),g=e.slice(b-1),_=t.slice(0,b),m=t.slice(b-1),o=Math.ceil(r.length/2),u=r.slice(0,o),v=r.slice(o-1),l=n.slice(0,o),c=n.slice(o-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,u,_,l,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,v,_,c,i)).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(g,u,m,l,i)).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(g,v,m,c,i))}var f=verb.eval.geom.intersect_segments(e[0],e[1],r[0],r[1],i);return null!=f?(f[0][0]=f[0][0]*(t[1]-t[0])+t[0],f[1][0]=f[1][0]*(n[1]-n[0])+n[0],[[f[0][0],f[1][0]]]):[]},verb.eval.geom.intersect_segments=function(e,r,t,n,i){var s=numeric.sub(r,e),a=Math.sqrt(numeric.dot(s,s)),o=numeric.mul(1/a,s),u=numeric.sub(n,t),v=Math.sqrt(numeric.dot(u,u)),l=numeric.mul(1/v,u),c=verb.eval.geom.intersect_rays(e,o,t,l);if(null!=c){var b=Math.min(Math.max(0,c[0]/a),1),h=Math.min(Math.max(0,c[1]/v),1),g=numeric.add(numeric.mul(b,s),e),_=numeric.add(numeric.mul(h,u),t),m=numeric.norm2Squared(numeric.sub(g,_));if(i*i>m)return[[b].concat(g),[h].concat(_)]}return null},verb.eval.geom.closest_point_on_ray=function(e,r,t){var n=numeric.sub(e,r),i=numeric.dot(n,t),s=numeric.add(r,numeric.mul(i,t));return s},verb.eval.geom.intersect_rays=function(e,r,t,n){var i=numeric.dot(r,n),s=numeric.dot(r,t),a=numeric.dot(r,e),o=numeric.dot(n,t),u=numeric.dot(n,e),v=numeric.dot(r,r),l=numeric.dot(n,n),c=v*l-i*i;if(Math.abs(c)m;m++){var f=verb.eval.geom.intersect_segment_with_plane(c[m][0],b[m][1],_,g);f.intersects&&h.push(f)}if(2!==h.length)return null;for(var d=[h[0].point,h[1].point],p=[],m=0;3>m;m++){var y=verb.eval.geom.intersect_segments(d[0],d[1],d,b1,tol);y&&p.push(y)}0===p.length||1===p.length||2===p.length},verb.eval.nurbs.tesselate_rational_surface_naive=function(e,r,t,n,i,s,a){1>s&&(s=1),1>a&&(a=1);for(var o=1/s,u=1/a,v=[],l=[],c=[],b=0;s+1>b;b++)for(var h=0;a+1>h;h++){var g=b*o,_=h*u;l.push([g,_]);var m=verb.eval.nurbs.rational_surface_derivs(e,r,t,n,i,1,g,_),f=m[0][0];v.push(f);var d=numeric.cross(m[0][1],m[1][0]);c.push(d)}for(var p=[],b=0;s>b;b++)for(var h=0;a>h;h++){var y=b*(a+1)+h,x=(b+1)*(a+1)+h,N=x+1,k=y+1,w=[y,x,N],E=[y,N,k];p.push(w),p.push(E)}return{points:v,faces:p,uvs:l,normals:c}},verb.eval.nurbs.rational_curve_regular_sample=function(e,r,t,n,i){return verb.eval.nurbs.rational_curve_regular_sample_range(e,r,t,0,1,n,i)},verb.eval.nurbs.rational_curve_regular_sample_range=function(e,r,t,n,i,s,a){1>s&&(s=2);for(var o=[],u=(i-n)/(s-1),v=0,l=0;s>l;l++)v=n+u*l,a?o.push([v].concat(verb.eval.nurbs.rational_curve_point(e,r,t,v))):o.push(verb.eval.nurbs.rational_curve_point(e,r,t,v));return o},verb.eval.nurbs.rational_curve_adaptive_sample=function(e,r,t,n,i){return 1===e?i?t.map(function(e,t){return[r[t+1]].concat(verb.eval.nurbs.dehomogenize(e))}):t.map(verb.eval.nurbs.dehomogenize):verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,t,0,1,n,i)},verb.eval.nurbs.rational_curve_adaptive_sample_range=function(e,r,t,n,i,s,a){var o=verb.eval.nurbs.rational_curve_point(e,r,t,n),u=verb.eval.nurbs.rational_curve_point(e,r,t,i),v=.5+.2*Math.random(),l=n+(i-n)*v,c=verb.eval.nurbs.rational_curve_point(e,r,t,l),b=numeric.sub(o,u),h=numeric.sub(o,c);if(s>numeric.dot(b,b)&&numeric.dot(h,h)>s||!verb.eval.nurbs.three_points_are_flat(o,c,u,s)){var g=n+.5*(i-n),_=verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,t,n,g,s,a),m=verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,t,g,i,s,a);return _.slice(0,-1).concat(m)}return a?[[n].concat(o),[i].concat(u)]:[o,u]},verb.eval.nurbs.three_points_are_flat=function(e,r,t,n){var i=numeric.sub(r,e),s=numeric.sub(t,e),a=crossprod(i,s),o=numeric.dot(a,a);return n>o},verb.eval.nurbs.divide_rational_surface_adaptive=function(e,r,t,n,i,s){for(var a={degree_u:e,knots_u:r,degree_v:t,knots_v:n,homo_control_points:i},o=s.minDivsU,u=s.minDivsV,v=Math.max.apply(null,r),l=Math.min.apply(null,r),c=Math.max.apply(null,n),b=Math.min.apply(null,n),h=(v-l)/o,g=(c-b)/u,_=[],m=0;o>m;m++)for(var f=0;u>f;f++){var d=l+h*m,p=l+h*(m+1),y=b+g*f,x=b+g*(f+1);_.push(new verb.eval.nurbs.AdaptiveRefinementNode(a,d,p,y,x,null,null))}for(var m=0;o>m;m++)for(var f=0;u>f;f++){var N=m*u+f,k=getNorthNeighbor(N,m,f,o,u,_),w=getEastNeighbor(N,m,f,o,u,_),E=getSouthNeighbor(N,m,f,o,u,_),A=getWestNeighbor(N,m,f,o,u,_);_[N].neighbors=[k,w,E,A],_.divide(s)}return _},verb.eval.nurbs.is_rational_surface_domain_flat=function(e){var r=verb.eval.nurbs.rational_surface_point,t=(u[1]-u[0]/2)*(.1*Math.random()+1),n=(v[1]-v[0]/2)*(.1*Math.random()+1),i=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[0],v[0]),s=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[0]+t,v[0]+n),a=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[1],v[1]);return verb.eval.nurbs.three_points_are_flat(i,s,a,tol)},verb.eval.nurbs.triangulate_adaptive_refinement_node_tree=function(e){var r={uvs:[],points:[],normals:[],faces:[]};return r.faces=e.map(function(e){e.triangulate(r)}).flatten(),r},verb.eval.nurbs.tesselate_rational_surface_adaptive=function(e,r,t,n,i,s){verb.eval.nurbs.divide_rational_surface_adaptive(e,r,t,n,i,s);var a=verb.eval.nurbs.triangulate_adaptive_refinement_node_tree(arrTree);return verb.eval.nurbs.unique_mesh(a)},verb.eval.nurbs.unique_mesh=function(e){return e},Array.prototype.where=function(e){if(0===this.length)return this;for(var r=[],t=0;this.length>t;t++)e(this[t])&&r.push(this[t]);return r},verb.eval.nurbs.AdaptiveRefinementNode=function(e,r,t,n,i,s,a){this.srf=e,this.u0=r,this.u1=t,this.v0=n,this.v1=i,this.parentNode=s,this.neighbors=a,this.leafEdgeUvs=[[r,n],[t,n],[t,i],[r,i]],this.cachedEdgeUvs=[]},verb.eval.nurbs.AdaptiveRefinementNode.prototype.isLeaf=function(){return void 0===this.children},verb.eval.nurbs.AdaptiveRefinementNode.prototype.evalSurface=function(){var e=verb.eval.nurbs.rational_surface_derivs(this.srf.degree_u,this.srf.knots_u,this.srf.degree_v,this.srf.knots_v,this.srf.homo_control_points,1,pt_u,pt_v),r=e[0][0]; -points.push(r);var t=numeric.cross(e[0][1],e[1][0]);return{point:r,normal:t}},verb.eval.nurbs.AdaptiveRefinementNode.prototype.getEdgeUvs=function(e){return this.isLeaf()?[this.leafEdgeUvs[e]]:(this.cachedEdgeUvs[e]=this.cachedEdgeUvs[e]||this.children[e].getEdgeUvs(e).concat(this.children[(e+1)%4].getEdgeUvs(e)),this.cachedEdgeUvs[e])},verb.eval.nurbs.AdaptiveRefinementNode.prototype.getAllEdgeUvs=function(e){var r=[this.leafEdgeUvs[e]];if(null===this.neighbors[e])return r;var t=this.neighbors[e].getEdgeUvs((e+2)%4),n=e%2,i=this,s=[function(e){return e[0]>i.u0+verb.EPSILON&&e[0]i.v0+verb.EPSILON&&e[1]n;n++)t.concat(this.getAllEdgeUvs(n));if(t.forEach(function(r){e.uvs.push(r);var t=this.evalSurface(r);e.points.push(t.point),e.normals.push(t.normal)}),4===t.length)return e.faces.push([r+1,r+4,r+2]),e.faces.push([r+4,r+3,r+2]),void 0;this.u05=this.u05||(this.u0+this.u1)/2,this.v05=this.v05||(this.v0+this.v1)/2,e.uvs.push([this.u05,this.v05]);var i=this.evalSurface([this.u05,this.v05]);e.points.push(i.point),e.normals.push(i.normal);for(var s=e.points.length-1,n=0;t.length>n;n++)e.faces.push([s,(r+n+2)%t.length,(r+n+1)%t.length])},verb.eval.nurbs.AdaptiveRefinementNode.prototype.triangulate=function(e){return this.isLeaf()?this.triangulateLeaf(e):(this.children.forEach(function(r){null!==r&&r.triangulate(e)}),void 0)},verb.eval.nurbs.AdaptiveRefinementNode.prototype.shouldDivide=function(e,r){return e.minDepth&&e.minDepth>r?!0:this.srf&&!verb.eval.nurbs.is_rational_surface_domain_flat(this.srf,this.u0,this.u1,this.v0,this.v1,e)?!0:!1},verb.eval.nurbs.AdaptiveRefinementNode.prototype.divide=function(e,r){void 0===r&&(r=0),this.shouldDivide(e,r)&&(r++,this.u05=(this.u0+this.u1)/2,this.v05=(this.v0+this.v1)/2,this.children=[new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u0,this.u05,this.v0,this.v05,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u05,this.u1,this.v0,this.v05,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u05,this.u1,this.v05,this.v1,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u0,this.u05,this.v05,this.v1,this)],this.children[0].neighbors=[this.neighbors[0],this.children[1],this.children[3],this.neighbors[3]],this.children[1].neighbors=[this.neighbors[0],this.neighbors[1],this.children[2],this.children[0]],this.children[2].neighbors=[this.children[1],this.neighbors[1],this.neighbors[2],this.children[3]],this.children[3].neighbors=[this.children[0],this.children[2],this.neighbors[2],this.neighbors[3]],this.children.forEach(function(t){t.divide(e,r)}))},verb.eval.nurbs.get_sweep1_surface=function(e,r,t,n,i,s,a,o){for(var u=verb.eval.nurbs.homogenize_1d(a,o),v=verb.eval.nurbs.rational_curve_point(s,i,u,0),l=1/a.length,c=[],b=[],h=0;a.length>h;h++){for(var g=verb.eval.nurbs.rational_curve_point(s,i,u,h*l),_=numeric.sub(g,v),m=[],f=[],d=0;t.length>d;d++)m.push(numeric.add(_,t[d])),f.push(n[d]*o[h]);c.push(m),b.push(f)}return{knots_u:i,knots_v:e,control_points:c,degree_u:s,degree_v:r,weights:b}},verb.eval.nurbs.get_ellipse_arc=function(e,r,t,n,i,s,a){s>a&&(a=2*Math.PI+s);var o=a-s,u=0;u=Math.PI/2>=o?1:Math.PI>=o?2:3*Math.PI/2>=o?3:4;var v=o/u,l=Math.cos(v/2),c=numeric.add(e,numeric.mul(n,Math.cos(s),r),numeric.mul(i,Math.sin(s),t)),b=numeric.sub(numeric.mul(Math.cos(s),t),numeric.mul(Math.sin(s),r)),h=verb.eval.nurbs.zeros_1d(2*u),g=verb.eval.nurbs.zeros_1d(2*u+3),_=0,m=s,f=verb.eval.nurbs.zeros_1d(2*u);h[0]=c,f[0]=1;for(var d=1;u>=d;d++){m+=v;var p=numeric.add(e,numeric.mul(n,Math.cos(m),r),numeric.mul(i,Math.sin(m),t));f[_+2]=1,h[_+2]=p;var y=numeric.sub(numeric.mul(Math.cos(m),t),numeric.mul(Math.sin(m),r)),x=verb.eval.geom.intersect_rays(c,numeric.mul(1/numeric.norm2(b),b),p,numeric.mul(1/numeric.norm2(y),y)),N=numeric.add(c,numeric.mul(b,x[0]));f[_+1]=l,h[_+1]=N,_+=2,u>d&&(c=p,b=y)}for(var k=2*u+1,d=0;3>d;d++)g[d]=0,g[d+k]=1;switch(u){case 1:break;case 2:g[3]=g[4]=.5;break;case 3:g[3]=g[4]=1/3,g[5]=g[6]=2/3;break;case 4:g[3]=g[4]=.25,g[5]=g[6]=.5,g[7]=g[8]=.75}return{knots:g,control_points:h,degree:2,weights:f}},verb.eval.nurbs.get_sphere_surface=function(e,r,t,n){var i=verb.eval.nurbs.get_arc(e,numeric.mul(r,-1),t,n,0,Math.PI);return verb.eval.nurbs.get_revolved_surface(e,r,2*Math.PI,i.knots,i.degree,i.control_points,i.weights)},verb.eval.nurbs.get_polyline_curve=function(e){for(var r=e.length-1,t=1/r,n=[0,0],i=1;r>i;i++)n.push(i*t);n.push(1),n.push(1);for(var s=[],i=0;e.length>i;i++)s.push(1);return{knots:n,control_points:e.slice(0),degree:1,weights:s}},verb.eval.nurbs.get_4pt_surface=function(e,r,t,n){return{knots_u:[0,0,1,1],knots_v:[0,0,1,1],control_points:[[e,n],[r,t]],degree_u:1,degree_v:1,weights:[[1,1],[1,1]]}},verb.eval.nurbs.get_cylinder_surface=function(e,r,t,n,i){var s=crossprod(e,r),a=(2*Math.PI,verb.eval.nurbs.get_arc(t,r,s,i,0,2*Math.PI));return verb.eval.nurbs.get_extruded_surface(e,n,a.knots,a.degree,a.control_points,a.weights)},verb.eval.nurbs.get_cone_surface=function(e,r,t,n,i){var s=2*Math.PI,a=1,o=[numeric.add(t,numeric.mul(n,e)),numeric.add(t,numeric.mul(i,r))],u=[0,0,1,1],v=[1,1];return verb.eval.nurbs.get_revolved_surface(t,e,s,u,a,o,v)},verb.eval.nurbs.get_extruded_surface=function(e,r,t,n,i,s){for(var a=verb.eval.nurbs.zeros_2d(3,i.length),o=verb.eval.nurbs.zeros_2d(3,i.length),u=numeric.mul(e,r),v=numeric.mul(e,.5*r),l=0;i.length>l;l++)a[0][l]=i[l],a[1][l]=numeric.add(v,i[l]),a[2][l]=numeric.add(u,i[l]),o[0][l]=s[l],o[1][l]=s[l],o[2][l]=s[l];return{knots_u:[0,0,0,1,1,1],knots_v:t,control_points:a,degree_u:2,degree_v:n,weights:o}},verb.eval.nurbs.get_revolved_surface=function(e,r,t,n,i,s,a){var o,u,v,l;Math.PI/2>=t?(o=1,u=verb.eval.nurbs.zeros_1d(6+2*(o-1))):Math.PI>=t?(o=2,u=verb.eval.nurbs.zeros_1d(6+2*(o-1)),u[3]=u[4]=.5):3*Math.PI/2>=t?(o=3,u=verb.eval.nurbs.zeros_1d(6+2*(o-1)),u[3]=u[4]=1/3,u[5]=u[6]=2/3):(o=4,u=verb.eval.nurbs.zeros_1d(6+2*(o-1)),u[3]=u[4]=.25,u[5]=u[6]=.5,u[7]=u[8]=.75);for(var c=t/o,b=3+2*(o-1),h=0;3>h;b++,h++)u[h]=0,u[b]=1;for(var g=Math.cos(c/2),_=0,m=verb.eval.nurbs.zeros_1d(o+1),f=verb.eval.nurbs.zeros_1d(o+1),v=verb.eval.nurbs.zeros_2d(2*o+1,s.length),l=verb.eval.nurbs.zeros_2d(2*o+1,s.length),h=1;o>=h;h++)_+=c,f[h]=Math.cos(_),m[h]=Math.sin(_);for(b=0;s.length>b;b++){var d=verb.eval.geom.closest_point_on_ray(s[b],e,r),p=numeric.sub(s[b],d),y=numeric.norm2(p),x=crossprod(r,p);y>verb.EPSILON&&(p=numeric.mul(1/y,p),x=numeric.mul(1/y,x)),v[0][b]=s[b];var N=s[b];l[0][b]=a[b];for(var k=x,w=0,_=0,h=1;o>=h;h++){var E=0==y?d:numeric.add(d,numeric.mul(y,f[h],p),numeric.mul(y,m[h],x));v[w+2][b]=E,l[w+2][b]=a[b];var A=numeric.sub(numeric.mul(f[h],x),numeric.mul(m[h],p));if(0==y)v[w+1][b]=d;else{var M=verb.eval.geom.intersect_rays(N,numeric.mul(1/numeric.norm2(k),k),E,numeric.mul(1/numeric.norm2(A),A)),z=numeric.add(N,numeric.mul(k,M[0]));v[w+1][b]=z}l[w+1][b]=g*a[b],w+=2,o>h&&(N=E,k=A)}}return{knots_u:u,knots_v:n,control_points:v,degree_u:2,degree_v:i,weights:l}},verb.eval.nurbs.get_arc=function(e,r,t,n,i,s){return verb.eval.nurbs.get_ellipse_arc(e,r,t,n,n,i,s)},verb.eval.nurbs.curve_knot_insert=function(e,r,t,n,i,s){var a=(t[0].length,r.length-e-2),o=t.length,u=verb.eval.nurbs.knot_span(e,n,r),v=a+e+1,l=o+s,c=Array(e+1),b=Array(r.length+s),h=Array(l),g=0;for(g=0;u>=g;g++)b[g]=r[g];for(g=1;s>=g;g++)b[u+g]=n;for(g=u+1;v>=g;g++)b[g+s]=r[g];for(g=0;u-e>=g;g++)h[g]=t[g];for(g=u-i;a>=g;g++)h[g+s]=t[g];for(g=0;e-i>=g;g++)c[g]=t[u-e+1];for(var _=0,m=0,f=1;s>=f;f++){for(_=u-e+f,g=0;e-f-i>=g;g++)m=(n-r[_+g])/(r[g+u+1]-r[_+g]),c[g]=numeric.add(numeric.mul(m,c[g+1]),numeric.mul(1-m,c[g]));h[_]=c[0],h[u+s-f-i]=c[e-f-i]}for(g=_+1;u-i>g;g++)h[g]=c[g-_];return[b,h]},verb.eval.nurbs.rational_surface_derivs=function(e,r,t,n,i,s,a,o){var u=verb.eval.nurbs.surface_derivs(e,r,t,n,i,s,a,o),v=verb.eval.nurbs.separate_homo_derivs_2d(u),l=v[0],c=v[1],b=0,h=0,g=0,_=0,m=[],f=l[0][0].length;for(b=0;s>=b;b++)for(m.push([]),_=0;s-b>=_;_++){var o=l[b][_];for(g=1;_>=g;g++)o=numeric.sub(o,numeric.mul(numeric.mul(binomial.get(_,g),c[0][g]),m[b][_-g]));for(h=1;b>=h;h++){o=numeric.sub(o,numeric.mul(numeric.mul(binomial.get(b,h),c[h][0]),m[b-h][_]));var d=verb.eval.nurbs.zeros_1d(f);for(g=1;_>=g;g++)d=numeric.add(d,numeric.mul(numeric.mul(binomial.get(_,g),c[h][g]),m[b-h][_-g]));o=numeric.sub(o,numeric.mul(binomial.get(b,h),d))}m[b].push(numeric.mul(1/c[0][0],o))}return m},verb.eval.nurbs.rational_surface_point=function(e,r,t,n,i,s,a){return verb.eval.nurbs.dehomogenize(verb.eval.nurbs.surface_point(e,r,t,n,i,s,a))},verb.eval.nurbs.rational_curve_derivs=function(e,r,t,n,i){var s=verb.eval.nurbs.separate_homo_derivs_1d(verb.eval.nurbs.curve_derivs(e,r,t,n,i)),a=s[0],o=s[1],u=0,v=0,l=[];for(u=0;i>=u;u++){var c=a[u];for(v=1;u>=v;v++)c=numeric.sub(c,numeric.mul(numeric.mul(binomial.get(u,v),o[v]),l[u-v]));l.push(numeric.mul(1/o[0],c))}return l},verb.eval.nurbs.separate_homo_derivs_1d=function(e){for(var r=e[0].length,t=r-1,n=[],i=[],s=0,a=e.length;a>s;s++)n.push(e[s].slice(0,t)),i.push(e[s][t]);return[n,i]},verb.eval.nurbs.separate_homo_derivs_2d=function(e){for(var r=[],t=[],n=0,i=e.length;i>n;n++){var s=verb.eval.nurbs.separate_homo_derivs_1d(e[n]);r.push(s[0]),t.push(s[1])}return[r,t]},verb.eval.nurbs.rational_curve_point=function(e,r,t,n){return verb.eval.nurbs.dehomogenize(verb.eval.nurbs.curve_point(e,r,t,n))},verb.eval.nurbs.dehomogenize=function(e){for(var r=e.length,t=[],n=e[r-1],i=0;e.length-1>i;i++)t.push(e[i]/n);return t},verb.eval.nurbs.homogenize_1d=function(e,r){for(var t=e.length,n=e[0].length,i=0,s=[],a=0,o=[],u=0;t>u;u++){var v=[];for(o=e[u],a=r[u],i=0;n>i;i++)v.push(o[i]*a);v.push(a),s.push(v)}return s},verb.eval.nurbs.homogenize_2d=function(e,r){for(var t=e.length,n=(e[0].length,e[0][0].length,[]),i=0;t>i;i++)n.push(verb.eval.nurbs.homogenize_1d(e[i],r[i]));return n},verb.eval.nurbs.rational_surface_curvature=function(e,r,t,n,i,s,a){var o=verb.eval.nurbs.rational_surface_derivs(e,r,t,n,i,2,s,a),u=o[0][1],v=o[1][0],l=o[0][2],c=o[2][0],b=o[1][1],h=numeric.cross(u,v),g=numeric.dot(l,h),_=numeric.dot(b,h),m=numeric.dot(c,h),f=[[g,_],[_,m]],d=numeric.eig(f),p=d.lambda.x[0],y=d.lambda.x[1],x=.5*(p+y),N=p*y,k=numeric.add(numeric.mul(d.E.x[0][0],u),numeric.mul(d.E.x[0][1],v)),w=numeric.add(numeric.mul(d.E.x[1][0],u),numeric.mul(d.E.x[1][1],v));return{point:o[0][0],normal:h,mean:x,gaussian:N,shapeOperator:f,k1:p,k2:y,p1:k,p2:w,p1p:d.E.x[0],p2p:d.E.x[1]}},verb.eval.nurbs.surface_derivs=function(e,r,t,n,i,s,a,o){var u=r.length-e-2,v=n.length-t-2;return verb.eval.nurbs.surface_derivs_given_n_m(u,e,r,v,t,n,i,s,a,o)},verb.eval.nurbs.surface_derivs_given_n_m=function(e,r,t,n,i,s,a,o,u,v){if(verb.eval.nurbs.are_valid_relations(r,a.length,t.length)===!1||verb.eval.nurbs.are_valid_relations(i,a[0].length,s.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var l=a[0][0].length,c=Math.min(o,r),b=Math.min(o,i),h=verb.eval.nurbs.zeros_3d(c+1,b+1,l),g=verb.eval.nurbs.knot_span_given_n(e,r,u,t),_=verb.eval.nurbs.knot_span_given_n(n,i,v,s),m=verb.eval.nurbs.deriv_basis_functions_given_n_i(g,u,r,e,t),f=verb.eval.nurbs.deriv_basis_functions_given_n_i(_,v,i,n,s),d=verb.eval.nurbs.zeros_2d(i+1,l),p=0,y=0,x=0,N=0,k=0;for(p=0;c>=p;p++){for(y=0;i>=y;y++)for(d[y]=verb.eval.nurbs.zeros_1d(l),x=0;r>=x;x++)d[y]=numeric.add(d[y],numeric.mul(m[p][x],a[g-r+x][_-i+y]));for(k=Math.min(o-p,b),N=0;k>=N;N++)for(h[p][N]=verb.eval.nurbs.zeros_1d(l),y=0;i>=y;y++)h[p][N]=numeric.add(h[p][N],numeric.mul(f[N][y],d[y]))}return h},verb.eval.nurbs.surface_point=function(e,r,t,n,i,s,a){var o=r.length-e-2,u=n.length-t-2;return verb.eval.nurbs.surface_point_given_n_m(o,e,r,u,t,n,i,s,a)},verb.eval.nurbs.volume_point=function(e,r,t,n,i,s,a,o,u,v){var l=r.length-e-2,c=n.length-t-2,b=s.length-i-2;return verb.eval.nurbs.volume_point_given_n_m_l(l,e,r,c,t,n,b,i,s,a,o,u,v)},verb.eval.nurbs.volume_point_given_n_m_l=function(e,r,t,n,i,s,a,o,u,v,l,c,b){if(!verb.eval.nurbs.are_valid_relations(r,v.length,t.length)||!verb.eval.nurbs.are_valid_relations(i,v[0].length,s.length)||!verb.eval.nurbs.are_valid_relations(o,v[0][0].length,u.length))return console.error("Invalid relations between control points and knot vector"),null;for(var h=v[0][0][0].length,g=verb.eval.nurbs.knot_span_given_n(e,r,l,t),_=verb.eval.nurbs.knot_span_given_n(n,i,c,s),m=verb.eval.nurbs.knot_span_given_n(a,o,b,u),f=verb.eval.nurbs.basis_functions_given_knot_span_index(g,l,r,t),d=verb.eval.nurbs.basis_functions_given_knot_span_index(_,c,i,s),p=verb.eval.nurbs.basis_functions_given_knot_span_index(m,b,o,u),y=g-r,x=_,N=m,k=verb.eval.nurbs.zeros_1d(h),w=verb.eval.nurbs.zeros_1d(h),E=verb.eval.nurbs.zeros_1d(h),A=0,M=0,z=0;o>=z;z++){for(E=verb.eval.nurbs.zeros_1d(h),N=m-o+z,A=0;i>=A;A++){for(w=verb.eval.nurbs.zeros_1d(h),x=_-i+A,M=0;r>=M;M++)w=numeric.add(w,numeric.mul(f[M],v[y+M][x][N]));E=numeric.add(E,numeric.mul(d[A],w))}k=numeric.add(k,numeric.mul(p[z],E))}return k},verb.eval.nurbs.surface_point_given_n_m=function(e,r,t,n,i,s,a,o,u){if(verb.eval.nurbs.are_valid_relations(r,a.length,t.length)===!1||verb.eval.nurbs.are_valid_relations(i,a[0].length,s.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var v=a[0][0].length,l=verb.eval.nurbs.knot_span_given_n(e,r,o,t),c=verb.eval.nurbs.knot_span_given_n(n,i,u,s),b=verb.eval.nurbs.basis_functions_given_knot_span_index(l,o,r,t),h=verb.eval.nurbs.basis_functions_given_knot_span_index(c,u,i,s),g=l-r,_=c,m=verb.eval.nurbs.zeros_1d(v),f=verb.eval.nurbs.zeros_1d(v),d=0,p=0;for(d=0;i>=d;d++){for(f=verb.eval.nurbs.zeros_1d(v),_=c-i+d,p=0;r>=p;p++)f=numeric.add(f,numeric.mul(b[p],a[g+p][_]));m=numeric.add(m,numeric.mul(h[d],f))}return m},verb.eval.nurbs.curve_derivs=function(e,r,t,n,i){var s=r.length-e-2;return verb.eval.nurbs.curve_derivs_given_n(s,e,r,t,n,i)},verb.eval.nurbs.curve_derivs_given_n=function(e,r,t,n,i,s){if(verb.eval.nurbs.are_valid_relations(r,n.length,t.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var a=n[0].length,o=Math.min(s,r),u=verb.eval.nurbs.zeros_2d(o+1,a),v=verb.eval.nurbs.knot_span_given_n(e,r,i,t),l=verb.eval.nurbs.deriv_basis_functions_given_n_i(v,i,r,o,t),c=0,b=0;for(c=0;o>=c;c++)for(b=0;r>=b;b++)u[c]=numeric.add(u[c],numeric.mul(l[c][b],n[v-r+b]));return u},verb.eval.nurbs.are_valid_relations=function(e,r,t){return 0===r+e+1-t?!0:!1},verb.eval.nurbs.curve_point=function(e,r,t,n){var i=r.length-e-2;return verb.eval.nurbs.curve_point_given_n(i,e,r,t,n)},verb.eval.nurbs.curve_point_given_n=function(e,r,t,n,i){if(verb.eval.nurbs.are_valid_relations(r,n.length,t.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;for(var s=verb.eval.nurbs.knot_span_given_n(e,r,i,t),a=verb.eval.nurbs.basis_functions_given_knot_span_index(s,i,r,t),o=verb.eval.nurbs.zeros_1d(n[0].length),u=0;r>=u;u++)o=numeric.add(o,numeric.mul(a[u],n[s-r+u]));return o},verb.eval.nurbs.zeros_1d=function(e){e=e>0?e:0;for(var r=[];e--;)r.push(0);return r},verb.eval.nurbs.zeros_2d=function(e,r){r=r>0?r:0,e=e>0?e:0;for(var t=[],n=r,i=e;e--;){for(t.push([]);n--;)t[i-e-1].push(0);n=r}return t},verb.eval.nurbs.zeros_3d=function(e,r,t){r=r>0?r:0,e=e>0?e:0;for(var n=[],i=r,s=e;e--;){for(n.push([]);i--;)n[s-e-1].push(verb.eval.nurbs.zeros_1d(t));i=r}return n},verb.eval.nurbs.deriv_basis_functions=function(e,r,t){var n=verb.eval.nurbs.knot_span(r,e,t),i=t.length-1,s=i-r-1;return verb.eval.nurbs.deriv_basis_functions_given_n_i(n,e,r,s,t)},verb.eval.nurbs.deriv_basis_functions_given_n_i=function(e,r,t,n,i){var s=verb.eval.nurbs.zeros_2d(t+1,t+1),a=Array(t+1),o=Array(t+1),u=0,v=0,l=1,c=0;for(s[0][0]=1,l=1;t>=l;l++){for(a[l]=r-i[e+1-l],o[l]=i[e+l]-r,u=0,c=0;l>c;c++)s[l][c]=o[c+1]+a[l-c],v=s[c][l-1]/s[l][c],s[c][l]=u+o[c+1]*v,u=a[l-c]*v;s[l][l]=u}var b=verb.eval.nurbs.zeros_2d(n+1,t+1),h=verb.eval.nurbs.zeros_2d(2,t+1),g=1,_=0,m=1,f=0,d=0,p=0,y=0,x=0;for(l=0;t>=l;l++)b[0][l]=s[l][t];for(c=0;t>=c;c++)for(_=0,m=1,h[0][0]=1,g=1;n>=g;g++){for(f=0,d=c-g,p=t-g,c>=g&&(h[m][0]=h[_][0]/s[p+1][d],f=h[m][0]*s[d][p]),y=d>=-1?1:-d,x=p>=c-1?g-1:t-c,l=y;x>=l;l++)h[m][l]=(h[_][l]-h[_][l-1])/s[p+1][d+l],f+=h[m][l]*s[d+l][p];p>=c&&(h[m][g]=-h[_][g-1]/s[p+1][c],f+=h[m][g]*s[c][p]),b[g][c]=f,l=_,_=m,m=l}for(c=t,g=1;n>=g;g++){for(l=0;t>=l;l++)b[g][l]*=c;c*=t-g}return b},verb.eval.nurbs.basis_functions=function(e,r,t){var n=verb.eval.nurbs.knot_span(e,r,t);return verb.eval.nurbs.basis_functions_given_knot_span_index(n,e,r,t)},verb.eval.nurbs.basis_functions_given_knot_span_index=function(e,r,t,n){var i=Array(t+1),s=Array(t+1),a=Array(t+1),o=0,u=0;i[0]=1;for(var v=1;t>=v;v++){s[v]=r-n[e+1-v],a[v]=n[e+v]-r,o=0;for(var l=0;v>l;l++)u=i[l]/(a[l+1]+s[v-l]),i[l]=o+a[l+1]*u,o=s[v-l]*u;i[v]=o}return i},verb.eval.nurbs.knot_span=function(e,r,t){var n=t.length-1,i=n-e-1;return verb.eval.nurbs.knot_span_given_n(i,e,r,t)},verb.eval.nurbs.knot_span_given_n=function(e,r,t,n){if(t>=n[e+1])return e;if(n[r]>t)return r;for(var i=r,s=e+1,a=Math.floor((i+s)/2);n[a]>t||t>=n[a+1];)n[a]>t?s=a:i=a,a=Math.floor((i+s)/2);return a}; \ No newline at end of file +points.push(r);var t=numeric.cross(e[0][1],e[1][0]);return{point:r,normal:t}},verb.eval.nurbs.AdaptiveRefinementNode.prototype.getEdgeUvs=function(e){return this.isLeaf()?[this.leafEdgeUvs[e]]:(this.cachedEdgeUvs[e]=this.cachedEdgeUvs[e]||this.children[e].getEdgeUvs(e).concat(this.children[(e+1)%4].getEdgeUvs(e)),this.cachedEdgeUvs[e])},verb.eval.nurbs.AdaptiveRefinementNode.prototype.getAllEdgeUvs=function(e){var r=[this.leafEdgeUvs[e]];if(null===this.neighbors[e])return r;var t=this.neighbors[e].getEdgeUvs((e+2)%4),n=e%2,i=this,s=[function(e){return e[0]>i.u0+verb.EPSILON&&e[0]i.v0+verb.EPSILON&&e[1]n;n++)t.concat(this.getAllEdgeUvs(n));if(t.forEach(function(r){e.uvs.push(r);var t=this.evalSurface(r);e.points.push(t.point),e.normals.push(t.normal)}),4===t.length)return e.faces.push([r+1,r+4,r+2]),e.faces.push([r+4,r+3,r+2]),void 0;this.u05=this.u05||(this.u0+this.u1)/2,this.v05=this.v05||(this.v0+this.v1)/2,e.uvs.push([this.u05,this.v05]);var i=this.evalSurface([this.u05,this.v05]);e.points.push(i.point),e.normals.push(i.normal);for(var s=e.points.length-1,n=0;t.length>n;n++)e.faces.push([s,(r+n+2)%t.length,(r+n+1)%t.length])},verb.eval.nurbs.AdaptiveRefinementNode.prototype.triangulate=function(e){return this.isLeaf()?this.triangulateLeaf(e):(this.children.forEach(function(r){null!==r&&r.triangulate(e)}),void 0)},verb.eval.nurbs.AdaptiveRefinementNode.prototype.shouldDivide=function(e,r){return e.minDepth&&e.minDepth>r?!0:this.srf&&!verb.eval.nurbs.is_rational_surface_domain_flat(this.srf,this.u0,this.u1,this.v0,this.v1,e)?!0:!1},verb.eval.nurbs.AdaptiveRefinementNode.prototype.divide=function(e,r){void 0===r&&(r=0),this.shouldDivide(e,r)&&(r++,this.u05=(this.u0+this.u1)/2,this.v05=(this.v0+this.v1)/2,this.children=[new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u0,this.u05,this.v0,this.v05,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u05,this.u1,this.v0,this.v05,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u05,this.u1,this.v05,this.v1,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u0,this.u05,this.v05,this.v1,this)],this.children[0].neighbors=[this.neighbors[0],this.children[1],this.children[3],this.neighbors[3]],this.children[1].neighbors=[this.neighbors[0],this.neighbors[1],this.children[2],this.children[0]],this.children[2].neighbors=[this.children[1],this.neighbors[1],this.neighbors[2],this.children[3]],this.children[3].neighbors=[this.children[0],this.children[2],this.neighbors[2],this.neighbors[3]],this.children.forEach(function(t){t.divide(e,r)}))},verb.eval.nurbs.get_sweep1_surface=function(e,r,t,n,i,s,a,o){for(var u=verb.eval.nurbs.homogenize_1d(a,o),v=verb.eval.nurbs.rational_curve_point(s,i,u,0),l=1/a.length,c=[],b=[],h=0;a.length>h;h++){for(var g=verb.eval.nurbs.rational_curve_point(s,i,u,h*l),_=numeric.sub(g,v),m=[],f=[],d=0;t.length>d;d++)m.push(numeric.add(_,t[d])),f.push(n[d]*o[h]);c.push(m),b.push(f)}return{knots_u:i,knots_v:e,control_points:c,degree_u:s,degree_v:r,weights:b}},verb.eval.nurbs.get_ellipse_arc=function(e,r,t,n,i,s,a){s>a&&(a=2*Math.PI+s);var o=a-s,u=0;u=Math.PI/2>=o?1:Math.PI>=o?2:3*Math.PI/2>=o?3:4;var v=o/u,l=Math.cos(v/2),c=numeric.add(e,numeric.mul(n,Math.cos(s),r),numeric.mul(i,Math.sin(s),t)),b=numeric.sub(numeric.mul(Math.cos(s),t),numeric.mul(Math.sin(s),r)),h=verb.eval.nurbs.zeros_1d(2*u),g=verb.eval.nurbs.zeros_1d(2*u+3),_=0,m=s,f=verb.eval.nurbs.zeros_1d(2*u);h[0]=c,f[0]=1;for(var d=1;u>=d;d++){m+=v;var p=numeric.add(e,numeric.mul(n,Math.cos(m),r),numeric.mul(i,Math.sin(m),t));f[_+2]=1,h[_+2]=p;var y=numeric.sub(numeric.mul(Math.cos(m),t),numeric.mul(Math.sin(m),r)),x=verb.eval.geom.intersect_rays(c,numeric.mul(1/numeric.norm2(b),b),p,numeric.mul(1/numeric.norm2(y),y)),N=numeric.add(c,numeric.mul(b,x[0]));f[_+1]=l,h[_+1]=N,_+=2,u>d&&(c=p,b=y)}for(var k=2*u+1,d=0;3>d;d++)g[d]=0,g[d+k]=1;switch(u){case 1:break;case 2:g[3]=g[4]=.5;break;case 3:g[3]=g[4]=1/3,g[5]=g[6]=2/3;break;case 4:g[3]=g[4]=.25,g[5]=g[6]=.5,g[7]=g[8]=.75}return{knots:g,control_points:h,degree:2,weights:f}},verb.eval.nurbs.get_sphere_surface=function(e,r,t,n){var i=verb.eval.nurbs.get_arc(e,numeric.mul(r,-1),t,n,0,Math.PI);return verb.eval.nurbs.get_revolved_surface(e,r,2*Math.PI,i.knots,i.degree,i.control_points,i.weights)},verb.eval.nurbs.get_polyline_curve=function(e){for(var r=e.length-1,t=1/r,n=[0,0],i=1;r>i;i++)n.push(i*t);n.push(1),n.push(1);for(var s=[],i=0;e.length>i;i++)s.push(1);return{knots:n,control_points:e.slice(0),degree:1,weights:s}},verb.eval.nurbs.get_4pt_surface=function(e,r,t,n){var i=numeric.mul(.5,numeric.add(e,n)),s=numeric.mul(.5,numeric.add(r,t)),a=numeric.mul(.5,numeric.add(t,n)),o=numeric.mul(.5,numeric.add(e,r)),u=numeric.mul(.5,numeric.add(i,s));return{knots_u:[0,0,0,1,1,1],knots_v:[0,0,0,1,1,1],control_points:[[e,i,n],[o,u,a],[r,s,t]],degree_u:2,degree_v:2,weights:[[1,1,1],[1,1,1],[1,1,1]]}},verb.eval.nurbs.get_cylinder_surface=function(e,r,t,n,i){var s=crossprod(e,r),a=(2*Math.PI,verb.eval.nurbs.get_arc(t,r,s,i,0,2*Math.PI));return verb.eval.nurbs.get_extruded_surface(e,n,a.knots,a.degree,a.control_points,a.weights)},verb.eval.nurbs.get_cone_surface=function(e,r,t,n,i){var s=2*Math.PI,a=1,o=[numeric.add(t,numeric.mul(n,e)),numeric.add(t,numeric.mul(i,r))],u=[0,0,1,1],v=[1,1];return verb.eval.nurbs.get_revolved_surface(t,e,s,u,a,o,v)},verb.eval.nurbs.get_extruded_surface=function(e,r,t,n,i,s){for(var a=verb.eval.nurbs.zeros_2d(3,i.length),o=verb.eval.nurbs.zeros_2d(3,i.length),u=numeric.mul(e,r),v=numeric.mul(e,.5*r),l=0;i.length>l;l++)a[0][l]=i[l],a[1][l]=numeric.add(v,i[l]),a[2][l]=numeric.add(u,i[l]),o[0][l]=s[l],o[1][l]=s[l],o[2][l]=s[l];return{knots_u:[0,0,0,1,1,1],knots_v:t,control_points:a,degree_u:2,degree_v:n,weights:o}},verb.eval.nurbs.get_revolved_surface=function(e,r,t,n,i,s,a){var o,u,v,l;Math.PI/2>=t?(o=1,u=verb.eval.nurbs.zeros_1d(6+2*(o-1))):Math.PI>=t?(o=2,u=verb.eval.nurbs.zeros_1d(6+2*(o-1)),u[3]=u[4]=.5):3*Math.PI/2>=t?(o=3,u=verb.eval.nurbs.zeros_1d(6+2*(o-1)),u[3]=u[4]=1/3,u[5]=u[6]=2/3):(o=4,u=verb.eval.nurbs.zeros_1d(6+2*(o-1)),u[3]=u[4]=.25,u[5]=u[6]=.5,u[7]=u[8]=.75);for(var c=t/o,b=3+2*(o-1),h=0;3>h;b++,h++)u[h]=0,u[b]=1;for(var g=Math.cos(c/2),_=0,m=verb.eval.nurbs.zeros_1d(o+1),f=verb.eval.nurbs.zeros_1d(o+1),v=verb.eval.nurbs.zeros_2d(2*o+1,s.length),l=verb.eval.nurbs.zeros_2d(2*o+1,s.length),h=1;o>=h;h++)_+=c,f[h]=Math.cos(_),m[h]=Math.sin(_);for(b=0;s.length>b;b++){var d=verb.eval.geom.closest_point_on_ray(s[b],e,r),p=numeric.sub(s[b],d),y=numeric.norm2(p),x=crossprod(r,p);y>verb.EPSILON&&(p=numeric.mul(1/y,p),x=numeric.mul(1/y,x)),v[0][b]=s[b];var N=s[b];l[0][b]=a[b];for(var k=x,w=0,_=0,h=1;o>=h;h++){var E=0==y?d:numeric.add(d,numeric.mul(y,f[h],p),numeric.mul(y,m[h],x));v[w+2][b]=E,l[w+2][b]=a[b];var A=numeric.sub(numeric.mul(f[h],x),numeric.mul(m[h],p));if(0==y)v[w+1][b]=d;else{var M=verb.eval.geom.intersect_rays(N,numeric.mul(1/numeric.norm2(k),k),E,numeric.mul(1/numeric.norm2(A),A)),z=numeric.add(N,numeric.mul(k,M[0]));v[w+1][b]=z}l[w+1][b]=g*a[b],w+=2,o>h&&(N=E,k=A)}}return{knots_u:u,knots_v:n,control_points:v,degree_u:2,degree_v:i,weights:l}},verb.eval.nurbs.get_arc=function(e,r,t,n,i,s){return verb.eval.nurbs.get_ellipse_arc(e,r,t,n,n,i,s)},verb.eval.nurbs.rational_surface_curvature=function(e,r,t,n,i,s,a){var o=verb.eval.nurbs.rational_surface_derivs(e,r,t,n,i,2,s,a);console.log(o);var u=o[0][1],v=o[1][0],l=o[0][2],c=o[2][0],b=o[1][1],h=numeric.cross(u,v),g=numeric.dot(l,h),_=numeric.dot(b,h),m=numeric.dot(c,h),f=[[g,_],[_,m]],d=numeric.eig(f),p=d.lambda.x[0],y=d.lambda.x[1],x=.5*(p+y),N=p*y,k=numeric.add(numeric.mul(d.E.x[0][0],u),numeric.mul(d.E.x[0][1],v)),w=numeric.add(numeric.mul(d.E.x[1][0],u),numeric.mul(d.E.x[1][1],v));return{point:o[0][0],normal:h,mean:x,gaussian:N,shapeOperator:f,k1:p,k2:y,p1:k,p2:w,p1p:d.E.x[0],p2p:d.E.x[1]}},verb.eval.nurbs.curve_knot_insert=function(e,r,t,n,i){var s=0,a=(t[0].length,t.length),o=verb.eval.nurbs.knot_span(e,n,r),u=(r.length,a+i),v=Array(e-s),l=Array(r.length+i),c=Array(u),b=0;for(b=0;o>=b;b++)l[b]=r[b];for(b=1;i>=b;b++)l[o+b]=n;for(b=o+1;r.length>b;b++)l[b+i]=r[b];for(b=0;o-e>=b;b++)c[b]=t[b];for(b=o-s;a>b;b++)c[b+i]=t[b];for(b=0;e-s>=b;b++)v[b]=t[o-e+b];for(var h=0,g=0,_=1;i>=_;_++){for(h=o-e+_,b=0;e-_-s>=b;b++)g=(n-r[h+b])/(r[b+o+1]-r[h+b]),v[b]=numeric.add(numeric.mul(g,v[b+1]),numeric.mul(1-g,v[b]));c[h]=v[0],c[o+i-_-s]=v[e-_-s]}for(b=h+1;o-s>b;b++)c[b]=v[b-h];return{knots:l,control_points:c}},verb.eval.nurbs.rational_surface_derivs=function(e,r,t,n,i,s,a,o){var u=verb.eval.nurbs.surface_derivs(e,r,t,n,i,s,a,o),v=verb.eval.nurbs.separate_homo_derivs_2d(u),l=v[0],c=v[1],b=0,h=0,g=0,_=0,m=[],f=l[0][0].length;for(b=0;s>=b;b++)for(m.push([]),_=0;s-b>=_;_++){var o=l[b][_];for(g=1;_>=g;g++)o=numeric.sub(o,numeric.mul(numeric.mul(binomial.get(_,g),c[0][g]),m[b][_-g]));for(h=1;b>=h;h++){o=numeric.sub(o,numeric.mul(numeric.mul(binomial.get(b,h),c[h][0]),m[b-h][_]));var d=verb.eval.nurbs.zeros_1d(f);for(g=1;_>=g;g++)d=numeric.add(d,numeric.mul(numeric.mul(binomial.get(_,g),c[h][g]),m[b-h][_-g]));o=numeric.sub(o,numeric.mul(binomial.get(b,h),d))}m[b].push(numeric.mul(1/c[0][0],o))}return m},verb.eval.nurbs.rational_surface_point=function(e,r,t,n,i,s,a){return verb.eval.nurbs.dehomogenize(verb.eval.nurbs.surface_point(e,r,t,n,i,s,a))},verb.eval.nurbs.rational_curve_derivs=function(e,r,t,n,i){var s=verb.eval.nurbs.separate_homo_derivs_1d(verb.eval.nurbs.curve_derivs(e,r,t,n,i)),a=s[0],o=s[1],u=0,v=0,l=[];for(u=0;i>=u;u++){var c=a[u];for(v=1;u>=v;v++)c=numeric.sub(c,numeric.mul(numeric.mul(binomial.get(u,v),o[v]),l[u-v]));l.push(numeric.mul(1/o[0],c))}return l},verb.eval.nurbs.separate_homo_derivs_1d=function(e){for(var r=e[0].length,t=r-1,n=[],i=[],s=0,a=e.length;a>s;s++)n.push(e[s].slice(0,t)),i.push(e[s][t]);return[n,i]},verb.eval.nurbs.separate_homo_derivs_2d=function(e){for(var r=[],t=[],n=0,i=e.length;i>n;n++){var s=verb.eval.nurbs.separate_homo_derivs_1d(e[n]);r.push(s[0]),t.push(s[1])}return[r,t]},verb.eval.nurbs.rational_curve_point=function(e,r,t,n){return verb.eval.nurbs.dehomogenize(verb.eval.nurbs.curve_point(e,r,t,n))},verb.eval.nurbs.dehomogenize=function(e){for(var r=e.length,t=[],n=e[r-1],i=0;e.length-1>i;i++)t.push(e[i]/n);return t},verb.eval.nurbs.homogenize_1d=function(e,r){for(var t=e.length,n=e[0].length,i=0,s=[],a=0,o=[],u=0;t>u;u++){var v=[];for(o=e[u],a=r[u],i=0;n>i;i++)v.push(o[i]*a);v.push(a),s.push(v)}return s},verb.eval.nurbs.homogenize_2d=function(e,r){for(var t=e.length,n=(e[0].length,e[0][0].length,[]),i=0;t>i;i++)n.push(verb.eval.nurbs.homogenize_1d(e[i],r[i]));return n},verb.eval.nurbs.surface_derivs=function(e,r,t,n,i,s,a,o){var u=r.length-e-2,v=n.length-t-2;return verb.eval.nurbs.surface_derivs_given_n_m(u,e,r,v,t,n,i,s,a,o)},verb.eval.nurbs.surface_derivs_given_n_m=function(e,r,t,n,i,s,a,o,u,v){if(verb.eval.nurbs.are_valid_relations(r,a.length,t.length)===!1||verb.eval.nurbs.are_valid_relations(i,a[0].length,s.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var l=a[0][0].length,c=Math.min(o,r),b=Math.min(o,i),h=verb.eval.nurbs.zeros_3d(c+1,b+1,l),g=verb.eval.nurbs.knot_span_given_n(e,r,u,t),_=verb.eval.nurbs.knot_span_given_n(n,i,v,s),m=verb.eval.nurbs.deriv_basis_functions_given_n_i(g,u,r,e,t),f=verb.eval.nurbs.deriv_basis_functions_given_n_i(_,v,i,n,s),d=verb.eval.nurbs.zeros_2d(i+1,l),p=0,y=0,x=0,N=0,k=0;for(p=0;c>=p;p++){for(y=0;i>=y;y++)for(d[y]=verb.eval.nurbs.zeros_1d(l),x=0;r>=x;x++)d[y]=numeric.add(d[y],numeric.mul(m[p][x],a[g-r+x][_-i+y]));for(k=Math.min(o-p,b),N=0;k>=N;N++)for(h[p][N]=verb.eval.nurbs.zeros_1d(l),y=0;i>=y;y++)h[p][N]=numeric.add(h[p][N],numeric.mul(f[N][y],d[y]))}return h},verb.eval.nurbs.surface_point=function(e,r,t,n,i,s,a){var o=r.length-e-2,u=n.length-t-2;return verb.eval.nurbs.surface_point_given_n_m(o,e,r,u,t,n,i,s,a)},verb.eval.nurbs.volume_point=function(e,r,t,n,i,s,a,o,u,v){var l=r.length-e-2,c=n.length-t-2,b=s.length-i-2;return verb.eval.nurbs.volume_point_given_n_m_l(l,e,r,c,t,n,b,i,s,a,o,u,v)},verb.eval.nurbs.volume_point_given_n_m_l=function(e,r,t,n,i,s,a,o,u,v,l,c,b){if(!verb.eval.nurbs.are_valid_relations(r,v.length,t.length)||!verb.eval.nurbs.are_valid_relations(i,v[0].length,s.length)||!verb.eval.nurbs.are_valid_relations(o,v[0][0].length,u.length))return console.error("Invalid relations between control points and knot vector"),null;for(var h=v[0][0][0].length,g=verb.eval.nurbs.knot_span_given_n(e,r,l,t),_=verb.eval.nurbs.knot_span_given_n(n,i,c,s),m=verb.eval.nurbs.knot_span_given_n(a,o,b,u),f=verb.eval.nurbs.basis_functions_given_knot_span_index(g,l,r,t),d=verb.eval.nurbs.basis_functions_given_knot_span_index(_,c,i,s),p=verb.eval.nurbs.basis_functions_given_knot_span_index(m,b,o,u),y=g-r,x=_,N=m,k=verb.eval.nurbs.zeros_1d(h),w=verb.eval.nurbs.zeros_1d(h),E=verb.eval.nurbs.zeros_1d(h),A=0,M=0,z=0;o>=z;z++){for(E=verb.eval.nurbs.zeros_1d(h),N=m-o+z,A=0;i>=A;A++){for(w=verb.eval.nurbs.zeros_1d(h),x=_-i+A,M=0;r>=M;M++)w=numeric.add(w,numeric.mul(f[M],v[y+M][x][N]));E=numeric.add(E,numeric.mul(d[A],w))}k=numeric.add(k,numeric.mul(p[z],E))}return k},verb.eval.nurbs.surface_point_given_n_m=function(e,r,t,n,i,s,a,o,u){if(verb.eval.nurbs.are_valid_relations(r,a.length,t.length)===!1||verb.eval.nurbs.are_valid_relations(i,a[0].length,s.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var v=a[0][0].length,l=verb.eval.nurbs.knot_span_given_n(e,r,o,t),c=verb.eval.nurbs.knot_span_given_n(n,i,u,s),b=verb.eval.nurbs.basis_functions_given_knot_span_index(l,o,r,t),h=verb.eval.nurbs.basis_functions_given_knot_span_index(c,u,i,s),g=l-r,_=c,m=verb.eval.nurbs.zeros_1d(v),f=verb.eval.nurbs.zeros_1d(v),d=0,p=0;for(d=0;i>=d;d++){for(f=verb.eval.nurbs.zeros_1d(v),_=c-i+d,p=0;r>=p;p++)f=numeric.add(f,numeric.mul(b[p],a[g+p][_]));m=numeric.add(m,numeric.mul(h[d],f))}return m},verb.eval.nurbs.curve_derivs=function(e,r,t,n,i){var s=r.length-e-2;return verb.eval.nurbs.curve_derivs_given_n(s,e,r,t,n,i)},verb.eval.nurbs.curve_derivs_given_n=function(e,r,t,n,i,s){if(verb.eval.nurbs.are_valid_relations(r,n.length,t.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var a=n[0].length,o=Math.min(s,r),u=verb.eval.nurbs.zeros_2d(o+1,a),v=verb.eval.nurbs.knot_span_given_n(e,r,i,t),l=verb.eval.nurbs.deriv_basis_functions_given_n_i(v,i,r,o,t),c=0,b=0;for(c=0;o>=c;c++)for(b=0;r>=b;b++)u[c]=numeric.add(u[c],numeric.mul(l[c][b],n[v-r+b]));return u},verb.eval.nurbs.are_valid_relations=function(e,r,t){return 0===r+e+1-t?!0:!1},verb.eval.nurbs.curve_point=function(e,r,t,n){var i=r.length-e-2;return verb.eval.nurbs.curve_point_given_n(i,e,r,t,n)},verb.eval.nurbs.curve_point_given_n=function(e,r,t,n,i){if(verb.eval.nurbs.are_valid_relations(r,n.length,t.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;for(var s=verb.eval.nurbs.knot_span_given_n(e,r,i,t),a=verb.eval.nurbs.basis_functions_given_knot_span_index(s,i,r,t),o=verb.eval.nurbs.zeros_1d(n[0].length),u=0;r>=u;u++)o=numeric.add(o,numeric.mul(a[u],n[s-r+u]));return o},verb.eval.nurbs.zeros_1d=function(e){e=e>0?e:0;for(var r=[];e--;)r.push(0);return r},verb.eval.nurbs.zeros_2d=function(e,r){r=r>0?r:0,e=e>0?e:0;for(var t=[],n=r,i=e;e--;){for(t.push([]);n--;)t[i-e-1].push(0);n=r}return t},verb.eval.nurbs.zeros_3d=function(e,r,t){r=r>0?r:0,e=e>0?e:0;for(var n=[],i=r,s=e;e--;){for(n.push([]);i--;)n[s-e-1].push(verb.eval.nurbs.zeros_1d(t));i=r}return n},verb.eval.nurbs.deriv_basis_functions=function(e,r,t){var n=verb.eval.nurbs.knot_span(r,e,t),i=t.length-1,s=i-r-1;return verb.eval.nurbs.deriv_basis_functions_given_n_i(n,e,r,s,t)},verb.eval.nurbs.deriv_basis_functions_given_n_i=function(e,r,t,n,i){var s=verb.eval.nurbs.zeros_2d(t+1,t+1),a=Array(t+1),o=Array(t+1),u=0,v=0,l=1,c=0;for(s[0][0]=1,l=1;t>=l;l++){for(a[l]=r-i[e+1-l],o[l]=i[e+l]-r,u=0,c=0;l>c;c++)s[l][c]=o[c+1]+a[l-c],v=s[c][l-1]/s[l][c],s[c][l]=u+o[c+1]*v,u=a[l-c]*v;s[l][l]=u}var b=verb.eval.nurbs.zeros_2d(n+1,t+1),h=verb.eval.nurbs.zeros_2d(2,t+1),g=1,_=0,m=1,f=0,d=0,p=0,y=0,x=0;for(l=0;t>=l;l++)b[0][l]=s[l][t];for(c=0;t>=c;c++)for(_=0,m=1,h[0][0]=1,g=1;n>=g;g++){for(f=0,d=c-g,p=t-g,c>=g&&(h[m][0]=h[_][0]/s[p+1][d],f=h[m][0]*s[d][p]),y=d>=-1?1:-d,x=p>=c-1?g-1:t-c,l=y;x>=l;l++)h[m][l]=(h[_][l]-h[_][l-1])/s[p+1][d+l],f+=h[m][l]*s[d+l][p];p>=c&&(h[m][g]=-h[_][g-1]/s[p+1][c],f+=h[m][g]*s[c][p]),b[g][c]=f,l=_,_=m,m=l}for(c=t,g=1;n>=g;g++){for(l=0;t>=l;l++)b[g][l]*=c;c*=t-g}return b},verb.eval.nurbs.basis_functions=function(e,r,t){var n=verb.eval.nurbs.knot_span(e,r,t);return verb.eval.nurbs.basis_functions_given_knot_span_index(n,e,r,t)},verb.eval.nurbs.basis_functions_given_knot_span_index=function(e,r,t,n){var i=Array(t+1),s=Array(t+1),a=Array(t+1),o=0,u=0;i[0]=1;for(var v=1;t>=v;v++){s[v]=r-n[e+1-v],a[v]=n[e+v]-r,o=0;for(var l=0;v>l;l++)u=i[l]/(a[l+1]+s[v-l]),i[l]=o+a[l+1]*u,o=s[v-l]*u;i[v]=o}return i},verb.eval.nurbs.knot_span=function(e,r,t){var n=t.length-1,i=n-e-1;return verb.eval.nurbs.knot_span_given_n(i,e,r,t)},verb.eval.nurbs.knot_span_given_n=function(e,r,t,n){if(t>=n[e+1])return e;if(n[r]>t)return r;for(var i=r,s=e+1,a=Math.floor((i+s)/2);n[a]>t||t>=n[a+1];)n[a]>t?s=a:i=a,a=Math.floor((i+s)/2);return a}; \ No newline at end of file diff --git a/build/verbEval.js b/build/verbEval.js index 9fcb90dd..7a0ffff4 100644 --- a/build/verbEval.js +++ b/build/verbEval.js @@ -2413,24 +2413,27 @@ verb.eval.nurbs.rational_surface_curvature = function( degree_u, knots_u, degree // // ####curve_knot_insert( degree, knots, control_points, u, s, r ) // -// Insert a knot along a rational curve +// Insert a knot along a rational curve. Note that this algorithm only works +// for r + s <= degree, where s is the initial multiplicity (number of duplicates) of the knot. +// +// Corresponds to algorithm A5.1 (Piegl & Tiller) +// +// Use the curve_knot_refine for applications like curve splitting. // // **params** // + *Number*, integer degree // + *Array*, array of nondecreasing knot values // + *Array*, array of control points // + *Number*, parameter at which to insert the knot -// + *Number*, initial multiplicity of the knot // + *Number*, number of times to insert the knot // // **returns** -// + *Object* the new curve, defined by degree, knots, and control_points +// + *Object* the new curve, defined by knots and control_points // verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, r ) { // num_pts is num control points for the initial curve - // nq is num control points for the output curve with knots inserted // k is the span on which the knots are inserted // s is the initial multiplicity of the knot // r is the number of times to insert the knot @@ -2438,13 +2441,10 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, var s = 0; // assume original multiplicity is 0 - TODO add check for multiplicity in knots - var dim = control_points[0].length - , num_pts = control_points.length + var num_pts = control_points.length , k = verb.eval.nurbs.knot_span( degree, u, knots ) // the span in which the knot will be inserted - , mp = knots.length - , nq = num_pts + r , num_pts_post = num_pts + r // a new control pt for every new knot - , Rw = new Array( degree - s ) + , control_points_temp = new Array( degree - s ) , knots_post = new Array( knots.length + r ) // r new knots , control_points_post = new Array( num_pts_post ) , i = 0; @@ -2480,7 +2480,7 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, // collect the affected control points in this temporary array for (i = 0; i <= degree-s; i++) { - Rw[i] = control_points[k-degree+i]; + control_points_temp[i] = control_points[k-degree+i]; } var L = 0 @@ -2494,27 +2494,30 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, for (i = 0; i <= degree-j-s; i++) { alpha = ( u - knots[L+i] ) / ( knots[i+k+1] - knots[L+i] ); - Rw[i] = numeric.add( numeric.mul( alpha, Rw[i+1] ), numeric.mul( (1.0 - alpha), Rw[i]) ); + + control_points_temp[i] = + numeric.add( + numeric.mul( alpha, control_points_temp[i+1] ), + numeric.mul( (1.0 - alpha), control_points_temp[i]) + ); + } - control_points_post[ L ] = Rw[0]; - control_points_post[k+r-j-s] = Rw[degree-j-s]; + control_points_post[ L ] = control_points_temp[0]; + control_points_post[k+r-j-s] = control_points_temp[degree-j-s]; } // not so confident about this part - for (i = L+1; i < k-s; i++) // set remaining control points - { - control_points_post[i] = Rw[ i - L ]; + for (i = L+1; i < k-s; i++) { + control_points_post[i] = control_points_temp[ i - L ]; } return { knots: knots_post, control_points: control_points_post }; } -// knot refinement - // // ####rational_surface_derivs( degree_u, knots_u, degree_v, knots_v, homo_control_points, num_derivs, u, v) diff --git a/build/verbEval.min.js b/build/verbEval.min.js index 2d8cea1e..0139989e 100644 --- a/build/verbEval.min.js +++ b/build/verbEval.min.js @@ -1,3 +1,3 @@ -/*! verb 2014-02-01 */ -function getEastNeighbor(e,r,n,t,i,s){return n===i-1?null:s[e+1]}function getNorthNeighbor(e,r,n,t,i,s){return 0===r?null:s[e-i]}function getSouthNeighbor(e,r,n,t,i,s){return r===t-1?null:s[e+i]}function getWestNeighbor(e,r,n,t,i,s){return 0===n?null:s[e-1]}function crossprod(e,r){return[e[1]*r[2]-e[2]*r[1],e[2]*r[0]-e[0]*r[2],e[0]*r[1]-e[1]*r[0]]}if("object"!=typeof exports||void 0===exports)importScripts("labor.js"),importScripts("binomial.js"),importScripts("numeric-1.2.6.min.js");else var labor=require("labor");var verb=verb||{};verb.eval=verb.eval||{},verb.eval.nurbs=verb.eval.nurbs||{},verb.eval.mesh=verb.eval.mesh||{},verb.eval.geom=verb.eval.geom||{},verb.geom=verb.geom||{},verb.EPSILON=1e-8,verb.TOLERANCE=.001;var router=new labor.Router(verb.eval.nurbs);numeric.normalized=function(e){return numeric.div(e,numeric.norm2(e))},numeric.cross=function(e,r){return[e[1]*r[2]-e[2]*r[1],e[2]*r[0]-e[0]*r[2],e[0]*r[1]-e[1]*r[0]]},verb.left=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(0,r)},verb.right=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(r)},verb.rightWithPivot=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(r-1)},verb.unique=function(e,r){if(0===e.length)return[];for(var n=[e.pop()],t=0;e.length>t;t++){for(var i=e.pop(),s=!0,a=0;n.length>a;a++)if(r(i,n[t])){s=!1;break}s&&n.push(i)}return n},verb.eval.nurbs.intersect_rational_curve_surface_by_aabb_refine=function(e,r,n,t,i,s,a,u,o,v,l,b){var c=verb.eval.nurbs.intersect_rational_curve_surface_by_aabb(e,r,n,t,i,s,a,u,o,v,l,b);return c.map(function(o){var v=[o.p,o.uv[0],o.uv[1]],l=verb.eval.nurbs.refine_rational_curve_surface_intersection(e,r,n,t,i,s,a,u,v);return o.p=l[0],o.uv[0]=l[1],o.uv[1]=l[2],o.distance=l[3],delete o.face,o})},verb.eval.nurbs.refine_rational_curve_surface_intersection=function(e,r,n,t,i,s,a,u,o){var v=function(o){var v=verb.eval.nurbs.rational_curve_point(s,a,u,o[0]),l=verb.eval.nurbs.rational_surface_point(e,r,n,t,i,o[1],o[2]),b=numeric.sub(v,l);return numeric.dot(b,b)},l=numeric.uncmin(v,o);return l.solution.concat(l.f)},verb.eval.nurbs.intersect_rational_curve_surface_by_aabb=function(e,r,n,t,i,s,a,u,o,v,l,b){var c=verb.eval.nurbs.rational_curve_adaptive_sample(s,a,u,o,!0),h=verb.eval.nurbs.tesselate_rational_surface_naive(e,r,n,t,i,l,b),_=c.map(function(e){return e[0]}),m=c.map(function(e){return e.slice(1)}),g=verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(m,_,h,verb.range(h.faces.length),v);return verb.unique(g,function(e,r){return v>numeric.norm2(numeric.sub(e.point,r.point))&&v>Math.abs(e.p-r.p)&&v>numeric.norm2(numeric.sub(e.uv,r.uv))})},verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb=function(e,r,n,t,i){var s=new verb.geom.BoundingBox(e),a=verb.eval.mesh.make_mesh_aabb(n.points,n.faces,t);if(!s.intersects(a,i))return[];if(2!==e.length||1!==t.length){if(1===t.length){var u=verb.left(e),o=verb.rightWithPivot(e),v=verb.left(r),l=verb.rightWithPivot(r);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,v,n,t,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,l,n,t,i))}if(2===e.length){var b=verb.eval.mesh.sort_tris_on_longest_axis(a,n.points,n.faces,t),c=verb.left(b),h=verb.right(b);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(e,r,n,c,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(e,r,n,h,i))}var b=verb.eval.mesh.sort_tris_on_longest_axis(a,n.points,n.faces,t),c=verb.left(b),h=verb.right(b),u=verb.left(e),o=verb.rightWithPivot(e),v=verb.left(r),l=verb.rightWithPivot(r);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,v,n,c,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,v,n,h,i)).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,l,n,c,i)).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,l,n,h,i))}var _=verb.eval.geom.intersect_segment_with_tri(e[0],e[1],n.points,n.faces[t[0]]);if(null!=_){var m=_.p*(r[1]-r[0])+r[0],g=n.faces[t][0],f=n.faces[t][1],d=n.faces[t][2],p=n.uvs[g],y=n.uvs[f],x=n.uvs[d],k=numeric.sub(y,p),N=numeric.sub(x,p),E=numeric.add(p,numeric.mul(_.s,k),numeric.mul(_.t,N));return[{point:_.point,p:m,uv:E,face:t[0]}]}return[]},verb.eval.geom.intersect_segment_with_tri=function(e,r,n,t){var i=n[t[0]],s=n[t[1]],a=n[t[2]],u=numeric.sub(s,i),o=numeric.sub(a,i),v=numeric.cross(u,o),l=numeric.sub(r,e),b=numeric.sub(e,i),c=-numeric.dot(v,b),h=numeric.dot(v,l);if(Math.abs(h)_||_>1)return null;var m=numeric.add(e,numeric.mul(_,l)),g=numeric.dot(u,o),f=numeric.dot(u,u),d=numeric.dot(o,o),p=numeric.sub(m,i),y=numeric.dot(p,u),x=numeric.dot(p,o),k=g*g-f*d,N=(g*x-d*y)/k,E=(g*y-f*x)/k;return N>1+verb.EPSILON||E>1+verb.EPSILON||-verb.EPSILON>E||-verb.EPSILON>N||N+E>1+verb.EPSILON?null:{point:m,s:N,t:E,p:_}},verb.eval.geom.intersect_segment_with_plane=function(e,r,n,t){var i=numeric.dot(t,numeric.sub(e,r));if(EPSILON>abs(i))return null;var s=numeric.dot(t,numeric.sub(n,e));return{p:s/i}},verb.eval.geom.intersect_aabb_trees=function(e,r,n,t,i,s){var a=i.bounding_box.intersects(s.bounding_box);return a?0===i.children.length&&0===s.children.length?[[i.triangle,s.triangle]]:0===i.children.length&&0!=s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,n,t,i,s.children[0]).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i,s.children[1])):0!=i.children.length&&0===s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[0],s).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[1],s)):0!=i.children.length&&0!=s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[0],s.children[0]).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[0],s.children[1])).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[1],s.children[0])).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[1],s.children[1])):void 0:[]},verb.eval.mesh.make_mesh_aabb_tree=function(e,r,n){var t={bounding_box:verb.eval.mesh.make_mesh_aabb(e,r,n),children:[]};if(1===n.length)return t.triangle=n[0],t;var i=verb.eval.mesh.sort_tris_on_longest_axis(t.bounding_box,e,r,n),s=i.slice(0,Math.floor(i.length/2)),a=i.slice(Math.floor(i.length/2),i.length);return t.children=[verb.eval.mesh.make_mesh_aabb_tree(e,r,s),verb.eval.mesh.make_mesh_aabb_tree(e,r,a)],t},verb.eval.mesh.make_mesh_aabb=function(e,r,n){var t=new verb.geom.BoundingBox;return n.forEach(function(n){t.add(e[r[n][0]]),t.add(e[r[n][1]]),t.add(e[r[n][2]])}),t},verb.eval.mesh.sort_tris_on_longest_axis=function(e,r,n,t){for(var i=e.get_longest_axis(),s=[],a=t.length-1;a>=0;a--){var u=t[a],o=verb.eval.mesh.get_min_coordinate_on_axis(r,n[u],i);s.push([o,u])}s.sort(function(e,r){return e[0]>r[0]});for(var v=[],a=0,l=s.length;l>a;a++)v.push(s[a][1]);return v},verb.eval.mesh.get_min_coordinate_on_axis=function(e,r,n){for(var t=[],i=0;3>i;i++)t.push(e[r[i]][n]);return Math.min.apply(Math,t)},verb.eval.geom.get_tri_centroid=function(e,r){for(var n=[0,0,0],t=0;3>t;t++)for(var i=0;3>i;i++)n[i]+=e[r[t]][i];for(var t=0;3>t;t++)n[t]/=3;return n},verb.eval.geom.get_tri_norm=function(e,r){var n=e[r[0]],t=e[r[1]],i=e[r[2]],s=numeric.sub(t,n),a=numeric.sub(i,n),u=numeric.cross(s,a);return numeric.mul(1/numeric.norm2(u),u)},verb.eval.nurbs.intersect_rational_curves_by_aabb_refine=function(e,r,n,t,i,s,a,u){var o=verb.eval.nurbs.intersect_rational_curves_by_aabb(e,r,n,t,i,s,a,u);return o.map(function(a){return verb.eval.nurbs.refine_rational_curve_intersection(e,r,n,t,i,s,a)})},verb.eval.nurbs.refine_rational_curve_intersection=function(e,r,n,t,i,s,a){var u=function(a){var u=verb.eval.nurbs.rational_curve_point(e,r,n,a[0]),o=verb.eval.nurbs.rational_curve_point(t,i,s,a[1]),v=numeric.sub(u,o);return numeric.dot(v,v)},o=numeric.uncmin(u,a);return o.solution.concat(o.f)},verb.eval.nurbs.intersect_rational_curves_by_aabb=function(e,r,n,t,i,s,a,u){var o=verb.eval.nurbs.rational_curve_adaptive_sample(e,r,n,a,!0),v=verb.eval.nurbs.rational_curve_adaptive_sample(t,i,s,a,!0),l=o.map(function(e){return e[0]}),b=v.map(function(e){return e[0]}),c=o.map(function(e){return e.slice(1)}),h=v.map(function(e){return e.slice(1)});return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(c,h,l,b,u)},verb.eval.nurbs.intersect_parametric_polylines_by_aabb=function(e,r,n,t,i){var s=new verb.geom.BoundingBox(e),a=new verb.geom.BoundingBox(r);if(!s.intersects(a,i))return[];if(2!==e.length||2!==r.length){if(2===e.length){var u=Math.ceil(r.length/2),o=r.slice(0,u),v=r.slice(u-1),l=t.slice(0,u),b=t.slice(u-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(e,o,n,l,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(e,v,n,b,i))}if(2===r.length){var c=Math.ceil(e.length/2),h=e.slice(0,c),_=e.slice(c-1),m=n.slice(0,c),g=n.slice(c-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,r,m,t,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(_,r,g,t,i))}var c=Math.ceil(e.length/2),h=e.slice(0,c),_=e.slice(c-1),m=n.slice(0,c),g=n.slice(c-1),u=Math.ceil(r.length/2),o=r.slice(0,u),v=r.slice(u-1),l=t.slice(0,u),b=t.slice(u-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,o,m,l,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,v,m,b,i)).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(_,o,g,l,i)).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(_,v,g,b,i))}var f=verb.eval.geom.intersect_segments(e[0],e[1],r[0],r[1],i);return null!=f?(f[0][0]=f[0][0]*(n[1]-n[0])+n[0],f[1][0]=f[1][0]*(t[1]-t[0])+t[0],[[f[0][0],f[1][0]]]):[]},verb.eval.geom.intersect_segments=function(e,r,n,t,i){var s=numeric.sub(r,e),a=Math.sqrt(numeric.dot(s,s)),u=numeric.mul(1/a,s),o=numeric.sub(t,n),v=Math.sqrt(numeric.dot(o,o)),l=numeric.mul(1/v,o),b=verb.eval.geom.intersect_rays(e,u,n,l);if(null!=b){var c=Math.min(Math.max(0,b[0]/a),1),h=Math.min(Math.max(0,b[1]/v),1),_=numeric.add(numeric.mul(c,s),e),m=numeric.add(numeric.mul(h,o),n),g=numeric.norm2Squared(numeric.sub(_,m));if(i*i>g)return[[c].concat(_),[h].concat(m)]}return null},verb.eval.geom.closest_point_on_ray=function(e,r,n){var t=numeric.sub(e,r),i=numeric.dot(t,n),s=numeric.add(r,numeric.mul(i,n));return s},verb.eval.geom.intersect_rays=function(e,r,n,t){var i=numeric.dot(r,t),s=numeric.dot(r,n),a=numeric.dot(r,e),u=numeric.dot(t,n),o=numeric.dot(t,e),v=numeric.dot(r,r),l=numeric.dot(t,t),b=v*l-i*i;if(Math.abs(b)g;g++){var f=verb.eval.geom.intersect_segment_with_plane(b[g][0],c[g][1],m,_);f.intersects&&h.push(f)}if(2!==h.length)return null;for(var d=[h[0].point,h[1].point],p=[],g=0;3>g;g++){var y=verb.eval.geom.intersect_segments(d[0],d[1],d,b1,tol);y&&p.push(y)}0===p.length||1===p.length||2===p.length},verb.eval.nurbs.tesselate_rational_surface_naive=function(e,r,n,t,i,s,a){1>s&&(s=1),1>a&&(a=1);for(var u=1/s,o=1/a,v=[],l=[],b=[],c=0;s+1>c;c++)for(var h=0;a+1>h;h++){var _=c*u,m=h*o;l.push([_,m]);var g=verb.eval.nurbs.rational_surface_derivs(e,r,n,t,i,1,_,m),f=g[0][0];v.push(f);var d=numeric.cross(g[0][1],g[1][0]);b.push(d)}for(var p=[],c=0;s>c;c++)for(var h=0;a>h;h++){var y=c*(a+1)+h,x=(c+1)*(a+1)+h,k=x+1,N=y+1,E=[y,x,k],M=[y,k,N];p.push(E),p.push(M)}return{points:v,faces:p,uvs:l,normals:b}},verb.eval.nurbs.rational_curve_regular_sample=function(e,r,n,t,i){return verb.eval.nurbs.rational_curve_regular_sample_range(e,r,n,0,1,t,i)},verb.eval.nurbs.rational_curve_regular_sample_range=function(e,r,n,t,i,s,a){1>s&&(s=2);for(var u=[],o=(i-t)/(s-1),v=0,l=0;s>l;l++)v=t+o*l,a?u.push([v].concat(verb.eval.nurbs.rational_curve_point(e,r,n,v))):u.push(verb.eval.nurbs.rational_curve_point(e,r,n,v));return u},verb.eval.nurbs.rational_curve_adaptive_sample=function(e,r,n,t,i){return 1===e?i?n.map(function(e,n){return[r[n+1]].concat(verb.eval.nurbs.dehomogenize(e))}):n.map(verb.eval.nurbs.dehomogenize):verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,n,0,1,t,i)},verb.eval.nurbs.rational_curve_adaptive_sample_range=function(e,r,n,t,i,s,a){var u=verb.eval.nurbs.rational_curve_point(e,r,n,t),o=verb.eval.nurbs.rational_curve_point(e,r,n,i),v=.5+.2*Math.random(),l=t+(i-t)*v,b=verb.eval.nurbs.rational_curve_point(e,r,n,l),c=numeric.sub(u,o),h=numeric.sub(u,b);if(s>numeric.dot(c,c)&&numeric.dot(h,h)>s||!verb.eval.nurbs.three_points_are_flat(u,b,o,s)){var _=t+.5*(i-t),m=verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,n,t,_,s,a),g=verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,n,_,i,s,a);return m.slice(0,-1).concat(g)}return a?[[t].concat(u),[i].concat(o)]:[u,o]},verb.eval.nurbs.three_points_are_flat=function(e,r,n,t){var i=numeric.sub(r,e),s=numeric.sub(n,e),a=crossprod(i,s),u=numeric.dot(a,a);return t>u},verb.eval.nurbs.divide_rational_surface_adaptive=function(e,r,n,t,i,s){for(var a={degree_u:e,knots_u:r,degree_v:n,knots_v:t,homo_control_points:i},u=s.minDivsU,o=s.minDivsV,v=Math.max.apply(null,r),l=Math.min.apply(null,r),b=Math.max.apply(null,t),c=Math.min.apply(null,t),h=(v-l)/u,_=(b-c)/o,m=[],g=0;u>g;g++)for(var f=0;o>f;f++){var d=l+h*g,p=l+h*(g+1),y=c+_*f,x=c+_*(f+1);m.push(new verb.eval.nurbs.AdaptiveRefinementNode(a,d,p,y,x,null,null))}for(var g=0;u>g;g++)for(var f=0;o>f;f++){var k=g*o+f,N=getNorthNeighbor(k,g,f,u,o,m),E=getEastNeighbor(k,g,f,u,o,m),M=getSouthNeighbor(k,g,f,u,o,m),w=getWestNeighbor(k,g,f,u,o,m);m[k].neighbors=[N,E,M,w],m.divide(s)}return m},verb.eval.nurbs.is_rational_surface_domain_flat=function(e){var r=verb.eval.nurbs.rational_surface_point,n=(u[1]-u[0]/2)*(.1*Math.random()+1),t=(v[1]-v[0]/2)*(.1*Math.random()+1),i=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[0],v[0]),s=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[0]+n,v[0]+t),a=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[1],v[1]);return verb.eval.nurbs.three_points_are_flat(i,s,a,tol)},verb.eval.nurbs.triangulate_adaptive_refinement_node_tree=function(e){var r={uvs:[],points:[],normals:[],faces:[]};return r.faces=e.map(function(e){e.triangulate(r)}).flatten(),r},verb.eval.nurbs.tesselate_rational_surface_adaptive=function(e,r,n,t,i,s){verb.eval.nurbs.divide_rational_surface_adaptive(e,r,n,t,i,s);var a=verb.eval.nurbs.triangulate_adaptive_refinement_node_tree(arrTree);return verb.eval.nurbs.unique_mesh(a)},verb.eval.nurbs.unique_mesh=function(e){return e},Array.prototype.where=function(e){if(0===this.length)return this;for(var r=[],n=0;this.length>n;n++)e(this[n])&&r.push(this[n]);return r},verb.eval.nurbs.AdaptiveRefinementNode=function(e,r,n,t,i,s,a){this.srf=e,this.u0=r,this.u1=n,this.v0=t,this.v1=i,this.parentNode=s,this.neighbors=a,this.leafEdgeUvs=[[r,t],[n,t],[n,i],[r,i]],this.cachedEdgeUvs=[]},verb.eval.nurbs.AdaptiveRefinementNode.prototype.isLeaf=function(){return void 0===this.children},verb.eval.nurbs.AdaptiveRefinementNode.prototype.evalSurface=function(){var e=verb.eval.nurbs.rational_surface_derivs(this.srf.degree_u,this.srf.knots_u,this.srf.degree_v,this.srf.knots_v,this.srf.homo_control_points,1,pt_u,pt_v),r=e[0][0];points.push(r);var n=numeric.cross(e[0][1],e[1][0]);return{point:r,normal:n}},verb.eval.nurbs.AdaptiveRefinementNode.prototype.getEdgeUvs=function(e){return this.isLeaf()?[this.leafEdgeUvs[e]]:(this.cachedEdgeUvs[e]=this.cachedEdgeUvs[e]||this.children[e].getEdgeUvs(e).concat(this.children[(e+1)%4].getEdgeUvs(e)),this.cachedEdgeUvs[e])},verb.eval.nurbs.AdaptiveRefinementNode.prototype.getAllEdgeUvs=function(e){var r=[this.leafEdgeUvs[e]];if(null===this.neighbors[e])return r;var n=this.neighbors[e].getEdgeUvs((e+2)%4),t=e%2,i=this,s=[function(e){return e[0]>i.u0+verb.EPSILON&&e[0]i.v0+verb.EPSILON&&e[1]t;t++)n.concat(this.getAllEdgeUvs(t));if(n.forEach(function(r){e.uvs.push(r);var n=this.evalSurface(r);e.points.push(n.point),e.normals.push(n.normal)}),4===n.length)return e.faces.push([r+1,r+4,r+2]),e.faces.push([r+4,r+3,r+2]),void 0;this.u05=this.u05||(this.u0+this.u1)/2,this.v05=this.v05||(this.v0+this.v1)/2,e.uvs.push([this.u05,this.v05]);var i=this.evalSurface([this.u05,this.v05]);e.points.push(i.point),e.normals.push(i.normal);for(var s=e.points.length-1,t=0;n.length>t;t++)e.faces.push([s,(r+t+2)%n.length,(r+t+1)%n.length])},verb.eval.nurbs.AdaptiveRefinementNode.prototype.triangulate=function(e){return this.isLeaf()?this.triangulateLeaf(e):(this.children.forEach(function(r){null!==r&&r.triangulate(e)}),void 0)},verb.eval.nurbs.AdaptiveRefinementNode.prototype.shouldDivide=function(e,r){return e.minDepth&&e.minDepth>r?!0:this.srf&&!verb.eval.nurbs.is_rational_surface_domain_flat(this.srf,this.u0,this.u1,this.v0,this.v1,e)?!0:!1},verb.eval.nurbs.AdaptiveRefinementNode.prototype.divide=function(e,r){void 0===r&&(r=0),this.shouldDivide(e,r)&&(r++,this.u05=(this.u0+this.u1)/2,this.v05=(this.v0+this.v1)/2,this.children=[new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u0,this.u05,this.v0,this.v05,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u05,this.u1,this.v0,this.v05,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u05,this.u1,this.v05,this.v1,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u0,this.u05,this.v05,this.v1,this)],this.children[0].neighbors=[this.neighbors[0],this.children[1],this.children[3],this.neighbors[3]],this.children[1].neighbors=[this.neighbors[0],this.neighbors[1],this.children[2],this.children[0]],this.children[2].neighbors=[this.children[1],this.neighbors[1],this.neighbors[2],this.children[3]],this.children[3].neighbors=[this.children[0],this.children[2],this.neighbors[2],this.neighbors[3]],this.children.forEach(function(n){n.divide(e,r)}))},verb.eval.nurbs.get_sweep1_surface=function(e,r,n,t,i,s,a,u){for(var o=verb.eval.nurbs.homogenize_1d(a,u),v=verb.eval.nurbs.rational_curve_point(s,i,o,0),l=1/a.length,b=[],c=[],h=0;a.length>h;h++){for(var _=verb.eval.nurbs.rational_curve_point(s,i,o,h*l),m=numeric.sub(_,v),g=[],f=[],d=0;n.length>d;d++)g.push(numeric.add(m,n[d])),f.push(t[d]*u[h]);b.push(g),c.push(f)}return{knots_u:i,knots_v:e,control_points:b,degree_u:s,degree_v:r,weights:c}},verb.eval.nurbs.get_ellipse_arc=function(e,r,n,t,i,s,a){s>a&&(a=2*Math.PI+s);var u=a-s,o=0;o=Math.PI/2>=u?1:Math.PI>=u?2:3*Math.PI/2>=u?3:4;var v=u/o,l=Math.cos(v/2),b=numeric.add(e,numeric.mul(t,Math.cos(s),r),numeric.mul(i,Math.sin(s),n)),c=numeric.sub(numeric.mul(Math.cos(s),n),numeric.mul(Math.sin(s),r)),h=verb.eval.nurbs.zeros_1d(2*o),_=verb.eval.nurbs.zeros_1d(2*o+3),m=0,g=s,f=verb.eval.nurbs.zeros_1d(2*o);h[0]=b,f[0]=1;for(var d=1;o>=d;d++){g+=v;var p=numeric.add(e,numeric.mul(t,Math.cos(g),r),numeric.mul(i,Math.sin(g),n));f[m+2]=1,h[m+2]=p;var y=numeric.sub(numeric.mul(Math.cos(g),n),numeric.mul(Math.sin(g),r)),x=verb.eval.geom.intersect_rays(b,numeric.mul(1/numeric.norm2(c),c),p,numeric.mul(1/numeric.norm2(y),y)),k=numeric.add(b,numeric.mul(c,x[0]));f[m+1]=l,h[m+1]=k,m+=2,o>d&&(b=p,c=y)}for(var N=2*o+1,d=0;3>d;d++)_[d]=0,_[d+N]=1;switch(o){case 1:break;case 2:_[3]=_[4]=.5;break;case 3:_[3]=_[4]=1/3,_[5]=_[6]=2/3;break;case 4:_[3]=_[4]=.25,_[5]=_[6]=.5,_[7]=_[8]=.75}return{knots:_,control_points:h,degree:2,weights:f}},verb.eval.nurbs.get_sphere_surface=function(e,r,n,t){var i=verb.eval.nurbs.get_arc(e,numeric.mul(r,-1),n,t,0,Math.PI);return verb.eval.nurbs.get_revolved_surface(e,r,2*Math.PI,i.knots,i.degree,i.control_points,i.weights)},verb.eval.nurbs.get_polyline_curve=function(e){for(var r=e.length-1,n=1/r,t=[0,0],i=1;r>i;i++)t.push(i*n);t.push(1),t.push(1);for(var s=[],i=0;e.length>i;i++)s.push(1);return{knots:t,control_points:e.slice(0),degree:1,weights:s}},verb.eval.nurbs.get_4pt_surface=function(e,r,n,t){return{knots_u:[0,0,1,1],knots_v:[0,0,1,1],control_points:[[e,t],[r,n]],degree_u:1,degree_v:1,weights:[[1,1],[1,1]]}},verb.eval.nurbs.get_cylinder_surface=function(e,r,n,t,i){var s=crossprod(e,r),a=(2*Math.PI,verb.eval.nurbs.get_arc(n,r,s,i,0,2*Math.PI));return verb.eval.nurbs.get_extruded_surface(e,t,a.knots,a.degree,a.control_points,a.weights)},verb.eval.nurbs.get_cone_surface=function(e,r,n,t,i){var s=2*Math.PI,a=1,u=[numeric.add(n,numeric.mul(t,e)),numeric.add(n,numeric.mul(i,r))],o=[0,0,1,1],v=[1,1];return verb.eval.nurbs.get_revolved_surface(n,e,s,o,a,u,v)},verb.eval.nurbs.get_extruded_surface=function(e,r,n,t,i,s){for(var a=verb.eval.nurbs.zeros_2d(3,i.length),u=verb.eval.nurbs.zeros_2d(3,i.length),o=numeric.mul(e,r),v=numeric.mul(e,.5*r),l=0;i.length>l;l++)a[0][l]=i[l],a[1][l]=numeric.add(v,i[l]),a[2][l]=numeric.add(o,i[l]),u[0][l]=s[l],u[1][l]=s[l],u[2][l]=s[l];return{knots_u:[0,0,0,1,1,1],knots_v:n,control_points:a,degree_u:2,degree_v:t,weights:u}},verb.eval.nurbs.get_revolved_surface=function(e,r,n,t,i,s,a){var u,o,v,l;Math.PI/2>=n?(u=1,o=verb.eval.nurbs.zeros_1d(6+2*(u-1))):Math.PI>=n?(u=2,o=verb.eval.nurbs.zeros_1d(6+2*(u-1)),o[3]=o[4]=.5):3*Math.PI/2>=n?(u=3,o=verb.eval.nurbs.zeros_1d(6+2*(u-1)),o[3]=o[4]=1/3,o[5]=o[6]=2/3):(u=4,o=verb.eval.nurbs.zeros_1d(6+2*(u-1)),o[3]=o[4]=.25,o[5]=o[6]=.5,o[7]=o[8]=.75);for(var b=n/u,c=3+2*(u-1),h=0;3>h;c++,h++)o[h]=0,o[c]=1;for(var _=Math.cos(b/2),m=0,g=verb.eval.nurbs.zeros_1d(u+1),f=verb.eval.nurbs.zeros_1d(u+1),v=verb.eval.nurbs.zeros_2d(2*u+1,s.length),l=verb.eval.nurbs.zeros_2d(2*u+1,s.length),h=1;u>=h;h++)m+=b,f[h]=Math.cos(m),g[h]=Math.sin(m);for(c=0;s.length>c;c++){var d=verb.eval.geom.closest_point_on_ray(s[c],e,r),p=numeric.sub(s[c],d),y=numeric.norm2(p),x=crossprod(r,p);y>verb.EPSILON&&(p=numeric.mul(1/y,p),x=numeric.mul(1/y,x)),v[0][c]=s[c];var k=s[c];l[0][c]=a[c];for(var N=x,E=0,m=0,h=1;u>=h;h++){var M=0==y?d:numeric.add(d,numeric.mul(y,f[h],p),numeric.mul(y,g[h],x));v[E+2][c]=M,l[E+2][c]=a[c];var w=numeric.sub(numeric.mul(f[h],x),numeric.mul(g[h],p));if(0==y)v[E+1][c]=d;else{var z=verb.eval.geom.intersect_rays(k,numeric.mul(1/numeric.norm2(N),N),M,numeric.mul(1/numeric.norm2(w),w)),A=numeric.add(k,numeric.mul(N,z[0]));v[E+1][c]=A}l[E+1][c]=_*a[c],E+=2,u>h&&(k=M,N=w)}}return{knots_u:o,knots_v:t,control_points:v,degree_u:2,degree_v:i,weights:l}},verb.eval.nurbs.get_arc=function(e,r,n,t,i,s){return verb.eval.nurbs.get_ellipse_arc(e,r,n,t,t,i,s)},verb.eval.nurbs.curve_knot_insert=function(e,r,n,t,i,s){var a=(n[0].length,r.length-e-2),u=n.length,o=verb.eval.nurbs.knot_span(e,t,r),v=a+e+1,l=u+s,b=Array(e+1),c=Array(r.length+s),h=Array(l),_=0;for(_=0;o>=_;_++)c[_]=r[_];for(_=1;s>=_;_++)c[o+_]=t;for(_=o+1;v>=_;_++)c[_+s]=r[_];for(_=0;o-e>=_;_++)h[_]=n[_];for(_=o-i;a>=_;_++)h[_+s]=n[_];for(_=0;e-i>=_;_++)b[_]=n[o-e+1];for(var m=0,g=0,f=1;s>=f;f++){for(m=o-e+f,_=0;e-f-i>=_;_++)g=(t-r[m+_])/(r[_+o+1]-r[m+_]),b[_]=numeric.add(numeric.mul(g,b[_+1]),numeric.mul(1-g,b[_]));h[m]=b[0],h[o+s-f-i]=b[e-f-i]}for(_=m+1;o-i>_;_++)h[_]=b[_-m];return[c,h]},verb.eval.nurbs.rational_surface_derivs=function(e,r,n,t,i,s,a,u){var o=verb.eval.nurbs.surface_derivs(e,r,n,t,i,s,a,u),v=verb.eval.nurbs.separate_homo_derivs_2d(o),l=v[0],b=v[1],c=0,h=0,_=0,m=0,g=[],f=l[0][0].length;for(c=0;s>=c;c++)for(g.push([]),m=0;s-c>=m;m++){var u=l[c][m];for(_=1;m>=_;_++)u=numeric.sub(u,numeric.mul(numeric.mul(binomial.get(m,_),b[0][_]),g[c][m-_]));for(h=1;c>=h;h++){u=numeric.sub(u,numeric.mul(numeric.mul(binomial.get(c,h),b[h][0]),g[c-h][m]));var d=verb.eval.nurbs.zeros_1d(f);for(_=1;m>=_;_++)d=numeric.add(d,numeric.mul(numeric.mul(binomial.get(m,_),b[h][_]),g[c-h][m-_]));u=numeric.sub(u,numeric.mul(binomial.get(c,h),d))}g[c].push(numeric.mul(1/b[0][0],u))}return g},verb.eval.nurbs.rational_surface_point=function(e,r,n,t,i,s,a){return verb.eval.nurbs.dehomogenize(verb.eval.nurbs.surface_point(e,r,n,t,i,s,a))},verb.eval.nurbs.rational_curve_derivs=function(e,r,n,t,i){var s=verb.eval.nurbs.separate_homo_derivs_1d(verb.eval.nurbs.curve_derivs(e,r,n,t,i)),a=s[0],u=s[1],o=0,v=0,l=[];for(o=0;i>=o;o++){var b=a[o];for(v=1;o>=v;v++)b=numeric.sub(b,numeric.mul(numeric.mul(binomial.get(o,v),u[v]),l[o-v]));l.push(numeric.mul(1/u[0],b))}return l},verb.eval.nurbs.separate_homo_derivs_1d=function(e){for(var r=e[0].length,n=r-1,t=[],i=[],s=0,a=e.length;a>s;s++)t.push(e[s].slice(0,n)),i.push(e[s][n]);return[t,i]},verb.eval.nurbs.separate_homo_derivs_2d=function(e){for(var r=[],n=[],t=0,i=e.length;i>t;t++){var s=verb.eval.nurbs.separate_homo_derivs_1d(e[t]);r.push(s[0]),n.push(s[1])}return[r,n]},verb.eval.nurbs.rational_curve_point=function(e,r,n,t){return verb.eval.nurbs.dehomogenize(verb.eval.nurbs.curve_point(e,r,n,t))},verb.eval.nurbs.dehomogenize=function(e){for(var r=e.length,n=[],t=e[r-1],i=0;e.length-1>i;i++)n.push(e[i]/t);return n},verb.eval.nurbs.homogenize_1d=function(e,r){for(var n=e.length,t=e[0].length,i=0,s=[],a=0,u=[],o=0;n>o;o++){var v=[];for(u=e[o],a=r[o],i=0;t>i;i++)v.push(u[i]*a);v.push(a),s.push(v)}return s},verb.eval.nurbs.homogenize_2d=function(e,r){for(var n=e.length,t=(e[0].length,e[0][0].length,[]),i=0;n>i;i++)t.push(verb.eval.nurbs.homogenize_1d(e[i],r[i]));return t},verb.eval.nurbs.rational_surface_curvature=function(e,r,n,t,i,s,a){var u=verb.eval.nurbs.rational_surface_derivs(e,r,n,t,i,2,s,a),o=u[0][1],v=u[1][0],l=u[0][2],b=u[2][0],c=u[1][1],h=numeric.cross(o,v),_=numeric.dot(l,h),m=numeric.dot(c,h),g=numeric.dot(b,h),f=[[_,m],[m,g]],d=numeric.eig(f),p=d.lambda.x[0],y=d.lambda.x[1],x=.5*(p+y),k=p*y,N=numeric.add(numeric.mul(d.E.x[0][0],o),numeric.mul(d.E.x[0][1],v)),E=numeric.add(numeric.mul(d.E.x[1][0],o),numeric.mul(d.E.x[1][1],v));return{point:u[0][0],normal:h,mean:x,gaussian:k,shapeOperator:f,k1:p,k2:y,p1:N,p2:E,p1p:d.E.x[0],p2p:d.E.x[1]}},verb.eval.nurbs.surface_derivs=function(e,r,n,t,i,s,a,u){var o=r.length-e-2,v=t.length-n-2;return verb.eval.nurbs.surface_derivs_given_n_m(o,e,r,v,n,t,i,s,a,u)},verb.eval.nurbs.surface_derivs_given_n_m=function(e,r,n,t,i,s,a,u,o,v){if(verb.eval.nurbs.are_valid_relations(r,a.length,n.length)===!1||verb.eval.nurbs.are_valid_relations(i,a[0].length,s.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var l=a[0][0].length,b=Math.min(u,r),c=Math.min(u,i),h=verb.eval.nurbs.zeros_3d(b+1,c+1,l),_=verb.eval.nurbs.knot_span_given_n(e,r,o,n),m=verb.eval.nurbs.knot_span_given_n(t,i,v,s),g=verb.eval.nurbs.deriv_basis_functions_given_n_i(_,o,r,e,n),f=verb.eval.nurbs.deriv_basis_functions_given_n_i(m,v,i,t,s),d=verb.eval.nurbs.zeros_2d(i+1,l),p=0,y=0,x=0,k=0,N=0;for(p=0;b>=p;p++){for(y=0;i>=y;y++)for(d[y]=verb.eval.nurbs.zeros_1d(l),x=0;r>=x;x++)d[y]=numeric.add(d[y],numeric.mul(g[p][x],a[_-r+x][m-i+y]));for(N=Math.min(u-p,c),k=0;N>=k;k++)for(h[p][k]=verb.eval.nurbs.zeros_1d(l),y=0;i>=y;y++)h[p][k]=numeric.add(h[p][k],numeric.mul(f[k][y],d[y]))}return h},verb.eval.nurbs.surface_point=function(e,r,n,t,i,s,a){var u=r.length-e-2,o=t.length-n-2;return verb.eval.nurbs.surface_point_given_n_m(u,e,r,o,n,t,i,s,a)},verb.eval.nurbs.volume_point=function(e,r,n,t,i,s,a,u,o,v){var l=r.length-e-2,b=t.length-n-2,c=s.length-i-2;return verb.eval.nurbs.volume_point_given_n_m_l(l,e,r,b,n,t,c,i,s,a,u,o,v)},verb.eval.nurbs.volume_point_given_n_m_l=function(e,r,n,t,i,s,a,u,o,v,l,b,c){if(!verb.eval.nurbs.are_valid_relations(r,v.length,n.length)||!verb.eval.nurbs.are_valid_relations(i,v[0].length,s.length)||!verb.eval.nurbs.are_valid_relations(u,v[0][0].length,o.length))return console.error("Invalid relations between control points and knot vector"),null;for(var h=v[0][0][0].length,_=verb.eval.nurbs.knot_span_given_n(e,r,l,n),m=verb.eval.nurbs.knot_span_given_n(t,i,b,s),g=verb.eval.nurbs.knot_span_given_n(a,u,c,o),f=verb.eval.nurbs.basis_functions_given_knot_span_index(_,l,r,n),d=verb.eval.nurbs.basis_functions_given_knot_span_index(m,b,i,s),p=verb.eval.nurbs.basis_functions_given_knot_span_index(g,c,u,o),y=_-r,x=m,k=g,N=verb.eval.nurbs.zeros_1d(h),E=verb.eval.nurbs.zeros_1d(h),M=verb.eval.nurbs.zeros_1d(h),w=0,z=0,A=0;u>=A;A++){for(M=verb.eval.nurbs.zeros_1d(h),k=g-u+A,w=0;i>=w;w++){for(E=verb.eval.nurbs.zeros_1d(h),x=m-i+w,z=0;r>=z;z++)E=numeric.add(E,numeric.mul(f[z],v[y+z][x][k]));M=numeric.add(M,numeric.mul(d[w],E))}N=numeric.add(N,numeric.mul(p[A],M))}return N},verb.eval.nurbs.surface_point_given_n_m=function(e,r,n,t,i,s,a,u,o){if(verb.eval.nurbs.are_valid_relations(r,a.length,n.length)===!1||verb.eval.nurbs.are_valid_relations(i,a[0].length,s.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var v=a[0][0].length,l=verb.eval.nurbs.knot_span_given_n(e,r,u,n),b=verb.eval.nurbs.knot_span_given_n(t,i,o,s),c=verb.eval.nurbs.basis_functions_given_knot_span_index(l,u,r,n),h=verb.eval.nurbs.basis_functions_given_knot_span_index(b,o,i,s),_=l-r,m=b,g=verb.eval.nurbs.zeros_1d(v),f=verb.eval.nurbs.zeros_1d(v),d=0,p=0;for(d=0;i>=d;d++){for(f=verb.eval.nurbs.zeros_1d(v),m=b-i+d,p=0;r>=p;p++)f=numeric.add(f,numeric.mul(c[p],a[_+p][m]));g=numeric.add(g,numeric.mul(h[d],f))}return g},verb.eval.nurbs.curve_derivs=function(e,r,n,t,i){var s=r.length-e-2;return verb.eval.nurbs.curve_derivs_given_n(s,e,r,n,t,i)},verb.eval.nurbs.curve_derivs_given_n=function(e,r,n,t,i,s){if(verb.eval.nurbs.are_valid_relations(r,t.length,n.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var a=t[0].length,u=Math.min(s,r),o=verb.eval.nurbs.zeros_2d(u+1,a),v=verb.eval.nurbs.knot_span_given_n(e,r,i,n),l=verb.eval.nurbs.deriv_basis_functions_given_n_i(v,i,r,u,n),b=0,c=0;for(b=0;u>=b;b++)for(c=0;r>=c;c++)o[b]=numeric.add(o[b],numeric.mul(l[b][c],t[v-r+c]));return o},verb.eval.nurbs.are_valid_relations=function(e,r,n){return 0===r+e+1-n?!0:!1},verb.eval.nurbs.curve_point=function(e,r,n,t){var i=r.length-e-2;return verb.eval.nurbs.curve_point_given_n(i,e,r,n,t)},verb.eval.nurbs.curve_point_given_n=function(e,r,n,t,i){if(verb.eval.nurbs.are_valid_relations(r,t.length,n.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;for(var s=verb.eval.nurbs.knot_span_given_n(e,r,i,n),a=verb.eval.nurbs.basis_functions_given_knot_span_index(s,i,r,n),u=verb.eval.nurbs.zeros_1d(t[0].length),o=0;r>=o;o++)u=numeric.add(u,numeric.mul(a[o],t[s-r+o]));return u},verb.eval.nurbs.zeros_1d=function(e){e=e>0?e:0;for(var r=[];e--;)r.push(0);return r},verb.eval.nurbs.zeros_2d=function(e,r){r=r>0?r:0,e=e>0?e:0;for(var n=[],t=r,i=e;e--;){for(n.push([]);t--;)n[i-e-1].push(0);t=r}return n},verb.eval.nurbs.zeros_3d=function(e,r,n){r=r>0?r:0,e=e>0?e:0;for(var t=[],i=r,s=e;e--;){for(t.push([]);i--;)t[s-e-1].push(verb.eval.nurbs.zeros_1d(n));i=r}return t},verb.eval.nurbs.deriv_basis_functions=function(e,r,n){var t=verb.eval.nurbs.knot_span(r,e,n),i=n.length-1,s=i-r-1;return verb.eval.nurbs.deriv_basis_functions_given_n_i(t,e,r,s,n)},verb.eval.nurbs.deriv_basis_functions_given_n_i=function(e,r,n,t,i){var s=verb.eval.nurbs.zeros_2d(n+1,n+1),a=Array(n+1),u=Array(n+1),o=0,v=0,l=1,b=0;for(s[0][0]=1,l=1;n>=l;l++){for(a[l]=r-i[e+1-l],u[l]=i[e+l]-r,o=0,b=0;l>b;b++)s[l][b]=u[b+1]+a[l-b],v=s[b][l-1]/s[l][b],s[b][l]=o+u[b+1]*v,o=a[l-b]*v;s[l][l]=o}var c=verb.eval.nurbs.zeros_2d(t+1,n+1),h=verb.eval.nurbs.zeros_2d(2,n+1),_=1,m=0,g=1,f=0,d=0,p=0,y=0,x=0;for(l=0;n>=l;l++)c[0][l]=s[l][n];for(b=0;n>=b;b++)for(m=0,g=1,h[0][0]=1,_=1;t>=_;_++){for(f=0,d=b-_,p=n-_,b>=_&&(h[g][0]=h[m][0]/s[p+1][d],f=h[g][0]*s[d][p]),y=d>=-1?1:-d,x=p>=b-1?_-1:n-b,l=y;x>=l;l++)h[g][l]=(h[m][l]-h[m][l-1])/s[p+1][d+l],f+=h[g][l]*s[d+l][p]; -p>=b&&(h[g][_]=-h[m][_-1]/s[p+1][b],f+=h[g][_]*s[b][p]),c[_][b]=f,l=m,m=g,g=l}for(b=n,_=1;t>=_;_++){for(l=0;n>=l;l++)c[_][l]*=b;b*=n-_}return c},verb.eval.nurbs.basis_functions=function(e,r,n){var t=verb.eval.nurbs.knot_span(e,r,n);return verb.eval.nurbs.basis_functions_given_knot_span_index(t,e,r,n)},verb.eval.nurbs.basis_functions_given_knot_span_index=function(e,r,n,t){var i=Array(n+1),s=Array(n+1),a=Array(n+1),u=0,o=0;i[0]=1;for(var v=1;n>=v;v++){s[v]=r-t[e+1-v],a[v]=t[e+v]-r,u=0;for(var l=0;v>l;l++)o=i[l]/(a[l+1]+s[v-l]),i[l]=u+a[l+1]*o,u=s[v-l]*o;i[v]=u}return i},verb.eval.nurbs.knot_span=function(e,r,n){var t=n.length-1,i=t-e-1;return verb.eval.nurbs.knot_span_given_n(i,e,r,n)},verb.eval.nurbs.knot_span_given_n=function(e,r,n,t){if(n>=t[e+1])return e;if(t[r]>n)return r;for(var i=r,s=e+1,a=Math.floor((i+s)/2);t[a]>n||n>=t[a+1];)t[a]>n?s=a:i=a,a=Math.floor((i+s)/2);return a}; \ No newline at end of file +/*! verb 2014-10-27 */ +function getEastNeighbor(e,r,n,t,i,s){return n===i-1?null:s[e+1]}function getNorthNeighbor(e,r,n,t,i,s){return 0===r?null:s[e-i]}function getSouthNeighbor(e,r,n,t,i,s){return r===t-1?null:s[e+i]}function getWestNeighbor(e,r,n,t,i,s){return 0===n?null:s[e-1]}function crossprod(e,r){return[e[1]*r[2]-e[2]*r[1],e[2]*r[0]-e[0]*r[2],e[0]*r[1]-e[1]*r[0]]}if("object"!=typeof exports||void 0===exports)importScripts("labor.js"),importScripts("binomial.js"),importScripts("numeric-1.2.6.min.js");else var labor=require("labor");var verb=verb||{};verb.eval=verb.eval||{},verb.eval.nurbs=verb.eval.nurbs||{},verb.eval.mesh=verb.eval.mesh||{},verb.eval.geom=verb.eval.geom||{},verb.geom=verb.geom||{},verb.EPSILON=1e-8,verb.TOLERANCE=.001;var router=new labor.Router(verb.eval.nurbs);numeric.normalized=function(e){return numeric.div(e,numeric.norm2(e))},numeric.cross=function(e,r){return[e[1]*r[2]-e[2]*r[1],e[2]*r[0]-e[0]*r[2],e[0]*r[1]-e[1]*r[0]]},verb.left=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(0,r)},verb.right=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(r)},verb.rightWithPivot=function(e){if(0===e.length)return[];var r=Math.ceil(e.length/2);return e.slice(r-1)},verb.unique=function(e,r){if(0===e.length)return[];for(var n=[e.pop()],t=0;e.length>t;t++){for(var i=e.pop(),s=!0,a=0;n.length>a;a++)if(r(i,n[t])){s=!1;break}s&&n.push(i)}return n},verb.eval.nurbs.intersect_rational_curve_surface_by_aabb_refine=function(e,r,n,t,i,s,a,u,o,v,l,b){var c=verb.eval.nurbs.intersect_rational_curve_surface_by_aabb(e,r,n,t,i,s,a,u,o,v,l,b);return c.map(function(o){var v=[o.p,o.uv[0],o.uv[1]],l=verb.eval.nurbs.refine_rational_curve_surface_intersection(e,r,n,t,i,s,a,u,v);return o.p=l[0],o.uv[0]=l[1],o.uv[1]=l[2],o.distance=l[3],delete o.face,o})},verb.eval.nurbs.refine_rational_curve_surface_intersection=function(e,r,n,t,i,s,a,u,o){var v=function(o){var v=verb.eval.nurbs.rational_curve_point(s,a,u,o[0]),l=verb.eval.nurbs.rational_surface_point(e,r,n,t,i,o[1],o[2]),b=numeric.sub(v,l);return numeric.dot(b,b)},l=numeric.uncmin(v,o);return l.solution.concat(l.f)},verb.eval.nurbs.intersect_rational_curve_surface_by_aabb=function(e,r,n,t,i,s,a,u,o,v,l,b){var c=verb.eval.nurbs.rational_curve_adaptive_sample(s,a,u,o,!0),h=verb.eval.nurbs.tesselate_rational_surface_naive(e,r,n,t,i,l,b),_=c.map(function(e){return e[0]}),m=c.map(function(e){return e.slice(1)}),g=verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(m,_,h,verb.range(h.faces.length),v);return verb.unique(g,function(e,r){return v>numeric.norm2(numeric.sub(e.point,r.point))&&v>Math.abs(e.p-r.p)&&v>numeric.norm2(numeric.sub(e.uv,r.uv))})},verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb=function(e,r,n,t,i){var s=new verb.geom.BoundingBox(e),a=verb.eval.mesh.make_mesh_aabb(n.points,n.faces,t);if(!s.intersects(a,i))return[];if(2!==e.length||1!==t.length){if(1===t.length){var u=verb.left(e),o=verb.rightWithPivot(e),v=verb.left(r),l=verb.rightWithPivot(r);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,v,n,t,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,l,n,t,i))}if(2===e.length){var b=verb.eval.mesh.sort_tris_on_longest_axis(a,n.points,n.faces,t),c=verb.left(b),h=verb.right(b);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(e,r,n,c,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(e,r,n,h,i))}var b=verb.eval.mesh.sort_tris_on_longest_axis(a,n.points,n.faces,t),c=verb.left(b),h=verb.right(b),u=verb.left(e),o=verb.rightWithPivot(e),v=verb.left(r),l=verb.rightWithPivot(r);return verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,v,n,c,i).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(u,v,n,h,i)).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,l,n,c,i)).concat(verb.eval.nurbs.intersect_parametric_polyline_mesh_by_aabb(o,l,n,h,i))}var _=verb.eval.geom.intersect_segment_with_tri(e[0],e[1],n.points,n.faces[t[0]]);if(null!=_){var m=_.p*(r[1]-r[0])+r[0],g=n.faces[t][0],d=n.faces[t][1],f=n.faces[t][2],p=n.uvs[g],y=n.uvs[d],x=n.uvs[f],k=numeric.sub(y,p),N=numeric.sub(x,p),E=numeric.add(p,numeric.mul(_.s,k),numeric.mul(_.t,N));return[{point:_.point,p:m,uv:E,face:t[0]}]}return[]},verb.eval.geom.intersect_segment_with_tri=function(e,r,n,t){var i=n[t[0]],s=n[t[1]],a=n[t[2]],u=numeric.sub(s,i),o=numeric.sub(a,i),v=numeric.cross(u,o),l=numeric.sub(r,e),b=numeric.sub(e,i),c=-numeric.dot(v,b),h=numeric.dot(v,l);if(Math.abs(h)_||_>1)return null;var m=numeric.add(e,numeric.mul(_,l)),g=numeric.dot(u,o),d=numeric.dot(u,u),f=numeric.dot(o,o),p=numeric.sub(m,i),y=numeric.dot(p,u),x=numeric.dot(p,o),k=g*g-d*f,N=(g*x-f*y)/k,E=(g*y-d*x)/k;return N>1+verb.EPSILON||E>1+verb.EPSILON||-verb.EPSILON>E||-verb.EPSILON>N||N+E>1+verb.EPSILON?null:{point:m,s:N,t:E,p:_}},verb.eval.geom.intersect_segment_with_plane=function(e,r,n,t){var i=numeric.dot(t,numeric.sub(e,r));if(EPSILON>abs(i))return null;var s=numeric.dot(t,numeric.sub(n,e));return{p:s/i}},verb.eval.geom.intersect_aabb_trees=function(e,r,n,t,i,s){var a=i.bounding_box.intersects(s.bounding_box);return a?0===i.children.length&&0===s.children.length?[[i.triangle,s.triangle]]:0===i.children.length&&0!=s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,n,t,i,s.children[0]).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i,s.children[1])):0!=i.children.length&&0===s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[0],s).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[1],s)):0!=i.children.length&&0!=s.children.length?verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[0],s.children[0]).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[0],s.children[1])).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[1],s.children[0])).concat(verb.eval.geom.intersect_aabb_trees(e,r,n,t,i.children[1],s.children[1])):void 0:[]},verb.eval.mesh.make_mesh_aabb_tree=function(e,r,n){var t={bounding_box:verb.eval.mesh.make_mesh_aabb(e,r,n),children:[]};if(1===n.length)return t.triangle=n[0],t;var i=verb.eval.mesh.sort_tris_on_longest_axis(t.bounding_box,e,r,n),s=i.slice(0,Math.floor(i.length/2)),a=i.slice(Math.floor(i.length/2),i.length);return t.children=[verb.eval.mesh.make_mesh_aabb_tree(e,r,s),verb.eval.mesh.make_mesh_aabb_tree(e,r,a)],t},verb.eval.mesh.make_mesh_aabb=function(e,r,n){var t=new verb.geom.BoundingBox;return n.forEach(function(n){t.add(e[r[n][0]]),t.add(e[r[n][1]]),t.add(e[r[n][2]])}),t},verb.eval.mesh.sort_tris_on_longest_axis=function(e,r,n,t){for(var i=e.get_longest_axis(),s=[],a=t.length-1;a>=0;a--){var u=t[a],o=verb.eval.mesh.get_min_coordinate_on_axis(r,n[u],i);s.push([o,u])}s.sort(function(e,r){return e[0]>r[0]});for(var v=[],a=0,l=s.length;l>a;a++)v.push(s[a][1]);return v},verb.eval.mesh.get_min_coordinate_on_axis=function(e,r,n){for(var t=[],i=0;3>i;i++)t.push(e[r[i]][n]);return Math.min.apply(Math,t)},verb.eval.geom.get_tri_centroid=function(e,r){for(var n=[0,0,0],t=0;3>t;t++)for(var i=0;3>i;i++)n[i]+=e[r[t]][i];for(var t=0;3>t;t++)n[t]/=3;return n},verb.eval.geom.get_tri_norm=function(e,r){var n=e[r[0]],t=e[r[1]],i=e[r[2]],s=numeric.sub(t,n),a=numeric.sub(i,n),u=numeric.cross(s,a);return numeric.mul(1/numeric.norm2(u),u)},verb.eval.nurbs.intersect_rational_curves_by_aabb_refine=function(e,r,n,t,i,s,a,u){var o=verb.eval.nurbs.intersect_rational_curves_by_aabb(e,r,n,t,i,s,a,u);return o.map(function(a){return verb.eval.nurbs.refine_rational_curve_intersection(e,r,n,t,i,s,a)})},verb.eval.nurbs.refine_rational_curve_intersection=function(e,r,n,t,i,s,a){var u=function(a){var u=verb.eval.nurbs.rational_curve_point(e,r,n,a[0]),o=verb.eval.nurbs.rational_curve_point(t,i,s,a[1]),v=numeric.sub(u,o);return numeric.dot(v,v)},o=numeric.uncmin(u,a);return o.solution.concat(o.f)},verb.eval.nurbs.intersect_rational_curves_by_aabb=function(e,r,n,t,i,s,a,u){var o=verb.eval.nurbs.rational_curve_adaptive_sample(e,r,n,a,!0),v=verb.eval.nurbs.rational_curve_adaptive_sample(t,i,s,a,!0),l=o.map(function(e){return e[0]}),b=v.map(function(e){return e[0]}),c=o.map(function(e){return e.slice(1)}),h=v.map(function(e){return e.slice(1)});return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(c,h,l,b,u)},verb.eval.nurbs.intersect_parametric_polylines_by_aabb=function(e,r,n,t,i){var s=new verb.geom.BoundingBox(e),a=new verb.geom.BoundingBox(r);if(!s.intersects(a,i))return[];if(2!==e.length||2!==r.length){if(2===e.length){var u=Math.ceil(r.length/2),o=r.slice(0,u),v=r.slice(u-1),l=t.slice(0,u),b=t.slice(u-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(e,o,n,l,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(e,v,n,b,i))}if(2===r.length){var c=Math.ceil(e.length/2),h=e.slice(0,c),_=e.slice(c-1),m=n.slice(0,c),g=n.slice(c-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,r,m,t,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(_,r,g,t,i))}var c=Math.ceil(e.length/2),h=e.slice(0,c),_=e.slice(c-1),m=n.slice(0,c),g=n.slice(c-1),u=Math.ceil(r.length/2),o=r.slice(0,u),v=r.slice(u-1),l=t.slice(0,u),b=t.slice(u-1);return verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,o,m,l,i).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(h,v,m,b,i)).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(_,o,g,l,i)).concat(verb.eval.nurbs.intersect_parametric_polylines_by_aabb(_,v,g,b,i))}var d=verb.eval.geom.intersect_segments(e[0],e[1],r[0],r[1],i);return null!=d?(d[0][0]=d[0][0]*(n[1]-n[0])+n[0],d[1][0]=d[1][0]*(t[1]-t[0])+t[0],[[d[0][0],d[1][0]]]):[]},verb.eval.geom.intersect_segments=function(e,r,n,t,i){var s=numeric.sub(r,e),a=Math.sqrt(numeric.dot(s,s)),u=numeric.mul(1/a,s),o=numeric.sub(t,n),v=Math.sqrt(numeric.dot(o,o)),l=numeric.mul(1/v,o),b=verb.eval.geom.intersect_rays(e,u,n,l);if(null!=b){var c=Math.min(Math.max(0,b[0]/a),1),h=Math.min(Math.max(0,b[1]/v),1),_=numeric.add(numeric.mul(c,s),e),m=numeric.add(numeric.mul(h,o),n),g=numeric.norm2Squared(numeric.sub(_,m));if(i*i>g)return[[c].concat(_),[h].concat(m)]}return null},verb.eval.geom.closest_point_on_ray=function(e,r,n){var t=numeric.sub(e,r),i=numeric.dot(t,n),s=numeric.add(r,numeric.mul(i,n));return s},verb.eval.geom.intersect_rays=function(e,r,n,t){var i=numeric.dot(r,t),s=numeric.dot(r,n),a=numeric.dot(r,e),u=numeric.dot(t,n),o=numeric.dot(t,e),v=numeric.dot(r,r),l=numeric.dot(t,t),b=v*l-i*i;if(Math.abs(b)g;g++){var d=verb.eval.geom.intersect_segment_with_plane(b[g][0],c[g][1],m,_);d.intersects&&h.push(d)}if(2!==h.length)return null;for(var f=[h[0].point,h[1].point],p=[],g=0;3>g;g++){var y=verb.eval.geom.intersect_segments(f[0],f[1],f,b1,tol);y&&p.push(y)}0===p.length||1===p.length||2===p.length},verb.eval.nurbs.tesselate_rational_surface_naive=function(e,r,n,t,i,s,a){1>s&&(s=1),1>a&&(a=1);for(var u=1/s,o=1/a,v=[],l=[],b=[],c=0;s+1>c;c++)for(var h=0;a+1>h;h++){var _=c*u,m=h*o;l.push([_,m]);var g=verb.eval.nurbs.rational_surface_derivs(e,r,n,t,i,1,_,m),d=g[0][0];v.push(d);var f=numeric.cross(g[0][1],g[1][0]);b.push(f)}for(var p=[],c=0;s>c;c++)for(var h=0;a>h;h++){var y=c*(a+1)+h,x=(c+1)*(a+1)+h,k=x+1,N=y+1,E=[y,x,k],M=[y,k,N];p.push(E),p.push(M)}return{points:v,faces:p,uvs:l,normals:b}},verb.eval.nurbs.rational_curve_regular_sample=function(e,r,n,t,i){return verb.eval.nurbs.rational_curve_regular_sample_range(e,r,n,0,1,t,i)},verb.eval.nurbs.rational_curve_regular_sample_range=function(e,r,n,t,i,s,a){1>s&&(s=2);for(var u=[],o=(i-t)/(s-1),v=0,l=0;s>l;l++)v=t+o*l,a?u.push([v].concat(verb.eval.nurbs.rational_curve_point(e,r,n,v))):u.push(verb.eval.nurbs.rational_curve_point(e,r,n,v));return u},verb.eval.nurbs.rational_curve_adaptive_sample=function(e,r,n,t,i){return 1===e?i?n.map(function(e,n){return[r[n+1]].concat(verb.eval.nurbs.dehomogenize(e))}):n.map(verb.eval.nurbs.dehomogenize):verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,n,0,1,t,i)},verb.eval.nurbs.rational_curve_adaptive_sample_range=function(e,r,n,t,i,s,a){var u=verb.eval.nurbs.rational_curve_point(e,r,n,t),o=verb.eval.nurbs.rational_curve_point(e,r,n,i),v=.5+.2*Math.random(),l=t+(i-t)*v,b=verb.eval.nurbs.rational_curve_point(e,r,n,l),c=numeric.sub(u,o),h=numeric.sub(u,b);if(s>numeric.dot(c,c)&&numeric.dot(h,h)>s||!verb.eval.nurbs.three_points_are_flat(u,b,o,s)){var _=t+.5*(i-t),m=verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,n,t,_,s,a),g=verb.eval.nurbs.rational_curve_adaptive_sample_range(e,r,n,_,i,s,a);return m.slice(0,-1).concat(g)}return a?[[t].concat(u),[i].concat(o)]:[u,o]},verb.eval.nurbs.three_points_are_flat=function(e,r,n,t){var i=numeric.sub(r,e),s=numeric.sub(n,e),a=crossprod(i,s),u=numeric.dot(a,a);return t>u},verb.eval.nurbs.divide_rational_surface_adaptive=function(e,r,n,t,i,s){for(var a={degree_u:e,knots_u:r,degree_v:n,knots_v:t,homo_control_points:i},u=s.minDivsU,o=s.minDivsV,v=Math.max.apply(null,r),l=Math.min.apply(null,r),b=Math.max.apply(null,t),c=Math.min.apply(null,t),h=(v-l)/u,_=(b-c)/o,m=[],g=0;u>g;g++)for(var d=0;o>d;d++){var f=l+h*g,p=l+h*(g+1),y=c+_*d,x=c+_*(d+1);m.push(new verb.eval.nurbs.AdaptiveRefinementNode(a,f,p,y,x,null,null))}for(var g=0;u>g;g++)for(var d=0;o>d;d++){var k=g*o+d,N=getNorthNeighbor(k,g,d,u,o,m),E=getEastNeighbor(k,g,d,u,o,m),M=getSouthNeighbor(k,g,d,u,o,m),w=getWestNeighbor(k,g,d,u,o,m);m[k].neighbors=[N,E,M,w],m.divide(s)}return m},verb.eval.nurbs.is_rational_surface_domain_flat=function(e){var r=verb.eval.nurbs.rational_surface_point,n=(u[1]-u[0]/2)*(.1*Math.random()+1),t=(v[1]-v[0]/2)*(.1*Math.random()+1),i=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[0],v[0]),s=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[0]+n,v[0]+t),a=r(e.degree_u,e.knots_u,e.degree_v,e.knots_v,e.homo_control_points,u[1],v[1]);return verb.eval.nurbs.three_points_are_flat(i,s,a,tol)},verb.eval.nurbs.triangulate_adaptive_refinement_node_tree=function(e){var r={uvs:[],points:[],normals:[],faces:[]};return r.faces=e.map(function(e){e.triangulate(r)}).flatten(),r},verb.eval.nurbs.tesselate_rational_surface_adaptive=function(e,r,n,t,i,s){verb.eval.nurbs.divide_rational_surface_adaptive(e,r,n,t,i,s);var a=verb.eval.nurbs.triangulate_adaptive_refinement_node_tree(arrTree);return verb.eval.nurbs.unique_mesh(a)},verb.eval.nurbs.unique_mesh=function(e){return e},Array.prototype.where=function(e){if(0===this.length)return this;for(var r=[],n=0;this.length>n;n++)e(this[n])&&r.push(this[n]);return r},verb.eval.nurbs.AdaptiveRefinementNode=function(e,r,n,t,i,s,a){this.srf=e,this.u0=r,this.u1=n,this.v0=t,this.v1=i,this.parentNode=s,this.neighbors=a,this.leafEdgeUvs=[[r,t],[n,t],[n,i],[r,i]],this.cachedEdgeUvs=[]},verb.eval.nurbs.AdaptiveRefinementNode.prototype.isLeaf=function(){return void 0===this.children},verb.eval.nurbs.AdaptiveRefinementNode.prototype.evalSurface=function(){var e=verb.eval.nurbs.rational_surface_derivs(this.srf.degree_u,this.srf.knots_u,this.srf.degree_v,this.srf.knots_v,this.srf.homo_control_points,1,pt_u,pt_v),r=e[0][0];points.push(r);var n=numeric.cross(e[0][1],e[1][0]);return{point:r,normal:n}},verb.eval.nurbs.AdaptiveRefinementNode.prototype.getEdgeUvs=function(e){return this.isLeaf()?[this.leafEdgeUvs[e]]:(this.cachedEdgeUvs[e]=this.cachedEdgeUvs[e]||this.children[e].getEdgeUvs(e).concat(this.children[(e+1)%4].getEdgeUvs(e)),this.cachedEdgeUvs[e])},verb.eval.nurbs.AdaptiveRefinementNode.prototype.getAllEdgeUvs=function(e){var r=[this.leafEdgeUvs[e]];if(null===this.neighbors[e])return r;var n=this.neighbors[e].getEdgeUvs((e+2)%4),t=e%2,i=this,s=[function(e){return e[0]>i.u0+verb.EPSILON&&e[0]i.v0+verb.EPSILON&&e[1]t;t++)n.concat(this.getAllEdgeUvs(t));if(n.forEach(function(r){e.uvs.push(r);var n=this.evalSurface(r);e.points.push(n.point),e.normals.push(n.normal)}),4===n.length)return e.faces.push([r+1,r+4,r+2]),e.faces.push([r+4,r+3,r+2]),void 0;this.u05=this.u05||(this.u0+this.u1)/2,this.v05=this.v05||(this.v0+this.v1)/2,e.uvs.push([this.u05,this.v05]);var i=this.evalSurface([this.u05,this.v05]);e.points.push(i.point),e.normals.push(i.normal);for(var s=e.points.length-1,t=0;n.length>t;t++)e.faces.push([s,(r+t+2)%n.length,(r+t+1)%n.length])},verb.eval.nurbs.AdaptiveRefinementNode.prototype.triangulate=function(e){return this.isLeaf()?this.triangulateLeaf(e):(this.children.forEach(function(r){null!==r&&r.triangulate(e)}),void 0)},verb.eval.nurbs.AdaptiveRefinementNode.prototype.shouldDivide=function(e,r){return e.minDepth&&e.minDepth>r?!0:this.srf&&!verb.eval.nurbs.is_rational_surface_domain_flat(this.srf,this.u0,this.u1,this.v0,this.v1,e)?!0:!1},verb.eval.nurbs.AdaptiveRefinementNode.prototype.divide=function(e,r){void 0===r&&(r=0),this.shouldDivide(e,r)&&(r++,this.u05=(this.u0+this.u1)/2,this.v05=(this.v0+this.v1)/2,this.children=[new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u0,this.u05,this.v0,this.v05,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u05,this.u1,this.v0,this.v05,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u05,this.u1,this.v05,this.v1,this),new verb.eval.nurbs.AdaptiveRefinementNode(this.srf,this.u0,this.u05,this.v05,this.v1,this)],this.children[0].neighbors=[this.neighbors[0],this.children[1],this.children[3],this.neighbors[3]],this.children[1].neighbors=[this.neighbors[0],this.neighbors[1],this.children[2],this.children[0]],this.children[2].neighbors=[this.children[1],this.neighbors[1],this.neighbors[2],this.children[3]],this.children[3].neighbors=[this.children[0],this.children[2],this.neighbors[2],this.neighbors[3]],this.children.forEach(function(n){n.divide(e,r)}))},verb.eval.nurbs.get_sweep1_surface=function(e,r,n,t,i,s,a,u){for(var o=verb.eval.nurbs.homogenize_1d(a,u),v=verb.eval.nurbs.rational_curve_point(s,i,o,0),l=1/a.length,b=[],c=[],h=0;a.length>h;h++){for(var _=verb.eval.nurbs.rational_curve_point(s,i,o,h*l),m=numeric.sub(_,v),g=[],d=[],f=0;n.length>f;f++)g.push(numeric.add(m,n[f])),d.push(t[f]*u[h]);b.push(g),c.push(d)}return{knots_u:i,knots_v:e,control_points:b,degree_u:s,degree_v:r,weights:c}},verb.eval.nurbs.get_ellipse_arc=function(e,r,n,t,i,s,a){s>a&&(a=2*Math.PI+s);var u=a-s,o=0;o=Math.PI/2>=u?1:Math.PI>=u?2:3*Math.PI/2>=u?3:4;var v=u/o,l=Math.cos(v/2),b=numeric.add(e,numeric.mul(t,Math.cos(s),r),numeric.mul(i,Math.sin(s),n)),c=numeric.sub(numeric.mul(Math.cos(s),n),numeric.mul(Math.sin(s),r)),h=verb.eval.nurbs.zeros_1d(2*o),_=verb.eval.nurbs.zeros_1d(2*o+3),m=0,g=s,d=verb.eval.nurbs.zeros_1d(2*o);h[0]=b,d[0]=1;for(var f=1;o>=f;f++){g+=v;var p=numeric.add(e,numeric.mul(t,Math.cos(g),r),numeric.mul(i,Math.sin(g),n));d[m+2]=1,h[m+2]=p;var y=numeric.sub(numeric.mul(Math.cos(g),n),numeric.mul(Math.sin(g),r)),x=verb.eval.geom.intersect_rays(b,numeric.mul(1/numeric.norm2(c),c),p,numeric.mul(1/numeric.norm2(y),y)),k=numeric.add(b,numeric.mul(c,x[0]));d[m+1]=l,h[m+1]=k,m+=2,o>f&&(b=p,c=y)}for(var N=2*o+1,f=0;3>f;f++)_[f]=0,_[f+N]=1;switch(o){case 1:break;case 2:_[3]=_[4]=.5;break;case 3:_[3]=_[4]=1/3,_[5]=_[6]=2/3;break;case 4:_[3]=_[4]=.25,_[5]=_[6]=.5,_[7]=_[8]=.75}return{knots:_,control_points:h,degree:2,weights:d}},verb.eval.nurbs.get_sphere_surface=function(e,r,n,t){var i=verb.eval.nurbs.get_arc(e,numeric.mul(r,-1),n,t,0,Math.PI);return verb.eval.nurbs.get_revolved_surface(e,r,2*Math.PI,i.knots,i.degree,i.control_points,i.weights)},verb.eval.nurbs.get_polyline_curve=function(e){for(var r=e.length-1,n=1/r,t=[0,0],i=1;r>i;i++)t.push(i*n);t.push(1),t.push(1);for(var s=[],i=0;e.length>i;i++)s.push(1);return{knots:t,control_points:e.slice(0),degree:1,weights:s}},verb.eval.nurbs.get_4pt_surface=function(e,r,n,t){var i=numeric.mul(.5,numeric.add(e,t)),s=numeric.mul(.5,numeric.add(r,n)),a=numeric.mul(.5,numeric.add(n,t)),u=numeric.mul(.5,numeric.add(e,r)),o=numeric.mul(.5,numeric.add(i,s));return{knots_u:[0,0,0,1,1,1],knots_v:[0,0,0,1,1,1],control_points:[[e,i,t],[u,o,a],[r,s,n]],degree_u:2,degree_v:2,weights:[[1,1,1],[1,1,1],[1,1,1]]}},verb.eval.nurbs.get_cylinder_surface=function(e,r,n,t,i){var s=crossprod(e,r),a=(2*Math.PI,verb.eval.nurbs.get_arc(n,r,s,i,0,2*Math.PI));return verb.eval.nurbs.get_extruded_surface(e,t,a.knots,a.degree,a.control_points,a.weights)},verb.eval.nurbs.get_cone_surface=function(e,r,n,t,i){var s=2*Math.PI,a=1,u=[numeric.add(n,numeric.mul(t,e)),numeric.add(n,numeric.mul(i,r))],o=[0,0,1,1],v=[1,1];return verb.eval.nurbs.get_revolved_surface(n,e,s,o,a,u,v)},verb.eval.nurbs.get_extruded_surface=function(e,r,n,t,i,s){for(var a=verb.eval.nurbs.zeros_2d(3,i.length),u=verb.eval.nurbs.zeros_2d(3,i.length),o=numeric.mul(e,r),v=numeric.mul(e,.5*r),l=0;i.length>l;l++)a[0][l]=i[l],a[1][l]=numeric.add(v,i[l]),a[2][l]=numeric.add(o,i[l]),u[0][l]=s[l],u[1][l]=s[l],u[2][l]=s[l];return{knots_u:[0,0,0,1,1,1],knots_v:n,control_points:a,degree_u:2,degree_v:t,weights:u}},verb.eval.nurbs.get_revolved_surface=function(e,r,n,t,i,s,a){var u,o,v,l;Math.PI/2>=n?(u=1,o=verb.eval.nurbs.zeros_1d(6+2*(u-1))):Math.PI>=n?(u=2,o=verb.eval.nurbs.zeros_1d(6+2*(u-1)),o[3]=o[4]=.5):3*Math.PI/2>=n?(u=3,o=verb.eval.nurbs.zeros_1d(6+2*(u-1)),o[3]=o[4]=1/3,o[5]=o[6]=2/3):(u=4,o=verb.eval.nurbs.zeros_1d(6+2*(u-1)),o[3]=o[4]=.25,o[5]=o[6]=.5,o[7]=o[8]=.75);for(var b=n/u,c=3+2*(u-1),h=0;3>h;c++,h++)o[h]=0,o[c]=1;for(var _=Math.cos(b/2),m=0,g=verb.eval.nurbs.zeros_1d(u+1),d=verb.eval.nurbs.zeros_1d(u+1),v=verb.eval.nurbs.zeros_2d(2*u+1,s.length),l=verb.eval.nurbs.zeros_2d(2*u+1,s.length),h=1;u>=h;h++)m+=b,d[h]=Math.cos(m),g[h]=Math.sin(m);for(c=0;s.length>c;c++){var f=verb.eval.geom.closest_point_on_ray(s[c],e,r),p=numeric.sub(s[c],f),y=numeric.norm2(p),x=crossprod(r,p);y>verb.EPSILON&&(p=numeric.mul(1/y,p),x=numeric.mul(1/y,x)),v[0][c]=s[c];var k=s[c];l[0][c]=a[c];for(var N=x,E=0,m=0,h=1;u>=h;h++){var M=0==y?f:numeric.add(f,numeric.mul(y,d[h],p),numeric.mul(y,g[h],x));v[E+2][c]=M,l[E+2][c]=a[c];var w=numeric.sub(numeric.mul(d[h],x),numeric.mul(g[h],p));if(0==y)v[E+1][c]=f;else{var z=verb.eval.geom.intersect_rays(k,numeric.mul(1/numeric.norm2(N),N),M,numeric.mul(1/numeric.norm2(w),w)),A=numeric.add(k,numeric.mul(N,z[0]));v[E+1][c]=A}l[E+1][c]=_*a[c],E+=2,u>h&&(k=M,N=w)}}return{knots_u:o,knots_v:t,control_points:v,degree_u:2,degree_v:i,weights:l}},verb.eval.nurbs.get_arc=function(e,r,n,t,i,s){return verb.eval.nurbs.get_ellipse_arc(e,r,n,t,t,i,s)},verb.eval.nurbs.rational_surface_curvature=function(e,r,n,t,i,s,a){var u=verb.eval.nurbs.rational_surface_derivs(e,r,n,t,i,2,s,a);console.log(u);var o=u[0][1],v=u[1][0],l=u[0][2],b=u[2][0],c=u[1][1],h=numeric.cross(o,v),_=numeric.dot(l,h),m=numeric.dot(c,h),g=numeric.dot(b,h),d=[[_,m],[m,g]],f=numeric.eig(d),p=f.lambda.x[0],y=f.lambda.x[1],x=.5*(p+y),k=p*y,N=numeric.add(numeric.mul(f.E.x[0][0],o),numeric.mul(f.E.x[0][1],v)),E=numeric.add(numeric.mul(f.E.x[1][0],o),numeric.mul(f.E.x[1][1],v));return{point:u[0][0],normal:h,mean:x,gaussian:k,shapeOperator:d,k1:p,k2:y,p1:N,p2:E,p1p:f.E.x[0],p2p:f.E.x[1]}},verb.eval.nurbs.curve_knot_insert=function(e,r,n,t,i){var s=0,a=(n[0].length,n.length),u=verb.eval.nurbs.knot_span(e,t,r),o=(r.length,a+i),v=Array(e-s),l=Array(r.length+i),b=Array(o),c=0;for(c=0;u>=c;c++)l[c]=r[c];for(c=1;i>=c;c++)l[u+c]=t;for(c=u+1;r.length>c;c++)l[c+i]=r[c];for(c=0;u-e>=c;c++)b[c]=n[c];for(c=u-s;a>c;c++)b[c+i]=n[c];for(c=0;e-s>=c;c++)v[c]=n[u-e+c];for(var h=0,_=0,m=1;i>=m;m++){for(h=u-e+m,c=0;e-m-s>=c;c++)_=(t-r[h+c])/(r[c+u+1]-r[h+c]),v[c]=numeric.add(numeric.mul(_,v[c+1]),numeric.mul(1-_,v[c]));b[h]=v[0],b[u+i-m-s]=v[e-m-s]}for(c=h+1;u-s>c;c++)b[c]=v[c-h];return{knots:l,control_points:b}},verb.eval.nurbs.rational_surface_derivs=function(e,r,n,t,i,s,a,u){var o=verb.eval.nurbs.surface_derivs(e,r,n,t,i,s,a,u),v=verb.eval.nurbs.separate_homo_derivs_2d(o),l=v[0],b=v[1],c=0,h=0,_=0,m=0,g=[],d=l[0][0].length;for(c=0;s>=c;c++)for(g.push([]),m=0;s-c>=m;m++){var u=l[c][m];for(_=1;m>=_;_++)u=numeric.sub(u,numeric.mul(numeric.mul(binomial.get(m,_),b[0][_]),g[c][m-_]));for(h=1;c>=h;h++){u=numeric.sub(u,numeric.mul(numeric.mul(binomial.get(c,h),b[h][0]),g[c-h][m]));var f=verb.eval.nurbs.zeros_1d(d);for(_=1;m>=_;_++)f=numeric.add(f,numeric.mul(numeric.mul(binomial.get(m,_),b[h][_]),g[c-h][m-_]));u=numeric.sub(u,numeric.mul(binomial.get(c,h),f))}g[c].push(numeric.mul(1/b[0][0],u))}return g},verb.eval.nurbs.rational_surface_point=function(e,r,n,t,i,s,a){return verb.eval.nurbs.dehomogenize(verb.eval.nurbs.surface_point(e,r,n,t,i,s,a))},verb.eval.nurbs.rational_curve_derivs=function(e,r,n,t,i){var s=verb.eval.nurbs.separate_homo_derivs_1d(verb.eval.nurbs.curve_derivs(e,r,n,t,i)),a=s[0],u=s[1],o=0,v=0,l=[];for(o=0;i>=o;o++){var b=a[o];for(v=1;o>=v;v++)b=numeric.sub(b,numeric.mul(numeric.mul(binomial.get(o,v),u[v]),l[o-v]));l.push(numeric.mul(1/u[0],b))}return l},verb.eval.nurbs.separate_homo_derivs_1d=function(e){for(var r=e[0].length,n=r-1,t=[],i=[],s=0,a=e.length;a>s;s++)t.push(e[s].slice(0,n)),i.push(e[s][n]);return[t,i]},verb.eval.nurbs.separate_homo_derivs_2d=function(e){for(var r=[],n=[],t=0,i=e.length;i>t;t++){var s=verb.eval.nurbs.separate_homo_derivs_1d(e[t]);r.push(s[0]),n.push(s[1])}return[r,n]},verb.eval.nurbs.rational_curve_point=function(e,r,n,t){return verb.eval.nurbs.dehomogenize(verb.eval.nurbs.curve_point(e,r,n,t))},verb.eval.nurbs.dehomogenize=function(e){for(var r=e.length,n=[],t=e[r-1],i=0;e.length-1>i;i++)n.push(e[i]/t);return n},verb.eval.nurbs.homogenize_1d=function(e,r){for(var n=e.length,t=e[0].length,i=0,s=[],a=0,u=[],o=0;n>o;o++){var v=[];for(u=e[o],a=r[o],i=0;t>i;i++)v.push(u[i]*a);v.push(a),s.push(v)}return s},verb.eval.nurbs.homogenize_2d=function(e,r){for(var n=e.length,t=(e[0].length,e[0][0].length,[]),i=0;n>i;i++)t.push(verb.eval.nurbs.homogenize_1d(e[i],r[i]));return t},verb.eval.nurbs.surface_derivs=function(e,r,n,t,i,s,a,u){var o=r.length-e-2,v=t.length-n-2;return verb.eval.nurbs.surface_derivs_given_n_m(o,e,r,v,n,t,i,s,a,u)},verb.eval.nurbs.surface_derivs_given_n_m=function(e,r,n,t,i,s,a,u,o,v){if(verb.eval.nurbs.are_valid_relations(r,a.length,n.length)===!1||verb.eval.nurbs.are_valid_relations(i,a[0].length,s.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var l=a[0][0].length,b=Math.min(u,r),c=Math.min(u,i),h=verb.eval.nurbs.zeros_3d(b+1,c+1,l),_=verb.eval.nurbs.knot_span_given_n(e,r,o,n),m=verb.eval.nurbs.knot_span_given_n(t,i,v,s),g=verb.eval.nurbs.deriv_basis_functions_given_n_i(_,o,r,e,n),d=verb.eval.nurbs.deriv_basis_functions_given_n_i(m,v,i,t,s),f=verb.eval.nurbs.zeros_2d(i+1,l),p=0,y=0,x=0,k=0,N=0;for(p=0;b>=p;p++){for(y=0;i>=y;y++)for(f[y]=verb.eval.nurbs.zeros_1d(l),x=0;r>=x;x++)f[y]=numeric.add(f[y],numeric.mul(g[p][x],a[_-r+x][m-i+y]));for(N=Math.min(u-p,c),k=0;N>=k;k++)for(h[p][k]=verb.eval.nurbs.zeros_1d(l),y=0;i>=y;y++)h[p][k]=numeric.add(h[p][k],numeric.mul(d[k][y],f[y]))}return h},verb.eval.nurbs.surface_point=function(e,r,n,t,i,s,a){var u=r.length-e-2,o=t.length-n-2;return verb.eval.nurbs.surface_point_given_n_m(u,e,r,o,n,t,i,s,a)},verb.eval.nurbs.volume_point=function(e,r,n,t,i,s,a,u,o,v){var l=r.length-e-2,b=t.length-n-2,c=s.length-i-2;return verb.eval.nurbs.volume_point_given_n_m_l(l,e,r,b,n,t,c,i,s,a,u,o,v)},verb.eval.nurbs.volume_point_given_n_m_l=function(e,r,n,t,i,s,a,u,o,v,l,b,c){if(!verb.eval.nurbs.are_valid_relations(r,v.length,n.length)||!verb.eval.nurbs.are_valid_relations(i,v[0].length,s.length)||!verb.eval.nurbs.are_valid_relations(u,v[0][0].length,o.length))return console.error("Invalid relations between control points and knot vector"),null;for(var h=v[0][0][0].length,_=verb.eval.nurbs.knot_span_given_n(e,r,l,n),m=verb.eval.nurbs.knot_span_given_n(t,i,b,s),g=verb.eval.nurbs.knot_span_given_n(a,u,c,o),d=verb.eval.nurbs.basis_functions_given_knot_span_index(_,l,r,n),f=verb.eval.nurbs.basis_functions_given_knot_span_index(m,b,i,s),p=verb.eval.nurbs.basis_functions_given_knot_span_index(g,c,u,o),y=_-r,x=m,k=g,N=verb.eval.nurbs.zeros_1d(h),E=verb.eval.nurbs.zeros_1d(h),M=verb.eval.nurbs.zeros_1d(h),w=0,z=0,A=0;u>=A;A++){for(M=verb.eval.nurbs.zeros_1d(h),k=g-u+A,w=0;i>=w;w++){for(E=verb.eval.nurbs.zeros_1d(h),x=m-i+w,z=0;r>=z;z++)E=numeric.add(E,numeric.mul(d[z],v[y+z][x][k]));M=numeric.add(M,numeric.mul(f[w],E))}N=numeric.add(N,numeric.mul(p[A],M))}return N},verb.eval.nurbs.surface_point_given_n_m=function(e,r,n,t,i,s,a,u,o){if(verb.eval.nurbs.are_valid_relations(r,a.length,n.length)===!1||verb.eval.nurbs.are_valid_relations(i,a[0].length,s.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var v=a[0][0].length,l=verb.eval.nurbs.knot_span_given_n(e,r,u,n),b=verb.eval.nurbs.knot_span_given_n(t,i,o,s),c=verb.eval.nurbs.basis_functions_given_knot_span_index(l,u,r,n),h=verb.eval.nurbs.basis_functions_given_knot_span_index(b,o,i,s),_=l-r,m=b,g=verb.eval.nurbs.zeros_1d(v),d=verb.eval.nurbs.zeros_1d(v),f=0,p=0;for(f=0;i>=f;f++){for(d=verb.eval.nurbs.zeros_1d(v),m=b-i+f,p=0;r>=p;p++)d=numeric.add(d,numeric.mul(c[p],a[_+p][m]));g=numeric.add(g,numeric.mul(h[f],d))}return g},verb.eval.nurbs.curve_derivs=function(e,r,n,t,i){var s=r.length-e-2;return verb.eval.nurbs.curve_derivs_given_n(s,e,r,n,t,i)},verb.eval.nurbs.curve_derivs_given_n=function(e,r,n,t,i,s){if(verb.eval.nurbs.are_valid_relations(r,t.length,n.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;var a=t[0].length,u=Math.min(s,r),o=verb.eval.nurbs.zeros_2d(u+1,a),v=verb.eval.nurbs.knot_span_given_n(e,r,i,n),l=verb.eval.nurbs.deriv_basis_functions_given_n_i(v,i,r,u,n),b=0,c=0;for(b=0;u>=b;b++)for(c=0;r>=c;c++)o[b]=numeric.add(o[b],numeric.mul(l[b][c],t[v-r+c]));return o},verb.eval.nurbs.are_valid_relations=function(e,r,n){return 0===r+e+1-n?!0:!1},verb.eval.nurbs.curve_point=function(e,r,n,t){var i=r.length-e-2;return verb.eval.nurbs.curve_point_given_n(i,e,r,n,t)},verb.eval.nurbs.curve_point_given_n=function(e,r,n,t,i){if(verb.eval.nurbs.are_valid_relations(r,t.length,n.length)===!1)return console.error("Invalid relations between control points, knot vector, and n"),null;for(var s=verb.eval.nurbs.knot_span_given_n(e,r,i,n),a=verb.eval.nurbs.basis_functions_given_knot_span_index(s,i,r,n),u=verb.eval.nurbs.zeros_1d(t[0].length),o=0;r>=o;o++)u=numeric.add(u,numeric.mul(a[o],t[s-r+o]));return u},verb.eval.nurbs.zeros_1d=function(e){e=e>0?e:0;for(var r=[];e--;)r.push(0);return r},verb.eval.nurbs.zeros_2d=function(e,r){r=r>0?r:0,e=e>0?e:0;for(var n=[],t=r,i=e;e--;){for(n.push([]);t--;)n[i-e-1].push(0);t=r}return n},verb.eval.nurbs.zeros_3d=function(e,r,n){r=r>0?r:0,e=e>0?e:0;for(var t=[],i=r,s=e;e--;){for(t.push([]);i--;)t[s-e-1].push(verb.eval.nurbs.zeros_1d(n));i=r}return t},verb.eval.nurbs.deriv_basis_functions=function(e,r,n){var t=verb.eval.nurbs.knot_span(r,e,n),i=n.length-1,s=i-r-1;return verb.eval.nurbs.deriv_basis_functions_given_n_i(t,e,r,s,n)},verb.eval.nurbs.deriv_basis_functions_given_n_i=function(e,r,n,t,i){var s=verb.eval.nurbs.zeros_2d(n+1,n+1),a=Array(n+1),u=Array(n+1),o=0,v=0,l=1,b=0;for(s[0][0]=1,l=1;n>=l;l++){for(a[l]=r-i[e+1-l],u[l]=i[e+l]-r,o=0,b=0;l>b;b++)s[l][b]=u[b+1]+a[l-b],v=s[b][l-1]/s[l][b],s[b][l]=o+u[b+1]*v,o=a[l-b]*v;s[l][l]=o}var c=verb.eval.nurbs.zeros_2d(t+1,n+1),h=verb.eval.nurbs.zeros_2d(2,n+1),_=1,m=0,g=1,d=0,f=0,p=0,y=0,x=0;for(l=0;n>=l;l++)c[0][l]=s[l][n]; +for(b=0;n>=b;b++)for(m=0,g=1,h[0][0]=1,_=1;t>=_;_++){for(d=0,f=b-_,p=n-_,b>=_&&(h[g][0]=h[m][0]/s[p+1][f],d=h[g][0]*s[f][p]),y=f>=-1?1:-f,x=p>=b-1?_-1:n-b,l=y;x>=l;l++)h[g][l]=(h[m][l]-h[m][l-1])/s[p+1][f+l],d+=h[g][l]*s[f+l][p];p>=b&&(h[g][_]=-h[m][_-1]/s[p+1][b],d+=h[g][_]*s[b][p]),c[_][b]=d,l=m,m=g,g=l}for(b=n,_=1;t>=_;_++){for(l=0;n>=l;l++)c[_][l]*=b;b*=n-_}return c},verb.eval.nurbs.basis_functions=function(e,r,n){var t=verb.eval.nurbs.knot_span(e,r,n);return verb.eval.nurbs.basis_functions_given_knot_span_index(t,e,r,n)},verb.eval.nurbs.basis_functions_given_knot_span_index=function(e,r,n,t){var i=Array(n+1),s=Array(n+1),a=Array(n+1),u=0,o=0;i[0]=1;for(var v=1;n>=v;v++){s[v]=r-t[e+1-v],a[v]=t[e+v]-r,u=0;for(var l=0;v>l;l++)o=i[l]/(a[l+1]+s[v-l]),i[l]=u+a[l+1]*o,u=s[v-l]*o;i[v]=u}return i},verb.eval.nurbs.knot_span=function(e,r,n){var t=n.length-1,i=t-e-1;return verb.eval.nurbs.knot_span_given_n(i,e,r,n)},verb.eval.nurbs.knot_span_given_n=function(e,r,n,t){if(n>=t[e+1])return e;if(t[r]>n)return r;for(var i=r,s=e+1,a=Math.floor((i+s)/2);t[a]>n||n>=t[a+1];)t[a]>n?s=a:i=a,a=Math.floor((i+s)/2);return a}; \ No newline at end of file diff --git a/docs/verb.html b/docs/verb.html index 541e1eef..4cd4c36a 100644 --- a/docs/verb.html +++ b/docs/verb.html @@ -6371,12 +6371,22 @@

get_4pt_surface( p1, p2, p3, p4 )

verb.eval.nurbs.get_4pt_surface = function( p1, p2, p3, p4 ){
 
-	return {"knots_u": [0,0,1,1], 
-			"knots_v": [0,0,1,1], 
-			"control_points": [ [p1, p4], [p2, p3] ], 
-			"degree_u": 1, 
-			"degree_v": 1,
-			"weights": [ [1, 1], [1, 1] ] };
+	var p1p4 = numeric.mul( 0.5, numeric.add( p1, p4 ));
+	var p2p3 = numeric.mul( 0.5, numeric.add( p2, p3 ));
+	var p3p4 = numeric.mul( 0.5, numeric.add( p3, p4 ));
+	var p1p2 = numeric.mul( 0.5, numeric.add( p1, p2 ));
+	var p1p4p2p3 = numeric.mul( 0.5, numeric.add( p1p4, p2p3 ));
+
+	return {"knots_u": [0,0,0,1,1,1], 
+			"knots_v": [0,0,0,1,1,1], 
+			"control_points": [ [p1, 		p1p4, 		p4], 
+													[p1p2, 	p1p4p2p3, p3p4], 
+													[p2, 		p2p3, 		p3] ], 
+			"degree_u": 2, 
+			"degree_v": 2,
+			"weights": [ [ 1, 1, 1], 
+									 [ 1, 1, 1], 
+									 [ 1, 1, 1] ] };
 			
 }
@@ -6916,18 +6926,18 @@

get_arc( cente
-

curve_knot_insert( degree, knots, control_points, u, s, r )

-

Insert a knot along a rational curve

+

surface_curvature( degree_u, knots_u, degree_v, knots_v, control_points, u, v, options )

+

Compute the gaussian curvature on a non-uniform, non-rational B spline surface

params

  • Number, integer degree of surface in u direction
  • Array, array of nondecreasing knot values in u direction
  • Number, integer degree of surface in v direction
  • Array, array of nondecreasing knot values in v direction
  • -
  • Array, 3d array of control points, where rows are the u dir, and columns run along the positive v direction, and where each control point is an array of length (dim)
  • +
  • Array, 3d array of control points, where rows are the u dir, and columns run alonsg the positive v direction, +and where each control point is an array of length (dim)
  • Number, u parameter at which to evaluate the derivatives
  • Number, v parameter at which to evaluate the derivatives
  • -
  • Array, 1d array of control point weights

returns

    @@ -6936,7 +6946,7 @@

    curve_knot_insert( -
    verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, s, r ) {
    +
    verb.eval.nurbs.rational_surface_curvature = function( degree_u, knots_u, degree_v, knots_v, homo_control_points, u, v ) {
    @@ -6947,80 +6957,254 @@

    curve_knot_insert(
    -

    np is n for the initial curve -nq is n for the output curve with knots inserted +

    compute the first fundamental form

    +

    symmetric matrix where

    +

    I = [ E F; F G ]

    +

    where:

    +

    E = Xu Xu +F = Xu Xv +G = Xv * Xv

    +

    second fundamental form (shape operator)

    +

    symmetric matrix where

    +

    II = [ L M; M N ]

    +

    where:

    +

    L = Xuu n +M = Xuv n +N = Xvv * n

    +

    principal curvatures are the eigenvalues of the second fundamental form

    + + + +
    	var derivs = verb.eval.nurbs.rational_surface_derivs( 	degree_u, 
    +															knots_u, 
    +															degree_v, 
    +															knots_v, 
    +															homo_control_points, 
    +															2, u, v );
    +
    +	console.log(derivs)
    + + + + +
  • +
    + +
    + +
    +

    structure of the derivatives

    +

    pos du vuu +dv duv +dvv

    + +
    + +
     
    +  var du = derivs[0][1];
    +  var dv = derivs[1][0];
    +  var duu = derivs[0][2];
    +  var dvv = derivs[2][0];
    +  var duv = derivs[1][1];
    +
    +  var n = numeric.cross( du, dv );
    +  var L = numeric.dot( duu, n );
    +  var M = numeric.dot( duv, n );
    +  var N = numeric.dot( dvv, n );
    +
    +  var shapeOperator = [ [ L, M ], [ M, N ] ];
    +
    +	var eigs = numeric.eig( shapeOperator );
    + +
  • + + +
  • +
    + +
    + +
    +

    contains: lambda - x + E - x

    + +
    + +
    	
    +	var k1 = eigs.lambda.x[0];
    +	var k2 = eigs.lambda.x[1];
    +	var mean = 0.5 * ( k1 + k2 );
    +	var gaussian = k1 * k2;
    +	var p1 = numeric.add( numeric.mul( eigs.E.x[0][0], du ), numeric.mul( eigs.E.x[0][1], dv ) );
    +	var p2 = numeric.add( numeric.mul( eigs.E.x[1][0], du ), numeric.mul( eigs.E.x[1][1], dv ) );
    +
    +	return { point: derivs[0][0], normal: n, mean: mean, gaussian: gaussian, shapeOperator: shapeOperator, k1: k1, k2: k2, p1: p1, p2: p2, p1p : eigs.E.x[0], p2p: eigs.E.x[1]  };
    +
    +};
    + +
  • + + +
  • +
    + +
    + +
    +

    curve_knot_insert( degree, knots, control_points, u, s, r )

    +

    Insert a knot along a rational curve

    +

    params

    +
      +
    • Number, integer degree
    • +
    • Array, array of nondecreasing knot values
    • +
    • Array, array of control points
    • +
    • Number, parameter at which to insert the knot
    • +
    • Number, initial multiplicity of the knot
    • +
    • Number, number of times to insert the knot
    • +
    +

    returns

    +
      +
    • Object the new curve, defined by degree, knots, and control_points
    • +
    + +
    + +
    verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, r ) {
    + +
  • + + +
  • +
    + +
    + +
    +

    num_pts is num control points for the initial curve +nq is num control points for the output curve with knots inserted k is the span on which the knots are inserted -s is the initial multiplicity of the point +s is the initial multiplicity of the knot r is the number of times to insert the knot control_points is initial set of control points

    -
    	var dim = control_points[0].length
    -		, np = knots.length - degree - 2
    +            
    	var s = 0; // assume original multiplicity is 0 - TODO add check for multiplicity in knots
    +
    +	var dim = control_points[0].length
     		, num_pts = control_points.length
    -		, k = verb.eval.nurbs.knot_span( degree, u, knots )
    -		, mp = np + degree + 1
    -		, nq = np + r
    -		, num_pts_post = num_pts + r    
    -		, Rw = new Array( degree + 1 )  
    -		, knots_post = new Array( knots.length + r ) 
    +		, k = verb.eval.nurbs.knot_span( degree, u, knots ) // the span in which the knot will be inserted
    +		, mp = knots.length
    +		, nq = num_pts + r
    +		, num_pts_post = num_pts + r // a new control pt for every new knot    
    +		, Rw = new Array( degree - s )  
    +		, knots_post = new Array( knots.length + r )  // r new knots
     		, control_points_post = new Array( num_pts_post ) 
     		, i = 0;
  • -
  • +
  • - +

    new knot vector

    +

    insert the k knots that will not be affected

    -
    	for (i = 0; i <= k; i++) {
    -		knots_post[i] = knots[i];
    -	}
    -	
    -	for (i = 1; i <= r; i++) {
    -		knots_post[k+i] = u; 
    -	}
    +            
    		for (i = 0; i <= k; i++) {
    +			knots_post[i] = knots[i];
    +		}
    + +
  • + + +
  • +
    + +
    + +
    +

    insert the new repeat knots

    - for (i = k+1; i <= mp; i++) - { - knots_post[i+r] = knots[i]; - }
    + + +
    		for (i = 1; i <= r; i++) {
    +			knots_post[k+i] = u; 
    +		}
  • -
  • +
  • - + +
    +

    insert the rest of the knots

    + +
    + +
    		for (i = k+1; i < knots.length; i++) {
    +			knots_post[i+r] = knots[i];
    +		}
    + +
  • + + +
  • +
    + +
    +

    control point generation

    +

    copy the original control points before the insertion span

    -
    	for (i = 0; i <= k-degree; i++)
    -	{
    -		control_points_post[i] = control_points[i]; 
    -	}
    +            
    		for (i = 0; i <= k - degree; i++) {
    +			control_points_post[i] = control_points[i]; 
    +		}
    + +
  • + + +
  • +
    + +
    + +
    +

    copy the original controls after the insertion span

    - for (i = k-s; i <= np; i++) - { - control_points_post[i+r] = control_points[i]; - } +
    + +
    		for (i = k-s; i < num_pts; i++) {
    +			control_points_post[i+r] = control_points[i];
    +		}
    + +
  • + + +
  • +
    + +
    + +
    +

    collect the affected control points in this temporary array

    - for (i = 0; i <= degree-s; i++) - { - Rw[i] = control_points[k-degree+1]; - } +
    + +
    		for (i = 0; i <= degree-s; i++) {
    +			Rw[i] = control_points[k-degree+i];
    +		}
     
     	var L = 0
     		, alpha = 0;
    @@ -7028,11 +7212,11 @@

    curve_knot_insert(

  • -
  • +
  • - +

    insert knot r times

    @@ -7057,11 +7241,11 @@

    curve_knot_insert(

  • -
  • +
  • - +

    not so confident about this part

    @@ -7072,20 +7256,21 @@

    curve_knot_insert( control_points_post[i] = Rw[ i - L ]; } - return [knots_post, control_points_post]; + return { knots: knots_post, control_points: control_points_post }; }

  • -
  • +
  • - +
    -

    rational_surface_derivs( degree_u, knots_u, degree_v, knots_v, homo_control_points, num_derivs, u, v)

    +

    knot refinement

    +

    rational_surface_derivs( degree_u, knots_u, degree_v, knots_v, homo_control_points, num_derivs, u, v)

    Compute the derivatives at a point on a NURBS surface

    params

      @@ -7153,11 +7338,11 @@

      +
    • - +

      rational_surface_point( degree_u, knots_u, degree_v, knots_v, homo_control_points, u, v )

      Compute a point on a NURBS surface

      @@ -7188,11 +7373,11 @@

      +
    • - +

      `

      rational_curve_derivs( degree, knots, homo_control_points, u, num_derivs )

      @@ -7216,11 +7401,11 @@

      ra

    • -
    • +
    • - +

      compute the derivatives of the control points separate derivative array into two

      @@ -7250,11 +7435,11 @@

      ra

    • -
    • +
    • - +

      separate_homo_derivs_1d( ck )

      Separate the array of derivatives into the A(u) component and w(u), i.e. the weight and everything else without dehomogenization

      @@ -7288,11 +7473,11 @@

      separate_homo_derivs_1d( ck )

    • -
    • +
    • - +

      separate_homo_derivs_2d( skl )

      Separate the array of derivatives into the A(u) component and w(u), i.e. the weight and everything else without dehomogenization

      @@ -7325,11 +7510,11 @@

      separate_homo_derivs_2d( skl )

    • -
    • +
    • - +

      rational_curve_point( degree, knots, homo_control_points, u)

      Compute a point on a NURBS curve

      @@ -7357,11 +7542,11 @@

      rational_curve

    • -
    • +
    • - +

      dehomogenize( homo_point )

      Dehomogenize a point

      @@ -7392,11 +7577,11 @@

      dehomogenize( homo_point )

    • -
    • +
    • - +

      homogenize_1d( control_points, weights)

      Transform a 1d array of points into their homogeneous equivalents

      @@ -7436,11 +7621,11 @@

      homogenize_1d( control_points, we

    • -
    • +
    • - +

      append the weight

      @@ -7458,11 +7643,11 @@

      homogenize_1d( control_points, we

    • -
    • +
    • - +

      homogenize_2d( control_points, weights)

      params

      @@ -7501,134 +7686,11 @@

      homogenize_2d( control_points, we

    • -
    • -
      - -
      - -
      -

      surface_curvature( degree_u, knots_u, degree_v, knots_v, control_points, u, v, options )

      -

      Compute the gaussian curvature on a non-uniform, non-rational B spline surface

      -

      params

      -
        -
      • Number, integer degree of surface in u direction
      • -
      • Array, array of nondecreasing knot values in u direction
      • -
      • Number, integer degree of surface in v direction
      • -
      • Array, array of nondecreasing knot values in v direction
      • -
      • Array, 3d array of control points, where rows are the u dir, and columns run alonsg the positive v direction, -and where each control point is an array of length (dim)
      • -
      • Number, u parameter at which to evaluate the derivatives
      • -
      • Number, v parameter at which to evaluate the derivatives
      • -
      -

      returns

      -
        -
      • Array, a point represented by an array of length (dim)
      • -
      - -
      - -
      verb.eval.nurbs.rational_surface_curvature = function( degree_u, knots_u, degree_v, knots_v, homo_control_points, u, v ) {
      - -
    • - - -
    • -
      - -
      - -
      -

      compute the first fundamental form

      -

      symmetric matrix where

      -

      I = [ E F; F G ]

      -

      where:

      -

      E = Xu Xu -F = Xu Xv -G = Xv * Xv

      -

      second fundamental form (shape operator)

      -

      symmetric matrix where

      -

      II = [ L M; M N ]

      -

      where:

      -

      L = Xuu n -M = Xuv n -N = Xvv * n

      -

      principal curvatures are the eigenvalues of the second fundamental form

      - -
      - -
      	var derivs = verb.eval.nurbs.rational_surface_derivs( 	degree_u, 
      -															knots_u, 
      -															degree_v, 
      -															knots_v, 
      -															homo_control_points, 
      -															2, u, v );
      - -
    • - - -
    • -
      - -
      - -
      -

      structure of the derivatives

      -

      pos du vuu -dv duv -dvv

      - -
      - -
       
      -  var du = derivs[0][1];
      -  var dv = derivs[1][0];
      -  var duu = derivs[0][2];
      -  var dvv = derivs[2][0];
      -  var duv = derivs[1][1];
      -
      -  var n = numeric.cross( du, dv );
      -  var L = numeric.dot( duu, n );
      -  var M = numeric.dot( duv, n );
      -  var N = numeric.dot( dvv, n );
      -
      -  var shapeOperator = [ [ L, M ], [ M, N ] ];
      -
      -	var eigs = numeric.eig( shapeOperator );
      - -
    • - - -
    • -
      - -
      - -
      -

      contains: lambda - x - E - x

      - -
      - -
      	
      -	var k1 = eigs.lambda.x[0];
      -	var k2 = eigs.lambda.x[1];
      -	var mean = 0.5 * ( k1 + k2 );
      -	var gaussian = k1 * k2;
      -	var p1 = numeric.add( numeric.mul( eigs.E.x[0][0], du ), numeric.mul( eigs.E.x[0][1], dv ) );
      -	var p2 = numeric.add( numeric.mul( eigs.E.x[1][0], du ), numeric.mul( eigs.E.x[1][1], dv ) );
      -
      -	return { point: derivs[0][0], normal: n, mean: mean, gaussian: gaussian, shapeOperator: shapeOperator, k1: k1, k2: k2, p1: p1, p2: p2, p1p : eigs.E.x[0], p2p: eigs.E.x[1]  };
      -
      -};
      - -
    • - - -
    • +
    • - +

      surface_derivs( degree_u, knots_u, degree_v, knots_v, control_points, num_derivatives, u, v )

      Compute the derivatives on a non-uniform, non-rational B spline surface

      @@ -7662,11 +7724,11 @@

      +
    • - +

      surface_derivs_given_n_m( n, degree_u, knots_u, m, degree_v, knots_v, control_points, num_derivatives, u, v )

      Compute the derivatives on a non-uniform, non-rational B spline surface @@ -7740,11 +7802,11 @@

      +
    • - +

      surface_point( degree_u, knots_u, degree_v, knots_v, control_points, u, v)

      Compute a point on a non-uniform, non-rational B-spline surface

      @@ -7778,11 +7840,11 @@

      sur

    • -
    • +
    • - +

      volume_point( degree_u, knots_u, degree_v, knots_v, degree_w, knots_w, control_points, u, v, w )

      Compute a point in a non-uniform, non-rational B spline volume

      @@ -7822,11 +7884,11 @@

      +
    • - +

      volume_point_given_n_m_l( n, degree_u, knots_u, m, degree_v, knots_v, l, degree_w, knots_w, control_points, u, v, w )

      Compute a point in a non-uniform, non-rational B spline volume

      @@ -7893,11 +7955,11 @@

      +
    • - +

      sample u isoline

      @@ -7910,11 +7972,11 @@

      +
    • - +

      add weighted contribution of u isoline

      @@ -7927,11 +7989,11 @@

      +
    • - +

      add weighted contribution from uv isosurfaces

      @@ -7948,11 +8010,11 @@

      +
    • - +

      surface_point_given_n_m( n, degree_u, knots_u, m, degree_v, knots_v, control_points, u, v )

      Compute a point on a non-uniform, non-rational B spline surface @@ -8004,11 +8066,11 @@

      +
    • - +

      sample u isoline

      @@ -8021,11 +8083,11 @@

      +
    • - +

      add point from u isoline

      @@ -8040,11 +8102,11 @@

      +
    • - +

      curve_derivs( degree, knots, control_points, u, num_derivs )

      Determine the derivatives of a non-uniform, non-rational B-spline curve at a given parameter

      @@ -8072,11 +8134,11 @@

      curve_derivs( de

    • -
    • +
    • - +

      curve_derivs_given_n( n, degree, knots, control_points, u, num_derivatives )

      Determine the derivatives of a non-uniform, non-rational B-spline curve at a given parameter @@ -8123,11 +8185,11 @@

      c

    • -
    • +
    • - +

      are_valid_relations( degree, num_control_points, knots_length )

      Confirm the relations between degree (p), number of control points(n+1), and the number of knots (m+1) @@ -8154,11 +8216,11 @@

      are_valid_r

    • -
    • +
    • - +

      curve_point( degree, knots, control_points, u)

      Compute a point on a non-uniform, non-rational b-spline curve

      @@ -8186,11 +8248,11 @@

      curve_point( degree, knots,

    • -
    • +
    • - +

      curve_point_given_n( n, degree, knots, control_points, u)

      Compute a point on a non-uniform, non-rational b-spline curve @@ -8231,11 +8293,11 @@

      curve_point_given_

    • -
    • +
    • - +

      zeros_1d(size)

      Generate a 1d array of zeros

      @@ -8265,11 +8327,11 @@

      zeros_1d(size)

    • -
    • +
    • - +

      zeros_2d(rows, cols)

      Generate a 2D array of zeros

      @@ -8308,11 +8370,11 @@

      zeros_2d(rows, cols)

    • -
    • +
    • - +

      zeros_3d(rows, cols, dim)

      Generate a 3D array of zeros

      @@ -8352,11 +8414,11 @@

      zeros_3d(rows, cols, dim)

    • -
    • +
    • - +

      deriv_basis_functions( u, degree, knots )

      Compute the non-vanishing basis functions and their derivatives

      @@ -8385,11 +8447,11 @@

      deriv_basis_functions( u, degree,

    • -
    • +
    • - +

      deriv_basis_functions_given_n_i( knot_span_index, u, p, n, knots )

      Compute the non-vanishing basis functions and their derivatives @@ -8516,11 +8578,11 @@

      deriv_basi

    • -
    • +
    • - +

      basis_functions( u, degree, knots )

      Compute the non-vanishing basis functions

      @@ -8546,11 +8608,11 @@

      basis_functions( u, degree, knots )

      -
    • +
    • - +

      basis_functions_given_knot_span_index( knot_span_index, u, degree, knots )

      Compute the non-vanishing basis functions @@ -8602,11 +8664,11 @@

      b

    • -
    • +
    • - +

      knot_span( degree, u, knots )

      Find the span on the knot vector without supplying n

      @@ -8636,11 +8698,11 @@

      knot_span( degree, u, knots )

    • -
    • +
    • - +

      knot_span_given_n( n, degree, u, knots )

      Find the span on the knot vector knots of the given parameter diff --git a/src/eval/eval.js b/src/eval/eval.js index de717ab9..53abb23e 100644 --- a/src/eval/eval.js +++ b/src/eval/eval.js @@ -95,24 +95,27 @@ verb.eval.nurbs.rational_surface_curvature = function( degree_u, knots_u, degree // // ####curve_knot_insert( degree, knots, control_points, u, s, r ) // -// Insert a knot along a rational curve +// Insert a knot along a rational curve. Note that this algorithm only works +// for r + s <= degree, where s is the initial multiplicity (number of duplicates) of the knot. +// +// Corresponds to algorithm A5.1 (Piegl & Tiller) +// +// Use the curve_knot_refine for applications like curve splitting. // // **params** // + *Number*, integer degree // + *Array*, array of nondecreasing knot values // + *Array*, array of control points // + *Number*, parameter at which to insert the knot -// + *Number*, initial multiplicity of the knot // + *Number*, number of times to insert the knot // // **returns** -// + *Object* the new curve, defined by degree, knots, and control_points +// + *Object* the new curve, defined by knots and control_points // verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, r ) { // num_pts is num control points for the initial curve - // nq is num control points for the output curve with knots inserted // k is the span on which the knots are inserted // s is the initial multiplicity of the knot // r is the number of times to insert the knot @@ -120,13 +123,10 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, var s = 0; // assume original multiplicity is 0 - TODO add check for multiplicity in knots - var dim = control_points[0].length - , num_pts = control_points.length + var num_pts = control_points.length , k = verb.eval.nurbs.knot_span( degree, u, knots ) // the span in which the knot will be inserted - , mp = knots.length - , nq = num_pts + r , num_pts_post = num_pts + r // a new control pt for every new knot - , Rw = new Array( degree - s ) + , control_points_temp = new Array( degree - s ) , knots_post = new Array( knots.length + r ) // r new knots , control_points_post = new Array( num_pts_post ) , i = 0; @@ -162,7 +162,7 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, // collect the affected control points in this temporary array for (i = 0; i <= degree-s; i++) { - Rw[i] = control_points[k-degree+i]; + control_points_temp[i] = control_points[k-degree+i]; } var L = 0 @@ -176,27 +176,30 @@ verb.eval.nurbs.curve_knot_insert = function( degree, knots, control_points, u, for (i = 0; i <= degree-j-s; i++) { alpha = ( u - knots[L+i] ) / ( knots[i+k+1] - knots[L+i] ); - Rw[i] = numeric.add( numeric.mul( alpha, Rw[i+1] ), numeric.mul( (1.0 - alpha), Rw[i]) ); + + control_points_temp[i] = + numeric.add( + numeric.mul( alpha, control_points_temp[i+1] ), + numeric.mul( (1.0 - alpha), control_points_temp[i]) + ); + } - control_points_post[ L ] = Rw[0]; - control_points_post[k+r-j-s] = Rw[degree-j-s]; + control_points_post[ L ] = control_points_temp[0]; + control_points_post[k+r-j-s] = control_points_temp[degree-j-s]; } // not so confident about this part - for (i = L+1; i < k-s; i++) // set remaining control points - { - control_points_post[i] = Rw[ i - L ]; + for (i = L+1; i < k-s; i++) { + control_points_post[i] = control_points_temp[ i - L ]; } return { knots: knots_post, control_points: control_points_post }; } -// knot refinement - // // ####rational_surface_derivs( degree_u, knots_u, degree_v, knots_v, homo_control_points, num_derivs, u, v) diff --git a/test/test.js b/test/test.js index 4d5adc21..854d3583 100644 --- a/test/test.js +++ b/test/test.js @@ -690,36 +690,6 @@ describe("verb.eval.nurbs.rational_surface_derivs",function(){ }); }); -describe("verb.eval.nurbs.curve_knot_insert",function(){ - - it('returns expected results when inserting a single knot in arc', function(){ - - // this represents a single quarter arc, using a bezier curve - var degree = 3 - , u = 2.5 - , knots = [ 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5 ]; - - var control_points = []; - for (var i = 0; i < 8; i++) control_points.push([i, 0, 0]); - - // console.log(control_points) - - var p = verb.eval.nurbs.curve_knot_insert( degree, knots, control_points, u, 1 ); - - // console.log(p); - - // var p0 = verb.eval.nurbs.curve_point( degree, knots, control_points, 0.5); - - // console.log(p0) - - // var p1 = verb.eval.nurbs.curve_point( degree, p.knots, p.control_points, 0.5); - - // console.log(p1) - - - }); - -}); describe("verb.eval.geom.three_points_are_flat",function(){ @@ -4457,6 +4427,125 @@ describe("verb.eval.nurbs.rational_surface_curvature ",function(){ }); + +describe("verb.eval.nurbs.curve_knot_insert",function(){ + + it('returns expected results when inserting 1 knot in the middle of a non-rational, cubic b-spline', function(){ + + var degree = 3 + , u = 2.5 + , knots = [ 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5 ] + , r = 1; + + var control_points = []; + for (var i = 0; i < 8; i++) control_points.push([i, 0, 0]); + + var after = verb.eval.nurbs.curve_knot_insert( degree, knots, control_points, u, r ); + + after.control_points.forEach(function(cp){ should.exist(cp); }); + after.knots.forEach(function(cp){ should.exist(cp); }); + + should.equal(knots.length + r, after.knots.length); + should.equal(control_points.length + r, after.control_points.length); + + after.control_points[3][0].should.be.approximately( 2.8333333333, verb.TOLERANCE ); + after.control_points[4][0].should.be.approximately( 3.5, verb.TOLERANCE ); + after.control_points[5][0].should.be.approximately( 4.1666666666, verb.TOLERANCE ); + + var p0 = verb.eval.nurbs.curve_point( degree, knots, control_points, 2.5); + + var p1 = verb.eval.nurbs.curve_point( degree, after.knots, after.control_points, 2.5); + + p0[0].should.be.approximately(p1[0], verb.TOLERANCE); + p0[1].should.be.approximately(p1[1], verb.TOLERANCE); + p0[2].should.be.approximately(p1[2], verb.TOLERANCE); + + }); + + it('returns expected results when inserting 3 knots at the middle of a non-rational, cubic b-spline', function(){ + + var degree = 3 + , u = 2.5 + , knots = [ 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5 ] + , r = 3; + + var control_points = []; + for (var i = 0; i < 8; i++) control_points.push([i, 0, 0]); + + var after = verb.eval.nurbs.curve_knot_insert( degree, knots, control_points, u, r ); + + after.control_points.forEach(function(cp){ should.exist(cp); }); + after.knots.forEach(function(cp){ should.exist(cp); }); + + should.equal(knots.length + r, after.knots.length); + should.equal(control_points.length + r, after.control_points.length); + + var p0 = verb.eval.nurbs.curve_point( degree, knots, control_points, 2.5); + var p1 = verb.eval.nurbs.curve_point( degree, after.knots, after.control_points, 2.5); + + p0[0].should.be.approximately(p1[0], verb.TOLERANCE); + p0[1].should.be.approximately(p1[1], verb.TOLERANCE); + p0[2].should.be.approximately(p1[2], verb.TOLERANCE); + + }); + + it('returns expected results when inserting 1 knots at the beginning of a non-rational, cubic b-spline', function(){ + + var degree = 3 + , u = 0.5 + , knots = [ 0, 0, 0, 0, 1, 2, 3, 4, 5, 5, 5, 5 ] + , r = 1; + + var control_points = []; + for (var i = 0; i < 8; i++) control_points.push([i, 0, 0]); + + var after = verb.eval.nurbs.curve_knot_insert( degree, knots, control_points, u, r ); + + after.control_points.forEach(function(cp){ should.exist(cp); }); + after.knots.forEach(function(cp){ should.exist(cp); }); + + should.equal(knots.length + r, after.knots.length); + should.equal(control_points.length + r, after.control_points.length); + + var p0 = verb.eval.nurbs.curve_point( degree, knots, control_points, 2.5); + var p1 = verb.eval.nurbs.curve_point( degree, after.knots, after.control_points, 2.5); + + p0[0].should.be.approximately(p1[0], verb.TOLERANCE); + p0[1].should.be.approximately(p1[1], verb.TOLERANCE); + p0[2].should.be.approximately(p1[2], verb.TOLERANCE); + + }); + + it('returns expected results when inserting 1 knot at the middle of a non-rational, linear b-spline', function(){ + + var degree = 1 + , u = 0.5 + , knots = [ 0, 0, 1, 2, 3, 4, 5, 5 ] + , r = 1; + + var control_points = []; + for (var i = 0; i < 6; i++) control_points.push([i, 0, 0]); + + var after = verb.eval.nurbs.curve_knot_insert( degree, knots, control_points, u, r ); + + after.control_points.forEach(function(cp){ should.exist(cp); }); + after.knots.forEach(function(cp){ should.exist(cp); }); + + should.equal(knots.length + r, after.knots.length); + should.equal(control_points.length + r, after.control_points.length); + + var p0 = verb.eval.nurbs.curve_point( degree, knots, control_points, 2.5); + var p1 = verb.eval.nurbs.curve_point( degree, after.knots, after.control_points, 2.5); + + p0[0].should.be.approximately(p1[0], verb.TOLERANCE); + p0[1].should.be.approximately(p1[1], verb.TOLERANCE); + p0[2].should.be.approximately(p1[2], verb.TOLERANCE); + + }); + + +}); + // describe("verb.eval.nurbs.AdaptiveRefinementNode.divide",function(){ // it('can be called with options.minDepth', function(){