svg-path-commander 2.1.2 → 2.1.5
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/README.md +4 -4
- package/dist/svg-path-commander.cjs +1 -1
- package/dist/svg-path-commander.cjs.map +1 -1
- package/dist/svg-path-commander.d.ts +755 -849
- package/dist/svg-path-commander.js +1 -1
- package/dist/svg-path-commander.js.map +1 -1
- package/dist/svg-path-commander.mjs +947 -611
- package/dist/svg-path-commander.mjs.map +1 -1
- package/package.json +14 -22
- package/.eslintrc.cjs +0 -225
- package/.prettierrc.json +0 -15
- package/dts.config.ts +0 -15
- package/src/convert/pathToAbsolute.ts +0 -18
- package/src/convert/pathToCurve.ts +0 -43
- package/src/convert/pathToRelative.ts +0 -18
- package/src/convert/pathToString.ts +0 -50
- package/src/index.ts +0 -454
- package/src/interface.ts +0 -130
- package/src/math/arcTools.ts +0 -396
- package/src/math/bezier.ts +0 -261
- package/src/math/cubicTools.ts +0 -124
- package/src/math/distanceSquareRoot.ts +0 -15
- package/src/math/lineTools.ts +0 -69
- package/src/math/midPoint.ts +0 -18
- package/src/math/polygonTools.ts +0 -48
- package/src/math/quadTools.ts +0 -100
- package/src/math/rotateVector.ts +0 -17
- package/src/math/roundTo.ts +0 -7
- package/src/options/options.ts +0 -9
- package/src/parser/error.ts +0 -2
- package/src/parser/finalizeSegment.ts +0 -35
- package/src/parser/invalidPathValue.ts +0 -2
- package/src/parser/isArcCommand.ts +0 -11
- package/src/parser/isDigit.ts +0 -12
- package/src/parser/isDigitStart.ts +0 -14
- package/src/parser/isMoveCommand.ts +0 -17
- package/src/parser/isPathCommand.ts +0 -28
- package/src/parser/isSpace.ts +0 -23
- package/src/parser/paramsCount.ts +0 -16
- package/src/parser/paramsParser.ts +0 -14
- package/src/parser/parsePathString.ts +0 -33
- package/src/parser/pathParser.ts +0 -29
- package/src/parser/scanFlag.ts +0 -29
- package/src/parser/scanParam.ts +0 -102
- package/src/parser/scanSegment.ts +0 -84
- package/src/parser/skipSpaces.ts +0 -17
- package/src/process/absolutizeSegment.ts +0 -63
- package/src/process/arcToCubic.ts +0 -128
- package/src/process/getSVGMatrix.ts +0 -70
- package/src/process/iterate.ts +0 -58
- package/src/process/lineToCubic.ts +0 -17
- package/src/process/normalizePath.ts +0 -33
- package/src/process/normalizeSegment.ts +0 -84
- package/src/process/optimizePath.ts +0 -63
- package/src/process/projection2d.ts +0 -52
- package/src/process/quadToCubic.ts +0 -31
- package/src/process/relativizeSegment.ts +0 -59
- package/src/process/reverseCurve.ts +0 -24
- package/src/process/reversePath.ts +0 -114
- package/src/process/roundPath.ts +0 -33
- package/src/process/roundSegment.ts +0 -9
- package/src/process/segmentToCubic.ts +0 -48
- package/src/process/shortenSegment.ts +0 -71
- package/src/process/splitCubic.ts +0 -29
- package/src/process/splitPath.ts +0 -63
- package/src/process/transformPath.ts +0 -110
- package/src/types.ts +0 -228
- package/src/util/distanceEpsilon.ts +0 -3
- package/src/util/getClosestPoint.ts +0 -15
- package/src/util/getDrawDirection.ts +0 -16
- package/src/util/getPathArea.ts +0 -70
- package/src/util/getPathBBox.ts +0 -98
- package/src/util/getPointAtLength.ts +0 -110
- package/src/util/getPropertiesAtLength.ts +0 -67
- package/src/util/getPropertiesAtPoint.ts +0 -84
- package/src/util/getSegmentAtLength.ts +0 -15
- package/src/util/getSegmentOfPoint.ts +0 -18
- package/src/util/getTotalLength.ts +0 -68
- package/src/util/isAbsoluteArray.ts +0 -18
- package/src/util/isCurveArray.ts +0 -15
- package/src/util/isNormalizedArray.ts +0 -16
- package/src/util/isPathArray.ts +0 -24
- package/src/util/isPointInStroke.ts +0 -16
- package/src/util/isRelativeArray.ts +0 -18
- package/src/util/isValidPath.ts +0 -27
- package/src/util/shapeParams.ts +0 -16
- package/src/util/shapeToPath.ts +0 -86
- package/src/util/shapeToPathArray.ts +0 -183
- package/test/class.test.ts +0 -504
- package/test/fixtures/getMarkup.ts +0 -17
- package/test/fixtures/shapeObjects.ts +0 -11
- package/test/fixtures/shapes.js +0 -104
- package/test/fixtures/simpleShapes.js +0 -75
- package/test/static.test.ts +0 -330
- package/vite.config.mts +0 -41
- package/vitest.config-ui.mts +0 -26
- package/vitest.config.mts +0 -26
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import getSVGMatrix from './getSVGMatrix';
|
|
2
|
-
import projection2d from './projection2d';
|
|
3
|
-
import defaultOptions from '../options/options';
|
|
4
|
-
import type { AbsoluteArray, AbsoluteSegment, CSegment, LSegment, PathArray, TransformObjectValues } from '../types';
|
|
5
|
-
import type { TransformObject } from '../interface';
|
|
6
|
-
import iterate from './iterate';
|
|
7
|
-
import parsePathString from '../parser/parsePathString';
|
|
8
|
-
import segmentToCubic from './segmentToCubic';
|
|
9
|
-
import normalizeSegment from './normalizeSegment';
|
|
10
|
-
import paramsParser from '../parser/paramsParser';
|
|
11
|
-
import absolutizeSegment from './absolutizeSegment';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Apply a 2D / 3D transformation to a `pathArray` instance.
|
|
15
|
-
*
|
|
16
|
-
* Since *SVGElement* doesn't support 3D transformation, this function
|
|
17
|
-
* creates a 2D projection of the <path> element.
|
|
18
|
-
*
|
|
19
|
-
* @param path the `pathArray` to apply transformation
|
|
20
|
-
* @param transform the transform functions `Object`
|
|
21
|
-
* @returns the resulted `pathArray`
|
|
22
|
-
*/
|
|
23
|
-
const transformPath = (pathInput: PathArray | string, transform?: Partial<TransformObject>) => {
|
|
24
|
-
// last x and y transformed values
|
|
25
|
-
let x = 0;
|
|
26
|
-
let y = 0;
|
|
27
|
-
// new x and y transformed
|
|
28
|
-
let lx = 0;
|
|
29
|
-
let ly = 0;
|
|
30
|
-
// segment params iteration index and length
|
|
31
|
-
let j = 0;
|
|
32
|
-
let jj = 0;
|
|
33
|
-
let pathCommand = 'M';
|
|
34
|
-
// transform uses it's own set of params
|
|
35
|
-
const transformParams = { ...paramsParser };
|
|
36
|
-
const path = parsePathString(pathInput);
|
|
37
|
-
const transformProps = transform && Object.keys(transform);
|
|
38
|
-
|
|
39
|
-
// when used as a static method, invalidate somehow
|
|
40
|
-
if (!transform || (transformProps && !transformProps.length)) return path.slice(0) as typeof path;
|
|
41
|
-
|
|
42
|
-
// transform origin is extremely important
|
|
43
|
-
if (!transform.origin) {
|
|
44
|
-
Object.assign(transform, { origin: defaultOptions.origin });
|
|
45
|
-
}
|
|
46
|
-
const origin = transform.origin as [number, number, number];
|
|
47
|
-
const matrixInstance = getSVGMatrix(transform as TransformObjectValues);
|
|
48
|
-
|
|
49
|
-
if (matrixInstance.isIdentity) return path.slice(0) as typeof path;
|
|
50
|
-
|
|
51
|
-
return iterate<AbsoluteArray>(path, (seg, index, lastX, lastY) => {
|
|
52
|
-
transformParams.x = lastX;
|
|
53
|
-
transformParams.y = lastY;
|
|
54
|
-
[pathCommand] = seg;
|
|
55
|
-
const absCommand = pathCommand.toUpperCase();
|
|
56
|
-
const isRelative = absCommand !== pathCommand;
|
|
57
|
-
const absoluteSegment = isRelative
|
|
58
|
-
? absolutizeSegment(seg, index, lastX, lastY)
|
|
59
|
-
: (seg.slice(0) as AbsoluteSegment);
|
|
60
|
-
|
|
61
|
-
let result =
|
|
62
|
-
absCommand === 'A'
|
|
63
|
-
? segmentToCubic(absoluteSegment, transformParams)
|
|
64
|
-
: ['V', 'H'].includes(absCommand)
|
|
65
|
-
? normalizeSegment(absoluteSegment, transformParams)
|
|
66
|
-
: absoluteSegment;
|
|
67
|
-
|
|
68
|
-
// update pathCommand
|
|
69
|
-
pathCommand = result[0];
|
|
70
|
-
const isLongArc = pathCommand === 'C' && result.length > 7;
|
|
71
|
-
const tempSegment = (isLongArc ? result.slice(0, 7) : result.slice(0)) as AbsoluteSegment;
|
|
72
|
-
|
|
73
|
-
if (isLongArc) {
|
|
74
|
-
path.splice(index + 1, 0, ['C' as typeof pathCommand | number].concat(result.slice(7)) as CSegment);
|
|
75
|
-
result = tempSegment as CSegment;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (pathCommand === 'L') {
|
|
79
|
-
[lx, ly] = projection2d(matrixInstance, [(result as LSegment)[1], (result as LSegment)[2]], origin);
|
|
80
|
-
|
|
81
|
-
/* istanbul ignore else @preserve */
|
|
82
|
-
if (x !== lx && y !== ly) {
|
|
83
|
-
result = ['L', lx, ly];
|
|
84
|
-
} else if (y === ly) {
|
|
85
|
-
result = ['H', lx];
|
|
86
|
-
} else if (x === lx) {
|
|
87
|
-
result = ['V', ly];
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
for (j = 1, jj = result.length; j < jj; j += 2) {
|
|
91
|
-
[lx, ly] = projection2d(matrixInstance, [+result[j], +result[j + 1]], origin);
|
|
92
|
-
result[j] = lx;
|
|
93
|
-
result[j + 1] = ly;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// now update x and y
|
|
97
|
-
x = lx;
|
|
98
|
-
y = ly;
|
|
99
|
-
|
|
100
|
-
const seglen = tempSegment.length;
|
|
101
|
-
transformParams.x1 = +tempSegment[seglen - 2];
|
|
102
|
-
transformParams.y1 = +tempSegment[seglen - 1];
|
|
103
|
-
transformParams.x2 = +tempSegment[seglen - 4] || transformParams.x1;
|
|
104
|
-
transformParams.y2 = +tempSegment[seglen - 3] || transformParams.y1;
|
|
105
|
-
|
|
106
|
-
return result;
|
|
107
|
-
});
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export default transformPath;
|
package/src/types.ts
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import type { LineAttr, CircleAttr, PolyAttr, RectAttr, EllipseAttr, GlyphAttr, TransformObject } from './interface';
|
|
2
|
-
|
|
3
|
-
export type SpaceNumber =
|
|
4
|
-
| 0x1680
|
|
5
|
-
| 0x180e
|
|
6
|
-
| 0x2000
|
|
7
|
-
| 0x2001
|
|
8
|
-
| 0x2002
|
|
9
|
-
| 0x2003
|
|
10
|
-
| 0x2004
|
|
11
|
-
| 0x2005
|
|
12
|
-
| 0x2006
|
|
13
|
-
| 0x2007
|
|
14
|
-
| 0x2008
|
|
15
|
-
| 0x2009
|
|
16
|
-
| 0x200a
|
|
17
|
-
| 0x202f
|
|
18
|
-
| 0x205f
|
|
19
|
-
| 0x3000
|
|
20
|
-
| 0xfeff
|
|
21
|
-
| 0x0a
|
|
22
|
-
| 0x0d
|
|
23
|
-
| 0x2028
|
|
24
|
-
| 0x2029
|
|
25
|
-
| 0x20
|
|
26
|
-
| 0x09
|
|
27
|
-
| 0x0b
|
|
28
|
-
| 0x0c
|
|
29
|
-
| 0xa0
|
|
30
|
-
| 0x1680;
|
|
31
|
-
|
|
32
|
-
export type PathCommandNumber = 0x6d | 0x7a | 0x6c | 0x68 | 0x76 | 0x63 | 0x73 | 0x71 | 0x74 | 0x61;
|
|
33
|
-
|
|
34
|
-
export type DigitNumber = 0x30 | 0x31 | 0x32 | 0x33 | 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39;
|
|
35
|
-
|
|
36
|
-
// custom types
|
|
37
|
-
export type MCommand = 'M';
|
|
38
|
-
export type mCommand = 'm';
|
|
39
|
-
|
|
40
|
-
export type LCommand = 'L';
|
|
41
|
-
export type lCommand = 'l';
|
|
42
|
-
|
|
43
|
-
export type VCommand = 'V';
|
|
44
|
-
export type vCommand = 'v';
|
|
45
|
-
|
|
46
|
-
export type HCommand = 'H';
|
|
47
|
-
export type hCommand = 'h';
|
|
48
|
-
|
|
49
|
-
export type ZCommand = 'Z';
|
|
50
|
-
export type zCommand = 'z';
|
|
51
|
-
|
|
52
|
-
export type CCommand = 'C';
|
|
53
|
-
export type cCommand = 'c';
|
|
54
|
-
|
|
55
|
-
export type SCommand = 'S';
|
|
56
|
-
export type sCommand = 's';
|
|
57
|
-
|
|
58
|
-
export type QCommand = 'Q';
|
|
59
|
-
export type qCommand = 'q';
|
|
60
|
-
|
|
61
|
-
export type TCommand = 'T';
|
|
62
|
-
export type tCommand = 't';
|
|
63
|
-
|
|
64
|
-
export type ACommand = 'A';
|
|
65
|
-
export type aCommand = 'a';
|
|
66
|
-
|
|
67
|
-
export type AbsoluteCommand =
|
|
68
|
-
| MCommand
|
|
69
|
-
| LCommand
|
|
70
|
-
| VCommand
|
|
71
|
-
| HCommand
|
|
72
|
-
| ZCommand
|
|
73
|
-
| CCommand
|
|
74
|
-
| SCommand
|
|
75
|
-
| QCommand
|
|
76
|
-
| TCommand
|
|
77
|
-
| ACommand;
|
|
78
|
-
|
|
79
|
-
export type RelativeCommand =
|
|
80
|
-
| mCommand
|
|
81
|
-
| lCommand
|
|
82
|
-
| vCommand
|
|
83
|
-
| hCommand
|
|
84
|
-
| zCommand
|
|
85
|
-
| cCommand
|
|
86
|
-
| sCommand
|
|
87
|
-
| qCommand
|
|
88
|
-
| tCommand
|
|
89
|
-
| aCommand;
|
|
90
|
-
|
|
91
|
-
export type PathCommand = AbsoluteCommand | RelativeCommand;
|
|
92
|
-
|
|
93
|
-
export type MSegment = [MCommand, number, number];
|
|
94
|
-
export type mSegment = [mCommand, number, number];
|
|
95
|
-
export type MoveSegment = MSegment | mSegment;
|
|
96
|
-
|
|
97
|
-
export type LSegment = [LCommand, number, number];
|
|
98
|
-
export type lSegment = [lCommand, number, number];
|
|
99
|
-
export type LineSegment = LSegment | lSegment;
|
|
100
|
-
|
|
101
|
-
export type VSegment = [VCommand, number];
|
|
102
|
-
export type vSegment = [vCommand, number];
|
|
103
|
-
export type VertLineSegment = vSegment | VSegment;
|
|
104
|
-
|
|
105
|
-
export type HSegment = [HCommand, number];
|
|
106
|
-
export type hSegment = [hCommand, number];
|
|
107
|
-
export type HorLineSegment = HSegment | hSegment;
|
|
108
|
-
|
|
109
|
-
export type ZSegment = [ZCommand];
|
|
110
|
-
export type zSegment = [zCommand];
|
|
111
|
-
export type CloseSegment = ZSegment | zSegment;
|
|
112
|
-
|
|
113
|
-
export type CSegment = [CCommand, number, number, number, number, number, number];
|
|
114
|
-
export type cSegment = [cCommand, number, number, number, number, number, number];
|
|
115
|
-
export type CubicSegment = CSegment | cSegment;
|
|
116
|
-
|
|
117
|
-
export type SSegment = [SCommand, number, number, number, number];
|
|
118
|
-
export type sSegment = [sCommand, number, number, number, number];
|
|
119
|
-
export type ShortCubicSegment = SSegment | sSegment;
|
|
120
|
-
|
|
121
|
-
export type QSegment = [QCommand, number, number, number, number];
|
|
122
|
-
export type qSegment = [qCommand, number, number, number, number];
|
|
123
|
-
export type QuadSegment = QSegment | qSegment;
|
|
124
|
-
|
|
125
|
-
export type TSegment = [TCommand, number, number];
|
|
126
|
-
export type tSegment = [tCommand, number, number];
|
|
127
|
-
export type ShortQuadSegment = TSegment | tSegment;
|
|
128
|
-
|
|
129
|
-
export type ASegment = [ACommand, number, number, number, number, number, number, number];
|
|
130
|
-
export type aSegment = [aCommand, number, number, number, number, number, number, number];
|
|
131
|
-
export type ArcSegment = ASegment | aSegment;
|
|
132
|
-
|
|
133
|
-
export type PathSegment =
|
|
134
|
-
| MoveSegment
|
|
135
|
-
| LineSegment
|
|
136
|
-
| VertLineSegment
|
|
137
|
-
| HorLineSegment
|
|
138
|
-
| CloseSegment
|
|
139
|
-
| CubicSegment
|
|
140
|
-
| ShortCubicSegment
|
|
141
|
-
| QuadSegment
|
|
142
|
-
| ShortQuadSegment
|
|
143
|
-
| ArcSegment;
|
|
144
|
-
|
|
145
|
-
export type ShortSegment = VertLineSegment | HorLineSegment | ShortCubicSegment | ShortQuadSegment | CloseSegment;
|
|
146
|
-
|
|
147
|
-
export type AbsoluteSegment =
|
|
148
|
-
| MSegment
|
|
149
|
-
| LSegment
|
|
150
|
-
| VSegment
|
|
151
|
-
| HSegment
|
|
152
|
-
| CSegment
|
|
153
|
-
| SSegment
|
|
154
|
-
| QSegment
|
|
155
|
-
| TSegment
|
|
156
|
-
| ASegment
|
|
157
|
-
| ZSegment;
|
|
158
|
-
|
|
159
|
-
export type RelativeSegment =
|
|
160
|
-
| mSegment
|
|
161
|
-
| lSegment
|
|
162
|
-
| vSegment
|
|
163
|
-
| hSegment
|
|
164
|
-
| cSegment
|
|
165
|
-
| sSegment
|
|
166
|
-
| qSegment
|
|
167
|
-
| tSegment
|
|
168
|
-
| aSegment
|
|
169
|
-
| zSegment;
|
|
170
|
-
|
|
171
|
-
export type NormalSegment = MSegment | LSegment | CSegment | QSegment | ASegment | ZSegment;
|
|
172
|
-
|
|
173
|
-
export type PathArray = [MSegment | mSegment, ...PathSegment[]];
|
|
174
|
-
export type AbsoluteArray = [MSegment, ...AbsoluteSegment[]];
|
|
175
|
-
export type RelativeArray = [MSegment, ...RelativeSegment[]];
|
|
176
|
-
export type NormalArray = [MSegment, ...NormalSegment[]];
|
|
177
|
-
export type CurveArray = [MSegment, ...CSegment[]];
|
|
178
|
-
export type PolygonArray = [MSegment, ...LSegment[], ZSegment];
|
|
179
|
-
export type PolylineArray = [MSegment, ...LSegment[]];
|
|
180
|
-
|
|
181
|
-
export type ShapeTypes =
|
|
182
|
-
| SVGPolylineElement
|
|
183
|
-
| SVGPolygonElement
|
|
184
|
-
| SVGLineElement
|
|
185
|
-
| SVGEllipseElement
|
|
186
|
-
| SVGCircleElement
|
|
187
|
-
| SVGRectElement;
|
|
188
|
-
|
|
189
|
-
export type ShapeTags = 'line' | 'polyline' | 'polygon' | 'ellipse' | 'circle' | 'rect' | 'glyph';
|
|
190
|
-
|
|
191
|
-
export type ShapeOps = LineAttr | PolyAttr | PolyAttr | EllipseAttr | CircleAttr | RectAttr | GlyphAttr;
|
|
192
|
-
|
|
193
|
-
export type TransformObjectValues = Partial<TransformObject> & { origin: [number, number, number] };
|
|
194
|
-
|
|
195
|
-
export type Point = {
|
|
196
|
-
x: number;
|
|
197
|
-
y: number;
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
export type PointTuple = [number, number];
|
|
201
|
-
|
|
202
|
-
export type DerivedPoint = Point & { t: number };
|
|
203
|
-
export type QuadPoints = [Point, Point, Point, Point, Point, Point];
|
|
204
|
-
export type CubicPoints = [Point, Point, Point, Point, Point, Point, Point, Point];
|
|
205
|
-
export type DerivedQuadPoints = [DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint, DerivedPoint];
|
|
206
|
-
export type DerivedCubicPoints = [
|
|
207
|
-
DerivedPoint,
|
|
208
|
-
DerivedPoint,
|
|
209
|
-
DerivedPoint,
|
|
210
|
-
DerivedPoint,
|
|
211
|
-
DerivedPoint,
|
|
212
|
-
DerivedPoint,
|
|
213
|
-
DerivedPoint,
|
|
214
|
-
DerivedPoint,
|
|
215
|
-
];
|
|
216
|
-
export type QuadCoordinates = [number, number, number, number, number, number];
|
|
217
|
-
export type CubicCoordinates = [number, number, number, number, number, number, number, number];
|
|
218
|
-
export type ArcCoordinates = [number, number, number, number, number, number, number, number, number];
|
|
219
|
-
export type LineCoordinates = [number, number, number, number];
|
|
220
|
-
|
|
221
|
-
export type DeriveCallback = (t: number) => Point;
|
|
222
|
-
|
|
223
|
-
export type IteratorCallback = (
|
|
224
|
-
segment: PathSegment,
|
|
225
|
-
index: number,
|
|
226
|
-
lastX: number,
|
|
227
|
-
lastY: number,
|
|
228
|
-
) => PathSegment | false | void | undefined;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { PathArray } from '../types';
|
|
2
|
-
import getPropertiesAtPoint from './getPropertiesAtPoint';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Returns the point in path closest to a given point.
|
|
6
|
-
*
|
|
7
|
-
* @param pathInput target `pathArray`
|
|
8
|
-
* @param point the given point
|
|
9
|
-
* @returns the best match
|
|
10
|
-
*/
|
|
11
|
-
const getClosestPoint = (pathInput: string | PathArray, point: { x: number; y: number }) => {
|
|
12
|
-
return getPropertiesAtPoint(pathInput, point).closest;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export default getClosestPoint;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import getPathArea from './getPathArea';
|
|
2
|
-
import pathToCurve from '../convert/pathToCurve';
|
|
3
|
-
import type { PathArray } from '../types';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Check if a path is drawn clockwise and returns true if so,
|
|
7
|
-
* false otherwise.
|
|
8
|
-
*
|
|
9
|
-
* @param path the path string or `pathArray`
|
|
10
|
-
* @returns true when clockwise or false if not
|
|
11
|
-
*/
|
|
12
|
-
const getDrawDirection = (path: string | PathArray) => {
|
|
13
|
-
return getPathArea(pathToCurve(path)) >= 0;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default getDrawDirection;
|
package/src/util/getPathArea.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import pathToCurve from '../convert/pathToCurve';
|
|
2
|
-
import type { PointTuple, PathArray } from '../types';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Returns the area of a single cubic-bezier segment.
|
|
6
|
-
*
|
|
7
|
-
* http://objectmix.com/graphics/133553-area-closed-bezier-curve.html
|
|
8
|
-
*
|
|
9
|
-
* @param x1 the starting point X
|
|
10
|
-
* @param y1 the starting point Y
|
|
11
|
-
* @param c1x the first control point X
|
|
12
|
-
* @param c1y the first control point Y
|
|
13
|
-
* @param c2x the second control point X
|
|
14
|
-
* @param c2y the second control point Y
|
|
15
|
-
* @param x2 the ending point X
|
|
16
|
-
* @param y2 the ending point Y
|
|
17
|
-
* @returns the area of the cubic-bezier segment
|
|
18
|
-
*/
|
|
19
|
-
const getCubicSegArea = (
|
|
20
|
-
x1: number,
|
|
21
|
-
y1: number,
|
|
22
|
-
c1x: number,
|
|
23
|
-
c1y: number,
|
|
24
|
-
c2x: number,
|
|
25
|
-
c2y: number,
|
|
26
|
-
x2: number,
|
|
27
|
-
y2: number,
|
|
28
|
-
) => {
|
|
29
|
-
return (
|
|
30
|
-
(3 *
|
|
31
|
-
((y2 - y1) * (c1x + c2x) -
|
|
32
|
-
(x2 - x1) * (c1y + c2y) +
|
|
33
|
-
c1y * (x1 - c2x) -
|
|
34
|
-
c1x * (y1 - c2y) +
|
|
35
|
-
y2 * (c2x + x1 / 3) -
|
|
36
|
-
x2 * (c2y + y1 / 3))) /
|
|
37
|
-
20
|
|
38
|
-
);
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Returns the area of a shape.
|
|
43
|
-
*
|
|
44
|
-
* @author Jürg Lehni & Jonathan Puckey
|
|
45
|
-
*
|
|
46
|
-
* @see https://github.com/paperjs/paper.js/blob/develop/src/path/Path.js
|
|
47
|
-
*
|
|
48
|
-
* @param path the shape `pathArray`
|
|
49
|
-
* @returns the length of the cubic-bezier segment
|
|
50
|
-
*/
|
|
51
|
-
const getPathArea = (path: PathArray) => {
|
|
52
|
-
let x = 0;
|
|
53
|
-
let y = 0;
|
|
54
|
-
let len = 0;
|
|
55
|
-
|
|
56
|
-
return pathToCurve(path)
|
|
57
|
-
.map(seg => {
|
|
58
|
-
switch (seg[0]) {
|
|
59
|
-
case 'M':
|
|
60
|
-
[, x, y] = seg;
|
|
61
|
-
return 0;
|
|
62
|
-
default:
|
|
63
|
-
len = getCubicSegArea(x, y, seg[1], seg[2], seg[3], seg[4], seg[5], seg[6]);
|
|
64
|
-
[x, y] = seg.slice(-2) as PointTuple;
|
|
65
|
-
return len;
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
.reduce((a, b) => a + b, 0);
|
|
69
|
-
};
|
|
70
|
-
export default getPathArea;
|
package/src/util/getPathBBox.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import iterate from '../process/iterate';
|
|
2
|
-
import { PathBBox } from '../interface';
|
|
3
|
-
import { MSegment, PathArray, Point } from '../types';
|
|
4
|
-
import { getLineBBox } from '../math/lineTools';
|
|
5
|
-
import { getArcBBox } from '../math/arcTools';
|
|
6
|
-
import { getCubicBBox } from '../math/cubicTools';
|
|
7
|
-
import { getQuadBBox } from '../math/quadTools';
|
|
8
|
-
import parsePathString from '../parser/parsePathString';
|
|
9
|
-
import paramsParser from '../parser/paramsParser';
|
|
10
|
-
import normalizeSegment from '../process/normalizeSegment';
|
|
11
|
-
|
|
12
|
-
const getPathBBox = (pathInput: PathArray | string) => {
|
|
13
|
-
if (!pathInput) {
|
|
14
|
-
return {
|
|
15
|
-
x: 0,
|
|
16
|
-
y: 0,
|
|
17
|
-
width: 0,
|
|
18
|
-
height: 0,
|
|
19
|
-
x2: 0,
|
|
20
|
-
y2: 0,
|
|
21
|
-
cx: 0,
|
|
22
|
-
cy: 0,
|
|
23
|
-
cz: 0,
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const path = parsePathString(pathInput);
|
|
28
|
-
let data = [] as number[];
|
|
29
|
-
let pathCommand = 'M';
|
|
30
|
-
const x = 0;
|
|
31
|
-
const y = 0;
|
|
32
|
-
let mx = 0;
|
|
33
|
-
let my = 0;
|
|
34
|
-
const MIN = [] as Point[];
|
|
35
|
-
const MAX = [] as Point[];
|
|
36
|
-
let min = { x, y };
|
|
37
|
-
let max = { x, y };
|
|
38
|
-
const params = { ...paramsParser };
|
|
39
|
-
|
|
40
|
-
iterate(path, (seg, _, lastX, lastY) => {
|
|
41
|
-
params.x = lastX;
|
|
42
|
-
params.y = lastY;
|
|
43
|
-
const result = normalizeSegment(seg, params);
|
|
44
|
-
[pathCommand] = result;
|
|
45
|
-
data = [lastX, lastY].concat(result.slice(1) as number[]);
|
|
46
|
-
|
|
47
|
-
// this segment is always ZERO
|
|
48
|
-
/* istanbul ignore else @preserve */
|
|
49
|
-
if (pathCommand === 'M') {
|
|
50
|
-
// remember mx, my for Z
|
|
51
|
-
[, mx, my] = result as MSegment;
|
|
52
|
-
min = { x: mx, y: my };
|
|
53
|
-
max = { x: mx, y: my };
|
|
54
|
-
} else if (pathCommand === 'L') {
|
|
55
|
-
({ min, max } = getLineBBox(data[0], data[1], data[2], data[3]));
|
|
56
|
-
} else if (pathCommand === 'A') {
|
|
57
|
-
({ min, max } = getArcBBox(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]));
|
|
58
|
-
} else if (pathCommand === 'C') {
|
|
59
|
-
({ min, max } = getCubicBBox(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]));
|
|
60
|
-
} else if (pathCommand === 'Q') {
|
|
61
|
-
({ min, max } = getQuadBBox(data[0], data[1], data[2], data[3], data[4], data[5]));
|
|
62
|
-
} else if (pathCommand === 'Z') {
|
|
63
|
-
data = [lastX, lastY, mx, my];
|
|
64
|
-
({ min, max } = getLineBBox(data[0], data[1], data[2], data[3]));
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
MIN.push(min);
|
|
68
|
-
MAX.push(max);
|
|
69
|
-
|
|
70
|
-
const seglen = result.length;
|
|
71
|
-
params.x1 = +result[seglen - 2];
|
|
72
|
-
params.y1 = +result[seglen - 1];
|
|
73
|
-
params.x2 = +result[seglen - 4] || params.x1;
|
|
74
|
-
params.y2 = +result[seglen - 3] || params.y1;
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
const xMin = Math.min(...MIN.map(n => n.x));
|
|
78
|
-
const xMax = Math.max(...MAX.map(n => n.x));
|
|
79
|
-
const yMin = Math.min(...MIN.map(n => n.y));
|
|
80
|
-
const yMax = Math.max(...MAX.map(n => n.y));
|
|
81
|
-
const width = xMax - xMin;
|
|
82
|
-
const height = yMax - yMin;
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
width,
|
|
86
|
-
height,
|
|
87
|
-
x: xMin,
|
|
88
|
-
y: yMin,
|
|
89
|
-
x2: xMax,
|
|
90
|
-
y2: yMax,
|
|
91
|
-
cx: xMin + width / 2,
|
|
92
|
-
cy: yMin + height / 2,
|
|
93
|
-
// an estimated guess
|
|
94
|
-
cz: Math.max(width, height) + Math.min(width, height) / 2,
|
|
95
|
-
} satisfies PathBBox;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
export default getPathBBox;
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import DISTANCE_EPSILON from './distanceEpsilon';
|
|
2
|
-
import type { MSegment, PathArray, PointTuple } from '../types';
|
|
3
|
-
import iterate from '../process/iterate';
|
|
4
|
-
import { getLineLength, getPointAtLineLength } from '../math/lineTools';
|
|
5
|
-
import { getArcLength, getPointAtArcLength } from '../math/arcTools';
|
|
6
|
-
import { getCubicLength, getPointAtCubicLength } from '../math/cubicTools';
|
|
7
|
-
import { getQuadLength, getPointAtQuadLength } from '../math/quadTools';
|
|
8
|
-
import normalizePath from '../process/normalizePath';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Returns [x,y] coordinates of a point at a given length of a shape.
|
|
12
|
-
*
|
|
13
|
-
* @param pathInput the `pathArray` to look into
|
|
14
|
-
* @param distance the length of the shape to look at
|
|
15
|
-
* @returns the requested {x, y} point coordinates
|
|
16
|
-
*/
|
|
17
|
-
const getPointAtLength = (pathInput: string | PathArray, distance?: number) => {
|
|
18
|
-
const path = normalizePath(pathInput);
|
|
19
|
-
let isM = false;
|
|
20
|
-
let data = [] as number[];
|
|
21
|
-
let pathCommand = 'M';
|
|
22
|
-
let x = 0;
|
|
23
|
-
let y = 0;
|
|
24
|
-
let [mx, my] = path[0].slice(1) as PointTuple;
|
|
25
|
-
const distanceIsNumber = typeof distance === 'number';
|
|
26
|
-
let point = { x: mx, y: my };
|
|
27
|
-
let length = 0;
|
|
28
|
-
let POINT = point;
|
|
29
|
-
let totalLength = 0;
|
|
30
|
-
|
|
31
|
-
if (!distanceIsNumber || distance < DISTANCE_EPSILON) return point;
|
|
32
|
-
|
|
33
|
-
// for (let i = 0; i < pathLen; i += 1) {
|
|
34
|
-
iterate(path, (seg, _, lastX, lastY) => {
|
|
35
|
-
[pathCommand] = seg;
|
|
36
|
-
isM = pathCommand === 'M';
|
|
37
|
-
data = !isM ? [lastX, lastY].concat(seg.slice(1) as number[]) : data;
|
|
38
|
-
|
|
39
|
-
// this segment is always ZERO
|
|
40
|
-
/* istanbul ignore else @preserve */
|
|
41
|
-
if (isM) {
|
|
42
|
-
// remember mx, my for Z
|
|
43
|
-
[, mx, my] = seg as MSegment;
|
|
44
|
-
point = { x: mx, y: my };
|
|
45
|
-
length = 0;
|
|
46
|
-
} else if (pathCommand === 'L') {
|
|
47
|
-
point = getPointAtLineLength(data[0], data[1], data[2], data[3], distance - totalLength);
|
|
48
|
-
length = getLineLength(data[0], data[1], data[2], data[3]);
|
|
49
|
-
} else if (pathCommand === 'A') {
|
|
50
|
-
point = getPointAtArcLength(
|
|
51
|
-
data[0],
|
|
52
|
-
data[1],
|
|
53
|
-
data[2],
|
|
54
|
-
data[3],
|
|
55
|
-
data[4],
|
|
56
|
-
data[5],
|
|
57
|
-
data[6],
|
|
58
|
-
data[7],
|
|
59
|
-
data[8],
|
|
60
|
-
distance - totalLength,
|
|
61
|
-
);
|
|
62
|
-
length = getArcLength(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]);
|
|
63
|
-
} else if (pathCommand === 'C') {
|
|
64
|
-
point = getPointAtCubicLength(
|
|
65
|
-
data[0],
|
|
66
|
-
data[1],
|
|
67
|
-
data[2],
|
|
68
|
-
data[3],
|
|
69
|
-
data[4],
|
|
70
|
-
data[5],
|
|
71
|
-
data[6],
|
|
72
|
-
data[7],
|
|
73
|
-
distance - totalLength,
|
|
74
|
-
);
|
|
75
|
-
length = getCubicLength(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
|
|
76
|
-
} else if (pathCommand === 'Q') {
|
|
77
|
-
point = getPointAtQuadLength(data[0], data[1], data[2], data[3], data[4], data[5], distance - totalLength);
|
|
78
|
-
length = getQuadLength(data[0], data[1], data[2], data[3], data[4], data[5]);
|
|
79
|
-
} else if (pathCommand === 'Z') {
|
|
80
|
-
data = [lastX, lastY, mx, my];
|
|
81
|
-
point = { x: mx, y: my };
|
|
82
|
-
|
|
83
|
-
length = getLineLength(data[0], data[1], data[2], data[3]);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
[x, y] = data.slice(-2);
|
|
87
|
-
|
|
88
|
-
if (totalLength < distance) {
|
|
89
|
-
POINT = point;
|
|
90
|
-
} else {
|
|
91
|
-
// totalLength >= distance
|
|
92
|
-
// stop right here
|
|
93
|
-
// stop iterator now!
|
|
94
|
-
return false;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
totalLength += length;
|
|
98
|
-
return;
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
// native `getPointAtLength` behavior when the given distance
|
|
102
|
-
// is higher than total length
|
|
103
|
-
if (distance > totalLength - DISTANCE_EPSILON) {
|
|
104
|
-
return { x, y };
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return POINT;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export default getPointAtLength;
|