@design-core/core 0.0.6 → 0.0.7

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 (145) hide show
  1. package/.eslintrc.json +4 -0
  2. package/TODO.md +49 -6
  3. package/core/core/core.js +0 -3
  4. package/core/dimensions/alignedDimension.js +5 -4
  5. package/core/dimensions/angularDimension.js +6 -5
  6. package/core/dimensions/baseCircularDimension.js +3 -2
  7. package/core/dimensions/baseDimension.js +59 -93
  8. package/core/dimensions/baseLinearDimension.js +6 -5
  9. package/core/dimensions/diametricDimension.js +4 -3
  10. package/core/dimensions/dimension.js +21 -14
  11. package/core/dimensions/radialDimension.js +4 -3
  12. package/core/dimensions/rotatedDimension.js +12 -11
  13. package/core/entities/arc.js +112 -145
  14. package/core/entities/arctext.js +212 -174
  15. package/core/entities/basePolyline.js +30 -282
  16. package/core/entities/circle.js +77 -99
  17. package/core/entities/entity.js +114 -93
  18. package/core/entities/hatch.js +322 -249
  19. package/core/entities/insert.js +66 -81
  20. package/core/entities/line.js +21 -142
  21. package/core/entities/lwpolyline.js +16 -11
  22. package/core/entities/polyline.js +4 -4
  23. package/core/entities/rectangle.js +3 -1
  24. package/core/entities/solid.js +6 -15
  25. package/core/entities/text.js +188 -199
  26. package/core/lib/auxiliary/rubberBand.js +32 -0
  27. package/core/lib/auxiliary/selectionWindow.js +63 -0
  28. package/core/lib/auxiliary/snapPoint.js +113 -0
  29. package/core/lib/auxiliary/trackingLine.js +76 -0
  30. package/core/lib/canvas.js +228 -166
  31. package/core/lib/clipboard.js +7 -1
  32. package/core/lib/colour.js +16 -0
  33. package/core/lib/commandLine.js +1 -6
  34. package/core/lib/commandManager.js +18 -8
  35. package/core/lib/constants.js +28 -0
  36. package/core/lib/dxf/dxf.js +4 -3
  37. package/core/lib/entityManager.js +18 -11
  38. package/core/lib/inputManager.js +35 -11
  39. package/core/lib/intersect.js +25 -0
  40. package/core/lib/patterns.js +8 -1
  41. package/core/lib/plotOptions.js +67 -0
  42. package/core/lib/polylineUtils.js +75 -0
  43. package/core/lib/renderers/cairoRenderer.js +371 -0
  44. package/core/lib/renderers/canvasRenderer.js +315 -0
  45. package/core/lib/renderers/pdfRenderer.js +366 -0
  46. package/core/lib/renderers/rendererBase.js +284 -0
  47. package/core/lib/renderers/svgRenderer.js +343 -0
  48. package/core/lib/scene.js +27 -5
  49. package/core/lib/selectionManager.js +2 -2
  50. package/core/lib/settings.js +4 -2
  51. package/core/lib/snapping.js +4 -191
  52. package/core/lib/stateManager.js +30 -1
  53. package/core/lib/utils.js +21 -2
  54. package/core/properties/entityProperties.js +104 -0
  55. package/core/properties/property.js +106 -2
  56. package/core/properties/propertyManager.js +29 -13
  57. package/core/tables/block.js +4 -37
  58. package/core/tables/endblk.js +1 -1
  59. package/core/tables/layer.js +8 -0
  60. package/core/tables/styleManagerBase.js +3 -2
  61. package/core/tables/tableManagerBase.js +8 -3
  62. package/core/tools/chamfer.js +111 -137
  63. package/core/tools/chamferFilletBase.js +135 -34
  64. package/core/tools/copy.js +3 -3
  65. package/core/tools/explode.js +2 -2
  66. package/core/tools/extend.js +132 -19
  67. package/core/tools/fillet.js +86 -183
  68. package/core/tools/matchProp.js +2 -11
  69. package/core/tools/mirror.js +7 -6
  70. package/core/tools/move.js +3 -3
  71. package/core/tools/offset.js +3 -5
  72. package/core/tools/pasteclip.js +1 -1
  73. package/core/tools/rotate.js +6 -3
  74. package/core/tools/scale.js +1 -1
  75. package/core/tools/trim.js +265 -23
  76. package/core/tools/zoom.js +1 -1
  77. package/jest.config.js +6 -0
  78. package/package.json +5 -3
  79. package/test/dimensions/alignedDimension.test.js +14 -7
  80. package/test/dimensions/angularDimension.test.js +6 -6
  81. package/test/dimensions/baseDimension.test.js +69 -8
  82. package/test/dimensions/baseLinearDimension.test.js +62 -0
  83. package/test/dimensions/diametricDimension.test.js +6 -6
  84. package/test/dimensions/radialDimension.test.js +6 -6
  85. package/test/dimensions/rotatedDimension.test.js +14 -7
  86. package/test/entities/arc.test.js +80 -83
  87. package/test/entities/arctext.test.js +180 -53
  88. package/test/entities/basePolyline.test.js +68 -2
  89. package/test/entities/circle.test.js +57 -85
  90. package/test/entities/entity.test.js +42 -8
  91. package/test/entities/hatch.test.js +543 -70
  92. package/test/entities/insert.test.js +96 -1
  93. package/test/entities/line.test.js +15 -41
  94. package/test/entities/lwpolyline.test.js +104 -0
  95. package/test/entities/polyline.test.js +11 -0
  96. package/test/entities/rectangle.test.js +11 -0
  97. package/test/entities/solid.test.js +1 -1
  98. package/test/entities/text.test.js +294 -69
  99. package/test/integration/exportIntegration.reference.dxf +9 -9
  100. package/test/integration/exportIntegration.test.js +2 -2
  101. package/test/integration/intersectionIntegration.test.js +4 -5
  102. package/test/integration/pdfRendererIntegration.reference.pdf +17709 -0
  103. package/test/integration/pdfRendererIntegration.test.js +61 -0
  104. package/test/integration/svgRendererIntegration.reference.svg +3343 -0
  105. package/test/integration/svgRendererIntegration.test.js +61 -0
  106. package/test/integration/userInputIntegration.reference.dxf +1165 -105
  107. package/test/integration/userInputIntegration.test.js +239 -132
  108. package/test/lib/canvas.test.js +742 -123
  109. package/test/lib/constants.test.js +27 -0
  110. package/test/lib/entityManager.test.js +4 -4
  111. package/test/lib/inputManager.test.js +80 -19
  112. package/test/lib/intersect.test.js +83 -0
  113. package/test/lib/plotOptions.test.js +179 -0
  114. package/test/lib/rubberBand.test.js +84 -0
  115. package/test/lib/settings.test.js +5 -6
  116. package/test/lib/snapping.test.js +71 -129
  117. package/test/lib/stateManager.test.js +7 -7
  118. package/test/lib/utils.test.js +36 -2
  119. package/test/properties/entityProperties.test.js +132 -0
  120. package/test/properties/property.test.js +53 -0
  121. package/test/properties/propertyManager.test.js +3 -3
  122. package/test/renderers/canvasRenderer.test.js +317 -0
  123. package/test/renderers/pdfRenderer.test.js +271 -0
  124. package/test/renderers/rendererBase.test.js +213 -0
  125. package/test/renderers/svgRenderer.test.js +326 -0
  126. package/test/tables/block.test.js +31 -1
  127. package/test/tables/endblk.test.js +2 -2
  128. package/test/tables/layer.test.js +30 -0
  129. package/test/test-helpers/hatchGridRenderer.js +180 -0
  130. package/test/test-helpers/test-helpers.js +152 -0
  131. package/test/tools/chamfer.test.js +227 -5
  132. package/test/tools/chamferFilletBase.test.js +98 -9
  133. package/test/tools/copy.test.js +2 -2
  134. package/test/tools/explode.test.js +3 -3
  135. package/test/tools/extend.test.js +331 -0
  136. package/test/tools/fillet.test.js +181 -0
  137. package/test/tools/matchProp.test.js +5 -5
  138. package/test/tools/mirror.test.js +13 -13
  139. package/test/tools/offset.test.js +170 -3
  140. package/test/tools/pasteclip.test.js +5 -5
  141. package/test/tools/rotate.test.js +32 -2
  142. package/test/tools/scale.test.js +5 -5
  143. package/test/tools/trim.test.js +526 -0
  144. package/test/tools/zoom.test.js +7 -7
  145. package/core/lib/selectionWindow.js +0 -83
