@design-core/core 0.0.4 → 0.0.6

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.
Files changed (56) hide show
  1. package/core/entities/arc.js +39 -22
  2. package/core/entities/arctext.js +6 -4
  3. package/core/entities/basePolyline.js +29 -20
  4. package/core/entities/circle.js +33 -15
  5. package/core/entities/entity.js +1 -1
  6. package/core/entities/hatch.js +2 -0
  7. package/core/entities/insert.js +9 -3
  8. package/core/entities/line.js +16 -11
  9. package/core/entities/lwpolyline.js +2 -0
  10. package/core/entities/point.js +3 -1
  11. package/core/entities/polyline.js +2 -0
  12. package/core/entities/rectangle.js +2 -0
  13. package/core/entities/solid.js +2 -0
  14. package/core/entities/text.js +5 -8
  15. package/core/lib/input.js +8 -4
  16. package/core/lib/inputManager.js +3 -5
  17. package/core/lib/selectionManager.js +4 -0
  18. package/core/lib/settings.js +9 -5
  19. package/core/lib/snapping.js +112 -17
  20. package/core/tables/block.js +2 -0
  21. package/core/tools/chamfer.js +2 -0
  22. package/core/tools/chamferFilletBase.js +2 -0
  23. package/core/tools/copy.js +2 -0
  24. package/core/tools/copybase.js +2 -0
  25. package/core/tools/copyclip.js +2 -0
  26. package/core/tools/cutclip.js +2 -0
  27. package/core/tools/distance.js +2 -0
  28. package/core/tools/erase.js +2 -0
  29. package/core/tools/explode.js +2 -0
  30. package/core/tools/extend.js +2 -0
  31. package/core/tools/fillet.js +5 -3
  32. package/core/tools/identify.js +2 -0
  33. package/core/tools/matchProp.js +2 -0
  34. package/core/tools/mirror.js +2 -0
  35. package/core/tools/move.js +2 -0
  36. package/core/tools/offset.js +2 -0
  37. package/core/tools/pan.js +2 -0
  38. package/core/tools/pasteclip.js +2 -0
  39. package/core/tools/purge.js +2 -0
  40. package/core/tools/rotate.js +2 -0
  41. package/core/tools/scale.js +2 -0
  42. package/core/tools/tool.js +1 -1
  43. package/core/tools/trim.js +2 -0
  44. package/core/tools/zoom.js +2 -0
  45. package/package.json +1 -1
  46. package/test/entities/arc.test.js +60 -11
  47. package/test/entities/arctext.test.js +18 -2
  48. package/test/entities/basePolyline.test.js +61 -0
  49. package/test/entities/circle.test.js +48 -22
  50. package/test/entities/insert.test.js +14 -4
  51. package/test/entities/line.test.js +53 -0
  52. package/test/entities/text.test.js +10 -1
  53. package/test/lib/input.test.js +117 -0
  54. package/test/lib/settings.test.js +5 -7
  55. package/test/lib/snapping.test.js +218 -12
  56. package/test/tools/fillet.test.js +115 -0
@@ -10,12 +10,15 @@ import { AddState, RemoveState } from '../lib/stateManager.js';
10
10
 
11
11
  import { DesignCore } from '../designCore.js';
12
12
  import { Property } from '../properties/property.js';
13
+ import { SnapPoint } from '../lib/snapping.js';
13
14
 
14
15
  /**
15
16
  * Arc Entity Class
16
17
  * @extends Entity
17
18
  * */
