plotboilerplate 1.20.0 → 1.20.1

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.
@@ -9,7 +9,8 @@
9
9
  * @author Ikaros Kappler
10
10
  * @date 2022-11-06
11
11
  * @modified 2022-12-21 (winter solstice) Porting this to Typescript.
12
- * @version 0.0.1-alpha
12
+ * @modified 2023-01-17 Handling multiple parameter sets now.
13
+ * @version 0.0.2-alpha
13
14
  **/
14
15
 
15
16
  import { CubicBezierCurve } from "../../../CubicBezierCurve";
@@ -55,9 +56,10 @@ export const parseSVGPathData = (dataString: string): Array<Line | CubicBezierCu
55
56
  const result: Array<Line | CubicBezierCurve> = [];
56
57
 
57
58
  var i = 0;
58
- const firstPoint = { x: NaN, y: NaN };
59
- const lastPoint = { x: NaN, y: NaN };
60
- const lastControlPoint = { x: NaN, y: NaN };
59
+ const firstPoint: XYCoords = { x: NaN, y: NaN };
60
+ const lastPoint: XYCoords = { x: NaN, y: NaN };
61
+ const lastControlPoint: XYCoords = { x: NaN, y: NaN };
62
+ const lastQuadraticControlPoint: XYCoords = { x: NaN, y: NaN };
61
63
 