package/.eslintrc.json CHANGED
@@ -9,10 +9,14 @@
9
9
  "ecmaVersion": "latest",
10
10
  "sourceType": "module"
11
11
  },
12
+ "plugins": [
13
+ "import"
14
+ ],
12
15
  "rules": {
13
16
  "require-jsdoc": 2,
14
17
  "valid-jsdoc": 2,
15
18
  "max-len": 0,
19
+ "import/first": "error",
16
20
  "function-paren-newline": "warn",
17
21
  "object-curly-spacing": [
18
22
  "error",
package/TODO.md CHANGED
@@ -1,12 +1,6 @@
1
1
  # Design-Core TODO list
2
2
 
3
3
  ## Beta
4
- ### UNDO / REDO
5
-
6
- ### Printing
7
-
8
- ### Export PDF
9
-
10
4
  ### Paperspace
11
5
 
12
6
  ### Entity Editing
@@ -17,3 +11,52 @@
17
11
  - Radial Dimension
18
12
  - Diametric Dimension
19
13
 
14
+ ### Text sizing
15
+ - Text size - need a non-hacky glyph-advance measuring API on each the renderer
16
+ - ArcAlignedText characterSpacing=0 overlap — Cairo's cap-height correction scales glyph advances wider than getApproximateWidth predicts;
17
+
18
+ ### performance optimisation
19
+
20
+ #### 1. `LType.getPattern(scale)` — cache the scaled array (easy)
21
+ Called once per entity per frame. Currently allocates a new array every call via `.map()`.
22
+ A two-field cache (`#lastScale`, `#cachedPattern`) returns the existing array when scale hasn't changed.
23
+
24
+ - **Effort**: ~10 lines, isolated to `ltype.js`
25
+ - **Expected gain**: small but consistent; removes N allocations per frame where N = entity count
26
+
27
+ #### 2. State dedup in renderers — skip no-op `setColour`/`setLineWidth`/`setDash` calls (medium)
28
+ `setContext` is called unconditionally for every entity. For entities sharing colour and line width (the common case), the underlying Canvas/Cairo API calls are redundant.
29
+ Track the last-set value in each renderer and return early when unchanged.
30
+
31
+ - **Effort**: ~20 lines per renderer, self-contained
32
+ - **Expected gain**: meaningful for large scenes with many same-layer entities; could save 10–30% of state-setting overhead
33
+
34
+ #### 3. Skip `save()`/`restore()` for leaf entities (medium)
35
+ `#paintEntity` wraps every entity in `save()`/`restore()` even though only container entities (Insert, BaseDimension) actually change the transform. Requires an `entity.isContainer` flag or restructuring to save lazily.
36
+
37
+ - **Effort**: entity API change + `#paintEntity` refactor
38
+ - **Expected gain**: ~1 `save`/`restore` pair eliminated per leaf entity per frame; measurable at high entity counts
39
+
40
+ #### 4. Offscreen canvas for static scene (large, architectural)
41
+ The full scene repaints on every mouse move (hover detection, rubber band, cursor). Splitting into a static layer (repaint on data change only) and a dynamic overlay (hover, preview, selection) would eliminate most per-frame work.
42
+
43
+ - **Effort**: significant — touches `canvas.js`, rendering pipeline, and UI integration
44
+ - **Expected gain**: potentially 3–5× frame rate improvement during mouse movement over a complex scene
45
+
46
+ #### 5. Viewport culling — skip entities outside the visible area (medium, high impact when zoomed in)
47
+ Every entity already has `boundingBox()` and `canvas.getSceneOffset()` returns the visible scene rectangle.
48
+ A simple AABB overlap test in `#paintEntities` would skip entities outside the viewport before calling `#paintEntity`.
49
+
50
+ - **Effort**: ~10 lines in `#paintEntities`; call `getSceneOffset()` once per `paint()` and pass it in
51
+
52
+ - **Caveat — bounding box caching**: `Hatch.boundingBox()` and `Block.boundingBox()` iterate all child entities on every call. Per-frame culling cost could exceed draw cost for those types unless bboxes are cached on the entity and invalidated on edit. Simple entity types (Line, Circle, Arc) have trivial bbox cost and benefit immediately.
53
+
54
+ - **Caveat — Text**: `Text.boundingBox()` depends on `boundingRect` which is only populated after the first `draw()` call — needs a fallback to avoid incorrectly culling undrawn text.
55
+
56
+ - **Expected gain**: negligible when fully zoomed out; potentially 5–50× reduction in draw calls when working zoomed into a small area of a large drawing
57
+
58
+ ### Test clean up
59
+ - Have the renderer changes provided any opportunity to clean up tests
60
+ - Is there opportunity for extended testing with the mock renderer
61
+
62
+
package/core/core/core.js CHANGED
@@ -24,9 +24,6 @@ import { Logging } from '../lib/logging.js';
24
24
 
25
25
  import { DesignCore } from '../designCore.js';
26
26
 
27
- // re-export core components for external use
28
- export { Patterns } from '../lib/patterns.js';
29
-
30
27
  /** Class representing design core. This is the primary entry point */
31
28
  export class Core {
32
29
  /** Create a core object */
@@ -7,6 +7,7 @@ import { Point } from '../entities/point.js';
7
7
  import { BaseLinearDimension } from './baseLinearDimension.js';
8
8
 
9
9
  import { DesignCore } from '../designCore.js';
10
+ import { Property } from '../properties/property.js';
10
11
 
11
12
 
12
13
  /**
@@ -42,7 +43,7 @@ export class AlignedDimension extends BaseLinearDimension {
42
43
  async execute() {
43
44
  try {
44
45
  DesignCore.Scene.selectionManager.reset();
45
- this.dimensionStyle = DesignCore.DimStyleManager.getCstyle();
46
+ this.setProperty(Property.Names.DIMENSIONSTYLE, DesignCore.DimStyleManager.getCstyle());
46
47
  this.dimType.setDimType(1); // Aligned dimension
47
48
 
48
49
  const op = new PromptOptions(Strings.Input.START, [Input.Type.POINT]);
@@ -118,10 +119,10 @@ export class AlignedDimension extends BaseLinearDimension {
118
119
  const Pt14 = this.getPointBySequence(this.points, 14);
119
120
 
120
121
  file.writeGroupCode('0', 'DIMENSION');
121
- file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
122
+ file.writeGroupCode('5', this.getProperty(Property.Names.HANDLE), DXFFile.Version.R2000); // Handle
122
123
  file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
123
124
  file.writeGroupCode('100', 'AcDbDimension', DXFFile.Version.R2000);
124
- file.writeGroupCode('8', this.layer);
125
+ file.writeGroupCode('8', this.getProperty(Property.Names.LAYER));
125
126
  // file.writeGroupCode('2', this.blockName); // Block not required
126
127
  file.writeGroupCode('10', Pt10.x); // X - definition / arrow point
127
128
  file.writeGroupCode('20', Pt10.y); // Y
@@ -130,7 +131,7 @@ export class AlignedDimension extends BaseLinearDimension {
130
131
  file.writeGroupCode('21', Pt11.y); // Y
131
132
  file.writeGroupCode('31', '0.0'); // Z
132
133
  file.writeGroupCode('70', this.dimType.getDimType()); // DIMENSION TYPE
133
- file.writeGroupCode('3', this.dimensionStyle); // DIMENSION STYLE
134
+ file.writeGroupCode('3', this.getProperty(Property.Names.DIMENSIONSTYLE)); // DIMENSION STYLE
134
135
  file.writeGroupCode('100', 'AcDbAlignedDimension', DXFFile.Version.R2000);
135
136
  file.writeGroupCode('13', Pt13.x); // X - start point of first extension line
136
137
  file.writeGroupCode('23', Pt13.y); // Y
@@ -14,6 +14,7 @@ import { Point } from '../entities/point.js';
14
14
  import { Text } from '../entities/text.js'; // used to debug the dimension points
15
15
 
16
16
  import { DesignCore } from '../designCore.js';
17
+ import { Property } from '../properties/property.js';
17
18
 
18
19
  /**
19
20
  * Angular Dimension Entity Class
@@ -47,7 +48,7 @@ export class AngularDimension extends BaseDimension {
47
48
  */
48
49
  async execute() {
49
50
  try {
50
- this.dimensionStyle = DesignCore.DimStyleManager.getCstyle();
51
+ this.setProperty(Property.Names.DIMENSIONSTYLE, DesignCore.DimStyleManager.getCstyle());
51
52
  this.dimType.setDimType(2); // Angular dimension
52
53
 
53
54
  let Pt10;
@@ -146,7 +147,7 @@ export class AngularDimension extends BaseDimension {
146
147
 
147
148
  const points = AngularDimension.getPointsFromSelection([tempLineOne, tempLineTwo], Pt11);
148
149
 
149
- DesignCore.Scene.tempEntities.create(this.type, { points: points, dimensionStyle: this.dimensionStyle });
150
+ DesignCore.Scene.previewEntities.create(this.type, { points: points, dimensionStyle: this.getProperty(Property.Names.DIMENSIONSTYLE) });
150
151
  }
151
152
  }
152
153
 
@@ -520,10 +521,10 @@ export class AngularDimension extends BaseDimension {
520
521
  const Pt16 = this.getPointBySequence(this.points, 16);
521
522
 
522
523
  file.writeGroupCode('0', 'DIMENSION');
523
- file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
524
+ file.writeGroupCode('5', this.getProperty(Property.Names.HANDLE), DXFFile.Version.R2000); // Handle
524
525
  file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
525
526
  file.writeGroupCode('100', 'AcDbDimension', DXFFile.Version.R2000);
526
- file.writeGroupCode('8', this.layer);
527
+ file.writeGroupCode('8', this.getProperty(Property.Names.LAYER));
527
528
  // file.writeGroupCode('2', this.blockName); // Block not required
528
529
  file.writeGroupCode('10', Pt10.x); // X - Start of Dimension Line
529
530
  file.writeGroupCode('20', Pt10.y); // Y
@@ -532,7 +533,7 @@ export class AngularDimension extends BaseDimension {
532
533
  file.writeGroupCode('21', Pt11.y); // Y
533
534
  file.writeGroupCode('31', '0.0'); // Z
534
535
  file.writeGroupCode('70', this.dimType.getDimType()); // DIMENSION TYPE
535
- file.writeGroupCode('3', this.dimensionStyle); // DIMENSION STYLE
536
+ file.writeGroupCode('3', this.getProperty(Property.Names.DIMENSIONSTYLE)); // DIMENSION STYLE
536
537
  file.writeGroupCode('100', 'AcDb2LineAngularDimension', DXFFile.Version.R2000);
537
538
  file.writeGroupCode('13', Pt13.x); // X
538
539
  file.writeGroupCode('23', Pt13.y); // Y
@@ -11,6 +11,7 @@ import { Logging } from '../lib/logging.js';
11
11
  import { BaseDimension } from './baseDimension.js';
12
12
 
13
13
  import { DesignCore } from '../designCore.js';
14
+ import { Property } from '../properties/property.js';
14
15
 
15
16
 
16
17
  /**
@@ -32,7 +33,7 @@ export class BaseCircularDimension extends BaseDimension {
32
33
  */
33
34
  async execute() {
34
35
  try {
35
- this.dimensionStyle = DesignCore.DimStyleManager.getCstyle();
36
+ this.setProperty(Property.Names.DIMENSIONSTYLE, DesignCore.DimStyleManager.getCstyle());
36
37
 
37
38
  let Pt10;
38
39
  let Pt15;
@@ -96,7 +97,7 @@ export class BaseCircularDimension extends BaseDimension {
96
97
  const tempCircle = new Circle({ points: [Pt10, Pt15] });
97
98
  const points = this.constructor.getPointsFromSelection([tempCircle], Pt11);
98
99
 
99
- DesignCore.Scene.tempEntities.create(this.type, { points: points });
100
+ DesignCore.Scene.previewEntities.create(this.type, { points: points });
100
101
  }
101
102
  }
102
103
 
@@ -24,91 +24,67 @@ export class BaseDimension extends Entity {
24
24
  constructor(data) {
25
25
  super(data);
26
26
 
27
- // hide inherited property
28
- // needs to be enumerable=false to not appear in the object props
29
- Object.defineProperty(this, 'lineType', {
30
- enumerable: false,
27
+ // lineType and lineWidth not applicable to dimensions
28
+ this.properties.remove(Property.Names.LINETYPE);
29
+ this.properties.remove(Property.Names.LINEWIDTH);
30
+
31
+ // DXF Groupcode 1 - Dimension text override
32
+ this.properties.add(Property.Names.TEXTOVERRIDE, {
33
+ type: Property.Type.STRING,
34
+ value: Property.loadValue([data?.[1], data?.textOverride], ''),
35
+ dxfCode: 1,
31
36
  });
32
37
 
33
- // hide inherited property
34
- Object.defineProperty(this, 'lineWidth', {
35
- enumerable: false,
38
+ // DXF Groupcode 2 - Block name
39
+ this.properties.add(Property.Names.BLOCKNAME, {
40
+ type: Property.Type.STRING,
41
+ value: Property.loadValue([data?.blockName, data?.[2]], ''),
42
+ dxfCode: 2,
43
+ visible: false,
36
44
  });
37
45
 
38
- Object.defineProperty(this, 'blockName', {
39
- value: '',
40
- writable: true,
41
- });
42
-
43
- Object.defineProperty(this, 'block', {
44
- value: new Block({ points: [new Point(), new Point()] }),
45
- writable: true,
46
- });
47
-
48
- /*
49
- Object.defineProperty(this, 'text', {
50
- value: new Text(),
51
- writable: true,
46
+ // DXF Groupcode 3 - Dimension Style Name
47
+ this.properties.add(Property.Names.DIMENSIONSTYLE, {
48
+ type: Property.Type.LIST,
49
+ value: Property.loadValue([data?.dimensionStyle, data?.[3]], 'STANDARD'),
50
+ dxfCode: 3,
52
51
  });
53
- */
54
52
 
55
- Object.defineProperty(this, 'textOverride', {
56
- value: '',
57
- writable: true,
58
- enumerable: true,
53
+ // DXF Groupcode 40 - Leader length for radius and diameter dimensions
54
+ this.properties.add(Property.Names.LEADERLENGTH, {
55
+ type: Property.Type.NUMBER,
56
+ value: Property.loadValue([data?.[40], data?.leaderLength], 0),
57
+ dxfCode: 40,
58
+ visible: false,
59
59
  });
60
60
 
61
- Object.defineProperty(this, 'dimType', {
62
- value: new DimType(),
63
- writable: true,
61
+ // DXF Groupcode 50 - Angle of rotated, horizontal, or vertical dimensions
62
+ this.properties.add(Property.Names.LINEARDIMANGLE, {
63
+ type: Property.Type.NUMBER,
64
+ value: Property.loadValue([data?.[50], data?.linearDimAngle], 0),
65
+ dxfCode: 50,
66
+ visible: false,
64
67
  });
65
68
 
66
- Object.defineProperty(this, 'dimensionStyle', {
67
- value: 'STANDARD',
68
- writable: true,
69
- enumerable: true,
69
+ // DXF Groupcode 53 - Rotation angle of dimension text away from default orientation
70
+ this.properties.add(Property.Names.ANGLE, {
71
+ type: Property.Type.NUMBER,
72
+ value: Property.loadValue([data?.[53], data?.angle], 0),
73
+ dxfCode: 53,
74
+ visible: false,
70
75
  });
71
76
 
72
- Object.defineProperty(this, 'leaderLength', {
73
- value: 0,
77
+ Object.defineProperty(this, 'block', {
78
+ value: new Block({ points: [new Point(), new Point()] }),
74
79
  writable: true,
75
80
  });
76
81
 
77
- Object.defineProperty(this, 'linearDimAngle', {
78
- value: 0,
82
+ Object.defineProperty(this, 'dimType', {
83
+ value: new DimType(),
79
84
  writable: true,
80
85
  });
81
86
 
82
87
  if (data) {
83
- if (data.hasOwnProperty('1')) {
84
- // DXF Groupcode 1 - Dimension text
85
- // The string explicitly entered by the user.
86
- // Optional; default is the measurement. If null or “<>”, the dimension measurement is drawn as the text,
87
- // if ““ (one blank space), the text is suppressed. Anything else is drawn as the text
88
- this.textOverride = Property.loadValue([data[1], data.textOverride], '');
89
- }
90
-
91
- /*
92
- if (data.hasOwnProperty('block')) {
93
- // Reference to block that contains the entities that make up this dimension
94
- this.block = data.block;
95
- }*/
96
-
97
- if (data.hasOwnProperty('blockName') || data.hasOwnProperty('2')) {
98
- // DXF Groupcode 2 - Blockname
99
- this.blockName = Property.loadValue([data.blockName, data[2]], '');
100
- }
101
-
102
- if (data.hasOwnProperty('dimensionStyle') || data.hasOwnProperty('3')) {
103
- // DXF Groupcode 3 - Dimension Style Name
104
- this.dimensionStyle = Property.loadValue([data.dimensionStyle, data[3]], 'STANDARD');
105
- }
106
-
107
- if (data.hasOwnProperty('40')) {
108
- // DXF Groupcode 40 - Leader length for radius and diameter dimensions
109
- this.leaderLength = data[40];
110
- }
111
-
112
88
  if (data.hasOwnProperty('41')) {
113
89
  // DXF Groupcode 41 - Line Spacing Factor
114
90
  // Percentage of default (3-on-5) line spacing to be applied.
@@ -124,11 +100,6 @@ export class BaseDimension extends Entity {
124
100
  Logging.instance.debug(`${this.type} - ${err}`);
125
101
  }
126
102
 
127
- if (data.hasOwnProperty('50')) {
128
- // DXF Groupcode 50 - Angle of rotated, horizontal, or vertical dimensions
129
- this.linearDimAngle = Property.loadValue([data[50]], 0);
130
- }
131
-
132
103
  if (data.hasOwnProperty('51')) {
133
104
  // DXF Groupcode 51 - Horizontal Direction
134
105
  // All dimension types have an optional 51 group code, which indicates the horizontal direction
@@ -140,12 +111,6 @@ export class BaseDimension extends Entity {
140
111
  Logging.instance.warn(`${this.type} - ${err}`);
141
112
  }
142
113
 
143
- if (data.hasOwnProperty('angle') || data.hasOwnProperty('53')) {
144
- // DXF Groupcode 53 - Rotation
145
- // rotation angle of the dimension text away from its default orientation
146
- this.angle = Property.loadValue([data.angle, data[53]], 0);
147
- }
148
-
149
114
  if (data.hasOwnProperty('dimType') || data.hasOwnProperty('70')) {
150
115
  // DXF Groupcode 70 - Dimension Type
151
116
  // Values 0-6 are integer values that represent the dimension type. Values 32, 64, and 128
@@ -197,10 +162,6 @@ export class BaseDimension extends Entity {
197
162
  const err = 'Groupcode 72 not implemented';
198
163
  Logging.instance.debug(`${this.type} - ${err}`);
199
164
  }
200
-
201
- if (data.leaderLength) {
202
- this.leaderLength = data.leaderLength;
203
- }
204
165
  }
205
166
  }
206
167
 
@@ -280,8 +241,9 @@ export class BaseDimension extends Entity {
280
241
  }
281
242
 
282
243
  // Handle textOverride
283
- if (this.textOverride !== '') {
284
- formattedDimensionValue = this.textOverride.replace(/<>/g, formattedDimensionValue);
244
+ const textOverride = this.getProperty(Property.Names.TEXTOVERRIDE);
245
+ if (textOverride !== '') {
246
+ formattedDimensionValue = textOverride.replace(/<>/g, formattedDimensionValue);
285
247
  }
286
248
 
287
249
  // TODO: Implement prefix and postsuffix - DIMPOST
@@ -338,13 +300,13 @@ export class BaseDimension extends Entity {
338
300
  // get the text height
339
301
  const textHeight = this.getDimensionStyle().getValue('DIMTXT');
340
302
  // set the text height
341
- text.height = textHeight;
303
+ text.setProperty(Property.Names.HEIGHT, textHeight);
342
304
  // Always set text horizontal alignment to center
343
- text.horizontalAlignment = 1;
305
+ text.setProperty(Property.Names.HORIZONTALALIGNMENT, 1);
344
306
  // Always set text vertical alignment to middle
345
- text.verticalAlignment = 2;
307
+ text.setProperty(Property.Names.VERTICALALIGNMENT, 2);
346
308
  // set the text value
347
- text.string = this.getDimensionValue(textValue);
309
+ text.setProperty(Property.Names.STRING, this.getDimensionValue(textValue));
348
310
  // set the text position
349
311
  text.points = [textPosition];
350
312
  // set the text rotation
@@ -385,7 +347,7 @@ export class BaseDimension extends Entity {
385
347
  * @return {Object} - the dimension style object
386
348
  */
387
349
  getDimensionStyle() {
388
- return DesignCore.DimStyleManager.getItemByName(this.dimensionStyle);
350
+ return DesignCore.DimStyleManager.getItemByName(this.getProperty(Property.Names.DIMENSIONSTYLE));
389
351
  }
390
352
 
391
353
  /**
@@ -470,15 +432,15 @@ export class BaseDimension extends Entity {
470
432
 
471
433
  /**
472
434
  * Draw the entity
473
- * @param {Object} ctx - context
474
- * @param {number} scale
435
+ * @param {Object} renderer
436
+ * @return {Array} block items for the canvas to render recursively
475
437
  */
476
- draw(ctx, scale) {
438
+ draw(renderer) {
477
439
  if (this.block.items.length === 0) {
478
440
  this.refresh();
479
441
  }
480
442
 
481
- this.block.draw(ctx, scale, this);
443
+ return this.block.items;
482
444
  }
483
445
 
484
446
  /**
@@ -538,7 +500,7 @@ export class BaseDimension extends Entity {
538
500
 
539
501
  entities.forEach((element) => {
540
502
  // For colour BYBLOCK for dimensions
541
- element.setColour('BYBLOCK');
503
+ element.setProperty(Property.Names.COLOUR, 'BYBLOCK');
542
504
  this.block.addItem(element);
543
505
  });
544
506
  }
@@ -550,6 +512,10 @@ export class BaseDimension extends Entity {
550
512
  * @param {any} value
551
513
  */
552
514
  setProperty(property, value) {
515
+ if (this.properties.has(property)) {
516
+ super.setProperty(property, value);
517
+ return;
518
+ }
553
519
  if (this.hasOwnProperty(property)) {
554
520
  this[property] = value;
555
521
  this.refresh();
@@ -7,7 +7,9 @@ import { BaseDimension } from './baseDimension.js';
7
7
  import { Point } from '../entities/point.js';
8
8
 
9
9
  import { DesignCore } from '../designCore.js';
10
+ import { Property } from '../properties/property.js';
10
11
  import { Utils } from '../lib/utils.js';
12
+ import { RubberBand } from '../lib/auxiliary/rubberBand.js';
11
13
 
12
14
  /**
13
15
  * Aligned Dimension Entity Class
@@ -29,7 +31,7 @@ export class BaseLinearDimension extends BaseDimension {
29
31
  async execute() {
30
32
  try {
31
33
  DesignCore.Scene.selectionManager.reset();
32
- this.dimensionStyle = DesignCore.DimStyleManager.getCstyle();
34
+ this.setProperty(Property.Names.DIMENSIONSTYLE, DesignCore.DimStyleManager.getCstyle());
33
35
  this.dimType.setDimType(0); // Rotated dimension
34
36
 
35
37
  const op = new PromptOptions(Strings.Input.START, [Input.Type.POINT]);
@@ -62,8 +64,7 @@ export class BaseLinearDimension extends BaseDimension {
62
64
  preview() {
63
65
  if (this.points.length == 1) {
64
66
  const mousePoint = DesignCore.Mouse.pointOnScene();
65
- const points = [this.points.at(0), mousePoint];
66
- DesignCore.Scene.tempEntities.create('Line', { points: points });
67
+ DesignCore.Scene.auxiliaryEntities.add(new RubberBand([this.points.at(0), mousePoint]));
67
68
  }
68
69
 
69
70
  if (this.points.length > 1) {
@@ -71,7 +72,7 @@ export class BaseLinearDimension extends BaseDimension {
71
72
  pt11.sequence = 11;
72
73
  const tempLine = new Line({ points: [...this.points] });
73
74
  const points = this.constructor.getPointsFromSelection([tempLine], pt11);
74
- DesignCore.Scene.tempEntities.create(this.type, { points: points, dimensionStyle: this.dimensionStyle });
75
+ DesignCore.Scene.previewEntities.create(this.type, { points: points, dimensionStyle: this.getProperty(Property.Names.DIMENSIONSTYLE) });
75
76
  }
76
77
  }
77
78
 
@@ -155,7 +156,7 @@ export class BaseLinearDimension extends BaseDimension {
155
156
  const midPoint = Pt13e.midPoint(Pt14e);
156
157
 
157
158
  // set the dimension line angle. This is required for rotated dimension dxf definition
158
- this.linearDimAngle = Utils.radians2degrees(dimLineAngle);
159
+ this.setProperty(Property.Names.LINEARDIMANGLE, Utils.radians2degrees(dimLineAngle));
159
160
 
160
161
  // Approximate text width based on height using the formatted dimension value i.e with units, precision and symbols
161
162
  const approxTextWidth = Text.getApproximateWidth(this.getDimensionValue(dimension), DIMTXT);
@@ -1,5 +1,6 @@
1
1
  import { DXFFile } from '../lib/dxf/dxfFile.js';
2
2
  import { BaseCircularDimension } from './baseCircularDimension.js';
3
+ import { Property } from '../properties/property.js';
3
4
 
4
5
  /**
5
6
  * Diametric Dimension Entity Class
@@ -61,10 +62,10 @@ export class DiametricDimension extends BaseCircularDimension {
61
62
  const Pt15 = this.getPointBySequence(this.points, 15);
62
63
 
63
64
  file.writeGroupCode('0', 'DIMENSION');
64
- file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
65
+ file.writeGroupCode('5', this.getProperty(Property.Names.HANDLE), DXFFile.Version.R2000); // Handle
65
66
  file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
66
67
  file.writeGroupCode('100', 'AcDbDimension', DXFFile.Version.R2000);
67
- file.writeGroupCode('8', this.layer);
68
+ file.writeGroupCode('8', this.getProperty(Property.Names.LAYER));
68
69
  // file.writeGroupCode('2', this.blockName); // Block not required
69
70
  file.writeGroupCode('10', Pt10.x); // X - Start of Dimension Line
70
71
  file.writeGroupCode('20', Pt10.y); // Y
@@ -73,7 +74,7 @@ export class DiametricDimension extends BaseCircularDimension {
73
74
  file.writeGroupCode('21', Pt11.y); // Y
74
75
  file.writeGroupCode('31', '0.0'); // Z
75
76
  file.writeGroupCode('70', this.dimType.getDimType()); // DIMENSION TYPE
76
- file.writeGroupCode('3', this.dimensionStyle); // DIMENSION STYLE
77
+ file.writeGroupCode('3', this.getProperty(Property.Names.DIMENSIONSTYLE)); // DIMENSION STYLE
77
78
  file.writeGroupCode('100', 'AcDbDiametricDimension', DXFFile.Version.R2000);
78
79
  file.writeGroupCode('15', Pt15.x); // X - End of Dimension Line
79
80
  file.writeGroupCode('25', Pt15.y); // Y
@@ -17,6 +17,7 @@ import { Logging } from '../lib/logging.js';
17
17
  import { Intersection } from '../lib/intersect.js';
18
18
 
19
19
  import { DesignCore } from '../designCore.js';
20
+ import { Property } from '../properties/property.js';
20
21
  import { SingleSelection } from '../lib/selectionManager.js';
21
22
  import { Utils } from '../lib/utils.js';
22
23
  import { DimType } from '../properties/dimType.js';
@@ -33,18 +34,24 @@ export class Dimension extends BaseDimension {
33
34
  constructor(data) {
34
35
  super(data);
35
36
 
36
- // map dimensions type to the class name
37
- this.dimensionMap = {
38
- 0: RotatedDimension,
39
- 1: AlignedDimension,
40
- 2: AngularDimension,
41
- 3: DiametricDimension,
42
- 4: RadialDimension,
43
- 5: null, // 5 = Angular 3 point;
44
- 6: null, // 6 = Ordinate;
45
- };
46
-
47
- this.selectedItems = [];
37
+ // map dimensions type to the class name — non-enumerable: internal workflow state
38
+ Object.defineProperty(this, 'dimensionMap', {
39
+ value: {
40
+ 0: RotatedDimension,
41
+ 1: AlignedDimension,
42
+ 2: AngularDimension,
43
+ 3: DiametricDimension,
44
+ 4: RadialDimension,
45
+ 5: null, // 5 = Angular 3 point;
46
+ 6: null, // 6 = Ordinate;
47
+ },
48
+ writable: true,
49
+ });
50
+
51
+ Object.defineProperty(this, 'selectedItems', {
52
+ value: [],
53
+ writable: true,
54
+ });
48
55
 
49
56
  if (data) {
50
57
  const item = new this.dimensionMap[DimType.getBaseType(this.dimType.getBaseDimType())](data);
@@ -80,7 +87,7 @@ export class Dimension extends BaseDimension {
80
87
  async execute() {
81
88
  try {
82
89
  let inputValid = false;
83
- this.dimensionStyle = DesignCore.DimStyleManager.getCstyle();
90
+ this.setProperty(Property.Names.DIMENSIONSTYLE, DesignCore.DimStyleManager.getCstyle());
84
91
 
85
92
  while (!inputValid) {
86
93
  DesignCore.Scene.selectionManager.reset();
@@ -292,7 +299,7 @@ export class Dimension extends BaseDimension {
292
299
  // get the points for the dimension
293
300
  const points = dimensionType.getPointsFromSelection(this.selectedItems, Pt11);
294
301
  // create the temporary dimension
295
- DesignCore.Scene.tempEntities.create(dimensionTypeString, { points: points, dimensionStyle: this.dimensionStyle });
302
+ DesignCore.Scene.previewEntities.create(dimensionTypeString, { points: points, dimensionStyle: this.getProperty(Property.Names.DIMENSIONSTYLE) });
296
303
  }
297
304
  }
298
305
  }
@@ -1,6 +1,7 @@
1
1
 
2
2
  import { DXFFile } from '../lib/dxf/dxfFile.js';
3
3
  import { BaseCircularDimension } from './baseCircularDimension.js';
4
+ import { Property } from '../properties/property.js';
4
5
 
5
6
  /**
6
7
  * Radial Dimension Entity Class
@@ -57,10 +58,10 @@ export class RadialDimension extends BaseCircularDimension {
57
58
  const Pt15 = this.getPointBySequence(this.points, 15);
58
59
 
59
60
  file.writeGroupCode('0', 'DIMENSION');
60
- file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
61
+ file.writeGroupCode('5', this.getProperty(Property.Names.HANDLE), DXFFile.Version.R2000); // Handle
61
62
  file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
62
63
  file.writeGroupCode('100', 'AcDbDimension', DXFFile.Version.R2000);
63
- file.writeGroupCode('8', this.layer);
64
+ file.writeGroupCode('8', this.getProperty(Property.Names.LAYER));
64
65
  // file.writeGroupCode('2', this.blockName); // Block not required
65
66
  file.writeGroupCode('10', Pt10.x); // X - Start of Dimension Line
66
67
  file.writeGroupCode('20', Pt10.y); // Y
@@ -69,7 +70,7 @@ export class RadialDimension extends BaseCircularDimension {
69
70
  file.writeGroupCode('21', Pt11.y); // Y
70
71
  file.writeGroupCode('31', '0.0'); // Z
71
72
  file.writeGroupCode('70', this.dimType.getDimType()); // DIMENSION TYPE
72
- file.writeGroupCode('3', this.dimensionStyle); // DIMENSION STYLE
73
+ file.writeGroupCode('3', this.getProperty(Property.Names.DIMENSIONSTYLE)); // DIMENSION STYLE
73
74
  file.writeGroupCode('100', 'AcDbRadialDimension', DXFFile.Version.R2000);
74
75
  file.writeGroupCode('15', Pt15.x); // X - End of Dimension Line
75
76
  file.writeGroupCode('25', Pt15.y); // Y