18
19
  export class Arc extends Entity {
20
+ static type = 'Arc';
21
+
19
22
  /**
20
23
  * Create an Arc Entity
21
24
  * @param {Array} data
@@ -392,31 +395,45 @@ export class Arc extends Entity {
392
395
  snaps(mousePoint, delta) {
393
396
  const snaps = [];
394
397
 
395
- if (DesignCore.Settings.endsnap) {
396
- // Speed this up by generating the proper start and end points when the arc is initialised
397
- const startPoint = new Point(
398
- this.points[0].x + (this.radius * Math.cos(this.startAngle())),
399
- this.points[0].y + (this.radius * Math.sin(this.startAngle())),
400
- );
401
- const endPoint = new Point(
402
- this.points[0].x + (this.radius * Math.cos(this.endAngle())),
403
- this.points[0].y + (this.radius * Math.sin(this.endAngle())),
404
- );
405
-
406
- snaps.push(startPoint, endPoint);
407
- }
398
+ const centre = this.points[0]; // arc centre point
399
+ const arcStartPoint = this.points[1]; // arc start point on circumference
400
+ const arcEndPoint = this.points[2]; // arc end point on circumference
401
+
402
+ snaps.push(new SnapPoint(centre, SnapPoint.Type.CENTRE));
403
+ snaps.push(new SnapPoint(arcStartPoint, SnapPoint.Type.END));
404
+ snaps.push(new SnapPoint(arcEndPoint, SnapPoint.Type.END));
408
405
 
409
- if (DesignCore.Settings.centresnap) {
410
- const centre = this.points[0];
411
- snaps.push(centre);
406
+ if (mousePoint) {
407
+ const [nearestPoint, nearestDistance, isOnArc] = this.closestPoint(mousePoint);
408
+ // Crude way to snap to the closest point on the arc
409
+ if (isOnArc === true && nearestDistance < delta / 10) {
410
+ snaps.push(new SnapPoint(nearestPoint, SnapPoint.Type.NEAREST));
411
+ }
412
412
  }
413
413
 
414
- if (DesignCore.Settings.nearestsnap) {
415
- const closest = this.closestPoint(mousePoint);
414
+ const fromPoint = DesignCore.Scene.inputManager.inputPoint; // last confirmed input point (line start)
415
+ if (fromPoint !== null) {
416
+ const distanceToCenter = centre.distance(fromPoint); // distance from the input point to the arc centre
417
+ const angleFromCentreToInput = centre.angle(fromPoint); // angle from centre toward fromPoint
418
+
419
+ // Tangent: only possible when fromPoint is outside the arc radius
420
+ if (distanceToCenter > this.radius) {
421
+ const tangentHalfAngle = Math.acos(this.radius / distanceToCenter); // half-angle between the two tangent directions
416
422
 
417
- // Crude way to snap to the closest point or a node
418
- if (closest[2] === true && closest[1] < delta / 10) {
419
- snaps.push(closest[0]);
423
+ for (const sign of [1, -1]) {
424
+ const tangentPoint = centre.project(angleFromCentreToInput + sign * tangentHalfAngle, this.radius);
425
+ if (tangentPoint.isOnArc(this.points[1], this.points[2], centre, this.direction)) {
426
+ snaps.push(new SnapPoint(tangentPoint, SnapPoint.Type.TANGENT));
427
+ }
428
+ }
429
+ }
430
+
431
+ // Perpendicular: point on the arc that lies on the line from fromPoint through the centre
432
+ if (distanceToCenter > 0) {
433
+ const perpendicularPoint = centre.project(angleFromCentreToInput, this.radius);
434
+ if (perpendicularPoint.isOnArc(this.points[1], this.points[2], centre, this.direction)) {
435
+ snaps.push(new SnapPoint(perpendicularPoint, SnapPoint.Type.PERPENDICULAR));
436
+ }
420
437
  }
421
438
  }
422
439
 
@@ -437,7 +454,7 @@ export class Arc extends Entity {
437
454
 
438
455
  if (pnt !== null) {
439
456
  const distance = P.distance(pnt);
440
- return [pnt, distance];
457
+ return [pnt, distance, true];
441
458
  }
442
459
 
443
460
  // closest point not on the arc
@@ -11,6 +11,7 @@ import { Property } from '../properties/property.js';
11
11
  import { Text } from './text.js';
12
12
 
13
13
  import { DesignCore } from '../designCore.js';
14
+ import { SnapPoint } from '../lib/snapping.js';
14
15
 
15
16
  /**
16
17
  * Arc Aligned Character Class
@@ -95,6 +96,8 @@ export class ArcAlignedCharacter {
95
96
  * @extends Entity
96
97
  */
97
98
  export class ArcAlignedText extends Entity {
99
+ static type = 'ArcAlignedText';
100
+
98
101
  /**
99
102
  * Create a Text Entity
100
103
  * @param {Array} data
@@ -566,16 +569,15 @@ export class ArcAlignedText extends Entity {
566
569
  snaps(mousePoint, delta) {
567
570
  const snaps = [];
568
571
 
569
- const ArcAlignedCharacters = this.getArcAlignedCharacters();
572
+ snaps.push(new SnapPoint(this.points[0], SnapPoint.Type.CENTRE)); // arc center
570
573
 
574
+ const ArcAlignedCharacters = this.getArcAlignedCharacters();
571
575
  for (const arcAlignedChar of ArcAlignedCharacters) {
572
576
  // Don't snap to space characters
573
577
  if (arcAlignedChar.character.trim() === '') continue;
574
- snaps.push(arcAlignedChar.position);
578
+ snaps.push(new SnapPoint(arcAlignedChar.position, SnapPoint.Type.NODE));
575
579
  }
576
580
 
577
- snaps.push(this.points[0]); // arc center
578
-
579
581
  return snaps;
580
582
  }
581
583
 
@@ -13,12 +13,15 @@ import { Property } from '../properties/property.js';
13
13
  import { AddState, RemoveState, UpdateState } from '../lib/stateManager.js';
14
14
 
15
15
  import { DesignCore } from '../designCore.js';
16
+ import { SnapPoint } from '../lib/snapping.js';
16
17
 
17
18
  /**
18
19
  * Base Polyline Entity Class
19
20
  * @extends Entity
20
21
  */
21
22
  export class BasePolyline extends Entity {
23
+ static type = 'BasePolyline';
24
+
22
25
  /**
23
26
  * Create a Base Polyline
24
27
  * @param {Array} data
@@ -268,35 +271,40 @@ export class BasePolyline extends Entity {
268
271
  snaps(mousePoint, delta) {
269
272
  const snaps = [];
270
273
 
271
- if (DesignCore.Settings.endsnap) {
272
- // End points for each segment
273
- for (let i = 0; i < this.points.length; i++) {
274
- snaps.push(this.points[i]);
275
- }
274
+ // End points for each segment
275
+ for (let i = 0; i < this.points.length; i++) {
276
+ snaps.push(new SnapPoint(this.points[i], SnapPoint.Type.END));
276
277
  }
277
278
 
278
- if (DesignCore.Settings.midsnap) {
279
- for (let i = 1; i < this.points.length; i++) {
280
- if (this.points[i - 1].bulge === 0) {
281
- snaps.push(this.points[i - 1].midPoint(this.points[i]));
282
- }
279
+ for (let i = 1; i < this.points.length; i++) {
280
+ if (this.points[i - 1].bulge === 0) {
281
+ snaps.push(new SnapPoint(this.points[i - 1].midPoint(this.points[i]), SnapPoint.Type.MID));
283
282
  }
284
283
  }
285
284
 
286
- if (DesignCore.Settings.centresnap) {
287
- for (let i = 1; i < this.points.length; i++) {
288
- if (this.points[i - 1].bulge !== 0) {
289
- snaps.push(this.points[i - 1].bulgeCentrePoint(this.points[i]));
290
- }
285
+ for (let i = 1; i < this.points.length; i++) {
286
+ if (this.points[i - 1].bulge !== 0) {
287
+ snaps.push(new SnapPoint(this.points[i - 1].bulgeCentrePoint(this.points[i]), SnapPoint.Type.CENTRE));
291
288
  }
292
289
  }
293
290
 
294
- if (DesignCore.Settings.nearestsnap) {
291
+ if (mousePoint) {
295
292
  const closest = this.closestPoint(mousePoint);
296
-
297
293
  // Crude way to snap to the closest point or a node
298
294
  if (closest[1] < delta / 10) {
299
- snaps.push(closest[0]);
295
+ snaps.push(new SnapPoint(closest[0], SnapPoint.Type.NEAREST));
296
+ }
297
+ }
298
+
299
+ const fromPoint = DesignCore.Scene.inputManager.inputPoint;
300
+ if (fromPoint !== null) {
301
+ for (let i = 1; i < this.points.length; i++) {
302
+ if (this.points[i - 1].bulge === 0) {
303
+ const foot = fromPoint.perpendicular(this.points[i - 1], this.points[i]);
304
+ if (foot.isOnLine(this.points[i - 1], this.points[i])) {
305
+ snaps.push(new SnapPoint(foot, SnapPoint.Type.PERPENDICULAR));
306
+ }
307
+ }
300
308
  }
301
309
  }
302
310
 
@@ -390,9 +398,10 @@ export class BasePolyline extends Entity {
390
398
  let distance = Infinity;
391
399
  let minPnt = P;
392
400
 
393
- for (let i = 1; i < this.points.length; i++) {
401
+ const segmentCount = this.flags.hasFlag(1) ? this.points.length : this.points.length - 1;
402
+ for (let i = 1; i <= segmentCount; i++) {
394
403
  const A = this.points[i - 1];
395
- const B = this.points[i];
404
+ const B = this.points[i % this.points.length];
396
405
 
397
406
  let pnt;
398
407
  if (A.bulge !== 0) {
@@ -10,12 +10,15 @@ import { Utils } from '../lib/utils.js';
10
10
 
11
11
  import { DesignCore } from '../designCore.js';
12
12
  import { AddState, RemoveState } from '../lib/stateManager.js';
13
+ import { SnapPoint } from '../lib/snapping.js';
13
14
 
14
15
  /**
15
16
  * Circle Entity Class
16
17
  * @extends Entity
17
18
  */
18
19
  export class Circle extends Entity {
20
+ static type = 'Circle';
21
+
19
22
  /**
20
23
  * Create a Circle Entity
21
24
  * @param {Array} data
@@ -246,26 +249,41 @@ export class Circle extends Entity {
246
249
  snaps(mousePoint, delta) {
247
250
  const snaps = [];
248
251
 
249
- if (DesignCore.Settings.centresnap) {
250
- const centre = new Point(this.points[0].x, this.points[0].y);
251
- snaps.push(centre);
252
- }
252
+ const centre = this.points[0]; // circle centre point
253
253
 
254
- if (DesignCore.Settings.quadrantsnap) {
255
- const angle0 = new Point(this.points[0].x + this.radius, this.points[0].y);
256
- const angle90 = new Point(this.points[0].x, this.points[0].y + this.radius);
257
- const angle180 = new Point(this.points[0].x - this.radius, this.points[0].y);
258
- const angle270 = new Point(this.points[0].x, this.points[0].y - this.radius);
254
+ snaps.push(new SnapPoint(centre, SnapPoint.Type.CENTRE));
259
255
 
260
- snaps.push(angle0, angle90, angle180, angle270);
256
+ snaps.push(
257
+ new SnapPoint(new Point(centre.x + this.radius, centre.y), SnapPoint.Type.QUADRANT), // 0°
258
+ new SnapPoint(new Point(centre.x, centre.y + this.radius), SnapPoint.Type.QUADRANT), // 90°
259
+ new SnapPoint(new Point(centre.x - this.radius, centre.y), SnapPoint.Type.QUADRANT), // 180°
260
+ new SnapPoint(new Point(centre.x, centre.y - this.radius), SnapPoint.Type.QUADRANT), // 270°
261
+ );
262
+
263
+ if (mousePoint) {
264
+ const [nearestPoint, nearestDistance] = this.closestPoint(mousePoint);
265
+ // Crude way to snap to the closest point on the circle
266
+ if (nearestDistance < delta / 10) {
267
+ snaps.push(new SnapPoint(nearestPoint, SnapPoint.Type.NEAREST));
268
+ }
261
269
  }
262
270
 
263
- if (DesignCore.Settings.nearestsnap) {
264
- const closest = this.closestPoint(mousePoint);
271
+ const fromPoint = DesignCore.Scene.inputManager.inputPoint; // last confirmed input point (line start)
272
+ if (fromPoint !== null) {
273
+ const distanceToCenter = centre.distance(fromPoint); // distance from the input point to the circle centre
274
+ const angleFromCentreToInput = centre.angle(fromPoint); // angle from centre toward fromPoint
275
+
276
+ // Tangent: only possible when fromPoint is outside the circle radius
277
+ if (distanceToCenter > this.radius) {
278
+ const tangentHalfAngle = Math.acos(this.radius / distanceToCenter); // half-angle between the two tangent directions
279
+
280
+ snaps.push(new SnapPoint(centre.project(angleFromCentreToInput + tangentHalfAngle, this.radius), SnapPoint.Type.TANGENT));
281
+ snaps.push(new SnapPoint(centre.project(angleFromCentreToInput - tangentHalfAngle, this.radius), SnapPoint.Type.TANGENT));
282
+ }
265
283
 
266
- // Crude way to snap to the closest point or a node
267
- if (closest[1] < delta / 10) {
268
- snaps.push(closest[0]);
284
+ // Perpendicular: point on the circle that lies on the line from fromPoint through the centre
285
+ if (distanceToCenter > 0) {
286
+ snaps.push(new SnapPoint(centre.project(angleFromCentreToInput, this.radius), SnapPoint.Type.PERPENDICULAR));
269
287
  }
270
288
  }
271
289
 
@@ -19,7 +19,7 @@ export class Entity {
19
19
  */
20
20
  constructor(data) {
21
21
  Object.defineProperty(this, 'type', {
22
- value: this.constructor.name,
22
+ value: this.constructor.type ?? this.constructor.name,
23
23
  writable: true,
24
24
  });
25
25
 
@@ -25,6 +25,8 @@ import { Property } from '../properties/property.js';
25
25
  * @extends Entity
26
26
  */
27
27
  export class Hatch extends Entity {
28
+ static type = 'Hatch';
29
+
28
30
  /**
29
31
  * Create a Hatch Entity
30
32
  * @param {Array} data
@@ -9,6 +9,7 @@ import { Property } from '../properties/property.js';
9
9
  import { Logging } from '../lib/logging.js';
10
10
 
11
11
  import { DesignCore } from '../designCore.js';
12
+ import { SnapPoint } from '../lib/snapping.js';
12
13
 
13
14
 
14
15
  /**
@@ -16,6 +17,8 @@ import { DesignCore } from '../designCore.js';
16
17
  * @extends Entity
17
18
  */
18
19
  export class Insert extends Entity {
20
+ static type = 'Insert';
21
+
19
22
  /**
20
23
  * Create an Insert
21
24
  * Inserts are used to define the location of blocks
@@ -209,15 +212,18 @@ export class Insert extends Entity {
209
212
  */
210
213
  snaps(mousePoint, delta) {
211
214
  const snaps = [];
215
+
216
+ snaps.push(new SnapPoint(this.points[0], SnapPoint.Type.NODE));
217
+
212
218
  const blockSnaps = this.block.snaps(mousePoint, delta);
213
219
 
214
220
  for (let snap = 0; snap < blockSnaps.length; snap++) {
215
- const snapPoint = blockSnaps[snap];
221
+ const sp = blockSnaps[snap];
216
222
  // offset the item snap point by the block insert location
217
- const rotatedPoint = snapPoint.add(this.points[0]);
223
+ const rotatedPoint = sp.snapPoint.add(this.points[0]);
218
224
  // rotate the snap point to match the item positions
219
225
  const adjustedPoint = rotatedPoint.rotate(this.points[0], Utils.degrees2radians(this.rotation));
220
- snaps.push(adjustedPoint);
226
+ snaps.push(new SnapPoint(adjustedPoint, sp.type));
221
227
  }
222
228
 
223
229
  return snaps;
@@ -9,6 +9,7 @@ import { AddState, RemoveState, UpdateState } from '../lib/stateManager.js';
9
9
 
10
10
  import { DesignCore } from '../designCore.js';
11
11
  import { Utils } from '../lib/utils.js';
12
+ import { SnapPoint } from '../lib/snapping.js';
12
13
 
13
14
 
14
15
  /**
@@ -16,6 +17,8 @@ import { Utils } from '../lib/utils.js';
16
17
  * @extends Entity
17
18
  */
18
19
  export class Line extends Entity {
20
+ static type = 'Line';
21
+
19
22
  /**
20
23
  * Create a Line Entity
21
24
  * @param {Array} data
@@ -295,22 +298,24 @@ export class Line extends Entity {
295
298
  snaps(mousePoint, delta) {
296
299
  const snaps = [];
297
300
 
298
- if (DesignCore.Settings.endsnap) {
299
- const start = new Point(this.points[0].x, this.points[0].y);
300
- const end = new Point(this.points[1].x, this.points[1].y);
301
- snaps.push(start, end);
302
- }
301
+ snaps.push(new SnapPoint(this.points[0], SnapPoint.Type.END));
302
+ snaps.push(new SnapPoint(this.points[1], SnapPoint.Type.END));
303
303
 
304
- if (DesignCore.Settings.midsnap) {
305
- snaps.push(this.midPoint());
306
- }
304
+ snaps.push(new SnapPoint(this.midPoint(), SnapPoint.Type.MID));
307
305
 
308
- if (DesignCore.Settings.nearestsnap) {
306
+ if (mousePoint) {
309
307
  const closest = this.closestPoint(mousePoint);
310
-
311
308
  // Crude way to snap to the closest point or a node
312
309
  if (closest[1] < delta / 10) {
313
- snaps.push(closest[0]);
310
+ snaps.push(new SnapPoint(closest[0], SnapPoint.Type.NEAREST));
311
+ }
312
+ }
313
+
314
+ const fromPoint = DesignCore.Scene.inputManager.inputPoint;
315
+ if (fromPoint !== null) {
316
+ const foot = fromPoint.perpendicular(this.points[0], this.points[1]);
317
+ if (foot.isOnLine(this.points[0], this.points[1])) {
318
+ snaps.push(new SnapPoint(foot, SnapPoint.Type.PERPENDICULAR));
314
319
  }
315
320
  }
316
321
 
@@ -7,6 +7,8 @@ import { Polyline } from './polyline.js';
7
7
  * @extends BasePolyline
8
8
  */
9
9
  export class Lwpolyline extends BasePolyline {
10
+ static type = 'Lwpolyline';
11
+
10
12
  /**
11
13
  * Create an LW Polyline
12
14
  * @param {Array} data
@@ -3,6 +3,8 @@ import { Constants } from '../lib/constants.js';
3
3
 
4
4
  /** Point Entity Class */
5
5
  export class Point {
6
+ static type = 'Point';
7
+
6
8
  /**
7
9
  * Create a Point
8
10
  * @param {number} x
@@ -11,7 +13,7 @@ export class Point {
11
13
  * @param {number} sequence - dxf group code sequence reference
12
14
  */
13
15
  constructor(x, y, bulge = 0, sequence) {
14
- this.type = this.constructor.name;
16
+ this.type = this.constructor.type ?? this.constructor.name;
15
17
  this.x = 0;
16
18
  this.y = 0;
17
19
  // sequence holds a reference to the dxf group code sequence the point represents
@@ -7,6 +7,8 @@ import { Point } from './point.js';
7
7
  * @extends BasePolyline
8
8
  */
9
9
  export class Polyline extends BasePolyline {
10
+ static type = 'Polyline';
11
+
10
12
  /**
11
13
  * Create a Polyline
12
14
  * @param {Array} data
@@ -12,6 +12,8 @@ import { DesignCore } from '../designCore.js';
12
12
  * @extends Entity
13
13
  */
14
14
  export class Rectangle extends Entity {
15
+ static type = 'Rectangle';
16
+
15
17
  /**
16
18
  * Create a Rectangle
17
19
  * @param {Array} data
@@ -7,6 +7,8 @@ import { BoundingBox } from '../lib/boundingBox.js';
7
7
  * @extends Entity
8
8
  */
9
9
  export class Solid extends Entity {
10
+ static type = 'Solid';
11
+
10
12
  /**
11
13
  * Create a Solid Entity
12
14
  * @param {Array} data
@@ -10,12 +10,15 @@ import { Flags } from '../properties/flags.js';
10
10
  import { Property } from '../properties/property.js';
11
11
 
12
12
  import { DesignCore } from '../designCore.js';
13
+ import { SnapPoint } from '../lib/snapping.js';
13
14
 
14
15
  /**
15
16
  * Text Entity Class
16
17
  * @extends Entity
17
18
  */
18
19
  export class Text extends Entity {
20
+ static type = 'Text';
21
+
19
22
  /**
20
23
  * Create a Text Entity
21
24
  * @param {Array} data
@@ -506,15 +509,9 @@ export class Text extends Entity {
506
509
  * @return {Array} - array of snap points
507
510
  */
508
511
  snaps(mousePoint, delta) {
509
- const frameCorners = this.getTextFrameCorners();
510
- const mid = frameCorners[0].midPoint(frameCorners[2]);
511
- const snaps = [...frameCorners, mid];
512
+ const snaps = [];
512
513
 
513
- // add insertion point if not already in snaps
514
- // this adds an extra snap point when alignment != 0.
515
- if (!snaps.some((point) => point.isSame(this.points[0]))) {
516
- snaps.push(this.points[0]);
517
- }
514
+ snaps.push(new SnapPoint(this.points[0], SnapPoint.Type.NODE));
518
515
 
519
516
  return snaps;
520
517
  }
package/core/lib/input.js CHANGED
@@ -1,8 +1,12 @@
1
1
  /** Sentinel resolved when a MOUSEDOWN prompt completes */
2
- export class MouseDown {}
2
+ export class MouseDown {
3
+ static type = 'MouseDown';
4
+ }
3
5
 
4
6
  /** Sentinel resolved when a MOUSEUP prompt completes */
5
- export class MouseUp {}
7
+ export class MouseUp {
8
+ static type = 'MouseUp';
9
+ }
6
10
 
7
11
  /** Input Class */
8
12
  export class Input {
@@ -16,7 +20,7 @@ export class Input {
16
20
  /**
17
21
  * Input type definitions.
18
22
  * Each entry describes an accepted input type:
19
- * value — matches value.constructor.name for runtime type detection via getType()
23
+ * value — matched against value.constructor.type (if defined) or value.constructor.name for runtime type detection via getType()
20
24
  * cursor — the cursor state to apply when this type is requested (null = DEFAULT)
21
25
  */
22
26
  static Type = {
@@ -40,7 +44,7 @@ export class Input {
40
44
  return undefined;
41
45
  }
42
46
 
43
- const name = value.constructor.name;
47
+ const name = value.constructor.type ?? value.constructor.name;
44
48
  return Object.values(Input.Type).find((t) => t.value === name);
45
49
  }
46
50
  }
@@ -29,7 +29,7 @@ export class InputManager {
29
29
  * Reset the inputManager
30
30
  */
31
31
  reset() {
32
- this.snapping.active = false;
32
+ this.snapping.reset();
33
33
  this.inputPoint = null;
34
34
  DesignCore.CommandLine.resetPrompt();
35
35
  this.activeCommand = undefined;
@@ -80,7 +80,7 @@ export class InputManager {
80
80
  this.inputPoint = input;
81
81
  }
82
82
 
83
- this.snapping.active = false;
83
+ this.snapping.reset();
84
84
  return input;
85
85
  });
86
86
  }
@@ -213,7 +213,6 @@ export class InputManager {
213
213
  const selection = DesignCore.Scene.selectionManager.singleSelect(DesignCore.Mouse.pointOnScene());
214
214
  this.onSelection(selection);
215
215
  } else if (this.promptOption !== undefined && this.promptOption.types.includes(Input.Type.POINT)) {
216
- this.snapping.active = false;
217
216
  this.promptOption.respond(point);
218
217
  }
219
218
  }
@@ -294,8 +293,7 @@ export class InputManager {
294
293
  * Handle single selection
295
294
  */
296
295
  singleSelect() {
297
- this.inputPoint = DesignCore.Mouse.pointOnScene();
298
- this.onLeftClick(this.inputPoint);
296
+ this.onLeftClick(DesignCore.Mouse.pointOnScene());
299
297
  }
300
298
 
301
299
  /**
@@ -5,6 +5,8 @@ import { DesignCore } from '../designCore.js';
5
5
 
6
6
  /** SingleSelection Class */
7
7
  export class SingleSelection {
8
+ static type = 'SingleSelection';
9
+
8
10
  /**
9
11
  * Create a SingleSelection
10
12
  * @param {number} index
@@ -18,6 +20,8 @@ export class SingleSelection {
18
20
 
19
21
  /** SelectionSet Class */
20
22
  export class SelectionSet {
23
+ static type = 'SelectionSet';
24
+
21
25
  /** Create SelectionSet */
22
26
  constructor() {
23
27
  this.accepted = false;
@@ -5,11 +5,10 @@ export class Settings {
5
5
  /** Create Setting */
6
6
  constructor() {
7
7
  this.canvasbackgroundcolour = { r: 30, g: 30, b: 30 };
8
- this.selecteditemscolour = { r: 0, g: 255, b: 0 };
9
- this.snapcolour = { r: 255, g: 0, b: 0 };
10
8
  this.gridcolour = { r: 119, g: 118, b: 123 };
11
- this.helpergeometrycolour = { r: 0, g: 195, b: 255 };
12
- this.polarsnapcolour = { r: 55, g: 180, b: 75 };
9
+ this.selecteditemscolour = { r: 0, g: 255, b: 0 };
10
+ this.snaptrackingcolour = { r: 55, g: 180, b: 75 };
11
+ // selectionWindow and crossingWindow colours
13
12
  this.selectionWindow = { r: 0, g: 255, b: 0 };
14
13
  this.crossingWindow = { r: 0, g: 0, b: 255 };
15
14
  // fontSettings
@@ -22,9 +21,14 @@ export class Settings {
22
21
  this.centresnap = true;
23
22
  this.nearestsnap = false;
24
23
  this.quadrantsnap = false;
25
- this.polarangle = 45;
24
+ this.tangentsnap = false;
25
+ this.nodesnap = false;
26
+ this.perpendicularsnap = false;
27
+ // trackingSettings
26
28
  this.polar = true;
29
+ this.polarangle = 45;
27
30
  this.ortho = false;
31
+ // gridSettings
28
32
  this.drawgrid = true;
29
33
  }
30
34