modern-path2d 0.1.6 → 0.1.8
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/index.cjs +372 -330
- package/dist/index.d.cts +146 -132
- package/dist/index.d.mts +146 -132
- package/dist/index.d.ts +146 -132
- package/dist/index.js +1 -1
- package/dist/index.mjs +371 -330
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
class
|
|
3
|
+
class Vector2 {
|
|
4
4
|
constructor(x = 0, y = 0) {
|
|
5
5
|
this.x = x;
|
|
6
6
|
this.y = y;
|
|
7
7
|
}
|
|
8
8
|
static get MAX() {
|
|
9
|
-
return new
|
|
9
|
+
return new Vector2(Infinity, Infinity);
|
|
10
10
|
}
|
|
11
11
|
static get MIN() {
|
|
12
|
-
return new
|
|
12
|
+
return new Vector2(-Infinity, -Infinity);
|
|
13
13
|
}
|
|
14
14
|
set(x, y) {
|
|
15
15
|
this.x = x;
|
|
16
16
|
this.y = y;
|
|
17
17
|
return this;
|
|
18
18
|
}
|
|
19
|
-
add(
|
|
20
|
-
this.x +=
|
|
21
|
-
this.y +=
|
|
19
|
+
add(vec) {
|
|
20
|
+
this.x += vec.x;
|
|
21
|
+
this.y += vec.y;
|
|
22
22
|
return this;
|
|
23
23
|
}
|
|
24
|
-
sub(
|
|
25
|
-
this.x -=
|
|
26
|
-
this.y -=
|
|
24
|
+
sub(vec) {
|
|
25
|
+
this.x -= vec.x;
|
|
26
|
+
this.y -= vec.y;
|
|
27
27
|
return this;
|
|
28
28
|
}
|
|
29
|
-
distanceTo(
|
|
30
|
-
return Math.sqrt(this.distanceToSquared(
|
|
29
|
+
distanceTo(vec) {
|
|
30
|
+
return Math.sqrt(this.distanceToSquared(vec));
|
|
31
31
|
}
|
|
32
|
-
distanceToSquared(
|
|
33
|
-
const dx = this.x -
|
|
34
|
-
const dy = this.y -
|
|
32
|
+
distanceToSquared(vec) {
|
|
33
|
+
const dx = this.x - vec.x;
|
|
34
|
+
const dy = this.y - vec.y;
|
|
35
35
|
return dx * dx + dy * dy;
|
|
36
36
|
}
|
|
37
37
|
length() {
|
|
@@ -58,8 +58,8 @@ class Point2D {
|
|
|
58
58
|
this.y = v1.y + (v2.y - v1.y) * alpha;
|
|
59
59
|
return this;
|
|
60
60
|
}
|
|
61
|
-
equals(
|
|
62
|
-
return this.x ===
|
|
61
|
+
equals(vec) {
|
|
62
|
+
return this.x === vec.x && this.y === vec.y;
|
|
63
63
|
}
|
|
64
64
|
applyMatrix3(m) {
|
|
65
65
|
const x = this.x;
|
|
@@ -69,13 +69,13 @@ class Point2D {
|
|
|
69
69
|
this.y = e[1] * x + e[4] * y + e[7];
|
|
70
70
|
return this;
|
|
71
71
|
}
|
|
72
|
-
copy(
|
|
73
|
-
this.x =
|
|
74
|
-
this.y =
|
|
72
|
+
copy(vec) {
|
|
73
|
+
this.x = vec.x;
|
|
74
|
+
this.y = vec.y;
|
|
75
75
|
return this;
|
|
76
76
|
}
|
|
77
77
|
clone() {
|
|
78
|
-
return new
|
|
78
|
+
return new Vector2(this.x, this.y);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
|
|
@@ -129,7 +129,7 @@ class BoundingBox {
|
|
|
129
129
|
return this;
|
|
130
130
|
}
|
|
131
131
|
getCenterPoint() {
|
|
132
|
-
return new
|
|
132
|
+
return new Vector2((this.left + this.right) / 2, (this.top + this.bottom) / 2);
|
|
133
133
|
}
|
|
134
134
|
clone() {
|
|
135
135
|
return new BoundingBox(this.left, this.top, this.width, this.height);
|
|
@@ -391,9 +391,9 @@ function getReflection(a, b) {
|
|
|
391
391
|
return a - (b - a);
|
|
392
392
|
}
|
|
393
393
|
function addPathCommandsToPath2D(commands, path) {
|
|
394
|
-
const point = new
|
|
395
|
-
const control = new
|
|
396
|
-
const firstPoint = new
|
|
394
|
+
const point = new Vector2();
|
|
395
|
+
const control = new Vector2();
|
|
396
|
+
const firstPoint = new Vector2();
|
|
397
397
|
let isFirstPoint = true;
|
|
398
398
|
let doSetFirstPoint = false;
|
|
399
399
|
for (let i = 0, l = commands.length; i < l; i++) {
|
|
@@ -920,7 +920,7 @@ class Curve {
|
|
|
920
920
|
__publicField$5(this, "_cacheArcLengths");
|
|
921
921
|
__publicField$5(this, "_needsUpdate", false);
|
|
922
922
|
}
|
|
923
|
-
getPointAt(u, output = new
|
|
923
|
+
getPointAt(u, output = new Vector2()) {
|
|
924
924
|
return this.getPoint(this.getUtoTmapping(u), output);
|
|
925
925
|
}
|
|
926
926
|
getPoints(divisions = 5) {
|
|
@@ -999,35 +999,48 @@ class Curve {
|
|
|
999
999
|
const segmentFraction = (targetArcLength - lengthBefore) / segmentLength;
|
|
1000
1000
|
return (i + segmentFraction) / (il - 1);
|
|
1001
1001
|
}
|
|
1002
|
-
getTangent(t, output = new
|
|
1002
|
+
getTangent(t, output = new Vector2()) {
|
|
1003
1003
|
const delta = 1e-4;
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
t2 = 1;
|
|
1010
|
-
return output.copy(this.getPoint(t2)).sub(this.getPoint(t1)).normalize();
|
|
1011
|
-
}
|
|
1012
|
-
getTangentAt(u, output = new Point2D()) {
|
|
1004
|
+
const t1 = Math.max(0, t - delta);
|
|
1005
|
+
const t2 = Math.min(1, t + delta);
|
|
1006
|
+
return output.copy(this.getPoint(t2).sub(this.getPoint(t1)).normalize());
|
|
1007
|
+
}
|
|
1008
|
+
getTangentAt(u, output) {
|
|
1013
1009
|
return this.getTangent(this.getUtoTmapping(u), output);
|
|
1014
1010
|
}
|
|
1015
1011
|
/** overrideable */
|
|
1016
1012
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
1013
|
+
transformPoint(cb) {
|
|
1014
|
+
return this;
|
|
1015
|
+
}
|
|
1017
1016
|
transform(matrix) {
|
|
1017
|
+
this.transformPoint((point) => point.applyMatrix3(matrix));
|
|
1018
1018
|
return this;
|
|
1019
1019
|
}
|
|
1020
|
-
/** overrideable */
|
|
1021
1020
|
getDivisions(divisions) {
|
|
1022
1021
|
return divisions;
|
|
1023
1022
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1023
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1024
|
+
this.getPoints().forEach((point) => {
|
|
1025
|
+
min.x = Math.min(min.x, point.x);
|
|
1026
|
+
min.y = Math.min(min.y, point.y);
|
|
1027
|
+
max.x = Math.max(max.x, point.x);
|
|
1028
|
+
max.y = Math.max(max.y, point.y);
|
|
1029
|
+
});
|
|
1026
1030
|
return { min, max };
|
|
1027
1031
|
}
|
|
1028
|
-
|
|
1032
|
+
getBoundingBox() {
|
|
1033
|
+
const { min, max } = this.getMinMax();
|
|
1034
|
+
return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
1035
|
+
}
|
|
1029
1036
|
getCommands() {
|
|
1030
|
-
return
|
|
1037
|
+
return this.getPoints().map((point, i) => {
|
|
1038
|
+
if (i === 0) {
|
|
1039
|
+
return { type: "M", x: point.x, y: point.y };
|
|
1040
|
+
} else {
|
|
1041
|
+
return { type: "L", x: point.x, y: point.y };
|
|
1042
|
+
}
|
|
1043
|
+
});
|
|
1031
1044
|
}
|
|
1032
1045
|
getData() {
|
|
1033
1046
|
return pathCommandsToPathData(this.getCommands());
|
|
@@ -1060,14 +1073,18 @@ class CircleCurve extends Curve {
|
|
|
1060
1073
|
}
|
|
1061
1074
|
getTangent(t) {
|
|
1062
1075
|
const { x, y } = this.getNormal(t);
|
|
1063
|
-
return new
|
|
1076
|
+
return new Vector2(-y, x);
|
|
1064
1077
|
}
|
|
1065
1078
|
getNormal(t) {
|
|
1066
1079
|
const { start, end } = this;
|
|
1067
1080
|
const _t = t * (end - start) + start - 0.5 * Math.PI;
|
|
1068
|
-
return new
|
|
1081
|
+
return new Vector2(Math.cos(_t), Math.sin(_t));
|
|
1082
|
+
}
|
|
1083
|
+
transformPoint(cb) {
|
|
1084
|
+
cb(this.center);
|
|
1085
|
+
return this;
|
|
1069
1086
|
}
|
|
1070
|
-
getMinMax(min =
|
|
1087
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1071
1088
|
min.x = Math.min(min.x, this.center.x - this.radius);
|
|
1072
1089
|
min.y = Math.min(min.y, this.center.y - this.radius);
|
|
1073
1090
|
max.x = Math.max(max.x, this.center.x + this.radius);
|
|
@@ -1115,54 +1132,54 @@ function cubicBezier(t, p0, p1, p2, p3) {
|
|
|
1115
1132
|
}
|
|
1116
1133
|
|
|
1117
1134
|
class CubicBezierCurve extends Curve {
|
|
1118
|
-
constructor(
|
|
1135
|
+
constructor(start = new Vector2(), startControl = new Vector2(), endControl = new Vector2(), end = new Vector2()) {
|
|
1119
1136
|
super();
|
|
1120
|
-
this.
|
|
1121
|
-
this.
|
|
1122
|
-
this.
|
|
1123
|
-
this.
|
|
1137
|
+
this.start = start;
|
|
1138
|
+
this.startControl = startControl;
|
|
1139
|
+
this.endControl = endControl;
|
|
1140
|
+
this.end = end;
|
|
1124
1141
|
}
|
|
1125
|
-
getPoint(t, output = new
|
|
1126
|
-
const {
|
|
1142
|
+
getPoint(t, output = new Vector2()) {
|
|
1143
|
+
const { start, startControl, endControl, end } = this;
|
|
1127
1144
|
output.set(
|
|
1128
|
-
cubicBezier(t,
|
|
1129
|
-
cubicBezier(t,
|
|
1145
|
+
cubicBezier(t, start.x, startControl.x, endControl.x, end.x),
|
|
1146
|
+
cubicBezier(t, start.y, startControl.y, endControl.y, end.y)
|
|
1130
1147
|
);
|
|
1131
1148
|
return output;
|
|
1132
1149
|
}
|
|
1133
|
-
|
|
1134
|
-
this.
|
|
1135
|
-
this.
|
|
1136
|
-
this.
|
|
1137
|
-
this.
|
|
1138
|
-
return this;
|
|
1139
|
-
}
|
|
1140
|
-
getMinMax(min =
|
|
1141
|
-
const {
|
|
1142
|
-
min.x = Math.min(min.x,
|
|
1143
|
-
min.y = Math.min(min.y,
|
|
1144
|
-
max.x = Math.max(max.x,
|
|
1145
|
-
max.y = Math.max(max.y,
|
|
1150
|
+
transformPoint(cb) {
|
|
1151
|
+
cb(this.start);
|
|
1152
|
+
cb(this.startControl);
|
|
1153
|
+
cb(this.endControl);
|
|
1154
|
+
cb(this.end);
|
|
1155
|
+
return this;
|
|
1156
|
+
}
|
|
1157
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1158
|
+
const { start, startControl, endControl, end } = this;
|
|
1159
|
+
min.x = Math.min(min.x, start.x, startControl.x, endControl.x, end.x);
|
|
1160
|
+
min.y = Math.min(min.y, start.y, startControl.y, endControl.y, end.y);
|
|
1161
|
+
max.x = Math.max(max.x, start.x, startControl.x, endControl.x, end.x);
|
|
1162
|
+
max.y = Math.max(max.y, start.y, startControl.y, endControl.y, end.y);
|
|
1146
1163
|
return { min, max };
|
|
1147
1164
|
}
|
|
1148
1165
|
getCommands() {
|
|
1149
|
-
const {
|
|
1166
|
+
const { start, startControl, endControl, end } = this;
|
|
1150
1167
|
return [
|
|
1151
|
-
{ type: "M", x:
|
|
1152
|
-
{ type: "C", x1:
|
|
1168
|
+
{ type: "M", x: start.x, y: start.y },
|
|
1169
|
+
{ type: "C", x1: startControl.x, y1: startControl.y, x2: endControl.x, y2: endControl.y, x: end.x, y: end.y }
|
|
1153
1170
|
];
|
|
1154
1171
|
}
|
|
1155
1172
|
drawTo(ctx) {
|
|
1156
|
-
const {
|
|
1157
|
-
ctx.bezierCurveTo(
|
|
1173
|
+
const { startControl, endControl, end } = this;
|
|
1174
|
+
ctx.bezierCurveTo(startControl.x, startControl.y, endControl.x, endControl.y, end.x, end.y);
|
|
1158
1175
|
return this;
|
|
1159
1176
|
}
|
|
1160
1177
|
copy(source) {
|
|
1161
1178
|
super.copy(source);
|
|
1162
|
-
this.
|
|
1163
|
-
this.
|
|
1164
|
-
this.
|
|
1165
|
-
this.
|
|
1179
|
+
this.start.copy(source.start);
|
|
1180
|
+
this.startControl.copy(source.startControl);
|
|
1181
|
+
this.endControl.copy(source.endControl);
|
|
1182
|
+
this.end.copy(source.end);
|
|
1166
1183
|
return this;
|
|
1167
1184
|
}
|
|
1168
1185
|
}
|
|
@@ -1170,12 +1187,11 @@ class CubicBezierCurve extends Curve {
|
|
|
1170
1187
|
const tempTransform0$1 = new Matrix3();
|
|
1171
1188
|
const tempTransform1$1 = new Matrix3();
|
|
1172
1189
|
const tempTransform2$1 = new Matrix3();
|
|
1173
|
-
const tempV2 = new
|
|
1190
|
+
const tempV2 = new Vector2();
|
|
1174
1191
|
class EllipseCurve extends Curve {
|
|
1175
|
-
constructor(
|
|
1192
|
+
constructor(center = new Vector2(), radiusX = 1, radiusY = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false, rotation = 0) {
|
|
1176
1193
|
super();
|
|
1177
|
-
this.
|
|
1178
|
-
this.y = y;
|
|
1194
|
+
this.center = center;
|
|
1179
1195
|
this.radiusX = radiusX;
|
|
1180
1196
|
this.radiusY = radiusY;
|
|
1181
1197
|
this.startAngle = startAngle;
|
|
@@ -1183,7 +1199,7 @@ class EllipseCurve extends Curve {
|
|
|
1183
1199
|
this.clockwise = clockwise;
|
|
1184
1200
|
this.rotation = rotation;
|
|
1185
1201
|
}
|
|
1186
|
-
getPoint(t, output = new
|
|
1202
|
+
getPoint(t, output = new Vector2()) {
|
|
1187
1203
|
const twoPi = Math.PI * 2;
|
|
1188
1204
|
let deltaAngle = this.endAngle - this.startAngle;
|
|
1189
1205
|
const samePoints = Math.abs(deltaAngle) < Number.EPSILON;
|
|
@@ -1206,15 +1222,15 @@ class EllipseCurve extends Curve {
|
|
|
1206
1222
|
}
|
|
1207
1223
|
}
|
|
1208
1224
|
const angle = this.startAngle + t * deltaAngle;
|
|
1209
|
-
let _x = this.x + this.radiusX * Math.cos(angle);
|
|
1210
|
-
let _y = this.y + this.radiusY * Math.sin(angle);
|
|
1225
|
+
let _x = this.center.x + this.radiusX * Math.cos(angle);
|
|
1226
|
+
let _y = this.center.y + this.radiusY * Math.sin(angle);
|
|
1211
1227
|
if (this.rotation !== 0) {
|
|
1212
1228
|
const cos = Math.cos(this.rotation);
|
|
1213
1229
|
const sin = Math.sin(this.rotation);
|
|
1214
|
-
const tx = _x - this.x;
|
|
1215
|
-
const ty = _y - this.y;
|
|
1216
|
-
_x = tx * cos - ty * sin + this.x;
|
|
1217
|
-
_y = tx * sin + ty * cos + this.y;
|
|
1230
|
+
const tx = _x - this.center.x;
|
|
1231
|
+
const ty = _y - this.center.y;
|
|
1232
|
+
_x = tx * cos - ty * sin + this.center.x;
|
|
1233
|
+
_y = tx * sin + ty * cos + this.center.y;
|
|
1218
1234
|
}
|
|
1219
1235
|
return output.set(_x, _y);
|
|
1220
1236
|
}
|
|
@@ -1222,38 +1238,37 @@ class EllipseCurve extends Curve {
|
|
|
1222
1238
|
return divisions * 2;
|
|
1223
1239
|
}
|
|
1224
1240
|
getCommands() {
|
|
1225
|
-
const {
|
|
1226
|
-
const
|
|
1227
|
-
const startX =
|
|
1228
|
-
const startY =
|
|
1229
|
-
const endX = x + radiusX * Math.cos(endAngle);
|
|
1230
|
-
const endY = y + radiusY * Math.sin(endAngle);
|
|
1241
|
+
const { center, radiusX: rx, radiusY: ry, startAngle, endAngle, clockwise, rotation } = this;
|
|
1242
|
+
const { x: cx, y: cy } = center;
|
|
1243
|
+
const startX = cx + rx * Math.cos(startAngle) * Math.cos(rotation) - ry * Math.sin(startAngle) * Math.sin(rotation);
|
|
1244
|
+
const startY = cy + rx * Math.cos(startAngle) * Math.sin(rotation) + ry * Math.sin(startAngle) * Math.cos(rotation);
|
|
1231
1245
|
const angleDiff = Math.abs(startAngle - endAngle);
|
|
1232
1246
|
const largeArcFlag = angleDiff > Math.PI ? 1 : 0;
|
|
1233
|
-
const sweepFlag =
|
|
1234
|
-
const
|
|
1235
|
-
const midY = y + radiusY * Math.sin(startAngle + (endAngle - startAngle) / 2);
|
|
1247
|
+
const sweepFlag = clockwise ? 1 : 0;
|
|
1248
|
+
const angle = rotation * 180 / Math.PI;
|
|
1236
1249
|
if (angleDiff >= 2 * Math.PI) {
|
|
1250
|
+
const midAngle = startAngle + Math.PI;
|
|
1251
|
+
const midX = cx + rx * Math.cos(midAngle) * Math.cos(rotation) - ry * Math.sin(midAngle) * Math.sin(rotation);
|
|
1252
|
+
const midY = cy + rx * Math.cos(midAngle) * Math.sin(rotation) + ry * Math.sin(midAngle) * Math.cos(rotation);
|
|
1237
1253
|
return [
|
|
1238
1254
|
{ type: "M", x: startX, y: startY },
|
|
1239
|
-
{ type: "A", rx
|
|
1240
|
-
{ type: "A", rx
|
|
1255
|
+
{ type: "A", rx, ry, angle, largeArcFlag: 0, sweepFlag, x: midX, y: midY },
|
|
1256
|
+
{ type: "A", rx, ry, angle, largeArcFlag: 0, sweepFlag, x: startX, y: startY }
|
|
1241
1257
|
];
|
|
1242
1258
|
} else {
|
|
1259
|
+
const endX = cx + rx * Math.cos(endAngle) * Math.cos(rotation) - ry * Math.sin(endAngle) * Math.sin(rotation);
|
|
1260
|
+
const endY = cy + rx * Math.cos(endAngle) * Math.sin(rotation) + ry * Math.sin(endAngle) * Math.cos(rotation);
|
|
1243
1261
|
return [
|
|
1244
1262
|
{ type: "M", x: startX, y: startY },
|
|
1245
|
-
{ type: "A", rx
|
|
1263
|
+
{ type: "A", rx, ry, angle, largeArcFlag, sweepFlag, x: endX, y: endY }
|
|
1246
1264
|
];
|
|
1247
1265
|
}
|
|
1248
1266
|
}
|
|
1249
1267
|
drawTo(ctx) {
|
|
1250
|
-
const {
|
|
1251
|
-
const startX = x + radiusX * Math.cos(startAngle);
|
|
1252
|
-
const startY = y + radiusY * Math.sin(startAngle);
|
|
1253
|
-
ctx.moveTo(startX, startY);
|
|
1268
|
+
const { center, radiusX, radiusY, rotation, startAngle, endAngle, clockwise } = this;
|
|
1254
1269
|
ctx.ellipse(
|
|
1255
|
-
x,
|
|
1256
|
-
y,
|
|
1270
|
+
center.x,
|
|
1271
|
+
center.y,
|
|
1257
1272
|
radiusX,
|
|
1258
1273
|
radiusY,
|
|
1259
1274
|
rotation,
|
|
@@ -1264,10 +1279,10 @@ class EllipseCurve extends Curve {
|
|
|
1264
1279
|
return this;
|
|
1265
1280
|
}
|
|
1266
1281
|
transform(matrix) {
|
|
1267
|
-
tempV2.set(this.x, this.y);
|
|
1282
|
+
tempV2.set(this.center.x, this.center.y);
|
|
1268
1283
|
tempV2.applyMatrix3(matrix);
|
|
1269
|
-
this.x = tempV2.x;
|
|
1270
|
-
this.y = tempV2.y;
|
|
1284
|
+
this.center.x = tempV2.x;
|
|
1285
|
+
this.center.y = tempV2.y;
|
|
1271
1286
|
if (isTransformSkewed(matrix)) {
|
|
1272
1287
|
transfEllipseGeneric(this, matrix);
|
|
1273
1288
|
} else {
|
|
@@ -1275,10 +1290,31 @@ class EllipseCurve extends Curve {
|
|
|
1275
1290
|
}
|
|
1276
1291
|
return this;
|
|
1277
1292
|
}
|
|
1293
|
+
transformPoint(cb) {
|
|
1294
|
+
cb(this.center);
|
|
1295
|
+
return this;
|
|
1296
|
+
}
|
|
1297
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1298
|
+
const { center, radiusX: rx, radiusY: ry, rotation: theta } = this;
|
|
1299
|
+
const { x: cx, y: cy } = center;
|
|
1300
|
+
const cosTheta = Math.cos(theta);
|
|
1301
|
+
const sinTheta = Math.sin(theta);
|
|
1302
|
+
const halfWidth = Math.sqrt(
|
|
1303
|
+
rx * rx * cosTheta * cosTheta + ry * ry * sinTheta * sinTheta
|
|
1304
|
+
);
|
|
1305
|
+
const halfHeight = Math.sqrt(
|
|
1306
|
+
rx * rx * sinTheta * sinTheta + ry * ry * cosTheta * cosTheta
|
|
1307
|
+
);
|
|
1308
|
+
min.x = Math.min(min.x, cx - halfWidth);
|
|
1309
|
+
min.y = Math.min(min.y, cy - halfHeight);
|
|
1310
|
+
max.x = Math.max(max.x, cx + halfWidth);
|
|
1311
|
+
max.y = Math.max(max.y, cy + halfHeight);
|
|
1312
|
+
return { min, max };
|
|
1313
|
+
}
|
|
1278
1314
|
copy(source) {
|
|
1279
1315
|
super.copy(source);
|
|
1280
|
-
this.x = source.x;
|
|
1281
|
-
this.y = source.y;
|
|
1316
|
+
this.center.x = source.center.x;
|
|
1317
|
+
this.center.y = source.center.y;
|
|
1282
1318
|
this.radiusX = source.radiusX;
|
|
1283
1319
|
this.radiusY = source.radiusY;
|
|
1284
1320
|
this.startAngle = source.startAngle;
|
|
@@ -1293,8 +1329,8 @@ function transfEllipseGeneric(curve, m) {
|
|
|
1293
1329
|
const b = curve.radiusY;
|
|
1294
1330
|
const cosTheta = Math.cos(curve.rotation);
|
|
1295
1331
|
const sinTheta = Math.sin(curve.rotation);
|
|
1296
|
-
const v1 = new
|
|
1297
|
-
const v2 = new
|
|
1332
|
+
const v1 = new Vector2(a * cosTheta, a * sinTheta);
|
|
1333
|
+
const v2 = new Vector2(-b * sinTheta, b * cosTheta);
|
|
1298
1334
|
const f1 = v1.applyMatrix3(m);
|
|
1299
1335
|
const f2 = v2.applyMatrix3(m);
|
|
1300
1336
|
const mF = tempTransform0$1.set(
|
|
@@ -1344,7 +1380,7 @@ function transfEllipseGeneric(curve, m) {
|
|
|
1344
1380
|
);
|
|
1345
1381
|
const mDRF = mDsqrt.multiply(mRT).multiply(mF);
|
|
1346
1382
|
const transformAngle = (phi) => {
|
|
1347
|
-
const { x: cosR, y: sinR } = new
|
|
1383
|
+
const { x: cosR, y: sinR } = new Vector2(Math.cos(phi), Math.sin(phi)).applyMatrix3(mDRF);
|
|
1348
1384
|
return Math.atan2(sinR, cosR);
|
|
1349
1385
|
};
|
|
1350
1386
|
curve.startAngle = transformAngle(curve.startAngle);
|
|
@@ -1429,61 +1465,64 @@ function eigenDecomposition(A, B, C) {
|
|
|
1429
1465
|
}
|
|
1430
1466
|
|
|
1431
1467
|
class LineCurve extends Curve {
|
|
1432
|
-
constructor(
|
|
1468
|
+
constructor(start = new Vector2(), end = new Vector2()) {
|
|
1433
1469
|
super();
|
|
1434
|
-
this.
|
|
1435
|
-
this.
|
|
1470
|
+
this.start = start;
|
|
1471
|
+
this.end = end;
|
|
1436
1472
|
}
|
|
1437
|
-
getPoint(t, output = new
|
|
1473
|
+
getPoint(t, output = new Vector2()) {
|
|
1438
1474
|
if (t === 1) {
|
|
1439
|
-
output.copy(this.
|
|
1475
|
+
output.copy(this.end);
|
|
1440
1476
|
} else {
|
|
1441
|
-
output.copy(this.
|
|
1442
|
-
output.multiplyScalar(t).add(this.v1);
|
|
1477
|
+
output.copy(this.end).sub(this.start).multiplyScalar(t).add(this.start);
|
|
1443
1478
|
}
|
|
1444
1479
|
return output;
|
|
1445
1480
|
}
|
|
1446
|
-
getPointAt(u, output = new
|
|
1481
|
+
getPointAt(u, output = new Vector2()) {
|
|
1447
1482
|
return this.getPoint(u, output);
|
|
1448
1483
|
}
|
|
1449
|
-
getTangent(
|
|
1450
|
-
return output.subVectors(this.
|
|
1484
|
+
getTangent(_t, output = new Vector2()) {
|
|
1485
|
+
return output.subVectors(this.end, this.start).normalize();
|
|
1451
1486
|
}
|
|
1452
|
-
getTangentAt(u, output = new
|
|
1487
|
+
getTangentAt(u, output = new Vector2()) {
|
|
1453
1488
|
return this.getTangent(u, output);
|
|
1454
1489
|
}
|
|
1455
|
-
|
|
1456
|
-
this.
|
|
1457
|
-
|
|
1490
|
+
getNormal(t, output = new Vector2()) {
|
|
1491
|
+
const { x, y } = this.getPoint(t).sub(this.start);
|
|
1492
|
+
return output.set(y, -x).normalize();
|
|
1493
|
+
}
|
|
1494
|
+
transformPoint(cb) {
|
|
1495
|
+
cb(this.start);
|
|
1496
|
+
cb(this.end);
|
|
1458
1497
|
return this;
|
|
1459
1498
|
}
|
|
1460
1499
|
getDivisions() {
|
|
1461
1500
|
return 1;
|
|
1462
1501
|
}
|
|
1463
|
-
getMinMax(min =
|
|
1464
|
-
const {
|
|
1465
|
-
min.x = Math.min(min.x,
|
|
1466
|
-
min.y = Math.min(min.y,
|
|
1467
|
-
max.x = Math.max(max.x,
|
|
1468
|
-
max.y = Math.max(max.y,
|
|
1502
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1503
|
+
const { start, end } = this;
|
|
1504
|
+
min.x = Math.min(min.x, start.x, end.x);
|
|
1505
|
+
min.y = Math.min(min.y, start.y, end.y);
|
|
1506
|
+
max.x = Math.max(max.x, start.x, end.x);
|
|
1507
|
+
max.y = Math.max(max.y, start.y, end.y);
|
|
1469
1508
|
return { min, max };
|
|
1470
1509
|
}
|
|
1471
1510
|
getCommands() {
|
|
1472
|
-
const {
|
|
1511
|
+
const { start, end } = this;
|
|
1473
1512
|
return [
|
|
1474
|
-
{ type: "M", x:
|
|
1475
|
-
{ type: "L", x:
|
|
1513
|
+
{ type: "M", x: start.x, y: start.y },
|
|
1514
|
+
{ type: "L", x: end.x, y: end.y }
|
|
1476
1515
|
];
|
|
1477
1516
|
}
|
|
1478
1517
|
drawTo(ctx) {
|
|
1479
|
-
const {
|
|
1480
|
-
ctx.lineTo(
|
|
1518
|
+
const { end } = this;
|
|
1519
|
+
ctx.lineTo(end.x, end.y);
|
|
1481
1520
|
return this;
|
|
1482
1521
|
}
|
|
1483
1522
|
copy(source) {
|
|
1484
1523
|
super.copy(source);
|
|
1485
|
-
this.
|
|
1486
|
-
this.
|
|
1524
|
+
this.start.copy(source.start);
|
|
1525
|
+
this.end.copy(source.end);
|
|
1487
1526
|
return this;
|
|
1488
1527
|
}
|
|
1489
1528
|
}
|
|
@@ -1501,66 +1540,68 @@ class HeartCurve extends Curve {
|
|
|
1501
1540
|
this.size = size;
|
|
1502
1541
|
this.start = start;
|
|
1503
1542
|
this.end = end;
|
|
1504
|
-
__publicField$4(this, "
|
|
1505
|
-
|
|
1543
|
+
__publicField$4(this, "curveT", 0);
|
|
1544
|
+
this.update();
|
|
1545
|
+
}
|
|
1546
|
+
update() {
|
|
1506
1547
|
const { x, y } = this.center;
|
|
1507
|
-
const A = new
|
|
1508
|
-
const t = new
|
|
1509
|
-
const i = new
|
|
1548
|
+
const A = new Vector2(x + 0.5 * this.size, y - 0.5 * this.size);
|
|
1549
|
+
const t = new Vector2(x - 0.5 * this.size, y - 0.5 * this.size);
|
|
1550
|
+
const i = new Vector2(x, y + 0.5 * this.size);
|
|
1510
1551
|
const curve1 = new CircleCurve(A, Math.SQRT1_2 * this.size, -0.25 * Math.PI, 0.75 * Math.PI);
|
|
1511
1552
|
const curve5 = new CircleCurve(t, Math.SQRT1_2 * this.size, -0.75 * Math.PI, 0.25 * Math.PI);
|
|
1512
1553
|
const curve3 = new CircleCurve(i, 0.5 * Math.SQRT1_2 * this.size, 0.75 * Math.PI, 1.25 * Math.PI);
|
|
1513
|
-
const e = new
|
|
1514
|
-
const l = new
|
|
1515
|
-
const c = new
|
|
1516
|
-
const h = new
|
|
1517
|
-
const a = new
|
|
1554
|
+
const e = new Vector2(x, y + this.size);
|
|
1555
|
+
const l = new Vector2(x + this.size, y);
|
|
1556
|
+
const c = new Vector2().lerpVectors(l, e, 0.75);
|
|
1557
|
+
const h = new Vector2(x - this.size, y);
|
|
1558
|
+
const a = new Vector2().lerpVectors(h, e, 0.75);
|
|
1518
1559
|
const curve2 = new LineCurve(l, c);
|
|
1519
1560
|
const curve4 = new LineCurve(a, h);
|
|
1520
1561
|
this.curves = [curve1, curve2, curve3, curve4, curve5];
|
|
1562
|
+
return this;
|
|
1521
1563
|
}
|
|
1522
|
-
getPoint(
|
|
1523
|
-
return this.
|
|
1564
|
+
getPoint(t) {
|
|
1565
|
+
return this.getCurve(t).getPoint(this.curveT);
|
|
1524
1566
|
}
|
|
1525
|
-
getPointAt(
|
|
1526
|
-
return this.getPoint(
|
|
1567
|
+
getPointAt(t) {
|
|
1568
|
+
return this.getPoint(t);
|
|
1527
1569
|
}
|
|
1528
|
-
|
|
1529
|
-
let val = (
|
|
1570
|
+
getCurve(t) {
|
|
1571
|
+
let val = (t * (this.end - this.start) + this.start) % 1;
|
|
1530
1572
|
val < 0 && (val += 1);
|
|
1531
1573
|
val *= 9 * Math.PI / 8 + 1.5;
|
|
1532
1574
|
let index;
|
|
1533
|
-
const
|
|
1534
|
-
if (val <
|
|
1575
|
+
const PI_1_2 = 0.5 * Math.PI;
|
|
1576
|
+
if (val < PI_1_2) {
|
|
1535
1577
|
index = 0;
|
|
1536
|
-
this.
|
|
1537
|
-
} else if (val <
|
|
1578
|
+
this.curveT = val / PI_1_2;
|
|
1579
|
+
} else if (val < PI_1_2 + 0.75) {
|
|
1538
1580
|
index = 1;
|
|
1539
|
-
this.
|
|
1581
|
+
this.curveT = (val - PI_1_2) / 0.75;
|
|
1540
1582
|
} else if (val < 5 * Math.PI / 8 + 0.75) {
|
|
1541
1583
|
index = 2;
|
|
1542
|
-
this.
|
|
1584
|
+
this.curveT = (val - PI_1_2 - 0.75) / (Math.PI / 8);
|
|
1543
1585
|
} else if (val < 5 * Math.PI / 8 + 1.5) {
|
|
1544
1586
|
index = 3;
|
|
1545
|
-
this.
|
|
1587
|
+
this.curveT = (val - 5 * Math.PI / 8 - 0.75) / 0.75;
|
|
1546
1588
|
} else {
|
|
1547
1589
|
index = 4;
|
|
1548
|
-
this.
|
|
1590
|
+
this.curveT = (val - 5 * Math.PI / 8 - 1.5) / PI_1_2;
|
|
1549
1591
|
}
|
|
1550
1592
|
return this.curves[index];
|
|
1551
1593
|
}
|
|
1552
|
-
getTangent(
|
|
1553
|
-
return this.
|
|
1594
|
+
getTangent(t) {
|
|
1595
|
+
return this.getCurve(t).getTangent(this.curveT);
|
|
1554
1596
|
}
|
|
1555
|
-
getNormal(
|
|
1556
|
-
|
|
1557
|
-
return new Point2D(line.v2.y - line.v1.y, -(line.v2.x - line.v1.x)).normalize();
|
|
1597
|
+
getNormal(t) {
|
|
1598
|
+
return this.getCurve(t).getNormal(this.curveT);
|
|
1558
1599
|
}
|
|
1559
|
-
|
|
1560
|
-
this.curves.forEach((curve) => curve.
|
|
1600
|
+
transformPoint(cb) {
|
|
1601
|
+
this.curves.forEach((curve) => curve.transformPoint(cb));
|
|
1561
1602
|
return this;
|
|
1562
1603
|
}
|
|
1563
|
-
getMinMax(min =
|
|
1604
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1564
1605
|
this.curves.forEach((curve) => curve.getMinMax(min, max));
|
|
1565
1606
|
return { min, max };
|
|
1566
1607
|
}
|
|
@@ -1580,54 +1621,59 @@ var __publicField$3 = (obj, key, value) => {
|
|
|
1580
1621
|
return value;
|
|
1581
1622
|
};
|
|
1582
1623
|
class PloygonCurve extends Curve {
|
|
1583
|
-
constructor(center, radius = 0,
|
|
1624
|
+
constructor(center, radius = 0, number = 0, start = 0, end = 1) {
|
|
1584
1625
|
super();
|
|
1585
1626
|
this.center = center;
|
|
1586
1627
|
this.radius = radius;
|
|
1587
|
-
this.
|
|
1628
|
+
this.number = number;
|
|
1588
1629
|
this.start = start;
|
|
1589
1630
|
this.end = end;
|
|
1590
1631
|
__publicField$3(this, "curves", []);
|
|
1632
|
+
__publicField$3(this, "curveT", 0);
|
|
1591
1633
|
__publicField$3(this, "points", []);
|
|
1592
|
-
|
|
1593
|
-
|
|
1634
|
+
this.update();
|
|
1635
|
+
}
|
|
1636
|
+
update() {
|
|
1637
|
+
for (let i = 0; i < this.number; i++) {
|
|
1638
|
+
let radian = i * 2 * Math.PI / this.number;
|
|
1594
1639
|
radian -= 0.5 * Math.PI;
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1640
|
+
this.points.push(
|
|
1641
|
+
new Vector2(
|
|
1642
|
+
this.radius * Math.cos(radian),
|
|
1643
|
+
this.radius * Math.sin(radian)
|
|
1644
|
+
).add(this.center)
|
|
1645
|
+
);
|
|
1598
1646
|
}
|
|
1599
|
-
for (let i = 0; i < this.
|
|
1600
|
-
this.curves.push(new LineCurve(this.points[i], this.points[(i + 1) % this.
|
|
1647
|
+
for (let i = 0; i < this.number; i++) {
|
|
1648
|
+
this.curves.push(new LineCurve(this.points[i], this.points[(i + 1) % this.number]));
|
|
1601
1649
|
}
|
|
1650
|
+
return this;
|
|
1602
1651
|
}
|
|
1603
|
-
|
|
1604
|
-
this.
|
|
1605
|
-
return this.currentLine.getPoint(this.pointK);
|
|
1606
|
-
}
|
|
1607
|
-
getPointAt(value) {
|
|
1608
|
-
return this.getPoint(value);
|
|
1609
|
-
}
|
|
1610
|
-
getCurrentLine(value) {
|
|
1611
|
-
let pos = (value * (this.end - this.start) + this.start) % 1;
|
|
1652
|
+
getCurve(t) {
|
|
1653
|
+
let pos = (t * (this.end - this.start) + this.start) % 1;
|
|
1612
1654
|
pos < 0 && (pos += 1);
|
|
1613
|
-
const v = pos * this.
|
|
1655
|
+
const v = pos * this.number;
|
|
1614
1656
|
const index = Math.floor(v);
|
|
1615
|
-
this.
|
|
1616
|
-
|
|
1617
|
-
return this.currentLine;
|
|
1657
|
+
this.curveT = v - index;
|
|
1658
|
+
return this.curves[index];
|
|
1618
1659
|
}
|
|
1619
|
-
|
|
1620
|
-
return this.
|
|
1660
|
+
getPoint(t, output) {
|
|
1661
|
+
return this.getCurve(t).getPoint(this.curveT, output);
|
|
1621
1662
|
}
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
return new Point2D(line.v2.y - line.v1.y, -(line.v2.x - line.v1.x)).normalize();
|
|
1663
|
+
getPointAt(u, output) {
|
|
1664
|
+
return this.getPoint(u, output);
|
|
1625
1665
|
}
|
|
1626
|
-
|
|
1627
|
-
this.
|
|
1666
|
+
getTangent(t, output) {
|
|
1667
|
+
return this.getCurve(t).getTangent(this.curveT, output);
|
|
1668
|
+
}
|
|
1669
|
+
getNormal(t, output) {
|
|
1670
|
+
return this.getCurve(t).getNormal(this.curveT, output);
|
|
1671
|
+
}
|
|
1672
|
+
transformPoint(cb) {
|
|
1673
|
+
this.curves.forEach((curve) => curve.transformPoint(cb));
|
|
1628
1674
|
return this;
|
|
1629
1675
|
}
|
|
1630
|
-
getMinMax(min =
|
|
1676
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1631
1677
|
this.curves.forEach((curve) => curve.getMinMax(min, max));
|
|
1632
1678
|
return { min, max };
|
|
1633
1679
|
}
|
|
@@ -1641,55 +1687,55 @@ class PloygonCurve extends Curve {
|
|
|
1641
1687
|
}
|
|
1642
1688
|
|
|
1643
1689
|
class QuadraticBezierCurve extends Curve {
|
|
1644
|
-
constructor(
|
|
1690
|
+
constructor(start = new Vector2(), control = new Vector2(), end = new Vector2()) {
|
|
1645
1691
|
super();
|
|
1646
|
-
this.
|
|
1647
|
-
this.
|
|
1648
|
-
this.
|
|
1692
|
+
this.start = start;
|
|
1693
|
+
this.control = control;
|
|
1694
|
+
this.end = end;
|
|
1649
1695
|
}
|
|
1650
|
-
getPoint(t, output = new
|
|
1651
|
-
const {
|
|
1696
|
+
getPoint(t, output = new Vector2()) {
|
|
1697
|
+
const { start, control, end } = this;
|
|
1652
1698
|
output.set(
|
|
1653
|
-
quadraticBezier(t,
|
|
1654
|
-
quadraticBezier(t,
|
|
1699
|
+
quadraticBezier(t, start.x, control.x, end.x),
|
|
1700
|
+
quadraticBezier(t, start.y, control.y, end.y)
|
|
1655
1701
|
);
|
|
1656
1702
|
return output;
|
|
1657
1703
|
}
|
|
1658
|
-
|
|
1659
|
-
this.
|
|
1660
|
-
this.
|
|
1661
|
-
this.
|
|
1662
|
-
return this;
|
|
1663
|
-
}
|
|
1664
|
-
getMinMax(min =
|
|
1665
|
-
const {
|
|
1666
|
-
const x1 = 0.5 * (
|
|
1667
|
-
const y1 = 0.5 * (
|
|
1668
|
-
const x2 = 0.5 * (
|
|
1669
|
-
const y2 = 0.5 * (
|
|
1670
|
-
min.x = Math.min(min.x,
|
|
1671
|
-
min.y = Math.min(min.y,
|
|
1672
|
-
max.x = Math.max(max.x,
|
|
1673
|
-
max.y = Math.max(max.y,
|
|
1704
|
+
transformPoint(cb) {
|
|
1705
|
+
cb(this.start);
|
|
1706
|
+
cb(this.control);
|
|
1707
|
+
cb(this.end);
|
|
1708
|
+
return this;
|
|
1709
|
+
}
|
|
1710
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1711
|
+
const { start, control, end } = this;
|
|
1712
|
+
const x1 = 0.5 * (start.x + control.x);
|
|
1713
|
+
const y1 = 0.5 * (start.y + control.y);
|
|
1714
|
+
const x2 = 0.5 * (start.x + end.x);
|
|
1715
|
+
const y2 = 0.5 * (start.y + end.y);
|
|
1716
|
+
min.x = Math.min(min.x, start.x, end.x, x1, x2);
|
|
1717
|
+
min.y = Math.min(min.y, start.y, end.y, y1, y2);
|
|
1718
|
+
max.x = Math.max(max.x, start.x, end.x, x1, x2);
|
|
1719
|
+
max.y = Math.max(max.y, start.y, end.y, y1, y2);
|
|
1674
1720
|
return { min, max };
|
|
1675
1721
|
}
|
|
1676
1722
|
getCommands() {
|
|
1677
|
-
const {
|
|
1723
|
+
const { start, control, end } = this;
|
|
1678
1724
|
return [
|
|
1679
|
-
{ type: "M", x:
|
|
1680
|
-
{ type: "Q", x1:
|
|
1725
|
+
{ type: "M", x: start.x, y: start.y },
|
|
1726
|
+
{ type: "Q", x1: control.x, y1: control.y, x: end.x, y: end.y }
|
|
1681
1727
|
];
|
|
1682
1728
|
}
|
|
1683
1729
|
drawTo(ctx) {
|
|
1684
|
-
const {
|
|
1685
|
-
ctx.quadraticCurveTo(
|
|
1730
|
+
const { control, end } = this;
|
|
1731
|
+
ctx.quadraticCurveTo(control.x, control.y, end.x, end.y);
|
|
1686
1732
|
return this;
|
|
1687
1733
|
}
|
|
1688
1734
|
copy(source) {
|
|
1689
1735
|
super.copy(source);
|
|
1690
|
-
this.
|
|
1691
|
-
this.
|
|
1692
|
-
this.
|
|
1736
|
+
this.start.copy(source.start);
|
|
1737
|
+
this.control.copy(source.control);
|
|
1738
|
+
this.end.copy(source.end);
|
|
1693
1739
|
return this;
|
|
1694
1740
|
}
|
|
1695
1741
|
}
|
|
@@ -1709,19 +1755,8 @@ class RectangularCurve extends Curve {
|
|
|
1709
1755
|
this.start = start;
|
|
1710
1756
|
this.end = end;
|
|
1711
1757
|
__publicField$2(this, "curves", []);
|
|
1712
|
-
__publicField$2(this, "
|
|
1713
|
-
|
|
1714
|
-
const offsetX = this.rx;
|
|
1715
|
-
const offsetY = this.rx / this.aspectRatio;
|
|
1716
|
-
const points = [
|
|
1717
|
-
new Point2D(x - offsetX, y - offsetY),
|
|
1718
|
-
new Point2D(x + offsetX, y - offsetY),
|
|
1719
|
-
new Point2D(x + offsetX, y + offsetY),
|
|
1720
|
-
new Point2D(x - offsetX, y + offsetY)
|
|
1721
|
-
];
|
|
1722
|
-
for (let i = 0; i < 4; i++) {
|
|
1723
|
-
this.curves.push(new LineCurve(points[i].clone(), points[(i + 1) % 4].clone()));
|
|
1724
|
-
}
|
|
1758
|
+
__publicField$2(this, "curveT", 0);
|
|
1759
|
+
this.update();
|
|
1725
1760
|
}
|
|
1726
1761
|
get x() {
|
|
1727
1762
|
return this.center.x - this.rx;
|
|
@@ -1735,44 +1770,58 @@ class RectangularCurve extends Curve {
|
|
|
1735
1770
|
get height() {
|
|
1736
1771
|
return this.rx / this.aspectRatio * 2;
|
|
1737
1772
|
}
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1773
|
+
update() {
|
|
1774
|
+
const { x, y } = this.center;
|
|
1775
|
+
const offsetX = this.rx;
|
|
1776
|
+
const offsetY = this.rx / this.aspectRatio;
|
|
1777
|
+
const points = [
|
|
1778
|
+
new Vector2(x - offsetX, y - offsetY),
|
|
1779
|
+
new Vector2(x + offsetX, y - offsetY),
|
|
1780
|
+
new Vector2(x + offsetX, y + offsetY),
|
|
1781
|
+
new Vector2(x - offsetX, y + offsetY)
|
|
1782
|
+
];
|
|
1783
|
+
for (let i = 0; i < 4; i++) {
|
|
1784
|
+
this.curves.push(new LineCurve(points[i].clone(), points[(i + 1) % 4].clone()));
|
|
1785
|
+
}
|
|
1786
|
+
return this;
|
|
1743
1787
|
}
|
|
1744
|
-
|
|
1745
|
-
let
|
|
1746
|
-
|
|
1747
|
-
|
|
1788
|
+
getCurve(t) {
|
|
1789
|
+
let current = (t * (this.end - this.start) + this.start) % 1;
|
|
1790
|
+
current < 0 && (current += 1);
|
|
1791
|
+
current *= (1 + this.aspectRatio) * 2;
|
|
1748
1792
|
let i;
|
|
1749
|
-
if (
|
|
1793
|
+
if (current < this.aspectRatio) {
|
|
1750
1794
|
i = 0;
|
|
1751
|
-
this.
|
|
1752
|
-
} else if (
|
|
1795
|
+
this.curveT = current / this.aspectRatio;
|
|
1796
|
+
} else if (current < this.aspectRatio + 1) {
|
|
1753
1797
|
i = 1;
|
|
1754
|
-
this.
|
|
1755
|
-
} else if (
|
|
1798
|
+
this.curveT = (current - this.aspectRatio) / 1;
|
|
1799
|
+
} else if (current < 2 * this.aspectRatio + 1) {
|
|
1756
1800
|
i = 2;
|
|
1757
|
-
this.
|
|
1801
|
+
this.curveT = (current - this.aspectRatio - 1) / this.aspectRatio;
|
|
1758
1802
|
} else {
|
|
1759
1803
|
i = 3;
|
|
1760
|
-
this.
|
|
1804
|
+
this.curveT = (current - 2 * this.aspectRatio - 1) / 1;
|
|
1761
1805
|
}
|
|
1762
1806
|
return this.curves[i];
|
|
1763
1807
|
}
|
|
1764
|
-
|
|
1765
|
-
return this.
|
|
1808
|
+
getPoint(t, output) {
|
|
1809
|
+
return this.getCurve(t).getPoint(this.curveT, output);
|
|
1766
1810
|
}
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
return new Point2D(v2.y - v1.y, -(v2.x - v1.x)).normalize();
|
|
1811
|
+
getPointAt(u, output) {
|
|
1812
|
+
return this.getPoint(u, output);
|
|
1770
1813
|
}
|
|
1771
|
-
|
|
1772
|
-
this.
|
|
1814
|
+
getTangent(t, output) {
|
|
1815
|
+
return this.getCurve(t).getTangent(this.curveT, output);
|
|
1816
|
+
}
|
|
1817
|
+
getNormal(t, output) {
|
|
1818
|
+
return this.getCurve(t).getNormal(this.curveT, output);
|
|
1819
|
+
}
|
|
1820
|
+
transformPoint(cb) {
|
|
1821
|
+
this.curves.forEach((curve) => curve.transformPoint(cb));
|
|
1773
1822
|
return this;
|
|
1774
1823
|
}
|
|
1775
|
-
getMinMax(min =
|
|
1824
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
1776
1825
|
this.curves.forEach((curve) => curve.getMinMax(min, max));
|
|
1777
1826
|
return { min, max };
|
|
1778
1827
|
}
|
|
@@ -1793,7 +1842,7 @@ class SplineCurve extends Curve {
|
|
|
1793
1842
|
getDivisions(divisions = 12) {
|
|
1794
1843
|
return divisions * this.points.length;
|
|
1795
1844
|
}
|
|
1796
|
-
getPoint(t, output = new
|
|
1845
|
+
getPoint(t, output = new Vector2()) {
|
|
1797
1846
|
const { points } = this;
|
|
1798
1847
|
const p = (points.length - 1) * t;
|
|
1799
1848
|
const _p = Math.floor(p);
|
|
@@ -1808,6 +1857,10 @@ class SplineCurve extends Curve {
|
|
|
1808
1857
|
);
|
|
1809
1858
|
return output;
|
|
1810
1859
|
}
|
|
1860
|
+
transformPoint(cb) {
|
|
1861
|
+
this.points.forEach((point) => cb(point));
|
|
1862
|
+
return this;
|
|
1863
|
+
}
|
|
1811
1864
|
copy(source) {
|
|
1812
1865
|
super.copy(source);
|
|
1813
1866
|
this.points = [];
|
|
@@ -1828,7 +1881,7 @@ class CurvePath extends Curve {
|
|
|
1828
1881
|
constructor(points) {
|
|
1829
1882
|
super();
|
|
1830
1883
|
__publicField$1(this, "curves", []);
|
|
1831
|
-
__publicField$1(this, "currentPoint", new
|
|
1884
|
+
__publicField$1(this, "currentPoint", new Vector2());
|
|
1832
1885
|
__publicField$1(this, "autoClose", false);
|
|
1833
1886
|
__publicField$1(this, "_cacheLengths", []);
|
|
1834
1887
|
if (points) {
|
|
@@ -1847,7 +1900,7 @@ class CurvePath extends Curve {
|
|
|
1847
1900
|
}
|
|
1848
1901
|
return this;
|
|
1849
1902
|
}
|
|
1850
|
-
getPoint(position, output = new
|
|
1903
|
+
getPoint(position, output = new Vector2()) {
|
|
1851
1904
|
const d = position * this.getLength();
|
|
1852
1905
|
const curveLengths = this.getCurveLengths();
|
|
1853
1906
|
let i = 0;
|
|
@@ -1899,10 +1952,10 @@ class CurvePath extends Curve {
|
|
|
1899
1952
|
let last;
|
|
1900
1953
|
for (let i = 0, curves = this.curves; i < curves.length; i++) {
|
|
1901
1954
|
const curve = curves[i];
|
|
1902
|
-
const
|
|
1903
|
-
for (let i2 = 0; i2 <
|
|
1904
|
-
const point =
|
|
1905
|
-
if (last
|
|
1955
|
+
const curvePoints = curve.getPoints(curve.getDivisions(divisions));
|
|
1956
|
+
for (let i2 = 0; i2 < curvePoints.length; i2++) {
|
|
1957
|
+
const point = curvePoints[i2];
|
|
1958
|
+
if (last?.equals(point))
|
|
1906
1959
|
continue;
|
|
1907
1960
|
points.push(point);
|
|
1908
1961
|
last = point;
|
|
@@ -1924,9 +1977,9 @@ class CurvePath extends Curve {
|
|
|
1924
1977
|
this.curves.push(
|
|
1925
1978
|
new CubicBezierCurve(
|
|
1926
1979
|
this.currentPoint.clone(),
|
|
1927
|
-
new
|
|
1928
|
-
new
|
|
1929
|
-
new
|
|
1980
|
+
new Vector2(cp1x, cp1y),
|
|
1981
|
+
new Vector2(cp2x, cp2y),
|
|
1982
|
+
new Vector2(x, y)
|
|
1930
1983
|
)
|
|
1931
1984
|
);
|
|
1932
1985
|
this.currentPoint.set(x, y);
|
|
@@ -1936,7 +1989,7 @@ class CurvePath extends Curve {
|
|
|
1936
1989
|
this.curves.push(
|
|
1937
1990
|
new LineCurve(
|
|
1938
1991
|
this.currentPoint.clone(),
|
|
1939
|
-
new
|
|
1992
|
+
new Vector2(x, y)
|
|
1940
1993
|
)
|
|
1941
1994
|
);
|
|
1942
1995
|
this.currentPoint.set(x, y);
|
|
@@ -1950,8 +2003,8 @@ class CurvePath extends Curve {
|
|
|
1950
2003
|
this.curves.push(
|
|
1951
2004
|
new QuadraticBezierCurve(
|
|
1952
2005
|
this.currentPoint.clone(),
|
|
1953
|
-
new
|
|
1954
|
-
new
|
|
2006
|
+
new Vector2(cpx, cpy),
|
|
2007
|
+
new Vector2(x, y)
|
|
1955
2008
|
)
|
|
1956
2009
|
);
|
|
1957
2010
|
this.currentPoint.set(x, y);
|
|
@@ -1960,7 +2013,7 @@ class CurvePath extends Curve {
|
|
|
1960
2013
|
rect(x, y, w, h) {
|
|
1961
2014
|
this.curves.push(
|
|
1962
2015
|
new RectangularCurve(
|
|
1963
|
-
new
|
|
2016
|
+
new Vector2(x + w / 2, y + h / 2),
|
|
1964
2017
|
w / 2,
|
|
1965
2018
|
w / h
|
|
1966
2019
|
)
|
|
@@ -1989,11 +2042,19 @@ class CurvePath extends Curve {
|
|
|
1989
2042
|
return this;
|
|
1990
2043
|
}
|
|
1991
2044
|
absellipse(x, y, radiusX, radiusY, startAngle, endAngle, clockwise = false, rotation = 0) {
|
|
1992
|
-
const curve = new EllipseCurve(
|
|
2045
|
+
const curve = new EllipseCurve(
|
|
2046
|
+
new Vector2(x, y),
|
|
2047
|
+
radiusX,
|
|
2048
|
+
radiusY,
|
|
2049
|
+
startAngle,
|
|
2050
|
+
endAngle,
|
|
2051
|
+
clockwise,
|
|
2052
|
+
rotation
|
|
2053
|
+
);
|
|
1993
2054
|
if (this.curves.length > 0) {
|
|
1994
|
-
const
|
|
1995
|
-
if (!
|
|
1996
|
-
this.lineTo(
|
|
2055
|
+
const first = curve.getPoint(0);
|
|
2056
|
+
if (!first.equals(this.currentPoint)) {
|
|
2057
|
+
this.lineTo(first.x, first.y);
|
|
1997
2058
|
}
|
|
1998
2059
|
}
|
|
1999
2060
|
this.curves.push(curve);
|
|
@@ -2003,7 +2064,7 @@ class CurvePath extends Curve {
|
|
|
2003
2064
|
getCommands() {
|
|
2004
2065
|
return this.curves.flatMap((curve) => curve.getCommands());
|
|
2005
2066
|
}
|
|
2006
|
-
getMinMax(min =
|
|
2067
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
2007
2068
|
this.curves.forEach((curve) => curve.getMinMax(min, max));
|
|
2008
2069
|
return { min, max };
|
|
2009
2070
|
}
|
|
@@ -2091,34 +2152,10 @@ class Path2D {
|
|
|
2091
2152
|
this.currentPath.absarc(x, y, radius, startAngle, endAngle, !counterclockwise);
|
|
2092
2153
|
return this;
|
|
2093
2154
|
}
|
|
2155
|
+
// TODO
|
|
2156
|
+
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
2094
2157
|
arcTo(x1, y1, x2, y2, radius) {
|
|
2095
|
-
|
|
2096
|
-
const currentX = point.x;
|
|
2097
|
-
const currentY = point.y;
|
|
2098
|
-
const dx1 = x1 - currentX;
|
|
2099
|
-
const dy1 = y1 - currentY;
|
|
2100
|
-
const dx2 = x2 - x1;
|
|
2101
|
-
const dy2 = y2 - y1;
|
|
2102
|
-
const len1 = Math.sqrt(dx1 * dx1 + dy1 * dy1);
|
|
2103
|
-
const len2 = Math.sqrt(dx2 * dx2 + dy2 * dy2);
|
|
2104
|
-
if (len1 < radius || len2 < radius) {
|
|
2105
|
-
this.lineTo(x2, y2);
|
|
2106
|
-
return this;
|
|
2107
|
-
}
|
|
2108
|
-
const unitV1 = { x: dx1 / len1, y: dy1 / len1 };
|
|
2109
|
-
const unitV2 = { x: dx2 / len2, y: dy2 / len2 };
|
|
2110
|
-
const centerX = x1 - unitV1.y * radius;
|
|
2111
|
-
const centerY = y1 + unitV1.x * radius;
|
|
2112
|
-
const startAngle = Math.atan2(unitV1.y, unitV1.x);
|
|
2113
|
-
const endAngle = Math.atan2(unitV2.y, unitV2.x);
|
|
2114
|
-
let angleDiff = endAngle - startAngle;
|
|
2115
|
-
if (angleDiff > Math.PI) {
|
|
2116
|
-
angleDiff -= 2 * Math.PI;
|
|
2117
|
-
} else if (angleDiff < -Math.PI) {
|
|
2118
|
-
angleDiff += 2 * Math.PI;
|
|
2119
|
-
}
|
|
2120
|
-
this.arc(centerX, centerY, radius, startAngle, startAngle + angleDiff, false);
|
|
2121
|
-
this.lineTo(x2, y2);
|
|
2158
|
+
console.warn("Method arcTo not supported yet");
|
|
2122
2159
|
return this;
|
|
2123
2160
|
}
|
|
2124
2161
|
ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, counterclockwise) {
|
|
@@ -2145,22 +2182,21 @@ class Path2D {
|
|
|
2145
2182
|
this.paths.forEach((path) => path.curves.forEach((curve) => cb(curve)));
|
|
2146
2183
|
return this;
|
|
2147
2184
|
}
|
|
2185
|
+
transformPoint(cb) {
|
|
2186
|
+
this.forEachCurve((curve) => curve.transformPoint(cb));
|
|
2187
|
+
return this;
|
|
2188
|
+
}
|
|
2148
2189
|
transform(matrix) {
|
|
2149
2190
|
this.forEachCurve((curve) => curve.transform(matrix));
|
|
2150
2191
|
return this;
|
|
2151
2192
|
}
|
|
2152
|
-
getMinMax(min =
|
|
2193
|
+
getMinMax(min = Vector2.MAX, max = Vector2.MIN) {
|
|
2153
2194
|
this.forEachCurve((curve) => curve.getMinMax(min, max));
|
|
2154
2195
|
return { min, max };
|
|
2155
2196
|
}
|
|
2156
2197
|
getBoundingBox() {
|
|
2157
2198
|
const { min, max } = this.getMinMax();
|
|
2158
|
-
return new BoundingBox(
|
|
2159
|
-
min.x,
|
|
2160
|
-
min.y,
|
|
2161
|
-
max.x - min.x,
|
|
2162
|
-
max.y - min.y
|
|
2163
|
-
);
|
|
2199
|
+
return new BoundingBox(min.x, min.y, max.x - min.x, max.y - min.y);
|
|
2164
2200
|
}
|
|
2165
2201
|
getCommands() {
|
|
2166
2202
|
return this.paths.flatMap((path) => path.curves.flatMap((curve) => curve.getCommands()));
|
|
@@ -2170,7 +2206,8 @@ class Path2D {
|
|
|
2170
2206
|
}
|
|
2171
2207
|
getSvgString() {
|
|
2172
2208
|
const { x, y, width, height } = this.getBoundingBox();
|
|
2173
|
-
|
|
2209
|
+
const strokeWidth = 1;
|
|
2210
|
+
return `<svg viewBox="${x - strokeWidth} ${y - strokeWidth} ${width + strokeWidth * 2} ${height + strokeWidth * 2}" xmlns="http://www.w3.org/2000/svg"><path fill="none" stroke="currentColor" d="${this.getData()}"></path></svg>`;
|
|
2174
2211
|
}
|
|
2175
2212
|
getSvgDataUri() {
|
|
2176
2213
|
return `data:image/svg+xml;base64,${btoa(this.getSvgString())}`;
|
|
@@ -2707,10 +2744,9 @@ function parseNode(node, style, paths = []) {
|
|
|
2707
2744
|
const dataUri = "data:image/svg+xml;";
|
|
2708
2745
|
const base64DataUri = `${dataUri}base64,`;
|
|
2709
2746
|
const utf8DataUri = `${dataUri}charset=utf8,`;
|
|
2710
|
-
function
|
|
2711
|
-
let node;
|
|
2712
|
-
let xml;
|
|
2747
|
+
function parseSvgToDom(svg) {
|
|
2713
2748
|
if (typeof svg === "string") {
|
|
2749
|
+
let xml;
|
|
2714
2750
|
if (svg.startsWith(base64DataUri)) {
|
|
2715
2751
|
svg = svg.substring(base64DataUri.length, svg.length);
|
|
2716
2752
|
xml = atob(svg);
|
|
@@ -2720,11 +2756,16 @@ function parseSvg(svg) {
|
|
|
2720
2756
|
} else {
|
|
2721
2757
|
xml = svg;
|
|
2722
2758
|
}
|
|
2723
|
-
|
|
2759
|
+
return new DOMParser().parseFromString(
|
|
2760
|
+
xml,
|
|
2761
|
+
"image/svg+xml"
|
|
2762
|
+
).documentElement;
|
|
2724
2763
|
} else {
|
|
2725
|
-
|
|
2764
|
+
return svg;
|
|
2726
2765
|
}
|
|
2727
|
-
|
|
2766
|
+
}
|
|
2767
|
+
function parseSvg(svg) {
|
|
2768
|
+
return parseNode(parseSvgToDom(svg), {
|
|
2728
2769
|
fill: "#000",
|
|
2729
2770
|
fillOpacity: 1,
|
|
2730
2771
|
strokeOpacity: 1,
|
|
@@ -2746,8 +2787,9 @@ exports.LineCurve = LineCurve;
|
|
|
2746
2787
|
exports.Matrix3 = Matrix3;
|
|
2747
2788
|
exports.Path2D = Path2D;
|
|
2748
2789
|
exports.PloygonCurve = PloygonCurve;
|
|
2749
|
-
exports.Point2D = Point2D;
|
|
2750
2790
|
exports.QuadraticBezierCurve = QuadraticBezierCurve;
|
|
2751
2791
|
exports.RectangularCurve = RectangularCurve;
|
|
2752
2792
|
exports.SplineCurve = SplineCurve;
|
|
2793
|
+
exports.Vector2 = Vector2;
|
|
2753
2794
|
exports.parseSvg = parseSvg;
|
|
2795
|
+
exports.parseSvgToDom = parseSvgToDom;
|