@remotion/paths 4.0.164 → 4.0.165
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/debug-path.d.ts +6 -0
- package/dist/debug-path.js +57 -0
- package/dist/get-end-position.d.ts +2 -0
- package/dist/get-end-position.js +70 -0
- package/dist/helpers/types.d.ts +13 -12
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -1
- package/dist/interpolate-path/{convert-to-same-type.d.ts → convert-to-same-instruction-type.d.ts} +2 -2
- package/dist/interpolate-path/convert-to-same-instruction-type.js +109 -0
- package/dist/interpolate-path/de-casteljau.d.ts +14 -0
- package/dist/interpolate-path/de-casteljau.js +44 -0
- package/dist/interpolate-path/extend-command.d.ts +2 -2
- package/dist/interpolate-path/extend-command.js +8 -7
- package/dist/interpolate-path/interpolate-instruction-of-same-kind.d.ts +2 -0
- package/dist/interpolate-path/interpolate-instruction-of-same-kind.js +73 -0
- package/dist/interpolate-path/interpolate-instructions.d.ts +16 -0
- package/dist/interpolate-path/interpolate-instructions.js +92 -0
- package/dist/interpolate-path/interpolate-path.js +8 -116
- package/dist/interpolate-path/points-to-command.d.ts +9 -0
- package/dist/interpolate-path/points-to-command.js +46 -0
- package/dist/interpolate-path/split-curve-as-points.d.ts +8 -0
- package/dist/interpolate-path/split-curve-as-points.js +40 -0
- package/dist/interpolate-path/split-curve.d.ts +3 -3
- package/dist/interpolate-path/split-curve.js +18 -122
- package/dist/interpolate-path/split-segment.d.ts +2 -2
- package/dist/interpolate-path/split-segment.js +12 -12
- package/dist/warp-path/warp-helpers.d.ts +0 -3
- package/dist/warp-path/warp-helpers.js +1 -4
- package/package.json +1 -1
- package/dist/interpolate-path/array-of-length.d.ts +0 -1
- package/dist/interpolate-path/array-of-length.js +0 -11
- package/dist/interpolate-path/command-to-string.d.ts +0 -7
- package/dist/interpolate-path/command-to-string.js +0 -15
- package/dist/interpolate-path/command.d.ts +0 -37
- package/dist/interpolate-path/command.js +0 -28
- package/dist/interpolate-path/convert-to-same-type.js +0 -68
- package/dist/interpolate-path/path-commands-from-string.d.ts +0 -8
- package/dist/interpolate-path/path-commands-from-string.js +0 -40
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.debugPath = void 0;
|
|
4
|
+
const normalize_path_1 = require("./normalize-path");
|
|
5
|
+
const parse_path_1 = require("./parse-path");
|
|
6
|
+
const serialize_instructions_1 = require("./serialize-instructions");
|
|
7
|
+
const debugPath = (d) => {
|
|
8
|
+
const instructions = (0, normalize_path_1.normalizeInstructions)((0, parse_path_1.parsePath)(d));
|
|
9
|
+
return instructions
|
|
10
|
+
.map((inst, i) => {
|
|
11
|
+
if (inst.type === 'Z') {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
if (inst.type === 'H' || inst.type === 'V') {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const topLeft = [inst.x - 5, inst.y - 5];
|
|
18
|
+
const topRight = [inst.x + 5, inst.y - 5];
|
|
19
|
+
const bottomLeft = [inst.x - 5, inst.y + 5];
|
|
20
|
+
const bottomRight = [inst.x + 5, inst.y + 5];
|
|
21
|
+
const triangle = [
|
|
22
|
+
{
|
|
23
|
+
type: 'M',
|
|
24
|
+
x: topLeft[0],
|
|
25
|
+
y: topLeft[1],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
type: 'L',
|
|
29
|
+
x: topRight[0],
|
|
30
|
+
y: topRight[1],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
type: 'L',
|
|
34
|
+
x: bottomRight[0],
|
|
35
|
+
y: bottomRight[1],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
type: 'L',
|
|
39
|
+
x: bottomLeft[0],
|
|
40
|
+
y: bottomLeft[1],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'Z',
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
return {
|
|
47
|
+
d: (0, serialize_instructions_1.serializeInstructions)(triangle),
|
|
48
|
+
color: i === instructions.length - 1
|
|
49
|
+
? 'red'
|
|
50
|
+
: inst.type === 'M'
|
|
51
|
+
? 'blue'
|
|
52
|
+
: 'green',
|
|
53
|
+
};
|
|
54
|
+
})
|
|
55
|
+
.filter(Boolean);
|
|
56
|
+
};
|
|
57
|
+
exports.debugPath = debugPath;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getEndPosition = void 0;
|
|
4
|
+
const getEndPosition = (instructions) => {
|
|
5
|
+
let x = 0;
|
|
6
|
+
let y = 0;
|
|
7
|
+
let moveX = 0;
|
|
8
|
+
let moveY = 0;
|
|
9
|
+
for (let i = 0; i < instructions.length; i++) {
|
|
10
|
+
const instruction = instructions[i];
|
|
11
|
+
if (instruction.type === 'M') {
|
|
12
|
+
moveX = instruction.x;
|
|
13
|
+
moveY = instruction.y;
|
|
14
|
+
}
|
|
15
|
+
else if (instruction.type === 'm') {
|
|
16
|
+
moveX += instruction.dx;
|
|
17
|
+
moveY += instruction.dy;
|
|
18
|
+
}
|
|
19
|
+
if (instruction.type === 'A' ||
|
|
20
|
+
instruction.type === 'C' ||
|
|
21
|
+
instruction.type === 'L' ||
|
|
22
|
+
instruction.type === 'M' ||
|
|
23
|
+
instruction.type === 'Q' ||
|
|
24
|
+
instruction.type === 'S' ||
|
|
25
|
+
instruction.type === 'T') {
|
|
26
|
+
x = instruction.x;
|
|
27
|
+
y = instruction.y;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (instruction.type === 'a' ||
|
|
31
|
+
instruction.type === 'c' ||
|
|
32
|
+
instruction.type === 'l' ||
|
|
33
|
+
instruction.type === 'm' ||
|
|
34
|
+
instruction.type === 'q' ||
|
|
35
|
+
instruction.type === 's' ||
|
|
36
|
+
instruction.type === 't') {
|
|
37
|
+
x += instruction.dx;
|
|
38
|
+
y += instruction.dy;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (instruction.type === 'H') {
|
|
42
|
+
x = instruction.x;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (instruction.type === 'V') {
|
|
46
|
+
y = instruction.y;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (instruction.type === 'Z') {
|
|
50
|
+
x = moveX;
|
|
51
|
+
y = moveY;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (instruction.type === 'h') {
|
|
55
|
+
x += instruction.dx;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (instruction.type === 'v') {
|
|
59
|
+
y += instruction.dy;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// @ts-expect-error
|
|
63
|
+
throw new Error('Unknown instruction type: ' + instruction.type);
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
x,
|
|
67
|
+
y,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
exports.getEndPosition = getEndPosition;
|
package/dist/helpers/types.d.ts
CHANGED
|
@@ -16,10 +16,6 @@ export interface Point {
|
|
|
16
16
|
y: number;
|
|
17
17
|
}
|
|
18
18
|
export type PointArray = [number, number];
|
|
19
|
-
export interface PointProperties {
|
|
20
|
-
tangentX: number;
|
|
21
|
-
tangentY: number;
|
|
22
|
-
}
|
|
23
19
|
export type BoundingBox = {
|
|
24
20
|
x1: number;
|
|
25
21
|
y1: number;
|
|
@@ -29,15 +25,12 @@ export type BoundingBox = {
|
|
|
29
25
|
width: number;
|
|
30
26
|
height: number;
|
|
31
27
|
};
|
|
32
|
-
export type
|
|
33
|
-
type: 'M';
|
|
34
|
-
x: number;
|
|
35
|
-
y: number;
|
|
36
|
-
} | {
|
|
28
|
+
export type LInstruction = {
|
|
37
29
|
type: 'L';
|
|
38
30
|
x: number;
|
|
39
31
|
y: number;
|
|
40
|
-
}
|
|
32
|
+
};
|
|
33
|
+
export type CInstruction = {
|
|
41
34
|
type: 'C';
|
|
42
35
|
cp1x: number;
|
|
43
36
|
cp1y: number;
|
|
@@ -45,15 +38,23 @@ export type ReducedInstruction = {
|
|
|
45
38
|
cp2y: number;
|
|
46
39
|
x: number;
|
|
47
40
|
y: number;
|
|
48
|
-
}
|
|
41
|
+
};
|
|
42
|
+
export type MInstruction = {
|
|
43
|
+
type: 'M';
|
|
44
|
+
x: number;
|
|
45
|
+
y: number;
|
|
46
|
+
};
|
|
47
|
+
export type QInstruction = {
|
|
49
48
|
type: 'Q';
|
|
50
49
|
cpx: number;
|
|
51
50
|
cpy: number;
|
|
52
51
|
x: number;
|
|
53
52
|
y: number;
|
|
54
|
-
}
|
|
53
|
+
};
|
|
54
|
+
export type ZInstruction = {
|
|
55
55
|
type: 'Z';
|
|
56
56
|
};
|
|
57
|
+
export type ReducedInstruction = MInstruction | LInstruction | CInstruction | QInstruction | ZInstruction;
|
|
57
58
|
export type AbsoluteInstruction = ReducedInstruction | {
|
|
58
59
|
type: 'A';
|
|
59
60
|
rx: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { getPointAtLength } from './get-point-at-length';
|
|
|
7
7
|
export { getSubpaths } from './get-subpaths';
|
|
8
8
|
export { getTangentAtLength } from './get-tangent-at-length';
|
|
9
9
|
export { AbsoluteInstruction, BoundingBox, Instruction, Part, ReducedInstruction, } from './helpers/types';
|
|
10
|
-
export { interpolatePath } from './interpolate-path';
|
|
10
|
+
export { interpolatePath } from './interpolate-path/interpolate-path';
|
|
11
11
|
export { normalizePath } from './normalize-path';
|
|
12
12
|
export { parsePath } from './parse-path';
|
|
13
13
|
export { reduceInstructions } from './reduce-instructions';
|
|
@@ -19,4 +19,8 @@ export { translatePath } from './translate-path';
|
|
|
19
19
|
export { WarpPathFn, warpPath } from './warp-path';
|
|
20
20
|
export declare const PathInternals: {
|
|
21
21
|
getBoundingBoxFromInstructions: (instructions: import("./helpers/types").ReducedInstruction[]) => import("./helpers/types").BoundingBox;
|
|
22
|
+
debugPath: (d: string) => {
|
|
23
|
+
d: string;
|
|
24
|
+
color: string;
|
|
25
|
+
}[];
|
|
22
26
|
};
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PathInternals = exports.warpPath = exports.translatePath = exports.serializeInstructions = exports.scalePath = exports.reversePath = exports.resetPath = exports.reduceInstructions = exports.parsePath = exports.normalizePath = exports.interpolatePath = exports.getTangentAtLength = exports.getSubpaths = exports.getPointAtLength = exports.getLength = exports.getInstructionIndexAtLength = exports.getBoundingBox = exports.extendViewBox = exports.evolvePath = void 0;
|
|
4
4
|
const get_bounding_box_1 = require("./get-bounding-box");
|
|
5
|
+
const debug_path_1 = require("./debug-path");
|
|
5
6
|
var evolve_path_1 = require("./evolve-path");
|
|
6
7
|
Object.defineProperty(exports, "evolvePath", { enumerable: true, get: function () { return evolve_path_1.evolvePath; } });
|
|
7
8
|
var extend_viewbox_1 = require("./extend-viewbox");
|
|
@@ -18,7 +19,7 @@ var get_subpaths_1 = require("./get-subpaths");
|
|
|
18
19
|
Object.defineProperty(exports, "getSubpaths", { enumerable: true, get: function () { return get_subpaths_1.getSubpaths; } });
|
|
19
20
|
var get_tangent_at_length_1 = require("./get-tangent-at-length");
|
|
20
21
|
Object.defineProperty(exports, "getTangentAtLength", { enumerable: true, get: function () { return get_tangent_at_length_1.getTangentAtLength; } });
|
|
21
|
-
var interpolate_path_1 = require("./interpolate-path");
|
|
22
|
+
var interpolate_path_1 = require("./interpolate-path/interpolate-path");
|
|
22
23
|
Object.defineProperty(exports, "interpolatePath", { enumerable: true, get: function () { return interpolate_path_1.interpolatePath; } });
|
|
23
24
|
var normalize_path_1 = require("./normalize-path");
|
|
24
25
|
Object.defineProperty(exports, "normalizePath", { enumerable: true, get: function () { return normalize_path_1.normalizePath; } });
|
|
@@ -40,4 +41,5 @@ var warp_path_1 = require("./warp-path");
|
|
|
40
41
|
Object.defineProperty(exports, "warpPath", { enumerable: true, get: function () { return warp_path_1.warpPath; } });
|
|
41
42
|
exports.PathInternals = {
|
|
42
43
|
getBoundingBoxFromInstructions: get_bounding_box_1.getBoundingBoxFromInstructions,
|
|
44
|
+
debugPath: debug_path_1.debugPath,
|
|
43
45
|
};
|
package/dist/interpolate-path/{convert-to-same-type.d.ts → convert-to-same-instruction-type.d.ts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Point, ReducedInstruction } from '../helpers/types';
|
|
2
2
|
/**
|
|
3
3
|
* Converts command A to have the same type as command B.
|
|
4
4
|
*
|
|
@@ -19,4 +19,4 @@ import type { Command } from './command';
|
|
|
19
19
|
* @param {Object} bCommand Command object from path `d` attribute to match against
|
|
20
20
|
* @return {Object} aCommand converted to type of bCommand
|
|
21
21
|
*/
|
|
22
|
-
export declare function
|
|
22
|
+
export declare function convertToSameInstructionType(aCommand: ReducedInstruction, bCommand: ReducedInstruction, currentPoint: Point): ReducedInstruction;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertToSameInstructionType = void 0;
|
|
4
|
+
const convertToLCommand = (command) => {
|
|
5
|
+
if (command.type === 'M' || command.type === 'L' || command.type === 'Z') {
|
|
6
|
+
throw new Error('unexpected');
|
|
7
|
+
}
|
|
8
|
+
return {
|
|
9
|
+
type: 'L',
|
|
10
|
+
x: command.x,
|
|
11
|
+
y: command.y,
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
const convertToCCommand = (command, currentPoint) => {
|
|
15
|
+
if (command.type === 'M' || command.type === 'C' || command.type === 'Z') {
|
|
16
|
+
throw new Error('unexpected');
|
|
17
|
+
}
|
|
18
|
+
if (command.type === 'L') {
|
|
19
|
+
return {
|
|
20
|
+
type: 'C',
|
|
21
|
+
cp1x: currentPoint.x,
|
|
22
|
+
cp1y: currentPoint.y,
|
|
23
|
+
cp2x: command.x,
|
|
24
|
+
cp2y: command.y,
|
|
25
|
+
x: command.x,
|
|
26
|
+
y: command.y,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (command.type === 'Q') {
|
|
30
|
+
return {
|
|
31
|
+
type: 'C',
|
|
32
|
+
cp1x: command.cpx,
|
|
33
|
+
cp1y: command.cpy,
|
|
34
|
+
cp2x: command.cpx,
|
|
35
|
+
cp2y: command.cpy,
|
|
36
|
+
x: command.x,
|
|
37
|
+
y: command.y,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
throw new Error('all types should be handled');
|
|
41
|
+
};
|
|
42
|
+
const convertToQCommand = (command) => {
|
|
43
|
+
if (command.type === 'M' || command.type === 'Q' || command.type === 'Z') {
|
|
44
|
+
throw new Error('unexpected');
|
|
45
|
+
}
|
|
46
|
+
if (command.type === 'C') {
|
|
47
|
+
return {
|
|
48
|
+
type: 'Q',
|
|
49
|
+
cpx: command.cp1x,
|
|
50
|
+
cpy: command.cp1y,
|
|
51
|
+
x: command.x,
|
|
52
|
+
y: command.y,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (command.type === 'L') {
|
|
56
|
+
return {
|
|
57
|
+
type: 'Q',
|
|
58
|
+
cpx: command.x,
|
|
59
|
+
cpy: command.y,
|
|
60
|
+
x: command.x,
|
|
61
|
+
y: command.y,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
throw new Error('unhandled');
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Converts command A to have the same type as command B.
|
|
68
|
+
*
|
|
69
|
+
* e.g., L0,5 -> C0,5,0,5,0,5
|
|
70
|
+
*
|
|
71
|
+
* Uses these rules:
|
|
72
|
+
* x1 <- x
|
|
73
|
+
* x2 <- x
|
|
74
|
+
* y1 <- y
|
|
75
|
+
* y2 <- y
|
|
76
|
+
* rx <- 0
|
|
77
|
+
* ry <- 0
|
|
78
|
+
* xAxisRotation <- read from B
|
|
79
|
+
* largeArcFlag <- read from B
|
|
80
|
+
* sweepflag <- read from B
|
|
81
|
+
*
|
|
82
|
+
* @param {Object} aCommand Command object from path `d` attribute
|
|
83
|
+
* @param {Object} bCommand Command object from path `d` attribute to match against
|
|
84
|
+
* @return {Object} aCommand converted to type of bCommand
|
|
85
|
+
*/
|
|
86
|
+
function convertToSameInstructionType(aCommand, bCommand, currentPoint) {
|
|
87
|
+
if (aCommand.type === 'M' || bCommand.type === 'M') {
|
|
88
|
+
return { ...aCommand };
|
|
89
|
+
}
|
|
90
|
+
if (aCommand.type === bCommand.type) {
|
|
91
|
+
return { ...aCommand };
|
|
92
|
+
}
|
|
93
|
+
if (bCommand.type === 'C') {
|
|
94
|
+
return convertToCCommand(aCommand, currentPoint);
|
|
95
|
+
}
|
|
96
|
+
if (bCommand.type === 'L') {
|
|
97
|
+
return convertToLCommand(aCommand);
|
|
98
|
+
}
|
|
99
|
+
if (bCommand.type === 'Q') {
|
|
100
|
+
return convertToQCommand(aCommand);
|
|
101
|
+
}
|
|
102
|
+
if (bCommand.type === 'Z') {
|
|
103
|
+
return {
|
|
104
|
+
type: 'Z',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
throw new TypeError('unhandled');
|
|
108
|
+
}
|
|
109
|
+
exports.convertToSameInstructionType = convertToSameInstructionType;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* de Casteljau's algorithm for drawing and splitting bezier curves.
|
|
3
|
+
* Inspired by https://pomax.github.io/bezierinfo/
|
|
4
|
+
*
|
|
5
|
+
* @param {Number[][]} points Array of [x,y] points: [start, control1, control2, ..., end]
|
|
6
|
+
* The original segment to split.
|
|
7
|
+
* @param {Number} t Where to split the curve (value between [0, 1])
|
|
8
|
+
* @return {Object} An object { left, right } where left is the segment from 0..t and
|
|
9
|
+
* right is the segment from t..1.
|
|
10
|
+
*/
|
|
11
|
+
export declare function decasteljau(points: number[][], t: number): {
|
|
12
|
+
left: number[][];
|
|
13
|
+
right: number[][];
|
|
14
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decasteljau = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* de Casteljau's algorithm for drawing and splitting bezier curves.
|
|
6
|
+
* Inspired by https://pomax.github.io/bezierinfo/
|
|
7
|
+
*
|
|
8
|
+
* @param {Number[][]} points Array of [x,y] points: [start, control1, control2, ..., end]
|
|
9
|
+
* The original segment to split.
|
|
10
|
+
* @param {Number} t Where to split the curve (value between [0, 1])
|
|
11
|
+
* @return {Object} An object { left, right } where left is the segment from 0..t and
|
|
12
|
+
* right is the segment from t..1.
|
|
13
|
+
*/
|
|
14
|
+
function decasteljau(points, t) {
|
|
15
|
+
const left = [];
|
|
16
|
+
const right = [];
|
|
17
|
+
function decasteljauRecurse(_points, _t) {
|
|
18
|
+
if (_points.length === 1) {
|
|
19
|
+
left.push(_points[0]);
|
|
20
|
+
right.push(_points[0]);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
const newPoints = Array(_points.length - 1);
|
|
24
|
+
for (let i = 0; i < newPoints.length; i++) {
|
|
25
|
+
if (i === 0) {
|
|
26
|
+
left.push(_points[0]);
|
|
27
|
+
}
|
|
28
|
+
if (i === newPoints.length - 1) {
|
|
29
|
+
right.push(_points[i + 1]);
|
|
30
|
+
}
|
|
31
|
+
newPoints[i] = [
|
|
32
|
+
(1 - _t) * _points[i][0] + _t * _points[i + 1][0],
|
|
33
|
+
(1 - _t) * _points[i][1] + _t * _points[i + 1][1],
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
decasteljauRecurse(newPoints, _t);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (points.length) {
|
|
40
|
+
decasteljauRecurse(points, t);
|
|
41
|
+
}
|
|
42
|
+
return { left, right: right.reverse() };
|
|
43
|
+
}
|
|
44
|
+
exports.decasteljau = decasteljau;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ReducedInstruction } from '../helpers/types';
|
|
2
2
|
/**
|
|
3
3
|
* Extends an array of commandsToExtend to the length of the referenceCommands by
|
|
4
4
|
* splitting segments until the number of commands match. Ensures all the actual
|
|
@@ -8,4 +8,4 @@ import type { Command } from './command';
|
|
|
8
8
|
* @param {Object[]} referenceCommands The command object array to match in length
|
|
9
9
|
* @return {Object[]} The extended commandsToExtend array
|
|
10
10
|
*/
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function extendInstruction(commandsToExtend: ReducedInstruction[], referenceCommands: ReducedInstruction[]): ReducedInstruction[];
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const array_of_length_1 = require("./array-of-length");
|
|
3
|
+
exports.extendInstruction = void 0;
|
|
5
4
|
const split_segment_1 = require("./split-segment");
|
|
6
5
|
/**
|
|
7
6
|
* Extends an array of commandsToExtend to the length of the referenceCommands by
|
|
@@ -12,7 +11,7 @@ const split_segment_1 = require("./split-segment");
|
|
|
12
11
|
* @param {Object[]} referenceCommands The command object array to match in length
|
|
13
12
|
* @return {Object[]} The extended commandsToExtend array
|
|
14
13
|
*/
|
|
15
|
-
function
|
|
14
|
+
function extendInstruction(commandsToExtend, referenceCommands) {
|
|
16
15
|
// compute insertion points:
|
|
17
16
|
// number of segments in the path to extend
|
|
18
17
|
const numSegmentsToExtend = commandsToExtend.length - 1;
|
|
@@ -24,7 +23,9 @@ function extend(commandsToExtend, referenceCommands) {
|
|
|
24
23
|
// should be added in that segment (should always be >= 1 since we need each
|
|
25
24
|
// point itself).
|
|
26
25
|
// 0 = segment 0-1, 1 = segment 1-2, n-1 = last vertex
|
|
27
|
-
const countPointsPerSegment =
|
|
26
|
+
const countPointsPerSegment = new Array(numReferenceSegments)
|
|
27
|
+
.fill(undefined)
|
|
28
|
+
.reduce((accum, _d, i) => {
|
|
28
29
|
const insertIndex = Math.floor(segmentRatio * i);
|
|
29
30
|
accum[insertIndex] = (accum[insertIndex] || 0) + 1;
|
|
30
31
|
return accum;
|
|
@@ -33,7 +34,7 @@ function extend(commandsToExtend, referenceCommands) {
|
|
|
33
34
|
const extended = countPointsPerSegment.reduce((_extended, segmentCount, i) => {
|
|
34
35
|
// if last command, just add `segmentCount` number of times
|
|
35
36
|
if (i === commandsToExtend.length - 1) {
|
|
36
|
-
const lastCommandCopies = (
|
|
37
|
+
const lastCommandCopies = new Array(segmentCount).fill({
|
|
37
38
|
...commandsToExtend[commandsToExtend.length - 1],
|
|
38
39
|
});
|
|
39
40
|
// convert M to L
|
|
@@ -45,10 +46,10 @@ function extend(commandsToExtend, referenceCommands) {
|
|
|
45
46
|
return _extended.concat(lastCommandCopies);
|
|
46
47
|
}
|
|
47
48
|
// otherwise, split the segment segmentCount times.
|
|
48
|
-
return _extended.concat((0, split_segment_1.
|
|
49
|
+
return _extended.concat((0, split_segment_1.splitSegmentInstructions)(commandsToExtend[i], commandsToExtend[i + 1], segmentCount));
|
|
49
50
|
}, []);
|
|
50
51
|
// add in the very first point since splitSegment only adds in the ones after it
|
|
51
52
|
extended.unshift(commandsToExtend[0]);
|
|
52
53
|
return extended;
|
|
53
54
|
}
|
|
54
|
-
exports.
|
|
55
|
+
exports.extendInstruction = extendInstruction;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { CInstruction, LInstruction, MInstruction, QInstruction, ReducedInstruction, ZInstruction } from '../helpers/types';
|
|
2
|
+
export declare const interpolateInstructionOfSameKind: (t: number, first: ReducedInstruction, second: ReducedInstruction) => LInstruction | CInstruction | MInstruction | QInstruction | ZInstruction;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.interpolateInstructionOfSameKind = void 0;
|
|
4
|
+
const interpolateLInstruction = (t, first, second) => {
|
|
5
|
+
return {
|
|
6
|
+
type: 'L',
|
|
7
|
+
x: (1 - t) * first.x + t * second.x,
|
|
8
|
+
y: (1 - t) * first.y + t * second.y,
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
const interpolateCInstructions = (t, first, second) => {
|
|
12
|
+
return {
|
|
13
|
+
type: 'C',
|
|
14
|
+
cp1x: (1 - t) * first.cp1x + t * second.cp1x,
|
|
15
|
+
cp2x: (1 - t) * first.cp2x + t * second.cp2x,
|
|
16
|
+
cp1y: (1 - t) * first.cp1y + t * second.cp1y,
|
|
17
|
+
cp2y: (1 - t) * first.cp2y + t * second.cp2y,
|
|
18
|
+
x: (1 - t) * first.x + t * second.x,
|
|
19
|
+
y: (1 - t) * first.y + t * second.y,
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
const interpolateQInstructions = (t, first, second) => {
|
|
23
|
+
return {
|
|
24
|
+
type: 'Q',
|
|
25
|
+
cpx: (1 - t) * first.cpx + t * second.cpx,
|
|
26
|
+
cpy: (1 - t) * first.cpy + t * second.cpy,
|
|
27
|
+
x: (1 - t) * first.x + t * second.x,
|
|
28
|
+
y: (1 - t) * first.y + t * second.y,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
const interpolateMInstructions = (t, first, second) => {
|
|
32
|
+
return {
|
|
33
|
+
type: 'M',
|
|
34
|
+
x: (1 - t) * first.x + t * second.x,
|
|
35
|
+
y: (1 - t) * first.y + t * second.y,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const interpolateInstructionOfSameKind = (t, first, second) => {
|
|
39
|
+
if (first.type === 'L') {
|
|
40
|
+
if (second.type !== 'L') {
|
|
41
|
+
throw new Error('mismatch');
|
|
42
|
+
}
|
|
43
|
+
return interpolateLInstruction(t, first, second);
|
|
44
|
+
}
|
|
45
|
+
if (first.type === 'C') {
|
|
46
|
+
if (second.type !== 'C') {
|
|
47
|
+
throw new Error('mismatch');
|
|
48
|
+
}
|
|
49
|
+
return interpolateCInstructions(t, first, second);
|
|
50
|
+
}
|
|
51
|
+
if (first.type === 'Q') {
|
|
52
|
+
if (second.type !== 'Q') {
|
|
53
|
+
throw new Error('mismatch');
|
|
54
|
+
}
|
|
55
|
+
return interpolateQInstructions(t, first, second);
|
|
56
|
+
}
|
|
57
|
+
if (first.type === 'M') {
|
|
58
|
+
if (second.type !== 'M') {
|
|
59
|
+
throw new Error('mismatch');
|
|
60
|
+
}
|
|
61
|
+
return interpolateMInstructions(t, first, second);
|
|
62
|
+
}
|
|
63
|
+
if (first.type === 'Z') {
|
|
64
|
+
if (second.type !== 'Z') {
|
|
65
|
+
throw new Error('mismatch');
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
type: 'Z',
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
throw new Error('mismatch');
|
|
72
|
+
};
|
|
73
|
+
exports.interpolateInstructionOfSameKind = interpolateInstructionOfSameKind;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ReducedInstruction } from '../helpers/types';
|
|
2
|
+
/**
|
|
3
|
+
* Interpolate from A to B by extending A and B during interpolation to have
|
|
4
|
+
* the same number of points. This allows for a smooth transition when they
|
|
5
|
+
* have a different number of points.
|
|
6
|
+
*
|
|
7
|
+
* Ignores the `Z` command in paths unless both A and B end with it.
|
|
8
|
+
*
|
|
9
|
+
* This function works directly with arrays of command objects instead of with
|
|
10
|
+
* path `d` strings (see interpolatePath for working with `d` strings).
|
|
11
|
+
*
|
|
12
|
+
* @param {Object[]} aCommandsInput Array of path commands
|
|
13
|
+
* @param {Object[]} bCommandsInput Array of path commands
|
|
14
|
+
* @returns {Function} Interpolation function that maps t ([0, 1]) to an array of path commands.
|
|
15
|
+
*/
|
|
16
|
+
export declare function interpolateInstructions(aCommandsInput: ReducedInstruction[], bCommandsInput: ReducedInstruction[]): (t: number) => ReducedInstruction[];
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.interpolateInstructions = void 0;
|
|
4
|
+
const get_end_position_1 = require("../get-end-position");
|
|
5
|
+
const convert_to_same_instruction_type_1 = require("./convert-to-same-instruction-type");
|
|
6
|
+
const extend_command_1 = require("./extend-command");
|
|
7
|
+
const interpolate_instruction_of_same_kind_1 = require("./interpolate-instruction-of-same-kind");
|
|
8
|
+
/**
|
|
9
|
+
* Interpolate from A to B by extending A and B during interpolation to have
|
|
10
|
+
* the same number of points. This allows for a smooth transition when they
|
|
11
|
+
* have a different number of points.
|
|
12
|
+
*
|
|
13
|
+
* Ignores the `Z` command in paths unless both A and B end with it.
|
|
14
|
+
*
|
|
15
|
+
* This function works directly with arrays of command objects instead of with
|
|
16
|
+
* path `d` strings (see interpolatePath for working with `d` strings).
|
|
17
|
+
*
|
|
18
|
+
* @param {Object[]} aCommandsInput Array of path commands
|
|
19
|
+
* @param {Object[]} bCommandsInput Array of path commands
|
|
20
|
+
* @returns {Function} Interpolation function that maps t ([0, 1]) to an array of path commands.
|
|
21
|
+
*/
|
|
22
|
+
function interpolateInstructions(aCommandsInput, bCommandsInput) {
|
|
23
|
+
// make a copy so we don't mess with the input arrays
|
|
24
|
+
let aCommands = aCommandsInput.slice();
|
|
25
|
+
let bCommands = bCommandsInput.slice();
|
|
26
|
+
// both input sets are empty, so we don't interpolate
|
|
27
|
+
if (!aCommands.length && !bCommands.length) {
|
|
28
|
+
return function () {
|
|
29
|
+
return [];
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// do we add Z during interpolation? yes if both have it. (we'd expect both to have it or not)
|
|
33
|
+
const addZ = (aCommands.length === 0 || aCommands[aCommands.length - 1].type === 'Z') &&
|
|
34
|
+
(bCommands.length === 0 || bCommands[bCommands.length - 1].type === 'Z');
|
|
35
|
+
// we temporarily remove Z
|
|
36
|
+
if (aCommands.length > 0 && aCommands[aCommands.length - 1].type === 'Z') {
|
|
37
|
+
aCommands.pop();
|
|
38
|
+
}
|
|
39
|
+
if (bCommands.length > 0 && bCommands[bCommands.length - 1].type === 'Z') {
|
|
40
|
+
bCommands.pop();
|
|
41
|
+
}
|
|
42
|
+
// if A is empty, treat it as if it used to contain just the first point
|
|
43
|
+
// of B. This makes it so the line extends out of from that first point.
|
|
44
|
+
if (!aCommands.length) {
|
|
45
|
+
aCommands.push(bCommands[0]);
|
|
46
|
+
// otherwise if B is empty, treat it as if it contains the first point
|
|
47
|
+
// of A. This makes it so the line retracts into the first point.
|
|
48
|
+
}
|
|
49
|
+
else if (!bCommands.length) {
|
|
50
|
+
bCommands.push(aCommands[0]);
|
|
51
|
+
}
|
|
52
|
+
// extend to match equal size
|
|
53
|
+
const numPointsToExtend = Math.abs(bCommands.length - aCommands.length);
|
|
54
|
+
if (numPointsToExtend !== 0) {
|
|
55
|
+
// B has more points than A, so add points to A before interpolating
|
|
56
|
+
if (bCommands.length > aCommands.length) {
|
|
57
|
+
aCommands = (0, extend_command_1.extendInstruction)(aCommands, bCommands);
|
|
58
|
+
// else if A has more points than B, add more points to B
|
|
59
|
+
}
|
|
60
|
+
else if (bCommands.length < aCommands.length) {
|
|
61
|
+
bCommands = (0, extend_command_1.extendInstruction)(bCommands, aCommands);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// commands have same length now.
|
|
65
|
+
// convert commands in A to the same type as those in B
|
|
66
|
+
const aSameType = aCommands.map((aCommand, i) => {
|
|
67
|
+
const commandsUntilNow = aCommands.slice(0, i);
|
|
68
|
+
const point = (0, get_end_position_1.getEndPosition)(commandsUntilNow);
|
|
69
|
+
return (0, convert_to_same_instruction_type_1.convertToSameInstructionType)(aCommand, bCommands[i], point);
|
|
70
|
+
});
|
|
71
|
+
const interpolatedCommands = [];
|
|
72
|
+
if (addZ) {
|
|
73
|
+
aSameType.push({ type: 'Z' }); // required for when returning at t == 0
|
|
74
|
+
bCommands.push({ type: 'Z' });
|
|
75
|
+
}
|
|
76
|
+
return function (t) {
|
|
77
|
+
// at 1 return the final value without the extensions used during interpolation
|
|
78
|
+
if (t === 1) {
|
|
79
|
+
return bCommandsInput;
|
|
80
|
+
}
|
|
81
|
+
// work with aCommands directly since interpolatedCommands are mutated
|
|
82
|
+
if (t === 0) {
|
|
83
|
+
return aSameType;
|
|
84
|
+
}
|
|
85
|
+
// interpolate the commands using the mutable interpolated command objs
|
|
86
|
+
for (let i = 0; i < aSameType.length; ++i) {
|
|
87
|
+
interpolatedCommands.push((0, interpolate_instruction_of_same_kind_1.interpolateInstructionOfSameKind)(t, aSameType[i], bCommands[i]));
|
|
88
|
+
}
|
|
89
|
+
return interpolatedCommands;
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
exports.interpolateInstructions = interpolateInstructions;
|