jointjs
Version:
JavaScript diagramming library
857 lines (683 loc) • 78.3 kB
JavaScript
'use strict';
QUnit.module('curve', function() {
var fixture = document.createElement('div');
fixture.id = 'qunit-fixture';
var getSvg = function() {
var svg = document.createElementNS('http://www.w3.org/2000/svg', 'path');
svg.setAttribute('width', 600);
svg.setAttribute('height', 800);
document.body.appendChild(fixture);
fixture.appendChild(svg);
return svg;
};
QUnit.module('constructor', function() {
QUnit.test('creates a new Curve object', function(assert) {
var curve = new g.Curve();
assert.ok(curve instanceof g.Curve, 'no arguments provided');
var curve1 = new g.Curve('10 10', '10 40', '50 40', '50 10');
assert.ok(curve1 instanceof g.Curve, 'returns instance of g.Curve');
assert.notEqual(typeof curve1.start, 'undefined', 'has "start" property');
assert.notEqual(typeof curve1.controlPoint1, 'undefined', 'has "controlPoint1" property');
assert.notEqual(typeof curve1.controlPoint2, 'undefined', 'has "controlPoint2" property');
assert.notEqual(typeof curve1.end, 'undefined', 'has "end" property');
assert.equal(curve1.start.x, 10, 'start.x is correct');
assert.equal(curve1.start.y, 10, 'start.y is correct');
assert.equal(curve1.controlPoint1.x, 10, 'controlPoint1.x is correct');
assert.equal(curve1.controlPoint1.y, 40, 'controlPoint1.y is correct');
assert.equal(curve1.controlPoint2.x, 50, 'controlPoint2.x is correct');
assert.equal(curve1.controlPoint2.y, 40, 'controlPoint2.y is correct');
assert.equal(curve1.end.x, 50, 'end.x is correct');
assert.equal(curve1.end.y, 10, 'end.y is correct');
var curve2 = new g.Curve(curve1);
assert.ok(curve2 instanceof g.Curve, 'returns instance of g.Curve');
assert.notEqual(typeof curve2.start, 'undefined', 'has "start" property');
assert.notEqual(typeof curve2.controlPoint1, 'undefined', 'has "controlPoint1" property');
assert.notEqual(typeof curve2.controlPoint2, 'undefined', 'has "controlPoint2" property');
assert.notEqual(typeof curve2.end, 'undefined', 'has "end" property');
assert.notOk(curve1 === curve2);
assert.equal(curve1.toString(), curve2.toString());
assert.ok(curve1.equals(curve2));
});
});
QUnit.module('throughPoints()', function() {
QUnit.test('creates an array of Curve objects', function(assert) {
var points;
var curves;
var path;
var error;
try {
curves = g.Curve.throughPoints();
} catch (e) {
error = e;
}
assert.ok(typeof error !== 'undefined', 'Should throw an error when called with no arguments.');
points = [new g.Point(100, 100)];
try {
curves = g.Curve.throughPoints(points);
} catch (e) {
error = e;
}
assert.ok(typeof error !== 'undefined', 'Should throw an error when called with one argument.');
points = [new g.Point(100, 100), new g.Point(200, 200)];
curves = g.Curve.throughPoints(points);
path = new g.Path(curves);
assert.ok(Array.isArray(curves), 'returns an array');
assert.ok(curves[0] instanceof g.Curve, 'array elements are curves');
assert.ok(path instanceof g.Path, 'can be used to create a path');
assert.equal(path.serialize(), 'M 100 100 C 133.33333333333334 133.33333333333334 166.66666666666669 166.66666666666669 200 200', 'path has correct serialization');
points = [new g.Point(0, 100), new g.Point(45.3125, 128.125), new g.Point(154.6875, 71.875), new g.Point(200, 100)];
curves = g.Curve.throughPoints(points);
path = new g.Path(curves);
assert.ok(Array.isArray(curves), 'returns an array');
assert.ok(curves[0] instanceof g.Curve, 'array elements are curves');
assert.ok(path instanceof g.Path, 'can be used to create a path');
assert.equal(path.serialize(), 'M 0 100 C 7.986111111111107 118.75 15.972222222222214 137.5 45.3125 128.125 C 74.65277777777779 118.75 125.34722222222223 81.25 154.6875 71.875 C 184.02777777777777 62.49999999999999 192.01388888888889 81.25 200 100', 'path has correct serialization');
});
});
QUnit.module('prototype', function() {
QUnit.module('bbox()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('10 10', '10 40', '50 40', '50 10');
assert.ok(curve.bbox() instanceof g.Rect);
});
QUnit.test('returns tight bounding box of the curve', function(assert) {
var curve = new g.Curve('10 10', '10 40', '50 40', '50 10');
assert.equal(curve.bbox().toString(), '10@10 50@32.5');
});
});
QUnit.module('clone()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
assert.ok(curve.clone() instanceof g.Curve);
});
QUnit.test('returns a clone', function(assert) {
var curve1 = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curve2 = curve1.clone();
assert.notOk(curve1 === curve2);
assert.equal(curve1.toString(), curve2.toString());
assert.ok(curve1.equals(curve2));
assert.equal(curve1.start.toString(), curve2.start.toString());
assert.equal(curve1.controlPoint1.toString(), curve2.controlPoint1.toString());
assert.equal(curve1.controlPoint2.toString(), curve2.controlPoint2.toString());
assert.equal(curve1.end.toString(), curve2.end.toString());
});
});
QUnit.module('closestPoint()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point = new g.Point(100, 100);
assert.ok(curve.closestPoint(point) instanceof g.Point);
assert.ok(curve.closestPoint(point, { precision: 0 }) instanceof g.Point);
assert.ok(curve.closestPoint(point, { precision: 1 }) instanceof g.Point);
assert.ok(curve.closestPoint(point, { precision: 2 }) instanceof g.Point);
assert.ok(curve.closestPoint(point, { precision: 3 }) instanceof g.Point);
assert.ok(curve.closestPoint(point, { precision: 4 }) instanceof g.Point);
assert.ok(curve.closestPoint(point, { precision: 5 }) instanceof g.Point);
});
QUnit.test('returns point closest to a given point up to precision', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point;
point = new g.Point(100, 100);
assert.equal(curve.closestPoint(point).toString(), '100@100');
assert.equal(curve.closestPoint(point, { precision: 0 }).toString(), '0@100');
assert.equal(curve.closestPoint(point, { precision: 1 }).toString(), '100@100');
assert.equal(curve.closestPoint(point, { precision: 2 }).toString(), '100@100');
assert.equal(curve.closestPoint(point, { precision: 3 }).toString(), '100@100');
assert.equal(curve.closestPoint(point, { precision: 4 }).toString(), '100@100');
assert.equal(curve.closestPoint(point, { precision: 5 }).toString(), '100@100');
point = new g.Point(125, 0);
assert.equal(curve.closestPoint(point).toString(), '148.1719970703125@73.468017578125');
assert.equal(curve.closestPoint(point, { precision: 0 }).toString(), '200@100');
assert.equal(curve.closestPoint(point, { precision: 1 }).toString(), '154.6875@71.875');
assert.equal(curve.closestPoint(point, { precision: 2 }).toString(), '141.5283203125@75.830078125');
assert.equal(curve.closestPoint(point, { precision: 3 }).toString(), '148.1719970703125@73.468017578125');
assert.equal(curve.closestPoint(point, { precision: 4 }).toString(), '148.1719970703125@73.468017578125');
assert.equal(curve.closestPoint(point, { precision: 5 }).toString(), '147.76033237576485@73.59425574541092');
});
});
QUnit.module('closestPointLength()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point = new g.Point(100, 100);
assert.equal(typeof curve.closestPointLength(point), 'number');
assert.equal(typeof curve.closestPointLength(point, { precision: 0 }), 'number');
assert.equal(typeof curve.closestPointLength(point, { precision: 1 }), 'number');
assert.equal(typeof curve.closestPointLength(point, { precision: 2 }), 'number');
assert.equal(typeof curve.closestPointLength(point, { precision: 3 }), 'number');
assert.equal(typeof curve.closestPointLength(point, { precision: 4 }), 'number');
assert.equal(typeof curve.closestPointLength(point, { precision: 5 }), 'number');
});
QUnit.test('returns length closest to a given point up to precision', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point;
point = new g.Point(100, 100);
assert.equal(curve.closestPointLength(point), 119.83144621268787);
assert.equal(curve.closestPointLength(point, { precision: 0 }), 0);
assert.equal(curve.closestPointLength(point, { precision: 1 }), 118.71384231844745);
assert.equal(curve.closestPointLength(point, { precision: 2 }), 119.56582529496731);
assert.equal(curve.closestPointLength(point, { precision: 3 }), 119.83144621268787);
assert.equal(curve.closestPointLength(point, { precision: 4 }), 119.8480263853086);
assert.equal(curve.closestPointLength(point, { precision: 5 }), 119.84885532824434);
point = new g.Point(125, 0);
assert.equal(curve.closestPointLength(point), 174.99499668773748);
assert.equal(curve.closestPointLength(point, { precision: 0 }), 200);
assert.equal(curve.closestPointLength(point, { precision: 1 }), 178.91071717402883);
assert.equal(curve.closestPointLength(point, { precision: 2 }), 167.4224378522156);
assert.equal(curve.closestPointLength(point, { precision: 3 }), 174.99499668773748);
assert.equal(curve.closestPointLength(point, { precision: 4 }), 175.0319261701376);
assert.equal(curve.closestPointLength(point, { precision: 5 }), 174.60364946776332);
});
});
QUnit.module('closestPointNormalizedLength()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point = new g.Point(100, 100);
assert.equal(typeof curve.closestPointNormalizedLength(point), 'number');
assert.equal(typeof curve.closestPointNormalizedLength(point, { precision: 0 }), 'number');
assert.equal(typeof curve.closestPointNormalizedLength(point, { precision: 1 }), 'number');
assert.equal(typeof curve.closestPointNormalizedLength(point, { precision: 2 }), 'number');
assert.equal(typeof curve.closestPointNormalizedLength(point, { precision: 3 }), 'number');
assert.equal(typeof curve.closestPointNormalizedLength(point, { precision: 4 }), 'number');
assert.equal(typeof curve.closestPointNormalizedLength(point, { precision: 5 }), 'number');
});
QUnit.test('returns normalized length closest to a given point up to precision', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point;
point = new g.Point(100, 100);
assert.equal(curve.closestPointNormalizedLength(point), 0.5);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 0 }), 0);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 1 }), 0.5);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 2 }), 0.5);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 3 }), 0.5);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 4 }), 0.4999999999999999);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 5 }), 0.5000000000000001);
point = new g.Point(125, 0);
assert.equal(curve.closestPointNormalizedLength(point), 0.7301714291970585);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 0 }), 1);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 1 }), 0.7535377243291667);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 2 }), 0.7001266350112445);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 3 }), 0.7301714291970585);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 4 }), 0.7302244828271682);
assert.equal(curve.closestPointNormalizedLength(point, { precision: 5 }), 0.7284326954544352);
});
});
QUnit.module('closestPointT()', function() {
// this method uses `while (true)` so it has a potential for an infinite loop
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point = new g.Point(100, 100);
assert.equal(typeof curve.closestPointT(point), 'number');
assert.equal(typeof curve.closestPointT(point, { precision: 0 }), 'number');
assert.equal(typeof curve.closestPointT(point, { precision: 1 }), 'number');
assert.equal(typeof curve.closestPointT(point, { precision: 2 }), 'number');
assert.equal(typeof curve.closestPointT(point, { precision: 3 }), 'number');
assert.equal(typeof curve.closestPointT(point, { precision: 4 }), 'number');
assert.equal(typeof curve.closestPointT(point, { precision: 5 }), 'number');
});
QUnit.test('returns t closest to a given point up to precision', function(assert) {
var curve;
var point;
curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
// test for a curve endpoint
point = new g.Point(0, 100);
assert.equal(curve.closestPointT(point), 0);
assert.equal(curve.closestPointT(point, { precision: 0 }), 0);
assert.equal(curve.closestPointT(point, { precision: 1 }), 0);
assert.equal(curve.closestPointT(point, { precision: 2 }), 0);
assert.equal(curve.closestPointT(point, { precision: 3 }), 0);
assert.equal(curve.closestPointT(point, { precision: 4 }), 0);
assert.equal(curve.closestPointT(point, { precision: 5 }), 0);
// test for a point lying exactly on the curve
point = new g.Point(100, 100);
assert.equal(curve.closestPointT(point), 0.5);
assert.equal(curve.closestPointT(point, { precision: 0 }), 0);
assert.equal(curve.closestPointT(point, { precision: 1 }), 0.5);
assert.equal(curve.closestPointT(point, { precision: 2 }), 0.5);
assert.equal(curve.closestPointT(point, { precision: 3 }), 0.5);
assert.equal(curve.closestPointT(point, { precision: 4 }), 0.5);
assert.equal(curve.closestPointT(point, { precision: 5 }), 0.5);
// tests the minimal-precision (first) criterion to exit the loop
point = new g.Point(125, 0);
assert.equal(curve.closestPointT(point), 0.71875);
assert.equal(curve.closestPointT(point, { precision: 0 }), 1);
assert.equal(curve.closestPointT(point, { precision: 1 }), 0.75);
assert.equal(curve.closestPointT(point, { precision: 2 }), 0.6875);
assert.equal(curve.closestPointT(point, { precision: 3 }), 0.71875);
assert.equal(curve.closestPointT(point, { precision: 4 }), 0.71875);
assert.equal(curve.closestPointT(point, { precision: 5 }), 0.716796875);
curve = new g.Curve('150 350', '203.68888888888887 344', '267.91111111111115 294', '318 275');
// tests the minimal-distance (second) criterion to exit the loop
point = new g.Point(174.8537225276232, 344.5625875517726);
assert.equal(curve.closestPointT(point), 0.150390625);
assert.equal(curve.closestPointT(point, { precision: 0 }), 0);
assert.equal(curve.closestPointT(point, { precision: 1 }), 0.15625);
assert.equal(curve.closestPointT(point, { precision: 2 }), 0.1484375);
assert.equal(curve.closestPointT(point, { precision: 3 }), 0.150390625);
assert.equal(curve.closestPointT(point, { precision: 4 }), 0.150390625);
assert.equal(curve.closestPointT(point, { precision: 5 }), 0.150390625);
});
QUnit.test('assert precision compared to pointAtT', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var t = 0.4;
assert.ok(Math.abs(curve.closestPointT(curve.pointAtT(t), { precision: 0 }) - t) < Math.pow(10, -0));
assert.ok(Math.abs(curve.closestPointT(curve.pointAtT(t), { precision: 1 }) - t) < Math.pow(10, -1));
assert.ok(Math.abs(curve.closestPointT(curve.pointAtT(t), { precision: 2 }) - t) < Math.pow(10, -2));
assert.ok(Math.abs(curve.closestPointT(curve.pointAtT(t), { precision: 3 }) - t) < Math.pow(10, -3));
assert.ok(Math.abs(curve.closestPointT(curve.pointAtT(t), { precision: 4 }) - t) < Math.pow(10, -4));
assert.ok(Math.abs(curve.closestPointT(curve.pointAtT(t), { precision: 5 }) - t) < Math.pow(10, -5));
});
});
QUnit.module('closestPointTangent()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point = new g.Point(100, 100);
assert.ok(curve.closestPointTangent(point) instanceof g.Line);
assert.ok(curve.closestPointTangent(point, { precision: 0 }) instanceof g.Line);
assert.ok(curve.closestPointTangent(point, { precision: 1 }) instanceof g.Line);
assert.ok(curve.closestPointTangent(point, { precision: 2 }) instanceof g.Line);
assert.ok(curve.closestPointTangent(point, { precision: 3 }) instanceof g.Line);
assert.ok(curve.closestPointTangent(point, { precision: 4 }) instanceof g.Line);
assert.ok(curve.closestPointTangent(point, { precision: 5 }) instanceof g.Line);
});
QUnit.test('returns tangent at point closest to a given point up to precision', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var point;
point = new g.Point(100, 100);
assert.equal(curve.closestPointTangent(point).toString(), '100@100 175@50');
assert.equal(curve.closestPointTangent(point, { precision: 0 }).toString(), '0@100 50@200');
assert.equal(curve.closestPointTangent(point, { precision: 1 }).toString(), '100@100 175@50');
assert.equal(curve.closestPointTangent(point, { precision: 2 }).toString(), '100@100 175@50');
assert.equal(curve.closestPointTangent(point, { precision: 3 }).toString(), '100@100 175@50');
assert.equal(curve.closestPointTangent(point, { precision: 4 }).toString(), '100@100 175@50');
assert.equal(curve.closestPointTangent(point, { precision: 5 }).toString(), '100@100 175@50');
point = new g.Point(125, 0);
assert.equal(curve.closestPointTangent(point).toString(), '148.1719970703125@73.468017578125 218.3868408203125@52.178955078125');
assert.equal(curve.closestPointTangent(point, { precision: 0 }).toString(), '200@100 250@200');
assert.equal(curve.closestPointTangent(point, { precision: 1 }).toString(), '154.6875@71.875 223.4375@59.375');
assert.equal(curve.closestPointTangent(point, { precision: 2 }).toString(), '141.5283203125@75.830078125 213.0126953125@46.923828125');
assert.equal(curve.closestPointTangent(point, { precision: 3 }).toString(), '148.1719970703125@73.468017578125 218.3868408203125@52.178955078125');
assert.equal(curve.closestPointTangent(point, { precision: 4 }).toString(), '148.1719970703125@73.468017578125 218.3868408203125@52.178955078125');
assert.equal(curve.closestPointTangent(point, { precision: 5 }).toString(), '147.76033237576485@73.59425574541092 218.06024387478828@51.794786751270294');
});
});
QUnit.module('containsPoint()', function() {
QUnit.test('returns true if point lies within the curve according to even-odd rule', function(assert) {
var curve = new g.Curve('40 0', '100 50', '0 50', '60 0');
var point;
point = new g.Point(40, 0);
assert.equal(curve.containsPoint(point), true, 'endpoint = inside');
point = new g.Point(50, 20);
assert.equal(curve.containsPoint(point), true, 'inside');
point = new g.Point(100, 50);
assert.equal(curve.containsPoint(point), false, 'control point = outside');
point = new g.Point(70, 0);
assert.equal(curve.containsPoint(point), false, 'outside');
});
});
QUnit.module('divideAt()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curveDivide;
curveDivide = curve.divideAt(0.5); // normal
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAt(0); // minimum
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAt(-1); // too little
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAt(1); // maximum
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAt(10); // too much
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
});
QUnit.test('returns an array with two curves, divided at provided `ratio`', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curveDivide;
curveDivide = curve.divideAt(0.5);
assert.equal(curveDivide[0].toString(), '0@100 25@150 62.5@125 100@100');
assert.equal(curveDivide[1].toString(), '100@100 137.5@75 175@50 200@100');
curveDivide = curve.divideAt(0);
assert.equal(curveDivide[0].toString(), '0@100 0@100 0@100 0@100');
assert.equal(curveDivide[1].toString(), '0@100 50@200 150@0 200@100');
curveDivide = curve.divideAt(-1);
assert.equal(curveDivide[0].toString(), '0@100 0@100 0@100 0@100');
assert.equal(curveDivide[1].toString(), '0@100 50@200 150@0 200@100');
curveDivide = curve.divideAt(1);
assert.equal(curveDivide[0].toString(), '0@100 50@200 150@0 200@100');
assert.equal(curveDivide[1].toString(), '200@100 200@100 200@100 200@100');
curveDivide = curve.divideAt(10);
assert.equal(curveDivide[0].toString(), '0@100 50@200 150@0 200@100');
assert.equal(curveDivide[1].toString(), '200@100 200@100 200@100 200@100');
});
});
QUnit.module('divideAtLength()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curveDivide;
curveDivide = curve.divideAtLength(120); // normal
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAtLength(-120); // normal negative
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAtLength(0); // minimum
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAtLength(1000); // too much
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAtLength(-1000); // too much negative
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
});
QUnit.test('returns an array with two curves, divided at provided `length`', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curveDivide;
curveDivide = curve.divideAtLength(120);
assert.equal(curveDivide[0].toString(), '0@100 25@150 62.5@125 100@100');
assert.equal(curveDivide[1].toString(), '100@100 137.5@75 175@50 200@100');
curveDivide = curve.divideAtLength(-120);
assert.equal(curveDivide[0].toString(), '0@100 25@150 62.5@125 100@100');
assert.equal(curveDivide[1].toString(), '100@100 137.5@75 175@50 200@100');
curveDivide = curve.divideAtLength(0);
assert.equal(curveDivide[0].toString(), '0@100 0@100 0@100 0@100');
assert.equal(curveDivide[1].toString(), '0@100 50@200 150@0 200@100');
curveDivide = curve.divideAtLength(1000);
assert.equal(curveDivide[0].toString(), '0@100 50@200 150@0 200@100');
assert.equal(curveDivide[1].toString(), '200@100 200@100 200@100 200@100');
curveDivide = curve.divideAtLength(-1000);
assert.equal(curveDivide[0].toString(), '0@100 0@100 0@100 0@100');
assert.equal(curveDivide[1].toString(), '0@100 50@200 150@0 200@100');
});
});
QUnit.module('divideAtT()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curveDivide;
curveDivide = curve.divideAtT(0.5); // normal
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAtT(0); // minimum
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAtT(-1); // too little
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAtT(1); // maximum
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
curveDivide = curve.divideAtT(10); // too much
assert.ok(Array.isArray(curveDivide));
assert.equal(curveDivide.length, 2);
assert.ok(curveDivide[0] instanceof g.Curve);
assert.ok(curveDivide[1] instanceof g.Curve);
});
QUnit.test('returns an array with two curves, divided at provided `t`', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curveDivide;
curveDivide = curve.divideAtT(0.5);
assert.equal(curveDivide[0].toString(), '0@100 25@150 62.5@125 100@100');
assert.equal(curveDivide[1].toString(), '100@100 137.5@75 175@50 200@100');
curveDivide = curve.divideAtT(0);
assert.equal(curveDivide[0].toString(), '0@100 0@100 0@100 0@100');
assert.equal(curveDivide[1].toString(), '0@100 50@200 150@0 200@100');
curveDivide = curve.divideAtT(-1);
assert.equal(curveDivide[0].toString(), '0@100 0@100 0@100 0@100');
assert.equal(curveDivide[1].toString(), '0@100 50@200 150@0 200@100');
curveDivide = curve.divideAtT(1);
assert.equal(curveDivide[0].toString(), '0@100 50@200 150@0 200@100');
assert.equal(curveDivide[1].toString(), '200@100 200@100 200@100 200@100');
curveDivide = curve.divideAtT(10);
assert.equal(curveDivide[0].toString(), '0@100 50@200 150@0 200@100');
assert.equal(curveDivide[1].toString(), '200@100 200@100 200@100 200@100');
});
});
QUnit.module('endpointDistance()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
assert.equal(typeof curve.endpointDistance(), 'number');
});
QUnit.test('returns distance between start and end', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
assert.equal(curve.endpointDistance(), 200);
});
});
QUnit.module('equals()', function() {
QUnit.test('sanity', function(assert) {
var curve1 = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curve2 = new g.Curve('0 100', '50 200', '150 0', '200 100'); // same
var curve3 = new g.Curve('200 100', '150 0', '50 200', '0 100'); // reverse
var curve4 = new g.Curve('0 100', '0 100', '200 100', '200 100'); // different
assert.equal(typeof curve1.equals(curve2), 'boolean');
assert.equal(typeof curve1.equals(curve3), 'boolean');
assert.equal(typeof curve1.equals(curve4), 'boolean');
assert.equal(typeof curve1.equals(null), 'boolean');
assert.equal(typeof curve1.equals(undefined), 'boolean');
});
QUnit.test('checks whether two curves are exactly the same', function(assert) {
var curve1 = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curve2 = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curve3 = new g.Curve('200 100', '150 0', '50 200', '0 100');
var curve4 = new g.Curve('0 100', '0 100', '200 100', '200 100');
assert.equal(curve1.equals(curve2), true);
assert.equal(curve1.equals(curve3), false);
assert.equal(curve1.equals(curve4), false);
assert.equal(curve1.equals(null), false);
assert.equal(curve1.equals(undefined), false);
});
});
QUnit.module('getSkeletonPoints()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curveSkeletonPoints;
curveSkeletonPoints = curve.getSkeletonPoints(0.5); // normal
assert.equal(typeof curveSkeletonPoints, 'object');
assert.ok(curveSkeletonPoints.startControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.startControlPoint2 instanceof g.Point);
assert.ok(curveSkeletonPoints.divider instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint2 instanceof g.Point);
curveSkeletonPoints = curve.getSkeletonPoints(0); // minimum
assert.equal(typeof curveSkeletonPoints, 'object');
assert.ok(curveSkeletonPoints.startControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.startControlPoint2 instanceof g.Point);
assert.ok(curveSkeletonPoints.divider instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint2 instanceof g.Point);
curveSkeletonPoints = curve.getSkeletonPoints(-1); // too little
assert.equal(typeof curveSkeletonPoints, 'object');
assert.ok(curveSkeletonPoints.startControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.startControlPoint2 instanceof g.Point);
assert.ok(curveSkeletonPoints.divider instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint2 instanceof g.Point);
curveSkeletonPoints = curve.getSkeletonPoints(1); // maximum
assert.equal(typeof curveSkeletonPoints, 'object');
assert.ok(curveSkeletonPoints.startControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.startControlPoint2 instanceof g.Point);
assert.ok(curveSkeletonPoints.divider instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint2 instanceof g.Point);
curveSkeletonPoints = curve.getSkeletonPoints(10); // too much
assert.equal(typeof curveSkeletonPoints, 'object');
assert.ok(curveSkeletonPoints.startControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.startControlPoint2 instanceof g.Point);
assert.ok(curveSkeletonPoints.divider instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint1 instanceof g.Point);
assert.ok(curveSkeletonPoints.dividerControlPoint2 instanceof g.Point);
});
QUnit.test('returns points necessary for division', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
var curveSkeletonPoints;
curveSkeletonPoints = curve.getSkeletonPoints(0.5);
assert.equal(curveSkeletonPoints.startControlPoint1.toString(), '25@150');
assert.equal(curveSkeletonPoints.startControlPoint2.toString(), '62.5@125');
assert.equal(curveSkeletonPoints.divider.toString(), '100@100');
assert.equal(curveSkeletonPoints.dividerControlPoint1.toString(), '137.5@75');
assert.equal(curveSkeletonPoints.dividerControlPoint2.toString(), '175@50');
curveSkeletonPoints = curve.getSkeletonPoints(0);
assert.equal(curveSkeletonPoints.startControlPoint1.toString(), '0@100');
assert.equal(curveSkeletonPoints.startControlPoint2.toString(), '0@100');
assert.equal(curveSkeletonPoints.divider.toString(), '0@100');
assert.equal(curveSkeletonPoints.dividerControlPoint1.toString(), '50@200');
assert.equal(curveSkeletonPoints.dividerControlPoint2.toString(), '150@0');
curveSkeletonPoints = curve.getSkeletonPoints(-1);
assert.equal(curveSkeletonPoints.startControlPoint1.toString(), '0@100');
assert.equal(curveSkeletonPoints.startControlPoint2.toString(), '0@100');
assert.equal(curveSkeletonPoints.divider.toString(), '0@100');
assert.equal(curveSkeletonPoints.dividerControlPoint1.toString(), '50@200');
assert.equal(curveSkeletonPoints.dividerControlPoint2.toString(), '150@0');
curveSkeletonPoints = curve.getSkeletonPoints(1);
assert.equal(curveSkeletonPoints.startControlPoint1.toString(), '50@200');
assert.equal(curveSkeletonPoints.startControlPoint2.toString(), '150@0');
assert.equal(curveSkeletonPoints.divider.toString(), '200@100');
assert.equal(curveSkeletonPoints.dividerControlPoint1.toString(), '200@100');
assert.equal(curveSkeletonPoints.dividerControlPoint2.toString(), '200@100');
curveSkeletonPoints = curve.getSkeletonPoints(10);
assert.equal(curveSkeletonPoints.startControlPoint1.toString(), '50@200');
assert.equal(curveSkeletonPoints.startControlPoint2.toString(), '150@0');
assert.equal(curveSkeletonPoints.divider.toString(), '200@100');
assert.equal(curveSkeletonPoints.dividerControlPoint1.toString(), '200@100');
assert.equal(curveSkeletonPoints.dividerControlPoint2.toString(), '200@100');
});
});
QUnit.module('getSubdivisions()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
assert.equal(Array.isArray(curve.getSubdivisions()), true);
assert.equal(Array.isArray(curve.getSubdivisions({ precision: 0 })), true);
assert.equal(Array.isArray(curve.getSubdivisions({ precision: 1 })), true);
assert.equal(Array.isArray(curve.getSubdivisions({ precision: 2 })), true);
assert.equal(Array.isArray(curve.getSubdivisions({ precision: 3 })), true);
assert.equal(Array.isArray(curve.getSubdivisions({ precision: 4 })), true);
assert.equal(Array.isArray(curve.getSubdivisions({ precision: 5 })), true);
});
QUnit.test('returns an array with curve subdivisions up to precision', function(assert) {
var curve = new g.Curve('0 100', '50 200', '150 0', '200 100');
assert.deepEqual(curve.getSubdivisions({ precision: 0 }), [
new g.Curve(new g.Point(0, 100), new g.Point(50, 200), new g.Point(150, 0), new g.Point(200, 100))
]);
assert.deepEqual(curve.getSubdivisions({ precision: 1 }), [
new g.Curve(new g.Point(0, 100), new g.Point(6.25, 112.5), new g.Point(13.28125, 120.3125), new g.Point(20.8984375, 124.609375)),
new g.Curve(new g.Point(20.8984375, 124.609375), new g.Point(28.515625, 128.90625), new g.Point(36.71875, 129.6875), new g.Point(45.3125, 128.125)),
new g.Curve(new g.Point(45.3125, 128.125), new g.Point(53.90625, 126.5625), new g.Point(62.890625, 122.65625), new g.Point(72.0703125, 117.578125)),
new g.Curve(new g.Point(72.0703125, 117.578125), new g.Point(81.25, 112.5), new g.Point(90.625, 106.25), new g.Point(100, 100)),
new g.Curve(new g.Point(100, 100), new g.Point(109.375, 93.75), new g.Point(118.75, 87.5), new g.Point(127.9296875, 82.421875)),
new g.Curve(new g.Point(127.9296875, 82.421875), new g.Point(137.109375, 77.34375), new g.Point(146.09375, 73.4375), new g.Point(154.6875, 71.875)),
new g.Curve(new g.Point(154.6875, 71.875), new g.Point(163.28125, 70.3125), new g.Point(171.484375, 71.09375), new g.Point(179.1015625, 75.390625)),
new g.Curve(new g.Point(179.1015625, 75.390625), new g.Point(186.71875, 79.6875), new g.Point(193.75, 87.5), new g.Point(200, 100))
]);
assert.deepEqual(curve.getSubdivisions({ precision: 2 }), [
new g.Curve(new g.Point(0, 100), new g.Point(3.125, 106.25), new g.Point(6.4453125, 111.328125), new g.Point(9.9365234375, 115.380859375)),
new g.Curve(new g.Point(9.9365234375, 115.380859375), new g.Point(13.427734375, 119.43359375), new g.Point(17.08984375, 122.4609375), new g.Point(20.8984375, 124.609375)),
new g.Curve(new g.Point(20.8984375, 124.609375), new g.Point(24.70703125, 126.7578125), new g.Point(28.662109375, 128.02734375), new g.Point(32.7392578125, 128.564453125)),
new g.Curve(new g.Point(32.7392578125, 128.564453125), new g.Point(36.81640625, 129.1015625), new g.Point(41.015625, 128.90625), new g.Point(45.3125, 128.125)),
new g.Curve(new g.Point(45.3125, 128.125), new g.Point(49.609375, 127.34375), new g.Point(54.00390625, 125.9765625), new g.Point(58.4716796875, 124.169921875)),
new g.Curve(new g.Point(58.4716796875, 124.169921875), new g.Point(62.939453125, 122.36328125), new g.Point(67.48046875, 120.1171875), new g.Point(72.0703125, 117.578125)),
new g.Curve(new g.Point(72.0703125, 117.578125), new g.Point(76.66015625, 115.0390625), new g.Point(81.298828125, 112.20703125), new g.Point(85.9619140625, 109.228515625)),
new g.Curve(new g.Point(85.9619140625, 109.228515625), new g.Point(90.625, 106.25), new g.Point(95.3125, 103.125), new g.Point(100, 100)),
new g.Curve(new g.Point(100, 100), new g.Point(104.6875, 96.875), new g.Point(109.375, 93.75), new g.Point(114.0380859375, 90.771484375)),
new g.Curve(new g.Point(114.0380859375, 90.771484375), new g.Point(118.701171875, 87.79296875), new g.Point(123.33984375, 84.9609375), new g.Point(127.9296875, 82.421875)),
new g.Curve(new g.Point(127.9296875, 82.421875), new g.Point(132.51953125, 79.8828125), new g.Point(137.060546875, 77.63671875), new g.Point(141.5283203125, 75.830078125)),
new g.Curve(new g.Point(141.5283203125, 75.830078125), new g.Point(145.99609375, 74.0234375), new g.Point(150.390625, 72.65625), new g.Point(154.6875, 71.875)),
new g.Curve(new g.Point(154.6875, 71.875), new g.Point(158.984375, 71.09375), new g.Point(163.18359375, 70.8984375), new g.Point(167.2607421875, 71.435546875)),
new g.Curve(new g.Point(167.2607421875, 71.435546875), new g.Point(171.337890625, 71.97265625), new g.Point(175.29296875, 73.2421875), new g.Point(179.1015625, 75.390625)),
new g.Curve(new g.Point(179.1015625, 75.390625), new g.Point(182.91015625, 77.5390625), new g.Point(186.572265625, 80.56640625), new g.Point(190.0634765625, 84.619140625)),
new g.Curve(new g.Point(190.0634765625, 84.619140625), new g.Point(193.5546875, 88.671875), new g.Point(196.875, 93.75), new g.Point(200, 100))
]);
});
});
QUnit.module('isDifferentiable()', function() {
QUnit.test('sanity', function(assert) {
var curve;
curve = new g.Curve('0 0', '0 200', '200 200', '200 0');
assert.equal(typeof curve.isDifferentiable(), 'boolean');
curve = new g.Curve('100 100', '100 100', '100 100', '100 0');
assert.equal(typeof curve.isDifferentiable(), 'boolean');
curve = new g.Curve('100 100', '100 100', '100 100', '100 100');
assert.equal(typeof curve.isDifferentiable(), 'boolean');
});
QUnit.test('checks whether the curve is differentiable (can have tangents)', function(assert) {
var curve;
curve = new g.Curve('0 0', '0 200', '200 200', '200 0');
assert.equal(curve.isDifferentiable(), true);
curve = new g.Curve('100 100', '100 100', '100 100', '100 0');
assert.equal(curve.isDifferentiable(), true);
curve = new g.Curve('100 100', '100 100', '100 100', '100 100');
assert.equal(curve.isDifferentiable(), false);
});
});
QUnit.module('length()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 0', '0 200', '200 200', '200 0');
assert.equal(typeof curve.length(), 'number');
assert.equal(typeof curve.length({ precision: 0 }), 'number');
assert.equal(typeof curve.length({ precision: 1 }), 'number');
assert.equal(typeof curve.length({ precision: 2 }), 'number');
assert.equal(typeof curve.length({ precision: 3 }), 'number');
assert.equal(typeof curve.length({ precision: 4 }), 'number');
assert.equal(typeof curve.length({ precision: 5 }), 'number');
});
QUnit.test('returns the length of the curve up to precision', function(assert) {
var curve = new g.Curve('0 0', '0 200', '200 200', '200 0');
assert.equal(curve.length(), 399.96164987703463);
assert.equal(curve.length({ precision: 0 }), 200);
assert.equal(curve.length({ precision: 1 }), 390.1438222301384);
assert.equal(curve.length({ precision: 2 }), 399.38625336882194);
assert.equal(curve.length({ precision: 3 }), 399.96164987703463);
assert.equal(curve.length({ precision: 4 }), 399.99041258236997);
assert.equal(curve.length({ precision: 5 }), 399.9994007886072);
});
QUnit.test('compare to browser implementation', function(assert) {
var svg = getSvg();
var gCurve = new g.Curve('0 0', '0 200', '200 200', '200 0');
var gCurvePath = new g.Path(gCurve);
var curvePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
curvePath.setAttribute('d', gCurvePath.serialize());
svg.appendChild(curvePath);
assert.equal(Math.round(gCurve.length({ precision: 3 })), Math.round(curvePath.getTotalLength()));
svg.remove();
});
});
QUnit.module('lengthAtT()', function() {
QUnit.test('sanity', function(assert) {
var curve = new g.Curve('0 0', '0 200', '200 200', '200 0');
var t = 0.4;
assert.equal(typeof curve.lengthAtT(t), 'number');
assert.equal(typeof curve.lengthAtT(t, { precision: 0 }), 'number');
assert.equal(typeof curve.lengthAtT(t, { precision: 1 }), 'number');
assert.equal(typeof curve.lengthAtT(t, { precision: 2 }), 'number');
assert.equal(typeof curve.lengthAtT(t, { precision: 3 }), 'number');
assert.equal