Skip to content

Commit

Permalink
bugfix issue #26 Spline3D (and 2D) ending with incorrect number of
Browse files Browse the repository at this point in the history
points, tested and compared to java output, BernsteinPolynomial output
tested as well
  • Loading branch information
hapticdata committed Jan 19, 2014
1 parent e26400b commit ee236b3
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 6 deletions.
8 changes: 7 additions & 1 deletion lib/toxi/geom/Spline2D.js
Expand Up @@ -52,6 +52,10 @@ Spline2D.prototype = {

computeVertices: function(res){
this.updateCoefficients();
if( res < 1 ){
res = 1;
}
res++;
if (this.bernstein === undefined || this.bernstein.resolution != res) {
this.bernstein = new BernsteinPolynomial(res);
}
Expand All @@ -60,12 +64,13 @@ Spline2D.prototype = {
this.findCPoints();
var deltaP = new Vec2D();
var deltaQ = new Vec2D();
res--;
for (var i = 0; i < this.numP - 1; i++) {
var p = this.points[i];
var q = this.points[i + 1];
deltaP.set(this.delta[i]).addSelf(p);
deltaQ.set(q).subSelf(this.delta[i + 1]);
for (var k = 0; k < bst.resolution; k++) {
for (var k = 0; k < res; k++) {
var x = p.x * bst.b0[k] + deltaP.x * bst.b1[k] +
deltaQ.x * bst.b2[k] +
q.x * bst.b3[k];
Expand All @@ -75,6 +80,7 @@ Spline2D.prototype = {
this.vertices.push(new Vec2D(x, y));
}
}
this.vertices.push(this.points[this.points.length-1].copy());
return this.vertices;
},

Expand Down
8 changes: 7 additions & 1 deletion lib/toxi/geom/Spline3D.js
Expand Up @@ -52,6 +52,10 @@ define([

computeVertices: function(res){
this.updateCoefficients();
if( res < 1 ){
res = 1;
}
res++;
if (this.bernstein === undefined || this.bernstein.resolution != res) {
this.bernstein = new BernsteinPolynomial(res);
}
Expand All @@ -60,12 +64,13 @@ define([
this.findCPoints();
var deltaP = new Vec3D();
var deltaQ = new Vec3D();
res--;
for (var i = 0; i < this.numP - 1; i++) {
var p = this.points[i];
var q = this.points[i + 1];
deltaP.set(this.delta[i]).addSelf(p);
deltaQ.set(q).subSelf(this.delta[i + 1]);
for (var k = 0; k < bst.resolution; k++) {
for (var k = 0; k < res; k++) {
var x = p.x * bst.b0[k] + deltaP.x * bst.b1[k] +
deltaQ.x * bst.b2[k] +
q.x * bst.b3[k];
Expand All @@ -77,6 +82,7 @@ define([
this.vertices.push(new Vec3D(x, y, z));
}
}
this.vertices.push(this.points[this.points.length-1].copy());
return this.vertices;
},

Expand Down
51 changes: 51 additions & 0 deletions test/geom.BernsteinPolynomial.js
@@ -0,0 +1,51 @@
var toxi = require('../index'),
assert = require('assert');

describe('BernsteinPolynomial', function(){
var isNear = function( v1, v2 ){
return Math.abs(v1-v2) < 0.0001;
};
var expected = {
4: [
[ 1.0, 0.29629624, 0.03703703, 0.0 ],
[ 0.0, 0.4444444, 0.2222222, 0.0 ],
[ 0.0, 0.22222224, 0.44444448, 0.0 ],
[ 0.0, 0.03703704, 0.29629633, 1.0 ]
],
6: [
[ 1.0, 0.512, 0.21600002, 0.06399999, 0.0079999985, 0.0 ],
[ 0.0, 0.38400003, 0.43200004, 0.288, 0.09599999, 0.0 ],
[ 0.0, 0.09600001, 0.28800002, 0.43199998, 0.384, 0.0 ],
[ 0.0, 0.0080, 0.064, 0.21600002, 0.512, 1.0 ]
],
13: [
[ 1.0, 0.7702547, 0.57870364, 0.421875, 0.29629624, 0.19849536, 0.125, 0.07233798, 0.03703705, 0.015625011, 0.004629636, 5.7870575E-4, 1.6940659E-21 ],
[ 0.0, 0.21006945, 0.3472222, 0.421875, 0.4444444, 0.4253472, 0.375, 0.30381948, 0.22222225, 0.14062504, 0.0694445, 0.019097265, 4.2632557E-14 ],
[ 0.0, 0.019097226, 0.06944445, 0.140625, 0.22222224, 0.30381945, 0.375, 0.4253472, 0.44444442, 0.42187503, 0.34722233, 0.21006964, 3.5762778E-7 ],
[ 0.0, 5.7870377E-4, 0.00462963, 0.015625, 0.03703704, 0.07233798, 0.125, 0.19849536, 0.29629624, 0.4218749, 0.5787035, 0.7702544, 0.99999964 ]
]
};
var eachNear = function(res,bNum){
return function(b, i){
assert.ok( isNear(b,expected[res][bNum][i]) );
};
};
var forBers = function( bers ){
var r = bers.resolution;
bers.b0.forEach(eachNear(r,0));
bers.b1.forEach(eachNear(r,1));
bers.b2.forEach(eachNear(r,2));
bers.b3.forEach(eachNear(r,3));
};
it('should match the java output for resolution 4', function(){
forBers(new toxi.geom.BernsteinPolynomial(4));
});

it('should match the java output for resolution 6', function(){
forBers(new toxi.geom.BernsteinPolynomial(6));
});

it('should match the java output for resolution 13', function(){
forBers(new toxi.geom.BernsteinPolynomial(13));
});
});
2 changes: 1 addition & 1 deletion test/geom.Spline2D.js
Expand Up @@ -78,7 +78,7 @@ describe("Spline2D", function(){
[2,3,4,5,6,7,8,9,10,20].forEach(function( res ){
it('for resolution ' + res, function(){
var vertices = instance.computeVertices( res );
assert.equal( vertices.length, instance.getNumPoints() * res - res );
assert.equal( vertices.length, instance.getNumPoints() * res - (res-1) );
//ensure that all vertex positions are valid numbers
vertices.forEach(function( vert ){
['x','y'].forEach(function( a ){
Expand Down
41 changes: 38 additions & 3 deletions test/geom.Spline3D.js
@@ -1,7 +1,6 @@
/*global describe, it*/
var toxi = require('../index'),
assert = require('assert');
//tests for toxi.geom.Spline2D
//TODO: test Spline3D#getDecimatedVertices()
describe("Spline3D", function(){
describe('default instance', function(){
Expand Down Expand Up @@ -57,6 +56,42 @@ describe("Spline3D", function(){
testInstance( instance );
});

describe('example instance with java output for comparison', function(){
var Vec3D = toxi.geom.Vec3D;
var spline = new toxi.geom.Spline3D();
spline.add (new Vec3D( 0.5, 0.0, 0.0 ) );
spline.add( new Vec3D( 0.65, 0.25, 0.5 ) );
spline.add( new Vec3D( 0.5, 0.5, 0.65 ) );
spline.add( new Vec3D( 0.35, 0.75, 0.5 ) );
spline.add( new Vec3D( 0.5, 1.0, 0.0 ) );


var eachNear = function(res){
return function(v, i){
assert.ok( v.equalsWithTolerance(expected[res][i], 0.01) );
};
};
var expected = {
4: [{x:0.5, y:0.0, z:0.0}, {x:0.5204241, y:0.023995537, z:0.05527344}, {x:0.56696427, y:0.08482143, z:0.1890625}, {x:0.6175223, y:0.16573662, z:0.3533203}, {x:0.65, y:0.25, z:0.5}, {x:0.6476562, y:0.32421875, z:0.5919922}, {x:0.6151786, y:0.38839284, z:0.6359375}, {x:0.5626116, y:0.44587052, z:0.64941406}, {x:0.5, y:0.5, z:0.65}, {x:0.4373884, y:0.5541295, z:0.64941406}, {x:0.38482141, y:0.6116072, z:0.63593745}, {x:0.35234374, y:0.67578125, z:0.59199214}, {x:0.35, y:0.75, z:0.5}, {x:0.38247767, y:0.8342634, z:0.35332033}, {x:0.43303573, y:0.91517854, z:0.1890625}, {x:0.47957587, y:0.9760045, z:0.055273443}, {x:0.5, y:1.0, z:0.0}],
8: [{x:0.5, y:0.0, z:0.0}, {x:0.5055664, y:0.0063476567, z:0.014819336}, {x:0.5204241, y:0.023995537, z:0.05527344}, {x:0.5418108, y:0.050851006, z:0.115356445}, {x:0.56696427, y:0.08482143, z:0.1890625}, {x:0.5931222, y:0.12381418, z:0.27038574}, {x:0.6175223, y:0.16573662, z:0.3533203}, {x:0.6374023, y:0.2084961, z:0.43186036}, {x:0.65, y:0.25, z:0.5}, {x:0.6532226, y:0.28857422, z:0.5531006}, {x:0.6476562, y:0.32421875, z:0.5919922}, {x:0.63455635, y:0.35735214, z:0.61887205}, {x:0.6151786, y:0.38839284, z:0.6359375}, {x:0.59077847, y:0.41775948, z:0.64538574}, {x:0.5626116, y:0.44587052, z:0.64941406}, {x:0.5319336, y:0.47314453, z:0.6502197}, {x:0.5, y:0.5, z:0.65}, {x:0.4680664, y:0.52685547, z:0.65021974}, {x:0.4373884, y:0.5541295, z:0.64941406}, {x:0.40922156, y:0.5822405, z:0.64538574}, {x:0.38482141, y:0.6116072, z:0.63593745}, {x:0.36544365, y:0.64264786, z:0.61887205}, {x:0.35234374, y:0.67578125, z:0.59199214}, {x:0.34677735, y:0.7114258, z:0.5531006}, {x:0.35, y:0.75, z:0.5}, {x:0.36259764, y:0.7915039, z:0.43186036}, {x:0.38247767, y:0.8342634, z:0.35332033}, {x:0.4068778, y:0.87618583, z:0.27038574}, {x:0.43303573, y:0.91517854, z:0.1890625}, {x:0.45818916, y:0.949149, z:0.11535645}, {x:0.47957587, y:0.9760045, z:0.055273443}, {x:0.49443358, y:0.99365234, z:0.014819337}, {x:0.5, y:1.0, z:0.0}],
13: [{x:0.5, y:0.0, z:0.0}, {x:0.5021751, y:0.0024546464, z:0.005757853}, {x:0.50827104, y:0.0094934665, z:0.02209832}, {x:0.51764417, y:0.020628782, z:0.04762176}, {x:0.52965087, y:0.035372917, z:0.08092856}, {x:0.5436471, y:0.053238183, z:0.12061903}, {x:0.5589895, y:0.07373691, z:0.16529359}, {x:0.57503414, y:0.09638144, z:0.2135526}, {x:0.5911373, y:0.12068406, z:0.2639964}, {x:0.6066551, y:0.14615712, z:0.31522533}, {x:0.62094414, y:0.1723129, z:0.36583978}, {x:0.6333604, y:0.19866377, z:0.41444016}, {x:0.64326024, y:0.22472203, z:0.45962676}, {x:0.65, y:0.25, z:0.5}, {x:0.6530918, y:0.27410755, z:0.53447884}, {x:0.65267247, y:0.29704466, z:0.56325674}, {x:0.6490344, y:0.31890887, z:0.58684564}, {x:0.6424703, y:0.33979782, z:0.60575795}, {x:0.6332725, y:0.35980877, z:0.62050515}, {x:0.6217342, y:0.37903965, z:0.63159996}, {x:0.60814744, y:0.39758763, z:0.6395539}, {x:0.59280515, y:0.41555044, z:0.6448794}, {x:0.57599974, y:0.43302557, z:0.6480883}, {x:0.5580239, y:0.45011052, z:0.6496928}, {x:0.53917027, y:0.4669029, z:0.6502048}, {x:0.51973146, y:0.4835002, z:0.6501365}, {x:0.5, y:0.5, z:0.65}, {x:0.48026854, y:0.5164998, z:0.65013653}, {x:0.46082973, y:0.53309715, z:0.65020484}, {x:0.441976, y:0.54988945, z:0.6496927}, {x:0.42400032, y:0.5669745, z:0.64808834}, {x:0.40719482, y:0.5844495, z:0.6448793}, {x:0.3918526, y:0.60241246, z:0.63955396}, {x:0.37826583, y:0.6209605, z:0.6315999}, {x:0.3667274, y:0.6401912, z:0.6205052}, {x:0.35752976, y:0.6602022, z:0.60575783}, {x:0.3509656, y:0.68109107, z:0.58684564}, {x:0.34732753, y:0.70295537, z:0.56325674}, {x:0.3469081, y:0.7258924, z:0.5344788}, {x:0.35, y:0.75, z:0.5}, {x:0.35673967, y:0.7752779, z:0.4596268}, {x:0.36663958, y:0.8013363, z:0.41444018}, {x:0.37905583, y:0.827687, z:0.36583975}, {x:0.39334485, y:0.85384303, z:0.31522536}, {x:0.40886268, y:0.87931585, z:0.2639963}, {x:0.4249659, y:0.90361863, z:0.21355262}, {x:0.44101048, y:0.92626315, z:0.16529357}, {x:0.45635283, y:0.94676185, z:0.120619036}, {x:0.47034916, y:0.9646271, z:0.080928534}, {x:0.4823558, y:0.9793712, z:0.047621757}, {x:0.491729, y:0.99050653, z:0.022098316}, {x:0.49782497, y:0.99754536, z:0.0057578515}, {x:0.5, y:1.0, z:0.0}]
};
var forRes = function( res ){
var verts = spline.computeVertices(res);
assert.equal(verts.length, expected[res].length);
verts.forEach(eachNear(res));
};
it('should match the java output', function(){
forRes(4);
});
it('should match for 8 points', function(){
forRes(8);
});
it('should match for 13 points', function(){
forRes(13);
});
});

function getNVec3D( n ){
var points = [];
for(var i=0; i<n; i++){
Expand All @@ -78,7 +113,7 @@ describe("Spline3D", function(){
[2,3,4,5,6,7,8,9,10,20].forEach(function( res ){
it('for resolution ' + res, function(){
var vertices = instance.computeVertices( res );
assert.equal( vertices.length, instance.getNumPoints() * res - res );
assert.equal( vertices.length, instance.getNumPoints() * res - (res-1) );
//ensure that all vertex positions are valid numbers
vertices.forEach(function( vert ){
['x','y'].forEach(function( a ){
Expand All @@ -97,4 +132,4 @@ describe("Spline3D", function(){
});
});
}
});
});

0 comments on commit ee236b3

Please sign in to comment.