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