62
64
  while (i < dataElements.length) {
63
65
  // Could this also be SVGPathShorthandQuadraticCurveToCommand?
@@ -191,28 +193,29 @@ const _handleLineTo = (
191
193
  lastControlPoint: XYCoords,
192
194
  result: Array<Line | CubicBezierCurve>
193
195
  ) => {
194
- // console.log("Handle LINETO", data);
195
196
  if (data.length < 3) {
196
197
  throw "Unsufficient params for LINETO";
197
198
  }
198
- // console.log("Y: ", Number(data[2]), "lastPoint", lastPoint);
199
- // result.push( new)
200
- const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
201
- if (isRelative) {
202
- line.b.x += Number(data[1]);
203
- line.b.y += Number(data[2]);
204
- } else {
205
- line.b.x = Number(data[1]);
206
- line.b.y = Number(data[2]);
207
- }
208
- result.push(line);
209
- lastPoint.x = line.b.x;
210
- lastPoint.y = line.b.y;
211
- lastControlPoint.x = line.b.x;
212
- lastControlPoint.y = line.b.y;
213
- if (isNaN(firstPoint.y)) {
214
- firstPoint.x = line.a.x;
215
- firstPoint.y = line.a.y;
199
+
200
+ for (var i = 1; i + 1 < data.length; i += 2) {
201
+ const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
202
+ if (isRelative) {
203
+ line.b.x += Number(data[i]);
204
+ line.b.y += Number(data[i + 1]);
205
+ } else {
206
+ line.b.x = Number(data[i]);
207
+ line.b.y = Number(data[i + 1]);
208
+ }
209
+ result.push(line);
210
+ lastPoint.x = line.b.x;
211
+ lastPoint.y = line.b.y;
212
+ lastControlPoint.x = line.b.x;
213
+ lastControlPoint.y = line.b.y;
214
+ if (isNaN(firstPoint.y)) {
215
+ firstPoint.x = line.a.x;
216
+ firstPoint.y = line.a.y;
217
+ }
218
+ console.log("LINETO LINE", i, line.toString());
216
219
  }
217
220
  };
218
221
 
@@ -228,23 +231,24 @@ const _handleHorizontalLineTo = (
228
231
  if (data.length < 2) {
229
232
  throw "Unsufficient params for HORIZONTALLINETO";
230
233
  }
231
- // console.log("Y: ", Number(data[2]), "lastPoint", lastPoint);
232
- // result.push( new)
233
- const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
234
- if (isRelative) {
235
- line.b.x += Number(data[1]);
236
- // line.b.y += Number(data[2]);
237
- } else {
238
- line.b.x = Number(data[1]);
239
- // line.b.y = Number(data[2]);
240
- }
241
- result.push(line);
242
- lastPoint.x = line.b.x;
243
- // lastPoint.y = line.b.y;
244
- lastControlPoint.x = line.b.x;
245
- if (isNaN(firstPoint.y)) {
246
- firstPoint.x = line.a.x;
247
- firstPoint.y = line.a.y;
234
+
235
+ for (var i = 1; i < data.length; i++) {
236
+ const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
237
+ if (isRelative) {
238
+ line.b.x += Number(data[i]);
239
+ // line.b.y += Number(data[2]);
240
+ } else {
241
+ line.b.x = Number(data[i]);
242
+ // line.b.y = Number(data[2]);
243
+ }
244
+ result.push(line);
245
+ lastPoint.x = line.b.x;
246
+ // lastPoint.y = line.b.y;
247
+ lastControlPoint.x = line.b.x;
248
+ if (isNaN(firstPoint.y)) {
249
+ firstPoint.x = line.a.x;
250
+ firstPoint.y = line.a.y;
251
+ }
248
252
  }
249
253
  };
250
254
 
@@ -256,27 +260,25 @@ const _handleVerticalLineTo = (
256
260
  lastControlPoint: XYCoords,
257
261
  result: Array<Line | CubicBezierCurve>
258
262
  ) => {
259
- // console.log("Handle VERTICALLINETO", data);
260
263
  if (data.length < 2) {
261
264
  throw "Unsufficient params for VERTICALLINETO";
262
265
  }
263
- // console.log("Y: ", Number(data[2]), "lastPoint", lastPoint);
264
- // result.push( new)
265
- const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
266
- if (isRelative) {
267
- // line.b.x += Number(data[1]);
268
- line.b.y += Number(data[1]);
269
- } else {
270
- // line.b.x = Number(data[1]);
271
- line.b.y = Number(data[1]);
272
- }
273
- result.push(line);
274
- // lastPoint.x = line.b.x;
275
- lastPoint.y = line.b.y;
276
- lastControlPoint.y = line.b.y;
277
- if (isNaN(firstPoint.y)) {
278
- firstPoint.x = line.a.x;
279
- firstPoint.y = line.a.y;
266
+
267
+ for (var i = 1; i < data.length; i++) {
268
+ const line = new Line(new Vertex(lastPoint), new Vertex(lastPoint));
269
+ if (isRelative) {
270
+ line.b.y += Number(data[i]);
271
+ } else {
272
+ line.b.y = Number(data[i]);
273
+ }
274
+ result.push(line);
275
+ // lastPoint.x = line.b.x;
276
+ lastPoint.y = line.b.y;
277
+ lastControlPoint.y = line.b.y;
278
+ if (isNaN(firstPoint.y)) {
279
+ firstPoint.x = line.a.x;
280
+ firstPoint.y = line.a.y;
281
+ }
280
282
  }
281
283
  };
282
284
 
@@ -293,32 +295,38 @@ const _handleCubicBezierTo = (
293
295
  if (data.length < 7) {
294
296
  throw "Unsufficient params for CUBICBEZIERTO";
295
297
  }
296
- // console.log("Y: ", Number(data[2]), "lastPoint", lastPoint);
297
- // result.push( new)
298
- const curve = new CubicBezierCurve(new Vertex(lastPoint), new Vertex(lastPoint), new Vertex(lastPoint), new Vertex(lastPoint));
299
- if (isRelative) {
300
- curve.startControlPoint.x += Number(data[1]);
301
- curve.startControlPoint.y += Number(data[2]);
302
- curve.endControlPoint.x += Number(data[3]);
303
- curve.endControlPoint.y += Number(data[4]);
304
- curve.endPoint.x += Number(data[5]);
305
- curve.endPoint.y += Number(data[6]);
306
- } else {
307
- curve.startControlPoint.x = Number(data[1]);
308
- curve.startControlPoint.y = Number(data[2]);
309
- curve.endControlPoint.x = Number(data[3]);
310
- curve.endControlPoint.y = Number(data[4]);
311
- curve.endPoint.x = Number(data[5]);
312
- curve.endPoint.y = Number(data[6]);
313
- }
314
- result.push(curve);
315
- lastPoint.x = curve.endPoint.x;
316
- lastPoint.y = curve.endPoint.y;
317
- lastControlPoint.x = curve.endControlPoint.x;
318
- lastControlPoint.y = curve.endControlPoint.y;
319
- if (isNaN(firstPoint.x)) {
320
- firstPoint.x = curve.startPoint.x;
321
- firstPoint.y = curve.startPoint.y;
298
+
299
+ for (var i = 1; i + 5 < data.length; i += 6) {
300
+ const curve = new CubicBezierCurve(
301
+ new Vertex(lastPoint),
302
+ new Vertex(lastPoint),
303
+ new Vertex(lastPoint),
304
+ new Vertex(lastPoint)
305
+ );
306
+ if (isRelative) {
307
+ curve.startControlPoint.x += Number(data[i]);
308
+ curve.startControlPoint.y += Number(data[i + 1]);
309
+ curve.endControlPoint.x += Number(data[i + 2]);
310
+ curve.endControlPoint.y += Number(data[i + 3]);
311
+ curve.endPoint.x += Number(data[i + 4]);
312
+ curve.endPoint.y += Number(data[i + 5]);
313
+ } else {
314
+ curve.startControlPoint.x = Number(data[i]);
315
+ curve.startControlPoint.y = Number(data[i + 1]);
316
+ curve.endControlPoint.x = Number(data[i + 2]);
317
+ curve.endControlPoint.y = Number(data[i + 3]);
318
+ curve.endPoint.x = Number(data[i + 4]);
319
+ curve.endPoint.y = Number(data[i + 5]);
320
+ }
321
+ result.push(curve);
322
+ lastPoint.x = curve.endPoint.x;
323
+ lastPoint.y = curve.endPoint.y;
324
+ lastControlPoint.x = curve.endControlPoint.x;
325
+ lastControlPoint.y = curve.endControlPoint.y;
326
+ if (isNaN(firstPoint.x)) {
327
+ firstPoint.x = curve.startPoint.x;
328
+ firstPoint.y = curve.startPoint.y;
329
+ }
322
330
  }
323
331
  };
324
332
 
@@ -335,102 +343,147 @@ const _handleQuadraticCurveTo = (
335
343
  if (data.length < 5) {
336
344
  throw "Unsufficient params for QUADRATICBEZIERTO";
337
345
  }
338
- // console.log("Y: ", Number(data[2]), "lastPoint", lastPoint);
339
- // result.push( new)
340
- const curve = new CubicBezierCurve(new Vertex(lastPoint), new Vertex(lastPoint), new Vertex(lastPoint), new Vertex(lastPoint));
341
- if (isRelative) {
342
- curve.startControlPoint.x += curve.startPoint.x + (Number(data[1]) - curve.startControlPoint.x); // * 0.666;
343
- curve.startControlPoint.y += curve.startPoint.y + (Number(data[2]) - curve.startControlPoint.y); // * 0.666;
344
- curve.endPoint.x += Number(data[3]);
345
- curve.endPoint.y += Number(data[4]);
346
- curve.endControlPoint.x = curve.startControlPoint.x;
347
- curve.endControlPoint.y = curve.startControlPoint.y;
348
- } else {
349
- curve.startControlPoint.x = curve.startPoint.x + (Number(data[1]) - curve.startControlPoint.x); // * 0.666;
350
- curve.startControlPoint.y = curve.startPoint.y + (Number(data[2]) - curve.startControlPoint.y); // * 0.666;
351
- curve.endPoint.x = Number(data[3]);
352
- curve.endPoint.y = Number(data[4]);
353
- curve.endControlPoint.x = curve.startControlPoint.x;
354
- curve.endControlPoint.y = curve.startControlPoint.y;
355
- }
356
- // var lastQuadraticControlPoint = { x: Number(data[1]), y: Number(data[2]) };
357
- const lastQuadraticControlPoint = { x: curve.endControlPoint.x, y: curve.endControlPoint.y };
358
- // Convert quadratic curve to cubic curve
359
- curve.startControlPoint.x = curve.startPoint.x + (curve.startControlPoint.x - curve.startPoint.x) * 0.666;
360
- curve.startControlPoint.y = curve.startPoint.y + (curve.startControlPoint.y - curve.startPoint.y) * 0.666;
361
- curve.endControlPoint.x = curve.endPoint.x + (curve.endControlPoint.x - curve.endPoint.x) * 0.666;
362
- curve.endControlPoint.y = curve.endPoint.y + (curve.endControlPoint.y - curve.endPoint.y) * 0.666;
363
346
 
364
- result.push(curve);
365
- lastPoint.x = curve.endPoint.x;
366
- lastPoint.y = curve.endPoint.y;
367
- lastControlPoint.x = curve.endControlPoint.x;
368
- lastControlPoint.y = curve.endControlPoint.y;
369
- if (isNaN(firstPoint.x)) {
370
- firstPoint.x = curve.startPoint.x;
371
- firstPoint.y = curve.startPoint.y;
372
- }
347
+ var i = 1;
348
+ var localLastQuadraticControlPoint = { x: 0, y: 0 };
349
+ // This loops runs at least once
350
+ while (i + 3 < data.length && data[i] !== "t" && data[i] !== "T") {
351
+ const curve = new CubicBezierCurve(
352
+ new Vertex(lastPoint),
353
+ new Vertex(lastPoint),
354
+ new Vertex(lastPoint),
355
+ new Vertex(lastPoint)
356
+ );
357
+ if (isRelative) {
358
+ curve.startControlPoint.x += curve.startPoint.x + (Number(data[i]) - curve.startControlPoint.x); // * 0.666;
359
+ curve.startControlPoint.y += curve.startPoint.y + (Number(data[i + 1]) - curve.startControlPoint.y); // * 0.666;
360
+ curve.endPoint.x += Number(data[i + 2]);
361
+ curve.endPoint.y += Number(data[i + 3]);
362
+ curve.endControlPoint.x = curve.startControlPoint.x;
363
+ curve.endControlPoint.y = curve.startControlPoint.y;
364
+ } else {
365
+ curve.startControlPoint.x = curve.startPoint.x + (Number(data[i]) - curve.startControlPoint.x); // * 0.666;
366
+ curve.startControlPoint.y = curve.startPoint.y + (Number(data[i + 1]) - curve.startControlPoint.y); // * 0.666;
367
+ curve.endPoint.x = Number(data[i + 2]);
368
+ curve.endPoint.y = Number(data[i + 3]);
369
+ curve.endControlPoint.x = curve.startControlPoint.x;
370
+ curve.endControlPoint.y = curve.startControlPoint.y;
371
+ }
372
+ // var lastQuadraticControlPoint = { x: Number(data[1]), y: Number(data[2]) };
373
+ localLastQuadraticControlPoint = { x: curve.endControlPoint.x, y: curve.endControlPoint.y };
374
+ // Convert quadratic curve to cubic curve
375
+ curve.startControlPoint.x = curve.startPoint.x + (curve.startControlPoint.x - curve.startPoint.x) * 0.666;
376
+ curve.startControlPoint.y = curve.startPoint.y + (curve.startControlPoint.y - curve.startPoint.y) * 0.666;
377
+ curve.endControlPoint.x = curve.endPoint.x + (curve.endControlPoint.x - curve.endPoint.x) * 0.666;
378
+ curve.endControlPoint.y = curve.endPoint.y + (curve.endControlPoint.y - curve.endPoint.y) * 0.666;
379
+
380
+ result.push(curve);
381
+ lastPoint.x = curve.endPoint.x;
382
+ lastPoint.y = curve.endPoint.y;
383
+ lastControlPoint.x = curve.endControlPoint.x;
384
+ lastControlPoint.y = curve.endControlPoint.y;
385
+ if (isNaN(firstPoint.x)) {
386
+ firstPoint.x = curve.startPoint.x;
387
+ firstPoint.y = curve.startPoint.y;
388
+ }
389
+ i += 4;
390
+ } // END while
373
391
 
374
392
  // 'T' or 't' command may follow
375
- if (data.length >= 8) {
393
+ // if (data.length >= 8) {
394
+ if (i < data.length && (data[i] == "t" || data[i] === "T")) {
376
395
  // TODO: think about this type cast!
377
396
  const subData: SVGPathShorthandQuadraticCurveToCommand = data.slice(5) as SVGPathShorthandQuadraticCurveToCommand;
378
397
  // var lastQuadraticControlPoint = { x: Number(data[1]), y: Number(data[2]) };
379
398
  if (subData[0] === "T") {
380
- // _handleShorthandQuadraticCurveTo(subData, false, firstPoint, lastPoint, lastControlPoint, result);
381
- _handleShorthandQuadraticCurveTo(subData, false, firstPoint, lastPoint, lastQuadraticControlPoint, result);
399
+ // _handleShorthandQuadraticCurveTo(subData, false, firstPoint, lastPoint, lastControlPoint, lastQuadraticControlPoint, result);
400
+ _handleShorthandQuadraticCurveTo(
401
+ subData,
402
+ false,
403
+ firstPoint,
404
+ lastPoint,
405
+ lastControlPoint,
406
+ localLastQuadraticControlPoint,
407
+ result
408
+ );
382
409
  } else if (subData[0] === "t") {
383
- // _handleShorthandQuadraticCurveTo(subData, true, firstPoint, lastPoint, lastControlPoint, result);
384
- _handleShorthandQuadraticCurveTo(subData, true, firstPoint, lastPoint, lastQuadraticControlPoint, result);
410
+ // _handleShorthandQuadraticCurveTo(subData, true, firstPoint, lastPoint, lastControlPoint, lastQuadraticControlPoint, result);
411
+ _handleShorthandQuadraticCurveTo(
412
+ subData,
413
+ true,
414
+ firstPoint,
415
+ lastPoint,
416
+ lastControlPoint,
417
+ localLastQuadraticControlPoint,
418
+ result
419
+ );
385
420
  }
386
421
  }
387
422
  };
388
423
 
389
424
  // This is a helper function and works only in combination with Quadratic Bézier Curves
390
- // T|t x y
425
+ // T|t (x y)+
391
426
  const _handleShorthandQuadraticCurveTo = (
392
427
  data: SVGPathShorthandQuadraticCurveToCommand,
393
428
  isRelative: boolean,
394
429
  firstPoint: XYCoords,
395
430
  lastPoint: XYCoords,
396
431
  lastControlPoint: XYCoords,
432
+ lastQuadraticControlPoint: XYCoords,
397
433
  result: Array<Line | CubicBezierCurve>
398
434
  ) => {
399
- // console.log("Handle SHORTHANDQUADRATICCURVETO", data);
400
435
  if (data.length < 3) {
401
436
  throw "Unsufficient params for SHORTHANDQUADRATICCURVETO";
402
437
  }
403
- const curve = new CubicBezierCurve(new Vertex(lastPoint), new Vertex(lastPoint), new Vertex(lastPoint), new Vertex(lastPoint));
404
- if (isRelative) {
405
- curve.endPoint.x += Number(data[1]);
406
- curve.endPoint.y += Number(data[2]);
407
- curve.startControlPoint.x += curve.startPoint.x - (lastControlPoint.x - lastPoint.x);
408
- curve.startControlPoint.y += curve.startPoint.y - (lastControlPoint.y - lastPoint.y);
409
- } else {
410
- curve.endPoint.x = Number(data[1]);
411
- curve.endPoint.y = Number(data[2]);
412
- curve.startControlPoint.x = curve.startPoint.x - (lastControlPoint.x - lastPoint.x);
413
- curve.startControlPoint.y = curve.startPoint.y - (lastControlPoint.y - lastPoint.y);
414
- }
415
- // First handle as symmetrical cubic curve
416
- curve.endControlPoint.x = curve.startControlPoint.x;
417
- curve.endControlPoint.y = curve.startControlPoint.y;
438
+ var i = 1;
439
+ while (i + 1 < data.length) {
440
+ // Respect multiple 'T|t' commands here
441
+ if (data[i] === "T" || data[i] === "t") {
442
+ i++;
443
+ continue;
444
+ }
445
+ const curve = new CubicBezierCurve(
446
+ new Vertex(lastPoint),
447
+ new Vertex(lastPoint),
448
+ new Vertex(lastPoint),
449
+ new Vertex(lastPoint)
450
+ );
451
+ if (isRelative) {
452
+ curve.endPoint.x += Number(data[i]);
453
+ curve.endPoint.y += Number(data[i + 1]);
454
+ curve.startControlPoint.x += curve.startPoint.x - (lastQuadraticControlPoint.x - lastPoint.x);
455
+ curve.startControlPoint.y += curve.startPoint.y - (lastQuadraticControlPoint.y - lastPoint.y);
456
+ } else {
457
+ curve.endPoint.x = Number(data[i]);
458
+ curve.endPoint.y = Number(data[i + 1]);
459
+ curve.startControlPoint.x = curve.startPoint.x - (lastQuadraticControlPoint.x - lastPoint.x);
460
+ curve.startControlPoint.y = curve.startPoint.y - (lastQuadraticControlPoint.y - lastPoint.y);
461
+ }
462
+ // First handle as symmetrical cubic curve
463
+ curve.endControlPoint.x = curve.startControlPoint.x;
464
+ curve.endControlPoint.y = curve.startControlPoint.y;
465
+ lastQuadraticControlPoint.y = curve.endControlPoint.y;
466
+ lastQuadraticControlPoint.x = curve.endControlPoint.x;
418
467
 
419
- // Convert quadratic curve to cubic curve
420
- curve.startControlPoint.x = curve.startPoint.x + (curve.startControlPoint.x - curve.startPoint.x) * 0.666;
421
- curve.startControlPoint.y = curve.startPoint.y + (curve.startControlPoint.y - curve.startPoint.y) * 0.666;
422
- curve.endControlPoint.x = curve.endPoint.x + (curve.endControlPoint.x - curve.endPoint.x) * 0.666;
423
- curve.endControlPoint.y = curve.endPoint.y + (curve.endControlPoint.y - curve.endPoint.y) * 0.666;
468
+ // Convert quadratic curve to cubic curve
469
+ var scaleFactor = 0.666; // i === 1 ? 0.666 : 1.0;
470
+ curve.startControlPoint.x = curve.startPoint.x + (curve.startControlPoint.x - curve.startPoint.x) * scaleFactor;
471
+ curve.startControlPoint.y = curve.startPoint.y + (curve.startControlPoint.y - curve.startPoint.y) * scaleFactor;
472
+ curve.endControlPoint.x = curve.endPoint.x + (curve.endControlPoint.x - curve.endPoint.x) * scaleFactor;
473
+ curve.endControlPoint.y = curve.endPoint.y + (curve.endControlPoint.y - curve.endPoint.y) * scaleFactor;
424
474
 
425
- // console.log("ADDING T CURVE", curve);
426
- result.push(curve);
427
- lastPoint.x = curve.endPoint.x;
428
- lastPoint.y = curve.endPoint.y;
429
- lastControlPoint.x = curve.endControlPoint.x;
430
- lastControlPoint.y = curve.endControlPoint.y;
431
- if (isNaN(firstPoint.x)) {
432
- firstPoint.x = curve.startPoint.x;
433
- firstPoint.y = curve.startPoint.y;
475
+ // console.log("ADDING T CURVE", curve);
476
+ result.push(curve);
477
+ lastPoint.x = curve.endPoint.x;
478
+ lastPoint.y = curve.endPoint.y;
479
+ lastControlPoint.x = curve.endControlPoint.x;
480
+ lastControlPoint.y = curve.endControlPoint.y;
481
+ if (isNaN(firstPoint.x)) {
482
+ firstPoint.x = curve.startPoint.x;
483
+ firstPoint.y = curve.startPoint.y;
484
+ }
485
+
486
+ i += 2;
434
487
  }
435
488
  };
436
489
 
@@ -486,70 +539,76 @@ const _handleArcTo = (
486
539
  lastControlPoint: XYCoords,
487
540
  result: Array<Line | CubicBezierCurve>
488
541
  ) => {
489
- // console.log("Handle ARCTO", data);
490
542
  if (data.length < 8) {
491
543
  throw "Unsufficient params for ARCTO";
492
544
  }
493
545
 
494
- const arcEndPoint = { x: Number(data[6]), y: Number(data[7]) };
495
- if (isRelative) {
496
- arcEndPoint.x += lastPoint.x;
497
- arcEndPoint.y += lastPoint.y;
498
- }
499
-
500
- // console.log(
501
- // "lastPoint.x",
502
- // lastPoint.x, // x1
503
- // "lastPoint.y",
504
- // lastPoint.y, // y1
505
- // "data[1]",
506
- // Number(data[1]), // rx
507
- // "data[2]",
508
- // Number(data[2]), // ry
509
- // "data[3]",
510
- // Number(data[3]), // phi: number,
511
- // "data[4]",
512
- // Boolean(data[4]), // fa: boolean,
513
- // "data[5]",
514
- // Boolean(data[5]), // fs: boolean,
515
- // "data[6]",
516
- // arcEndPoint.x, // Number(data[6]), // x2: number,
517
- // "data[7]",
518
- // arcEndPoint.y // Number(data[7]) // y2: number
519
- // );
520
- // A 5 4 0 1 1 -10 -5
521
- // TODO: respect relative/absolute here
522
- const ellipseSector = VEllipseSector.ellipseSectorUtils.endpointToCenterParameters(
523
- lastPoint.x,
524
- lastPoint.y,
525
- Number(data[1]),
526
- Number(data[2]),
527
- Number(data[3]) * DEG_TO_RAD,
528
- Boolean(data[4]),
529
- Boolean(data[5]),
530
- arcEndPoint.x,
531
- arcEndPoint.y // Number(data[7]) // y2: number
532
- );
533
-
534
- // console.log("ellipseSector", ellipseSector);
535
- const curves = ellipseSector.toCubicBezier(4); // 4 segments already seems to be a good approximation
536
- for (var i = 0; i < curves.length; i++) {
537
- result.push(curves[i]); // Destruct!
538
- }
539
- // result.push(ellipseSector.ellipse);
540
- if (curves.length > 0) {
541
- // console.log("curves", curves);
542
- const lastCurve = curves[curves.length - 1];
543
- lastPoint.x = lastCurve.endPoint.x;
544
- lastPoint.y = lastCurve.endPoint.y;
545
- lastControlPoint.x = lastCurve.endControlPoint.x;
546
- lastControlPoint.y = lastCurve.endControlPoint.y;
547
- if (isNaN(firstPoint.x)) {
548
- firstPoint.x = curves[0].startPoint.x;
549
- firstPoint.y = curves[0].startPoint.y;
546
+ for (var i = 1; i + 6 < data.length; i += 7) {
547
+ const arcEndPoint = { x: Number(data[i + 5]), y: Number(data[i + 6]) };
548
+ if (isRelative) {
549
+ arcEndPoint.x += lastPoint.x;
550
+ arcEndPoint.y += lastPoint.y;
550
551
  }
551
- }
552
+ // console.log(
553
+ // "ARC",
554
+ // "data.length",
555
+ // data.length,
556
+ // "i",
557
+ // i,
558
+ // "lastPoint.x",
559
+ // lastPoint.x, // x1
560
+ // "lastPoint.y",
561
+ // lastPoint.y, // y1
562
+ // "data[i]",
563
+ // Number(data[i]), // rx
564
+ // "data[i+1]",
565
+ // Number(data[i + 1]), // ry
566
+ // "data[i+2]",
567
+ // Number(data[i + 2]), // phi: number,
568
+ // "data[i+3]",
569
+ // Boolean(data[i + 3]), // fa: boolean,
570
+ // "data[i+4]",
571
+ // Boolean(data[i + 4]), // fs: boolean,
572
+ // "data[i+5]",
573
+ // arcEndPoint.x, // Number(data[6]), // x2: number,
574
+ // "data[i+6]",
575
+ // arcEndPoint.y // Number(data[7]) // y2: number
576
+ // );
577
+ // A 5 4 0 1 1 -10 -5
578
+ // TODO: respect relative/absolute here
579
+ const ellipseSector = VEllipseSector.ellipseSectorUtils.endpointToCenterParameters(
580
+ lastPoint.x,
581
+ lastPoint.y,
582
+ Number(data[i]),
583
+ Number(data[i + 1]),
584
+ Number(data[i + 2]) * DEG_TO_RAD,
585
+ Boolean(data[i + 3]),
586
+ Boolean(data[i + 4]),
587
+ arcEndPoint.x,
588
+ arcEndPoint.y // Number(data[7]) // y2: number
589
+ );
552
590
 
591
+ // console.log("ellipseSector", ellipseSector);
592
+ const curves = ellipseSector.toCubicBezier(4); // 4 segments already seems to be a good approximation
593
+ for (var j = 0; j < curves.length; j++) {
594
+ result.push(curves[j]); // Destruct!
595
+ }
596
+ // result.push(ellipseSector.ellipse);
597
+ if (curves.length > 0) {
598
+ // console.log("curves", curves);
599
+ const lastCurve = curves[curves.length - 1];
600
+ // lastPoint.x = lastCurve.endPoint.x;
601
+ // lastPoint.y = lastCurve.endPoint.y;
602
+ lastControlPoint.x = lastCurve.endControlPoint.x;
603
+ lastControlPoint.y = lastCurve.endControlPoint.y;
604
+ if (isNaN(firstPoint.x)) {
605
+ firstPoint.x = curves[0].startPoint.x;
606
+ firstPoint.y = curves[0].startPoint.y;
607
+ }
608
+ }
609
+ lastPoint.x = arcEndPoint.x;
610
+ lastPoint.y = arcEndPoint.y;
611
+ } // END for
553
612
  // TODO: track first/last/control point
554
613
  };
555
614
 
@@ -20,13 +20,17 @@ import { SVGPathCommand } from "./types";
20
20
  * @param {string} dataString - The SVG path data to split. This should be some string
21
21
  **/
22
22
  export const splitSVGPathData = (dataString: string): Array<SVGPathCommand> | null => {
23
+ // I used a modified version of this Josh Frank's SVG path data RexEx.
23
24
  // Source
24
25
  // https://javascript.plainenglish.io/june-3-parsing-and-validating-svg-paths-with-regex-7bd0e245115
26
+ // const validCommand =
27
+ // /([ml](\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))|([hv](\s?-?((\d+(\.\d+)?)|(\.\d+))))|(c(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){5})|(q(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3}(\s?t?(\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))*)|(a(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2}[,\s]?[01][,\s]+[01][,\s]+([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2})|(s(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3})|z/gi;
28
+ //
29
+ // My Version allows multiple param sets, too, like 'm|M (x y)+' or 'q|Q (x1 y1 x y)+'. Look at the plus.
25
30
  const validCommand =
26
- /([ml](\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))|([hv](\s?-?((\d+(\.\d+)?)|(\.\d+))))|(c(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){5})|(q(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3}(\s?t?(\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))*)|(a(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2}[,\s]?[01][,\s]+[01][,\s]+([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2})|(s(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3})|z/gi;
31
+ /([ml]((\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))+)|([hv]((\s?-?((\d+(\.\d+)?)|(\.\d+))))+)|(c((\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){5})+)|(q((\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3})+(\s?(t?(\s?-?((\d+(\.\d+)?)|(\.\d+)))[,\s]?(-?((\d+(\.\d+)?)|(\.\d+))))*)+)|(a((\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2}[,\s]?[01][,\s]+[01][,\s]+([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){2})+)|(s(\s?-?((\d+(\.\d+)?)|(\.\d+)))([,\s]?(-?((\d+(\.\d+)?)|(\.\d+)))){3})|z/gi;
27
32
 
28
33
  const dataElements = dataString.match(validCommand);
29
- // console.log("Splitted: ", dataElements);
30
34
  if (!dataElements) {
31
35
  return null;
32
36
  }