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 CHANGED
@@ -1,37 +1,37 @@
1
1
  'use strict';
2
2
 
3
- class Point2D {
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 Point2D(Infinity, Infinity);
9
+ return new Vector2(Infinity, Infinity);
10
10
  }
11
11
  static get MIN() {
12
- return new Point2D(-Infinity, -Infinity);
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(point) {
20
- this.x += point.x;
21
- this.y += point.y;
19
+ add(vec) {
20
+ this.x += vec.x;
21
+ this.y += vec.y;
22
22
  return this;
23
23
  }
24
- sub(point) {
25
- this.x -= point.x;
26
- this.y -= point.y;
24
+ sub(vec) {
25
+ this.x -= vec.x;
26
+ this.y -= vec.y;
27
27
  return this;
28
28
  }
29
- distanceTo(point) {
30
- return Math.sqrt(this.distanceToSquared(point));
29
+ distanceTo(vec) {
30
+ return Math.sqrt(this.distanceToSquared(vec));
31
31
  }
32
- distanceToSquared(point) {
33
- const dx = this.x - point.x;
34
- const dy = this.y - point.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(point) {
62
- return this.x === point.x && this.y === point.y;
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(point) {
73
- this.x = point.x;
74
- this.y = point.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 Point2D(this.x, this.y);
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 Point2D((this.left + this.right) / 2, (this.top + this.bottom) / 2);
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 Point2D();
395
- const control = new Point2D();
396
- const firstPoint = new Point2D();
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 Point2D()) {
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 Point2D()) {
1002
+ getTangent(t, output = new Vector2()) {
1003
1003
  const delta = 1e-4;
1004
- let t1 = t - delta;
1005
- let t2 = t + delta;
1006
- if (t1 < 0)
1007
- t1 = 0;
1008
- if (t2 > 1)
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
- /** overrideable */
1025
- getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
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
- /** overrideable */
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 Point2D(-y, x);
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 Point2D(Math.cos(_t), Math.sin(_t));
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 = Point2D.MAX, max = Point2D.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(v0 = new Point2D(), v1 = new Point2D(), v2 = new Point2D(), v3 = new Point2D()) {
1135
+ constructor(start = new Vector2(), startControl = new Vector2(), endControl = new Vector2(), end = new Vector2()) {
1119
1136
  super();
1120
- this.v0 = v0;
1121
- this.v1 = v1;
1122
- this.v2 = v2;
1123
- this.v3 = v3;
1137
+ this.start = start;
1138
+ this.startControl = startControl;
1139
+ this.endControl = endControl;
1140
+ this.end = end;
1124
1141
  }
1125
- getPoint(t, output = new Point2D()) {
1126
- const { v0, v1, v2, v3 } = this;
1142
+ getPoint(t, output = new Vector2()) {
1143
+ const { start, startControl, endControl, end } = this;
1127
1144
  output.set(
1128
- cubicBezier(t, v0.x, v1.x, v2.x, v3.x),
1129
- cubicBezier(t, v0.y, v1.y, v2.y, v3.y)
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
- transform(matrix) {
1134
- this.v0.applyMatrix3(matrix);
1135
- this.v1.applyMatrix3(matrix);
1136
- this.v2.applyMatrix3(matrix);
1137
- this.v3.applyMatrix3(matrix);
1138
- return this;
1139
- }
1140
- getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
1141
- const { v0, v1, v2, v3 } = this;
1142
- min.x = Math.min(min.x, v0.x, v1.x, v2.x, v3.x);
1143
- min.y = Math.min(min.y, v0.y, v1.y, v2.y, v3.y);
1144
- max.x = Math.max(max.x, v0.x, v1.x, v2.x, v3.x);
1145
- max.y = Math.max(max.y, v0.y, v1.y, v2.y, v3.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 { v0, v1, v2, v3 } = this;
1166
+ const { start, startControl, endControl, end } = this;
1150
1167
  return [
1151
- { type: "M", x: v0.x, y: v0.y },
1152
- { type: "C", x1: v1.x, y1: v1.y, x2: v2.x, y2: v2.y, x: v3.x, y: v3.y }
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 { v1, v2, v3 } = this;
1157
- ctx.bezierCurveTo(v1.x, v1.y, v2.x, v2.y, v3.x, v3.y);
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.v0.copy(source.v0);
1163
- this.v1.copy(source.v1);
1164
- this.v2.copy(source.v2);
1165
- this.v3.copy(source.v3);
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 Point2D();
1190
+ const tempV2 = new Vector2();
1174
1191
  class EllipseCurve extends Curve {
1175
- constructor(x = 0, y = 0, radiusX = 1, radiusY = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false, rotation = 0) {
1192
+ constructor(center = new Vector2(), radiusX = 1, radiusY = 1, startAngle = 0, endAngle = Math.PI * 2, clockwise = false, rotation = 0) {
1176
1193
  super();
1177
- this.x = x;
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 Point2D()) {
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 { x, y, radiusX, radiusY, startAngle, endAngle, clockwise } = this;
1226
- const anticlockwise = !clockwise;
1227
- const startX = x + radiusX * Math.cos(startAngle);
1228
- const startY = y + radiusY * Math.sin(startAngle);
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 = anticlockwise ? 0 : 1;
1234
- const midX = x + radiusX * Math.cos(startAngle + (endAngle - startAngle) / 2);
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: radiusX, ry: radiusY, angle: 0, largeArcFlag: 1, sweepFlag, x: midX, y: midY },
1240
- { type: "A", rx: radiusX, ry: radiusY, angle: 0, largeArcFlag: 1, sweepFlag, x: startX, y: startY }
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: radiusX, ry: radiusY, angle: 0, largeArcFlag, sweepFlag, x: endX, y: endY }
1263
+ { type: "A", rx, ry, angle, largeArcFlag, sweepFlag, x: endX, y: endY }
1246
1264
  ];
1247
1265
  }
1248
1266
  }
1249
1267
  drawTo(ctx) {
1250
- const { x, y, radiusX, radiusY, rotation, startAngle, endAngle, clockwise } = this;
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 Point2D(a * cosTheta, a * sinTheta);
1297
- const v2 = new Point2D(-b * sinTheta, b * cosTheta);
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 Point2D(Math.cos(phi), Math.sin(phi)).applyMatrix3(mDRF);
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(v1 = new Point2D(), v2 = new Point2D()) {
1468
+ constructor(start = new Vector2(), end = new Vector2()) {
1433
1469
  super();
1434
- this.v1 = v1;
1435
- this.v2 = v2;
1470
+ this.start = start;
1471
+ this.end = end;
1436
1472
  }
1437
- getPoint(t, output = new Point2D()) {
1473
+ getPoint(t, output = new Vector2()) {
1438
1474
  if (t === 1) {
1439
- output.copy(this.v2);
1475
+ output.copy(this.end);
1440
1476
  } else {
1441
- output.copy(this.v2).sub(this.v1);
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 Point2D()) {
1481
+ getPointAt(u, output = new Vector2()) {
1447
1482
  return this.getPoint(u, output);
1448
1483
  }
1449
- getTangent(t, output = new Point2D()) {
1450
- return output.subVectors(this.v2, this.v1).normalize();
1484
+ getTangent(_t, output = new Vector2()) {
1485
+ return output.subVectors(this.end, this.start).normalize();
1451
1486
  }
1452
- getTangentAt(u, output = new Point2D()) {
1487
+ getTangentAt(u, output = new Vector2()) {
1453
1488
  return this.getTangent(u, output);
1454
1489
  }
1455
- transform(matrix) {
1456
- this.v1.applyMatrix3(matrix);
1457
- this.v2.applyMatrix3(matrix);
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 = Point2D.MAX, max = Point2D.MIN) {
1464
- const { v1, v2 } = this;
1465
- min.x = Math.min(min.x, v1.x, v2.x);
1466
- min.y = Math.min(min.y, v1.y, v2.y);
1467
- max.x = Math.max(max.x, v1.x, v2.x);
1468
- max.y = Math.max(max.y, v1.y, v2.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 { v1, v2 } = this;
1511
+ const { start, end } = this;
1473
1512
  return [
1474
- { type: "M", x: v1.x, y: v1.y },
1475
- { type: "L", x: v2.x, y: v2.y }
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 { v2 } = this;
1480
- ctx.lineTo(v2.x, v2.y);
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.v1.copy(source.v1);
1486
- this.v2.copy(source.v2);
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, "curves");
1505
- __publicField$4(this, "pointT", 0);
1543
+ __publicField$4(this, "curveT", 0);
1544
+ this.update();
1545
+ }
1546
+ update() {
1506
1547
  const { x, y } = this.center;
1507
- const A = new Point2D(x + 0.5 * this.size, y - 0.5 * this.size);
1508
- const t = new Point2D(x - 0.5 * this.size, y - 0.5 * this.size);
1509
- const i = new Point2D(x, y + 0.5 * this.size);
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 Point2D(x, y + this.size);
1514
- const l = new Point2D(x + this.size, y);
1515
- const c = new Point2D().lerpVectors(l, e, 0.75);
1516
- const h = new Point2D(x - this.size, y);
1517
- const a = new Point2D().lerpVectors(h, e, 0.75);
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(value) {
1523
- return this.getCurrentLine(value).getPoint(this.pointT);
1564
+ getPoint(t) {
1565
+ return this.getCurve(t).getPoint(this.curveT);
1524
1566
  }
1525
- getPointAt(value) {
1526
- return this.getPoint(value);
1567
+ getPointAt(t) {
1568
+ return this.getPoint(t);
1527
1569
  }
1528
- getCurrentLine(value) {
1529
- let val = (value * (this.end - this.start) + this.start) % 1;
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 t = 0.5 * Math.PI;
1534
- if (val < t) {
1575
+ const PI_1_2 = 0.5 * Math.PI;
1576
+ if (val < PI_1_2) {
1535
1577
  index = 0;
1536
- this.pointT = val / t;
1537
- } else if (val < t + 0.75) {
1578
+ this.curveT = val / PI_1_2;
1579
+ } else if (val < PI_1_2 + 0.75) {
1538
1580
  index = 1;
1539
- this.pointT = (val - t) / 0.75;
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.pointT = (val - t - 0.75) / (Math.PI / 8);
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.pointT = (val - 5 * Math.PI / 8 - 0.75) / 0.75;
1587
+ this.curveT = (val - 5 * Math.PI / 8 - 0.75) / 0.75;
1546
1588
  } else {
1547
1589
  index = 4;
1548
- this.pointT = (val - 5 * Math.PI / 8 - 1.5) / t;
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(value) {
1553
- return this.getCurrentLine(value).getTangent(this.pointT).normalize();
1594
+ getTangent(t) {
1595
+ return this.getCurve(t).getTangent(this.curveT);
1554
1596
  }
1555
- getNormal(value) {
1556
- const line = this.getCurrentLine(value);
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
- transform(matrix) {
1560
- this.curves.forEach((curve) => curve.transform(matrix));
1600
+ transformPoint(cb) {
1601
+ this.curves.forEach((curve) => curve.transformPoint(cb));
1561
1602
  return this;
1562
1603
  }
1563
- getMinMax(min = Point2D.MAX, max = Point2D.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, num = 0, start = 0, end = 1) {
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.num = num;
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
- for (let i = 0; i < this.num; i++) {
1593
- let radian = i * 2 * Math.PI / this.num;
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
- const point = new Point2D(this.radius * Math.cos(radian), this.radius * Math.sin(radian));
1596
- point.add(this.center);
1597
- this.points.push(point);
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.num; i++) {
1600
- this.curves.push(new LineCurve(this.points[i], this.points[(i + 1) % this.num]));
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
- getPoint(value) {
1604
- this.getCurrentLine(value);
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.num;
1655
+ const v = pos * this.number;
1614
1656
  const index = Math.floor(v);
1615
- this.pointK = v - index;
1616
- this.currentLine = this.curves[index];
1617
- return this.currentLine;
1657
+ this.curveT = v - index;
1658
+ return this.curves[index];
1618
1659
  }
1619
- getTangent(value) {
1620
- return this.getCurrentLine(value).getTangent(0).normalize();
1660
+ getPoint(t, output) {
1661
+ return this.getCurve(t).getPoint(this.curveT, output);
1621
1662
  }
1622
- getNormal(value) {
1623
- const line = this.getCurrentLine(value);
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
- transform(matrix) {
1627
- this.curves.forEach((curve) => curve.transform(matrix));
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 = Point2D.MAX, max = Point2D.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(v0 = new Point2D(), v1 = new Point2D(), v2 = new Point2D()) {
1690
+ constructor(start = new Vector2(), control = new Vector2(), end = new Vector2()) {
1645
1691
  super();
1646
- this.v0 = v0;
1647
- this.v1 = v1;
1648
- this.v2 = v2;
1692
+ this.start = start;
1693
+ this.control = control;
1694
+ this.end = end;
1649
1695
  }
1650
- getPoint(t, output = new Point2D()) {
1651
- const { v0, v1, v2 } = this;
1696
+ getPoint(t, output = new Vector2()) {
1697
+ const { start, control, end } = this;
1652
1698
  output.set(
1653
- quadraticBezier(t, v0.x, v1.x, v2.x),
1654
- quadraticBezier(t, v0.y, v1.y, v2.y)
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
- transform(matrix) {
1659
- this.v0.applyMatrix3(matrix);
1660
- this.v1.applyMatrix3(matrix);
1661
- this.v2.applyMatrix3(matrix);
1662
- return this;
1663
- }
1664
- getMinMax(min = Point2D.MAX, max = Point2D.MIN) {
1665
- const { v0, v1, v2 } = this;
1666
- const x1 = 0.5 * (v0.x + v1.x);
1667
- const y1 = 0.5 * (v0.y + v1.y);
1668
- const x2 = 0.5 * (v0.x + v2.x);
1669
- const y2 = 0.5 * (v0.y + v2.y);
1670
- min.x = Math.min(min.x, v0.x, v2.x, x1, x2);
1671
- min.y = Math.min(min.y, v0.y, v2.y, y1, y2);
1672
- max.x = Math.max(max.x, v0.x, v2.x, x1, x2);
1673
- max.y = Math.max(max.y, v0.y, v2.y, y1, y2);
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 { v0, v1, v2 } = this;
1723
+ const { start, control, end } = this;
1678
1724
  return [
1679
- { type: "M", x: v0.x, y: v0.y },
1680
- { type: "Q", x1: v1.x, y1: v1.y, x: v2.x, y: v2.y }
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 { v1, v2 } = this;
1685
- ctx.quadraticCurveTo(v1.x, v1.y, v2.x, v2.y);
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.v0.copy(source.v0);
1691
- this.v1.copy(source.v1);
1692
- this.v2.copy(source.v2);
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, "pointT", 0);
1713
- const { x, y } = this.center;
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
- getPoint(t) {
1739
- return this.getCurrentLine(t).getPoint(this.pointT);
1740
- }
1741
- getPointAt(u) {
1742
- return this.getPoint(u);
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
- getCurrentLine(t) {
1745
- let flag = (t * (this.end - this.start) + this.start) % 1;
1746
- flag < 0 && (flag += 1);
1747
- flag *= (1 + this.aspectRatio) * 2;
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 (flag < this.aspectRatio) {
1793
+ if (current < this.aspectRatio) {
1750
1794
  i = 0;
1751
- this.pointT = flag / this.aspectRatio;
1752
- } else if (flag < this.aspectRatio + 1) {
1795
+ this.curveT = current / this.aspectRatio;
1796
+ } else if (current < this.aspectRatio + 1) {
1753
1797
  i = 1;
1754
- this.pointT = (flag - this.aspectRatio) / 1;
1755
- } else if (flag < 2 * this.aspectRatio + 1) {
1798
+ this.curveT = (current - this.aspectRatio) / 1;
1799
+ } else if (current < 2 * this.aspectRatio + 1) {
1756
1800
  i = 2;
1757
- this.pointT = (flag - this.aspectRatio - 1) / this.aspectRatio;
1801
+ this.curveT = (current - this.aspectRatio - 1) / this.aspectRatio;
1758
1802
  } else {
1759
1803
  i = 3;
1760
- this.pointT = (flag - 2 * this.aspectRatio - 1) / 1;
1804
+ this.curveT = (current - 2 * this.aspectRatio - 1) / 1;
1761
1805
  }
1762
1806
  return this.curves[i];
1763
1807
  }
1764
- getTangent(t) {
1765
- return this.getCurrentLine(t).getTangent(0).normalize();
1808
+ getPoint(t, output) {
1809
+ return this.getCurve(t).getPoint(this.curveT, output);
1766
1810
  }
1767
- getNormal(value) {
1768
- const { v1, v2 } = this.getCurrentLine(value);
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
- transform(matrix) {
1772
- this.curves.forEach((curve) => curve.transform(matrix));
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 = Point2D.MAX, max = Point2D.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 Point2D()) {
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 Point2D());
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 Point2D()) {
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 pts = curve.getPoints(curve.getDivisions(divisions));
1903
- for (let i2 = 0; i2 < pts.length; i2++) {
1904
- const point = pts[i2];
1905
- if (last && last.equals(point))
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 Point2D(cp1x, cp1y),
1928
- new Point2D(cp2x, cp2y),
1929
- new Point2D(x, y)
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 Point2D(x, y)
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 Point2D(cpx, cpy),
1954
- new Point2D(x, y)
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 Point2D(x + w / 2, y + h / 2),
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(x, y, radiusX, radiusY, startAngle, endAngle, clockwise, rotation);
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 firstPoint = curve.getPoint(0);
1995
- if (!firstPoint.equals(this.currentPoint)) {
1996
- this.lineTo(firstPoint.x, firstPoint.y);
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 = Point2D.MAX, max = Point2D.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
- const point = this.currentPath.currentPoint;
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 = Point2D.MAX, max = Point2D.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
- return `<svg viewBox="${x} ${y} ${width} ${height}" xmlns="http://www.w3.org/2000/svg"><path fill="none" stroke="currentColor" d="${this.getData()}"></path></svg>`;
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 parseSvg(svg) {
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
- node = new DOMParser().parseFromString(xml, "image/svg+xml").documentElement;
2759
+ return new DOMParser().parseFromString(
2760
+ xml,
2761
+ "image/svg+xml"
2762
+ ).documentElement;
2724
2763
  } else {
2725
- node = svg;
2764
+ return svg;
2726
2765
  }
2727
- return parseNode(node, {
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;