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.mjs CHANGED
@@ -1,35 +1,35 @@
1
- class Point2D {
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 Point2D(Infinity, Infinity);
7
+ return new Vector2(Infinity, Infinity);
8
8
  }
9
9
  static get MIN() {
10
- return new Point2D(-Infinity, -Infinity);
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(point) {
18
- this.x += point.x;
19
- this.y += point.y;
17
+ add(vec) {
18
+ this.x += vec.x;
19
+ this.y += vec.y;
20
20
  return this;
21
21
  }
22
- sub(point) {
23
- this.x -= point.x;
24
- this.y -= point.y;
22
+ sub(vec) {
23
+ this.x -= vec.x;
24
+ this.y -= vec.y;
25
25
  return this;
26
26
  }
27
- distanceTo(point) {
28
- return Math.sqrt(this.distanceToSquared(point));
27
+ distanceTo(vec) {
28
+ return Math.sqrt(this.distanceToSquared(vec));
29
29
  }
30
- distanceToSquared(point) {
31
- const dx = this.x - point.x;
32
- const dy = this.y - point.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(point) {
60
- return this.x === point.x && this.y === point.y;
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(point) {
71
- this.x = point.x;
72
- this.y = point.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 Point2D(this.x, this.y);
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 Point2D((this.left + this.right) / 2, (this.top + this.bottom) / 2);
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 Point2D();
393
- const control = new Point2D();
394
- const firstPoint = new Point2D();
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 Point2D()) {
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 Point2D()) {
1000
+ getTangent(t, output = new Vector2()) {
1001
1001
  const delta = 1e-4;
1002
- let t1 = t - delta;
1003
- let t2 = t + delta;
1004
- if (t1 < 0)
1005
- t1 = 0;
1006
- if (t2 > 1)
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
- /** overrideable */
1023
- getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
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
- /** overrideable */
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 Point2D(-y, x);
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 Point2D(Math.cos(_t), Math.sin(_t));
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 = Point2D.MAX, max = Point2D.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(v0 = new Point2D(), v1 = new Point2D(), v2 = new Point2D(), v3 = new Point2D()) {
1133
+ constructor(start = new Vector2(), startControl = new Vector2(), endControl = new Vector2(), end = new Vector2()) {
1117
1134
  super();
1118
- this.v0 = v0;
1119
- this.v1 = v1;
1120
- this.v2 = v2;
1121
- this.v3 = v3;
1135
+ this.start = start;
1136
+ this.startControl = startControl;
1137
+ this.endControl = endControl;
1138
+ this.end = end;
1122
1139
  }
1123
- getPoint(t, output = new Point2D()) {
1124
- const { v0, v1, v2, v3 } = this;
1140
+ getPoint(t, output = new Vector2()) {
1141
+ const { start, startControl, endControl, end } = this;
1125
1142
  output.set(
1126
- cubicBezier(t, v0.x, v1.x, v2.x, v3.x),
1127
- cubicBezier(t, v0.y, v1.y, v2.y, v3.y)
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
- transform(matrix) {
1132
- this.v0.applyMatrix3(matrix);
1133
- this.v1.applyMatrix3(matrix);
1134
- this.v2.applyMatrix3(matrix);
1135
- this.v3.applyMatrix3(matrix);
1136
- return this;
1137
- }
1138
- getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
1139
- const { v0, v1, v2, v3 } = this;
1140
- min.x = Math.min(min.x, v0.x, v1.x, v2.x, v3.x);
1141
- min.y = Math.min(min.y, v0.y, v1.y, v2.y, v3.y);
1142
- max.x = Math.max(max.x, v0.x, v1.x, v2.x, v3.x);
1143
- max.y = Math.max(max.y, v0.y, v1.y, v2.y, v3.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 { v0, v1, v2, v3 } = this;
1164
+ const { start, startControl, endControl, end } = this;
1148
1165
  return [
1149
- { type: "M", x: v0.x, y: v0.y },
1150
- { type: "C", x1: v1.x, y1: v1.y, x2: v2.x, y2: v2.y, x: v3.x, y: v3.y }
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 { v1, v2, v3 } = this;
1155
- ctx.bezierCurveTo(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y);
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.v0.copy(source.v0);
1161
- this.v1.copy(source.v1);
1162
- this.v2.copy(source.v2);
1163
- this.v3.copy(source.v3);
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 Point2D();
1188
+ const tempV2 = new Vector2();
1172
1189
  class EllipseCurve extends Curve {
1173
- constructor(x = 0, y = 0, radiusX = 1, radiusY = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false, rotation = 0) {
1190
+ constructor(center = new Vector2(), radiusX = 1, radiusY = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false, rotation = 0) {
1174
1191
  super();
1175
- this.x = x;
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 Point2D()) {
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 { x, y, radiusX, radiusY, startAngle, endAngle, clockwise } = this;
1224
- const anticlockwise = !clockwise;
1225
- const startX = x + radiusX * Math.cos(startAngle);
1226
- const startY = y + radiusY * Math.sin(startAngle);
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 = anticlockwise ? 0 : 1;
1232
- const midX = x + radiusX * Math.cos(startAngle + (endAngle - startAngle) / 2);
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: radiusX, ry: radiusY, angle: 0, largeArcFlag: 1, sweepFlag, x: midX, y: midY },
1238
- { type: "A", rx: radiusX, ry: radiusY, angle: 0, largeArcFlag: 1, sweepFlag, x: startX, y: startY }
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: radiusX, ry: radiusY, angle: 0, largeArcFlag, sweepFlag, x: endX, y: endY }
1261
+ { type: "A", rx, ry, angle, largeArcFlag, sweepFlag, x: endX, y: endY }
1244
1262
  ];
1245
1263
  }
1246
1264
  }
1247
1265
  drawTo(ctx) {
1248
- const { x, y, radiusX, radiusY, rotation, startAngle, endAngle, clockwise } = this;
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 Point2D(a * cosTheta, a * sinTheta);
1295
- const v2 = new Point2D(-b * sinTheta, b * cosTheta);
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 Point2D(Math.cos(phi), Math.sin(phi)).applyMatrix3(mDRF);
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(v1 = new Point2D(), v2 = new Point2D()) {
1466
+ constructor(start = new Vector2(), end = new Vector2()) {
1431
1467
  super();
1432
- this.v1 = v1;
1433
- this.v2 = v2;
1468
+ this.start = start;
1469
+ this.end = end;
1434
1470
  }
1435
- getPoint(t, output = new Point2D()) {
1471
+ getPoint(t, output = new Vector2()) {
1436
1472
  if (t === 1) {
1437
- output.copy(this.v2);
1473
+ output.copy(this.end);
1438
1474
  } else {
1439
- output.copy(this.v2).sub(this.v1);
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 Point2D()) {
1479
+ getPointAt(u, output = new Vector2()) {
1445
1480
  return this.getPoint(u, output);
1446
1481
  }
1447
- getTangent(t, output = new Point2D()) {
1448
- return output.subVectors(this.v2, this.v1).normalize();
1482
+ getTangent(_t, output = new Vector2()) {
1483
+ return output.subVectors(this.end, this.start).normalize();
1449
1484
  }
1450
- getTangentAt(u, output = new Point2D()) {
1485
+ getTangentAt(u, output = new Vector2()) {
1451
1486
  return this.getTangent(u, output);
1452
1487
  }
1453
- transform(matrix) {
1454
- this.v1.applyMatrix3(matrix);
1455
- this.v2.applyMatrix3(matrix);
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 = Point2D.MAX, max = Point2D.MIN) {
1462
- const { v1, v2 } = this;
1463
- min.x = Math.min(min.x, v1.x, v2.x);
1464
- min.y = Math.min(min.y, v1.y, v2.y);
1465
- max.x = Math.max(max.x, v1.x, v2.x);
1466
- max.y = Math.max(max.y, v1.y, v2.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 { v1, v2 } = this;
1509
+ const { start, end } = this;
1471
1510
  return [
1472
- { type: "M", x: v1.x, y: v1.y },
1473
- { type: "L", x: v2.x, y: v2.y }
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 { v2 } = this;
1478
- ctx.lineTo(v2.x, v2.y);
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.v1.copy(source.v1);
1484
- this.v2.copy(source.v2);
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, "curves");
1503
- __publicField$4(this, "pointT", 0);
1541
+ __publicField$4(this, "curveT", 0);
1542
+ this.update();
1543
+ }
1544
+ update() {
1504
1545
  const { x, y } = this.center;
1505
- const A = new Point2D(x + 0.5 * this.size, y - 0.5 * this.size);
1506
- const t = new Point2D(x - 0.5 * this.size, y - 0.5 * this.size);
1507
- const i = new Point2D(x, y + 0.5 * this.size);
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 Point2D(x, y + this.size);
1512
- const l = new Point2D(x + this.size, y);
1513
- const c = new Point2D().lerpVectors(l, e, 0.75);
1514
- const h = new Point2D(x - this.size, y);
1515
- const a = new Point2D().lerpVectors(h, e, 0.75);
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(value) {
1521
- return this.getCurrentLine(value).getPoint(this.pointT);
1562
+ getPoint(t) {
1563
+ return this.getCurve(t).getPoint(this.curveT);
1522
1564
  }
1523
- getPointAt(value) {
1524
- return this.getPoint(value);
1565
+ getPointAt(t) {
1566
+ return this.getPoint(t);
1525
1567
  }
1526
- getCurrentLine(value) {
1527
- let val = (value * (this.end - this.start) + this.start) % 1;
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 t = 0.5 * Math.PI;
1532
- if (val < t) {
1573
+ const PI_1_2 = 0.5 * Math.PI;
1574
+ if (val < PI_1_2) {
1533
1575
  index = 0;
1534
- this.pointT = val / t;
1535
- } else if (val < t + 0.75) {
1576
+ this.curveT = val / PI_1_2;
1577
+ } else if (val < PI_1_2 + 0.75) {
1536
1578
  index = 1;
1537
- this.pointT = (val - t) / 0.75;
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.pointT = (val - t - 0.75) / (Math.PI / 8);
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.pointT = (val - 5 * Math.PI / 8 - 0.75) / 0.75;
1585
+ this.curveT = (val - 5 * Math.PI / 8 - 0.75) / 0.75;
1544
1586
  } else {
1545
1587
  index = 4;
1546
- this.pointT = (val - 5 * Math.PI / 8 - 1.5) / t;
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(value) {
1551
- return this.getCurrentLine(value).getTangent(this.pointT).normalize();
1592
+ getTangent(t) {
1593
+ return this.getCurve(t).getTangent(this.curveT);
1552
1594
  }
1553
- getNormal(value) {
1554
- const line = this.getCurrentLine(value);
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
- transform(matrix) {
1558
- this.curves.forEach((curve) => curve.transform(matrix));
1598
+ transformPoint(cb) {
1599
+ this.curves.forEach((curve) => curve.transformPoint(cb));
1559
1600
  return this;
1560
1601
  }
1561
- getMinMax(min = Point2D.MAX, max = Point2D.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, num = 0, start = 0, end = 1) {
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.num = num;
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
- for (let i = 0; i < this.num; i++) {
1591
- let radian = i * 2 * Math.PI / this.num;
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
- const point = new Point2D(this.radius * Math.cos(radian), this.radius * Math.sin(radian));
1594
- point.add(this.center);
1595
- this.points.push(point);
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.num; i++) {
1598
- this.curves.push(new LineCurve(this.points[i], this.points[(i + 1) % this.num]));
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
- getPoint(value) {
1602
- this.getCurrentLine(value);
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.num;
1653
+ const v = pos * this.number;
1612
1654
  const index = Math.floor(v);
1613
- this.pointK = v - index;
1614
- this.currentLine = this.curves[index];
1615
- return this.currentLine;
1655
+ this.curveT = v - index;
1656
+ return this.curves[index];
1616
1657
  }
1617
- getTangent(value) {
1618
- return this.getCurrentLine(value).getTangent(0).normalize();
1658
+ getPoint(t, output) {
1659
+ return this.getCurve(t).getPoint(this.curveT, output);
1619
1660
  }
1620
- getNormal(value) {
1621
- const line = this.getCurrentLine(value);
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
- transform(matrix) {
1625
- this.curves.forEach((curve) => curve.transform(matrix));
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 = Point2D.MAX, max = Point2D.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(v0 = new Point2D(), v1 = new Point2D(), v2 = new Point2D()) {
1688
+ constructor(start = new Vector2(), control = new Vector2(), end = new Vector2()) {
1643
1689
  super();
1644
- this.v0 = v0;
1645
- this.v1 = v1;
1646
- this.v2 = v2;
1690
+ this.start = start;
1691
+ this.control = control;
1692
+ this.end = end;
1647
1693
  }
1648
- getPoint(t, output = new Point2D()) {
1649
- const { v0, v1, v2 } = this;
1694
+ getPoint(t, output = new Vector2()) {
1695
+ const { start, control, end } = this;
1650
1696
  output.set(
1651
- quadraticBezier(t, v0.x, v1.x, v2.x),
1652
- quadraticBezier(t, v0.y, v1.y, v2.y)
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
- transform(matrix) {
1657
- this.v0.applyMatrix3(matrix);
1658
- this.v1.applyMatrix3(matrix);
1659
- this.v2.applyMatrix3(matrix);
1660
- return this;
1661
- }
1662
- getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
1663
- const { v0, v1, v2 } = this;
1664
- const x1 = 0.5 * (v0.x + v1.x);
1665
- const y1 = 0.5 * (v0.y + v1.y);
1666
- const x2 = 0.5 * (v0.x + v2.x);
1667
- const y2 = 0.5 * (v0.y + v2.y);
1668
- min.x = Math.min(min.x, v0.x, v2.x, x1, x2);
1669
- min.y = Math.min(min.y, v0.y, v2.y, y1, y2);
1670
- max.x = Math.max(max.x, v0.x, v2.x, x1, x2);
1671
- max.y = Math.max(max.y, v0.y, v2.y, y1, y2);
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 { v0, v1, v2 } = this;
1721
+ const { start, control, end } = this;
1676
1722
  return [
1677
- { type: "M", x: v0.x, y: v0.y },
1678
- { type: "Q", x1: v1.x, y1: v1.y, x: v2.x, y: v2.y }
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 { v1, v2 } = this;
1683
- ctx.quadraticCurveTo(v1.x, v1.y, v2.x, v2.y);
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.v0.copy(source.v0);
1689
- this.v1.copy(source.v1);
1690
- this.v2.copy(source.v2);
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, "pointT", 0);
1711
- const { x, y } = this.center;
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
- getPoint(t) {
1737
- return this.getCurrentLine(t).getPoint(this.pointT);
1738
- }
1739
- getPointAt(u) {
1740
- return this.getPoint(u);
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
- getCurrentLine(t) {
1743
- let flag = (t * (this.end - this.start) + this.start) % 1;
1744
- flag < 0 && (flag += 1);
1745
- flag *= (1 + this.aspectRatio) * 2;
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 (flag < this.aspectRatio) {
1791
+ if (current < this.aspectRatio) {
1748
1792
  i = 0;
1749
- this.pointT = flag / this.aspectRatio;
1750
- } else if (flag < this.aspectRatio + 1) {
1793
+ this.curveT = current / this.aspectRatio;
1794
+ } else if (current < this.aspectRatio + 1) {
1751
1795
  i = 1;
1752
- this.pointT = (flag - this.aspectRatio) / 1;
1753
- } else if (flag < 2 * this.aspectRatio + 1) {
1796
+ this.curveT = (current - this.aspectRatio) / 1;
1797
+ } else if (current < 2 * this.aspectRatio + 1) {
1754
1798
  i = 2;
1755
- this.pointT = (flag - this.aspectRatio - 1) / this.aspectRatio;
1799
+ this.curveT = (current - this.aspectRatio - 1) / this.aspectRatio;
1756
1800
  } else {
1757
1801
  i = 3;
1758
- this.pointT = (flag - 2 * this.aspectRatio - 1) / 1;
1802
+ this.curveT = (current - 2 * this.aspectRatio - 1) / 1;
1759
1803
  }
1760
1804
  return this.curves[i];
1761
1805
  }
1762
- getTangent(t) {
1763
- return this.getCurrentLine(t).getTangent(0).normalize();
1806
+ getPoint(t, output) {
1807
+ return this.getCurve(t).getPoint(this.curveT, output);
1764
1808
  }
1765
- getNormal(value) {
1766
- const { v1, v2 } = this.getCurrentLine(value);
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
- transform(matrix) {
1770
- this.curves.forEach((curve) => curve.transform(matrix));
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 = Point2D.MAX, max = Point2D.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 Point2D()) {
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 Point2D());
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 Point2D()) {
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 pts = curve.getPoints(curve.getDivisions(divisions));
1901
- for (let i2 = 0; i2 < pts.length; i2++) {
1902
- const point = pts[i2];
1903
- if (last && last.equals(point))
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 Point2D(cp1x, cp1y),
1926
- new Point2D(cp2x, cp2y),
1927
- new Point2D(x, y)
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 Point2D(x, y)
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 Point2D(cpx, cpy),
1952
- new Point2D(x, y)
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 Point2D(x + w / 2, y + h / 2),
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(x, y, radiusX, radiusY, startAngle, endAngle, clockwise, rotation);
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 firstPoint = curve.getPoint(0);
1993
- if (!firstPoint.equals(this.currentPoint)) {
1994
- this.lineTo(firstPoint.x, firstPoint.y);
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 = Point2D.MAX, max = Point2D.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
- const point = this.currentPath.currentPoint;
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 = Point2D.MAX, max = Point2D.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
- return `<svg viewBox="${x} ${y} ${width} ${height}" xmlns="http://www.w3.org/2000/svg"><path fill="none" stroke="currentColor" d="${this.getData()}"></path></svg>`;
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 parseSvg(svg) {
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
- node = new DOMParser().parseFromString(xml, "image/svg+xml").documentElement;
2757
+ return new DOMParser().parseFromString(
2758
+ xml,
2759
+ "image/svg+xml"
2760
+ ).documentElement;
2722
2761
  } else {
2723
- node = svg;
2762
+ return svg;
2724
2763
  }
2725
- return parseNode(node, {
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, Point2D, QuadraticBezierCurve, RectangularCurve, SplineCurve, parseSvg };
2777
+ export { BoundingBox, CircleCurve, CubicBezierCurve, Curve, CurvePath, EllipseCurve, HeartCurve, LineCurve, Matrix3, Path2D, PloygonCurve, QuadraticBezierCurve, RectangularCurve, SplineCurve, Vector2, parseSvg, parseSvgToDom };