@js-draw/math
Version:
A math library for js-draw.
224 lines (204 loc) • 5.33 kB
text/typescript
// Tests to ensure that Paths can be deserialized
import Path, { PathCommandType } from './Path';
import { Vec2 } from '../Vec2';
describe('Path.fromString', () => {
it('should handle an empty path', () => {
const path = Path.fromString('');
expect(path.geometry.length).toBe(0);
});
it('should properly handle absolute moveTo commands', () => {
const path1 = Path.fromString('M0,0');
const path2 = Path.fromString('M 0 0');
const path3 = Path.fromString('M 1,1M 2,2 M 3,3');
expect(path1.parts.length).toBe(0);
expect(path1.startPoint).toMatchObject(Vec2.zero);
expect(path2.parts.length).toBe(0);
expect(path2.startPoint).toMatchObject(Vec2.zero);
expect(path3.parts).toMatchObject([
{
kind: PathCommandType.MoveTo,
point: Vec2.of(2, 2),
},
{
kind: PathCommandType.MoveTo,
point: Vec2.of(3, 3),
},
]);
expect(path3.startPoint).toMatchObject(Vec2.of(1, 1));
});
it('should properly handle relative moveTo commands', () => {
const path = Path.fromString('m1,1 m0,0 m 3,3');
expect(path.parts).toMatchObject([
{
kind: PathCommandType.MoveTo,
point: Vec2.of(1, 1),
},
{
kind: PathCommandType.MoveTo,
point: Vec2.of(4, 4),
},
]);
expect(path.startPoint).toMatchObject(Vec2.of(1, 1));
});
it('should handle lineTo commands', () => {
const path = Path.fromString('l1,2L-1,0l0.1,-1.0');
// l is a relative lineTo, but because there
// is no previous command, it should act like an
// absolute moveTo.
expect(path.startPoint).toMatchObject(Vec2.of(1, 2));
expect(path.parts).toMatchObject([
{
kind: PathCommandType.LineTo,
point: Vec2.of(-1, 0),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(-0.9, -1.0),
},
]);
});
it('"z" should close strokes', () => {
const path1 = Path.fromString('m3,3 l1,2 l1,1 z');
const path2 = Path.fromString('m3,3 l1,2 l1,1 Z');
expect(path1.startPoint).toMatchObject(Vec2.of(3, 3));
expect(path2.startPoint).toMatchObject(path1.startPoint);
expect(path1.parts).toMatchObject(path2.parts);
expect(path1.parts).toMatchObject([
{
kind: PathCommandType.LineTo,
point: Vec2.of(4, 5),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(5, 6),
},
{
kind: PathCommandType.LineTo,
point: path1.startPoint,
},
]);
});
it('should break compoents at -s', () => {
const path = Path.fromString('m1-1 L-1-1-3-4-5-6,5-1');
expect(path.parts.length).toBe(4);
expect(path.parts).toMatchObject([
{
kind: PathCommandType.LineTo,
point: Vec2.of(-1, -1),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(-3, -4),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(-5, -6),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(5, -1),
},
]);
});
it('should properly handle cubic Bézier curves', () => {
const path = Path.fromString('m1,1 c1,1 0-3 4 5 C1,1 0.1, 0.1 0, 0');
expect(path.parts.length).toBe(2);
expect(path.parts).toMatchObject([
{
kind: PathCommandType.CubicBezierTo,
controlPoint1: Vec2.of(2, 2),
controlPoint2: Vec2.of(1, -2),
endPoint: Vec2.of(5, 6),
},
{
kind: PathCommandType.CubicBezierTo,
controlPoint1: Vec2.of(1, 1),
controlPoint2: Vec2.of(0.1, 0.1),
endPoint: Vec2.zero,
},
]);
});
it('should handle quadratic Bézier curves', () => {
const path = Path.fromString(' Q1 1,2 3 q-1 -2,-3 -4 Q 1 2,3 4');
expect(path.parts).toMatchObject([
{
kind: PathCommandType.QuadraticBezierTo,
controlPoint: Vec2.of(1, 1),
endPoint: Vec2.of(2, 3),
},
{
kind: PathCommandType.QuadraticBezierTo,
controlPoint: Vec2.of(1, 1),
endPoint: Vec2.of(-1, -1),
},
{
kind: PathCommandType.QuadraticBezierTo,
controlPoint: Vec2.of(1, 2),
endPoint: Vec2.of(3, 4),
},
]);
expect(path.startPoint).toMatchObject(Vec2.of(1, 1));
});
it('should correctly handle a command followed by multiple sets of arguments', () => {
// Commands followed by multiple sets of arguments, for example,
// l 5,10 5,4 3,2,
// should be interpreted as multiple commands. Our example, is therefore equivalent to,
// l 5,10 l 5,4 l 3,2
const path = Path.fromString(`
L5,10 1,1
2,2 -3,-1
q 1,2 1,1
-1,-1 -3,-4
h -4 -1
V 3 5 1
`);
expect(path.parts).toMatchObject([
{
kind: PathCommandType.LineTo,
point: Vec2.of(1, 1),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(2, 2),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(-3, -1),
},
// q 1,2 1,1 -1,-1 -3,-4
{
kind: PathCommandType.QuadraticBezierTo,
controlPoint: Vec2.of(-2, 1),
endPoint: Vec2.of(-2, 0),
},
{
kind: PathCommandType.QuadraticBezierTo,
controlPoint: Vec2.of(-3, -1),
endPoint: Vec2.of(-5, -4),
},
// h -4 -1
{
kind: PathCommandType.LineTo,
point: Vec2.of(-9, -4),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(-10, -4),
},
// V 3 5 1
{
kind: PathCommandType.LineTo,
point: Vec2.of(-10, 3),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(-10, 5),
},
{
kind: PathCommandType.LineTo,
point: Vec2.of(-10, 1),
},
]);
expect(path.startPoint).toMatchObject(Vec2.of(5, 10));
});
});