Files
iD/test/spec/geo/vector.js

194 lines
7.1 KiB
JavaScript

describe('iD.geo - vector', function() {
describe('geoVecEqual', function() {
it('tests vectors for exact equality', function() {
expect(iD.geoVecEqual([1, 2], [1, 2])).to.be.true;
expect(iD.geoVecEqual([1, 2], [1, 0])).to.be.false;
expect(iD.geoVecEqual([1, 2], [2, 1])).to.be.false;
});
it('tests vectors for equality within epsilon', function() {
expect(iD.geoVecEqual([1, 2], [1.0000001, 2.0000001], 1e-5)).to.be.true;
expect(iD.geoVecEqual([1, 2], [1.0000001, 2.0000001], 1e-8)).to.be.false;
});
});
describe('geoVecAdd', function() {
it('adds vectors', function() {
expect(iD.geoVecAdd([1, 2], [3, 4])).to.eql([4, 6]);
expect(iD.geoVecAdd([1, 2], [0, 0])).to.eql([1, 2]);
expect(iD.geoVecAdd([1, 2], [-3, -4])).to.eql([-2, -2]);
});
});
describe('geoVecSubtract', function() {
it('subtracts vectors', function() {
expect(iD.geoVecSubtract([1, 2], [3, 4])).to.eql([-2, -2]);
expect(iD.geoVecSubtract([1, 2], [0, 0])).to.eql([1, 2]);
expect(iD.geoVecSubtract([1, 2], [-3, -4])).to.eql([4, 6]);
});
});
describe('geoVecScale', function() {
it('multiplies vectors', function() {
expect(iD.geoVecScale([1, 2], 0)).to.eql([0, 0]);
expect(iD.geoVecScale([1, 2], 1)).to.eql([1, 2]);
expect(iD.geoVecScale([1, 2], 2)).to.eql([2, 4]);
expect(iD.geoVecScale([1, 2], 0.5)).to.eql([0.5, 1]);
});
});
describe('geoVecFloor (was: geoRoundCoordinates)', function() {
it('rounds vectors', function() {
expect(iD.geoVecFloor([0.1, 1])).to.eql([0, 1]);
expect(iD.geoVecFloor([0, 1])).to.eql([0, 1]);
expect(iD.geoVecFloor([0, 1.1])).to.eql([0, 1]);
});
});
describe('geoVecInterp', function() {
it('interpolates halfway', function() {
var a = [0, 0];
var b = [10, 10];
expect(iD.geoVecInterp(a, b, 0.5)).to.eql([5, 5]);
});
it('interpolates to one side', function() {
var a = [0, 0];
var b = [10, 10];
expect(iD.geoVecInterp(a, b, 0)).to.eql([0, 0]);
});
});
describe('geoVecLength (was: geoEuclideanDistance)', function() {
it('distance between two same points is zero', function() {
var a = [0, 0];
var b = [0, 0];
expect(iD.geoVecLength(a, b)).to.eql(0);
});
it('a straight 10 unit line is 10', function() {
var a = [0, 0];
var b = [10, 0];
expect(iD.geoVecLength(a, b)).to.eql(10);
});
it('a pythagorean triangle is right', function() {
var a = [0, 0];
var b = [4, 3];
expect(iD.geoVecLength(a, b)).to.eql(5);
});
});
describe('geoVecNormalize', function() {
it('gets unit vectors', function() {
expect(iD.geoVecNormalize([0, 0])).to.eql([0, 0]);
expect(iD.geoVecNormalize([1, 0])).to.eql([1, 0]);
expect(iD.geoVecNormalize([5, 0])).to.eql([1, 0]);
expect(iD.geoVecNormalize([-5, 0])).to.eql([-1, 0]);
expect(iD.geoVecNormalize([1, 1])[0]).to.be.closeTo(Math.sqrt(2)/2, 1e-6);
expect(iD.geoVecNormalize([1, 1])[1]).to.be.closeTo(Math.sqrt(2)/2, 1e-6);
});
});
describe('geoVecAngle', function() {
it('returns angle between a and b', function() {
expect(iD.geoVecAngle([0, 0], [1, 0])).to.be.closeTo(0, 1e-6);
expect(iD.geoVecAngle([0, 0], [0, 1])).to.be.closeTo(Math.PI / 2, 1e-6);
expect(iD.geoVecAngle([0, 0], [-1, 0])).to.be.closeTo(Math.PI, 1e-6);
expect(iD.geoVecAngle([0, 0], [0, -1])).to.be.closeTo(-Math.PI / 2, 1e-6);
});
});
describe('geoVecDot', function() {
it('dot product of right angle is zero', function() {
var a = [1, 0];
var b = [0, 1];
expect(iD.geoVecDot(a, b)).to.eql(0);
});
it('dot product of same vector multiplies', function() {
var a = [2, 0];
var b = [2, 0];
expect(iD.geoVecDot(a, b)).to.eql(4);
});
});
describe('geoVecNormalizedDot', function() {
it('normalized dot product of right angle is zero', function() {
var a = [2, 0];
var b = [0, 2];
expect(iD.geoVecNormalizedDot(a, b)).to.eql(0);
});
it('normalized dot product of same vector multiplies unit vectors', function() {
var a = [2, 0];
var b = [2, 0];
expect(iD.geoVecNormalizedDot(a, b)).to.eql(1);
});
it('normalized dot product of 45 degrees', function() {
var a = [0, 2];
var b = [2, 2];
expect(iD.geoVecNormalizedDot(a, b)).to.be.closeTo(Math.sqrt(2)/2, 1e-6);
});
});
describe('geoVecCross', function() {
it('2D cross product of right hand turn is positive', function() {
var a = [2, 0];
var b = [0, 2];
expect(iD.geoVecCross(a, b)).to.eql(4);
});
it('2D cross product of left hand turn is negative', function() {
var a = [2, 0];
var b = [0, -2];
expect(iD.geoVecCross(a, b)).to.eql(-4);
});
it('2D cross product of colinear points is zero', function() {
var a = [-2, 0];
var b = [2, 0];
expect(iD.geoVecCross(a, b)).to.equal(0);
});
});
describe('geoVecProject', function() {
it('returns null for a degenerate path (no nodes)', function() {
expect(iD.geoVecProject([0, 1], [])).to.be.null;
});
it('returns null for a degenerate path (single node)', function() {
expect(iD.geoVecProject([0, 1], [0, 0])).to.be.null;
});
it('calculates the orthogonal projection of a point onto a path', function() {
// c
// |
// a --*--- b
//
// * = [2, 0]
var a = [0, 0];
var b = [5, 0];
var c = [2, 1];
var choice = iD.geoVecProject(c, [a, b]);
expect(choice.index).to.eql(1);
expect(choice.distance).to.eql(1);
expect(choice.target).to.eql([2, 0]);
});
it('returns the starting vertex when the orthogonal projection is < 0', function() {
var a = [0, 0];
var b = [5, 0];
var c = [-3, 4];
var choice = iD.geoVecProject(c, [a, b]);
expect(choice.index).to.eql(1);
expect(choice.distance).to.eql(5);
expect(choice.target).to.eql([0, 0]);
});
it('returns the ending vertex when the orthogonal projection is > 1', function() {
var a = [0, 0];
var b = [5, 0];
var c = [8, 4];
var choice = iD.geoVecProject(c, [a, b]);
expect(choice.index).to.eql(1);
expect(choice.distance).to.eql(5);
expect(choice.target).to.eql([5, 0]);
});
});
});