@design-core/core 0.0.1 → 0.0.3

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 (254) hide show
  1. package/.eslintrc.json +14 -7
  2. package/.github/workflows/DesignCoreQA.yml +3 -1
  3. package/README.md +11 -4
  4. package/TODO.md +19 -0
  5. package/core/core/core.js +49 -42
  6. package/core/designCore.js +61 -2
  7. package/core/dimensions/alignedDimension.js +142 -0
  8. package/core/dimensions/angularDimension.js +550 -0
  9. package/core/dimensions/baseCircularDimension.js +244 -0
  10. package/core/dimensions/baseDimension.js +558 -0
  11. package/core/dimensions/baseLinearDimension.js +371 -0
  12. package/core/dimensions/diametricDimension.js +82 -0
  13. package/core/dimensions/dimension.js +298 -0
  14. package/core/dimensions/linearDimension.js +29 -0
  15. package/core/dimensions/radialDimension.js +78 -0
  16. package/core/dimensions/rotatedDimension.js +167 -0
  17. package/core/entities/arc.js +314 -60
  18. package/core/entities/arctext.js +642 -0
  19. package/core/entities/basePolyline.js +553 -94
  20. package/core/entities/circle.js +181 -54
  21. package/core/entities/entity.js +154 -74
  22. package/core/entities/hatch.js +807 -0
  23. package/core/entities/insert.js +200 -39
  24. package/core/entities/line.js +196 -134
  25. package/core/entities/lwpolyline.js +21 -44
  26. package/core/entities/point.js +194 -29
  27. package/core/entities/polyline.js +54 -7
  28. package/core/entities/rectangle.js +43 -13
  29. package/core/entities/solid.js +43 -6
  30. package/core/entities/text.js +324 -181
  31. package/core/lib/boundingBox.js +73 -13
  32. package/core/lib/canvas.js +256 -65
  33. package/core/lib/clipboard.js +198 -0
  34. package/core/lib/colour.js +144 -0
  35. package/core/lib/colours.js +367 -301
  36. package/core/lib/commandLine.js +16 -28
  37. package/core/lib/commandManager.js +115 -58
  38. package/core/lib/constants.js +23 -0
  39. package/core/lib/dxf/dxf.js +249 -34
  40. package/core/lib/dxf/dxfFile.js +23 -38
  41. package/core/lib/dxf/dxfIterator.js +17 -5
  42. package/core/lib/dxf/dxfRead.js +23 -7
  43. package/core/lib/dxf/dxfWrite.js +39 -129
  44. package/core/lib/dxf/handleManager.js +97 -0
  45. package/core/lib/dxf/sections/blocks.js +16 -2
  46. package/core/lib/dxf/sections/entities.js +17 -3
  47. package/core/lib/dxf/sections/header.js +10 -1
  48. package/core/lib/dxf/sections/objects.js +36 -0
  49. package/core/lib/dxf/sections/section.js +43 -5
  50. package/core/lib/dxf/sections/tables.js +17 -3
  51. package/core/lib/entityManager.js +178 -0
  52. package/core/lib/fileio.js +14 -4
  53. package/core/lib/headers.js +229 -0
  54. package/core/lib/input.js +46 -0
  55. package/core/lib/inputManager.js +199 -194
  56. package/core/lib/intersect.js +341 -468
  57. package/core/lib/logging.js +25 -1
  58. package/core/lib/matrix.js +6 -8
  59. package/core/lib/mouse.js +24 -79
  60. package/core/lib/patterns.js +690 -0
  61. package/core/lib/promptOptions.js +133 -0
  62. package/core/lib/scene.js +71 -174
  63. package/core/lib/selectionManager.js +74 -48
  64. package/core/lib/selectionWindow.js +24 -10
  65. package/core/lib/settings.js +18 -11
  66. package/core/lib/snapping.js +129 -21
  67. package/core/lib/stateManager.js +288 -0
  68. package/core/lib/strings.js +57 -5
  69. package/core/lib/utils.js +95 -11
  70. package/core/objects/dictionary.js +43 -0
  71. package/core/objects/dictionaryManager.js +80 -0
  72. package/core/properties/dimType.js +117 -0
  73. package/core/properties/flags.js +66 -0
  74. package/core/properties/property.js +26 -0
  75. package/core/properties/propertyManager.js +65 -19
  76. package/core/tables/appId.js +31 -0
  77. package/core/tables/appIdManager.js +44 -0
  78. package/core/tables/block.js +323 -0
  79. package/core/tables/blockManager.js +48 -0
  80. package/core/tables/blockRecord.js +29 -0
  81. package/core/tables/blockRecordManager.js +37 -0
  82. package/core/tables/dimStyle.js +627 -0
  83. package/core/tables/dimStyleManager.js +187 -0
  84. package/core/tables/endblk.js +28 -0
  85. package/core/tables/layer.js +219 -0
  86. package/core/tables/layerManager.js +47 -0
  87. package/core/tables/ltype.js +85 -0
  88. package/core/tables/ltypeManager.js +65 -0
  89. package/core/tables/style.js +145 -0
  90. package/core/tables/styleManager.js +55 -0
  91. package/core/tables/styleManagerBase.js +110 -0
  92. package/core/tables/tableManagerBase.js +354 -0
  93. package/core/tables/ucs.js +28 -0
  94. package/core/tables/ucsManager.js +44 -0
  95. package/core/tables/view.js +28 -0
  96. package/core/tables/viewManager.js +44 -0
  97. package/core/tables/vport.js +70 -0
  98. package/core/tables/vportManager.js +65 -0
  99. package/core/tools/chamfer.js +343 -0
  100. package/core/tools/chamferFilletBase.js +162 -0
  101. package/core/tools/copy.js +68 -40
  102. package/core/tools/copybase.js +65 -0
  103. package/core/tools/copyclip.js +59 -0
  104. package/core/tools/cornerEntity.js +138 -0
  105. package/core/tools/cutclip.js +72 -0
  106. package/core/tools/distance.js +37 -9
  107. package/core/tools/erase.js +43 -13
  108. package/core/tools/explode.js +117 -0
  109. package/core/tools/extend.js +71 -32
  110. package/core/tools/fillet.js +336 -0
  111. package/core/tools/identify.js +33 -6
  112. package/core/tools/matchProp.js +106 -0
  113. package/core/tools/mirror.js +141 -0
  114. package/core/tools/move.js +65 -32
  115. package/core/tools/offset.js +321 -0
  116. package/core/tools/pan.js +54 -0
  117. package/core/tools/pasteclip.js +93 -0
  118. package/core/tools/purge.js +90 -0
  119. package/core/tools/rotate.js +105 -70
  120. package/core/tools/scale.js +166 -0
  121. package/core/tools/tool.js +14 -4
  122. package/core/tools/trim.js +71 -32
  123. package/core/tools/zoom.js +152 -0
  124. package/package.json +3 -305
  125. package/test/dimensions/alignedDimension.test.js +211 -0
  126. package/test/dimensions/angularDimension.test.js +243 -0
  127. package/test/dimensions/baseDimension.test.js +239 -0
  128. package/test/dimensions/diametricDimension.test.js +203 -0
  129. package/test/dimensions/dimension.test.js +102 -0
  130. package/test/dimensions/radialDimension.test.js +203 -0
  131. package/test/dimensions/rotatedDimension.test.js +224 -0
  132. package/test/entities/arc.test.js +463 -41
  133. package/test/entities/arctext.test.js +329 -0
  134. package/test/entities/basePolyline.test.js +459 -10
  135. package/test/entities/circle.test.js +312 -7
  136. package/test/entities/entity.test.js +28 -9
  137. package/test/entities/hatch.test.js +606 -0
  138. package/test/entities/insert.test.js +90 -0
  139. package/test/entities/line.test.js +182 -6
  140. package/test/entities/point.test.js +375 -37
  141. package/test/entities/solid.test.js +156 -0
  142. package/test/entities/text.test.js +533 -7
  143. package/test/integration/exportIntegration.reference.dxf +1706 -0
  144. package/test/integration/exportIntegration.test.js +186 -0
  145. package/test/integration/importExportIntegration.test.js +126 -0
  146. package/test/integration/intersectionIntegration.test.js +880 -0
  147. package/test/integration/userInputIntegration.reference.dxf +1410 -0
  148. package/test/integration/userInputIntegration.test.js +269 -0
  149. package/test/lib/boundingBox.test.js +26 -2
  150. package/test/lib/canvas.test.js +613 -5
  151. package/test/lib/clipboard.test.js +70 -0
  152. package/test/lib/colour.test.js +114 -0
  153. package/test/lib/colours.test.js +63 -18
  154. package/test/lib/commandLine.test.js +159 -22
  155. package/test/lib/commandManager.test.js +4 -4
  156. package/test/lib/constants.test.js +9 -0
  157. package/test/lib/dxf/dxfFile.test.js +6 -2
  158. package/test/lib/dxf/dxfIterator.test.js +1 -1
  159. package/test/lib/dxf/dxfWrite.test.js +173 -0
  160. package/test/lib/dxf/handleManager.test.js +137 -0
  161. package/test/lib/dxf/sections/blocks.test.js +5 -5
  162. package/test/lib/dxf/sections/entities.test.js +4 -4
  163. package/test/lib/dxf/sections/header.test.js +18 -4
  164. package/test/lib/dxf/sections/objects.test.js +132 -0
  165. package/test/lib/dxf/sections/section.test.js +29 -29
  166. package/test/lib/dxf/sections/tables.test.js +3 -3
  167. package/test/lib/entityManager.test.js +163 -0
  168. package/test/lib/headers.test.js +233 -0
  169. package/test/lib/inputManager.test.js +1144 -5
  170. package/test/lib/intersect.test.js +454 -331
  171. package/test/lib/logging.test.js +1 -1
  172. package/test/lib/matrix.test.js +1 -1
  173. package/test/lib/mouse.test.js +327 -4
  174. package/test/lib/patterns.test.js +105 -0
  175. package/test/lib/promptOptions.test.js +179 -0
  176. package/test/lib/scene.test.js +16 -52
  177. package/test/lib/selectionManager.test.js +17 -5
  178. package/test/lib/settings.test.js +111 -5
  179. package/test/lib/snapping.test.js +142 -4
  180. package/test/lib/stateManager.test.js +155 -0
  181. package/test/lib/utils.test.js +81 -1
  182. package/test/objects/dictionary.test.js +81 -0
  183. package/test/objects/dictionaryManager.test.js +34 -0
  184. package/test/properties/dimType.test.js +62 -0
  185. package/test/properties/flags.test.js +164 -0
  186. package/test/properties/property.test.js +13 -0
  187. package/test/properties/propertyManager.test.js +10 -11
  188. package/test/tables/appId.test.js +46 -0
  189. package/test/tables/appIdManager.test.js +72 -0
  190. package/test/tables/block.test.js +157 -0
  191. package/test/tables/blockManager.test.js +52 -0
  192. package/test/tables/blockRecord.test.js +39 -0
  193. package/test/tables/blockRecordManager.test.js +60 -0
  194. package/test/tables/dimstyle.test.js +72 -0
  195. package/test/tables/endblk.test.js +30 -0
  196. package/test/tables/layer.test.js +95 -0
  197. package/test/tables/layerManager.test.js +172 -0
  198. package/test/{styles → tables}/ltype.test.js +7 -7
  199. package/test/{styles → tables}/ltypeManager.test.js +2 -2
  200. package/test/tables/style.test.js +44 -0
  201. package/test/tables/stylemanagerbase.test.js +220 -0
  202. package/test/tables/tableManagerBase.test.js +194 -0
  203. package/test/tables/ucs.test.js +37 -0
  204. package/test/tables/ucsManager.test.js +48 -0
  205. package/test/tables/view.test.js +37 -0
  206. package/test/tables/viewManager.test.js +48 -0
  207. package/test/tables/vport.test.js +117 -0
  208. package/test/tables/vportManager.test.js +54 -0
  209. package/test/test-helpers/test-helpers.js +66 -0
  210. package/test/tools/chamfer.test.js +970 -0
  211. package/test/tools/chamferFilletBase.test.js +446 -0
  212. package/test/tools/copy.test.js +22 -14
  213. package/test/tools/copybase.test.js +93 -0
  214. package/test/tools/copyclip.test.js +92 -0
  215. package/test/tools/cornerEntity.test.js +201 -0
  216. package/test/tools/cutclip.test.js +94 -0
  217. package/test/tools/distance.test.js +140 -18
  218. package/test/tools/erase.test.js +12 -12
  219. package/test/tools/explode.test.js +45 -0
  220. package/test/tools/extend.test.js +326 -44
  221. package/test/tools/fillet.test.js +831 -0
  222. package/test/tools/identify.test.js +115 -16
  223. package/test/tools/matchProp.test.js +84 -0
  224. package/test/tools/mirror.test.js +475 -0
  225. package/test/tools/move.test.js +75 -19
  226. package/test/tools/offset.test.js +748 -0
  227. package/test/tools/pan.test.js +72 -0
  228. package/test/tools/pasteclip.test.js +100 -0
  229. package/test/tools/purge.test.js +89 -0
  230. package/test/tools/rotate.test.js +89 -23
  231. package/test/tools/scale.test.js +529 -0
  232. package/test/tools/trim.test.js +419 -84
  233. package/test/tools/zoom.test.js +504 -0
  234. package/core/entities/alignedDimension.js +0 -279
  235. package/core/entities/angularDimension.js +0 -194
  236. package/core/entities/baseDimension.js +0 -227
  237. package/core/entities/block.js +0 -247
  238. package/core/entities/diametricDimension.js +0 -133
  239. package/core/entities/dimension.js +0 -202
  240. package/core/entities/radialDimension.js +0 -126
  241. package/core/styles/dimStyle.js +0 -719
  242. package/core/styles/dimStyleManager.js +0 -47
  243. package/core/styles/layer.js +0 -133
  244. package/core/styles/layerManager.js +0 -40
  245. package/core/styles/ltype.js +0 -86
  246. package/core/styles/ltypeManager.js +0 -50
  247. package/core/styles/style.js +0 -158
  248. package/core/styles/styleManager.js +0 -43
  249. package/core/styles/styleManagerBase.js +0 -299
  250. package/test/entities/block.test.js +0 -22
  251. package/test/styles/dimstyle.test.js +0 -19
  252. package/test/styles/layerManager.test.js +0 -150
  253. package/test/styles/style.test.js +0 -33
  254. package/test/styles/stylemanagerbase.test.js +0 -219
@@ -0,0 +1,243 @@
1
+
2
+ import { AngularDimension } from '../../core/dimensions/angularDimension.js';
3
+ import { Point } from '../../core/entities/point.js';
4
+ import { Line } from '../../core/entities/line.js';
5
+ import { Polyline } from '../../core/entities/polyline.js';
6
+ import { Core } from '../../core/core/core.js';
7
+ import { DesignCore } from '../../core/designCore.js';
8
+ import { SingleSelection } from '../../core/lib/selectionManager.js';
9
+
10
+ import { File, withMockInput } from '../test-helpers/test-helpers.js';
11
+
12
+ // initialise core
13
+ new Core();
14
+
15
+
16
+ // Test cases for user input
17
+ const scenarios = [
18
+
19
+ { desc: 'Angular dimension from line selection - 45 degrees',
20
+ input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, 5)],
21
+ selectedItems: [new Line({ points: [new Point(0, 0), new Point(10, 0)] }), new Line({ points: [new Point(0, 0), new Point(10, 10)] })],
22
+ expectedDimType: 2,
23
+ dimensionValue: 45,
24
+ dimensionEntities: 5,
25
+ },
26
+ { desc: 'Angular dimension from line selection - 135 degrees',
27
+ input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(-5, 5)],
28
+ selectedItems: [new Line({ points: [new Point(0, 0), new Point(10, 0)] }), new Line({ points: [new Point(0, 0), new Point(10, 10)] })],
29
+ expectedDimType: 2,
30
+ dimensionValue: 135,
31
+ dimensionEntities: 6,
32
+ },
33
+ { desc: 'Angular dimension from line selection - 45 degrees',
34
+ input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(-5, -5)],
35
+ selectedItems: [new Line({ points: [new Point(0, 0), new Point(10, 0)] }), new Line({ points: [new Point(0, 0), new Point(10, 10)] })],
36
+ expectedDimType: 2,
37
+ dimensionValue: 45,
38
+ dimensionEntities: 7,
39
+ },
40
+ { desc: 'Angular dimension from line selection - 135 degrees',
41
+ input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, -5)],
42
+ selectedItems: [new Line({ points: [new Point(0, 0), new Point(10, 0)] }), new Line({ points: [new Point(0, 0), new Point(10, 10)] })],
43
+ expectedDimType: 2,
44
+ dimensionValue: 135,
45
+ dimensionEntities: 6,
46
+ },
47
+ { desc: 'Angular dimension from polyline selection - 45 degrees',
48
+ input: [new SingleSelection(0, new Point(5, 0)), new SingleSelection(1, new Point(5, 5)), new Point(5, 5)],
49
+ selectedItems: [new Polyline({ points: [new Point(0, 0), new Point(10, 0)] }), new Polyline({ points: [new Point(0, 0), new Point(10, 10)] })],
50
+ expectedDimType: 2,
51
+ dimensionValue: 45,
52
+ dimensionEntities: 5,
53
+ },
54
+ ];
55
+
56
+ test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
57
+ const { input, selectedItems, expectedDimType, dimensionValue, dimensionEntities } = scenario;
58
+
59
+ await withMockInput(DesignCore.Scene, input, async () => {
60
+ const dim = new AngularDimension();
61
+ await dim.execute();
62
+
63
+ expect(dim.dimType.getBaseDimType()).toBe(expectedDimType);
64
+ // get the text entities from the dimension block
65
+ const dimensionBlockEntities = dim.buildDimension();
66
+ expect(dimensionBlockEntities.length).toBe(dimensionEntities);
67
+
68
+ // check if the text value matches the expected dimension value
69
+ for (const entity of dimensionBlockEntities) {
70
+ if (entity.type === 'Text') {
71
+ // remove all non-numeric characters except . and -
72
+ const numbersOnly = entity.string.replace(/[^0-9.-]+/g, '');
73
+ expect(Number(numbersOnly)).toBeCloseTo(dimensionValue);
74
+ expect(entity.string).toContain('°');
75
+ }
76
+ }
77
+ }, { selectedItems });
78
+ });
79
+
80
+ test('constructor sets default properties', () => {
81
+ const dim = new AngularDimension();
82
+ expect(dim).toBeInstanceOf(AngularDimension);
83
+ expect(dim.points).toBeDefined();
84
+ });
85
+
86
+ test('register returns command object', () => {
87
+ expect(AngularDimension.register()).toEqual({ command: 'AngularDimension', shortcut: 'DIMANG' });
88
+ });
89
+
90
+ test('getPointsFromSelection returns correct sequenced points', () => {
91
+ const pt1 = new Point(0, 0);
92
+ const pt2 = new Point(10, 0);
93
+ const pt3 = new Point(10, 10);
94
+ const textPos = new Point(5, 5);
95
+ const line1 = new Line({ points: [pt1, pt2] });
96
+ const line2 = new Line({ points: [pt2, pt3] });
97
+ const result = AngularDimension.getPointsFromSelection([line1, line2], textPos);
98
+ expect(Array.isArray(result)).toBe(true);
99
+ expect(result.length).toBeGreaterThanOrEqual(4);
100
+ });
101
+
102
+ test('AngularDimension.preview runs without error and calls createTempItem', () => {
103
+ const origCreateTempItem = DesignCore.Scene.tempEntities.create;
104
+ const origPointOnScene = DesignCore.Mouse.pointOnScene;
105
+ // Manual mock for createTempItem
106
+ const createTempItemCalls = [];
107
+ DesignCore.Scene.tempEntities.create = function(type, obj) {
108
+ createTempItemCalls.push([type, obj]);
109
+ };
110
+ // Manual mock for pointOnScene
111
+ DesignCore.Mouse.pointOnScene = function() {
112
+ return new Point(5, 5);
113
+ };
114
+
115
+
116
+ // Test with >4 point (should call createTempItem with this.type)
117
+ const dim2 = new AngularDimension();
118
+
119
+ dim2.points = [];
120
+
121
+ const Pt10 = new Point();
122
+ Pt10.sequence = 10;
123
+ dim2.points.push(Pt10);
124
+
125
+ const Pt13 = new Point();
126
+ Pt13.sequence = 13;
127
+ dim2.points.push(Pt13);
128
+
129
+ const Pt14 = new Point();
130
+ Pt14.sequence = 14;
131
+ dim2.points.push(Pt14);
132
+
133
+ const Pt15 = new Point();
134
+ Pt15.sequence = 15;
135
+ dim2.points.push(Pt15);
136
+
137
+ expect(() => dim2.preview()).not.toThrow();
138
+ expect(createTempItemCalls.some((call) => call[0] === dim2.type)).toBe(true);
139
+
140
+ // Restore
141
+ DesignCore.Scene.tempEntities.create = origCreateTempItem;
142
+ DesignCore.Mouse.pointOnScene = origPointOnScene;
143
+ });
144
+
145
+ test('Test AngularDimension.dxf', () => {
146
+ const points = [];
147
+
148
+ const Pt10 = new Point(5, 6);
149
+ Pt10.sequence = 10;
150
+ points.push(Pt10);
151
+
152
+ const Pt11 = new Point(7, 8);
153
+ Pt11.sequence = 11;
154
+ points.push(Pt11);
155
+
156
+ const Pt13 = new Point(9, 10);
157
+ Pt13.sequence = 13;
158
+ points.push(Pt13);
159
+
160
+ const Pt14 = new Point(11, 12);
161
+ Pt14.sequence = 14;
162
+ points.push(Pt14);
163
+
164
+ const Pt15 = new Point(13, 14);
165
+ Pt15.sequence = 15;
166
+ points.push(Pt15);
167
+
168
+ const Pt16 = new Point(15, 16);
169
+ Pt16.sequence = 16;
170
+ points.push(Pt16);
171
+
172
+
173
+ points.push(Pt10, Pt11, Pt13, Pt14, Pt15, Pt16);
174
+
175
+ const dimension = new AngularDimension({ points: points, handle: '1' });
176
+ let file = new File();
177
+ dimension.dxf(file);
178
+ // console.log(file.contents);
179
+
180
+ const dxfString = `0
181
+ DIMENSION
182
+ 5
183
+ 1
184
+ 100
185
+ AcDbEntity
186
+ 100
187
+ AcDbDimension
188
+ 8
189
+ 0
190
+ 10
191
+ 5
192
+ 20
193
+ 6
194
+ 30
195
+ 0.0
196
+ 11
197
+ 7
198
+ 21
199
+ 8
200
+ 31
201
+ 0.0
202
+ 70
203
+ 2
204
+ 3
205
+ STANDARD
206
+ 100
207
+ AcDb2LineAngularDimension
208
+ 13
209
+ 9
210
+ 23
211
+ 10
212
+ 33
213
+ 0.0
214
+ 14
215
+ 11
216
+ 24
217
+ 12
218
+ 34
219
+ 0.0
220
+ 15
221
+ 13
222
+ 25
223
+ 14
224
+ 35
225
+ 0.0
226
+ 16
227
+ 15
228
+ 26
229
+ 16
230
+ 36
231
+ 0.0
232
+ `;
233
+
234
+ expect(file.contents).toEqual(dxfString);
235
+
236
+ // create new entity from entity data to ensure all props are loaded
237
+ const newDimension = new AngularDimension(dimension);
238
+ file = new File();
239
+ newDimension.dxf(file);
240
+ expect(file.contents).toEqual(dxfString);
241
+ });
242
+
243
+
@@ -0,0 +1,239 @@
1
+ import { BaseDimension } from '../../core/dimensions/baseDimension.js';
2
+ import { Point } from '../../core/entities/point.js';
3
+ import { Core } from '../../core/core/core.js';
4
+ import { Text } from '../../core/entities/text.js';
5
+ // import { DimType } from '../../core/properties/dimType.js';
6
+
7
+ // initialise core
8
+ new Core();
9
+
10
+ describe('BaseDimension', () => {
11
+ let baseDim;
12
+
13
+ beforeEach(() => {
14
+ baseDim = new BaseDimension({});
15
+ baseDim.points = [new Point(1, 2, 0), new Point(3, 4, 0)];
16
+ });
17
+
18
+ test('constructor sets default properties', () => {
19
+ expect(baseDim.textOverride).toBe('');
20
+ expect(baseDim.blockName).toBe('');
21
+ expect(baseDim.dimensionStyle).toBe('STANDARD');
22
+ expect(baseDim.leaderLength).toBe(0);
23
+ expect(baseDim.linearDimAngle).toBe(0);
24
+ });
25
+
26
+ test('getDimensionValue formats values by dimension type', () => {
27
+ baseDim.dimType.setDimType(0);
28
+ expect(baseDim.getDimensionValue(12.3456)).toBe('12.3456');
29
+ baseDim.dimType.setDimType(2);
30
+ expect(baseDim.getDimensionValue(45)).toContain('°');
31
+ baseDim.dimType.setDimType(3);
32
+ expect(baseDim.getDimensionValue(10)).toContain('Ø');
33
+ baseDim.dimType.setDimType(4);
34
+ expect(baseDim.getDimensionValue(5)).toContain('R');
35
+ baseDim.dimType.setDimType(6);
36
+ expect(baseDim.getDimensionValue(7)).toContain('7.00');
37
+ });
38
+
39
+
40
+ describe('getDimensionValue formats to style', () => {
41
+ // Test cases for dimension value formatting
42
+ const scenarios = [
43
+
44
+ { desc: 'comma separator, 2 decimal places',
45
+ dimType: 0,
46
+ inputValue: 12.34,
47
+ expectedValue: '12,34',
48
+ DIMDSEP: ',',
49
+ DIMDEC: 2,
50
+ DIMADEC: 2,
51
+ DIMRND: 0.0000,
52
+ },
53
+ { desc: 'comma separator, 3 decimal places',
54
+ dimType: 0,
55
+ inputValue: 12.34,
56
+ expectedValue: '12,340',
57
+ DIMDSEP: ',',
58
+ DIMDEC: 3,
59
+ DIMADEC: 2,
60
+ DIMRND: 0.0000,
61
+ },
62
+ { desc: 'dot separator, 3 decimal places',
63
+ dimType: 0,
64
+ inputValue: 12.34,
65
+ expectedValue: '12.340',
66
+ DIMDSEP: '.',
67
+ DIMDEC: 3,
68
+ DIMADEC: 2,
69
+ DIMRND: 0.0000,
70
+ },
71
+ { desc: 'hash separator, 4 decimal places',
72
+ dimType: 0,
73
+ inputValue: 12.3456789,
74
+ expectedValue: '12#3457',
75
+ DIMDSEP: '#',
76
+ DIMDEC: 4,
77
+ DIMADEC: 2,
78
+ DIMRND: 0.0000,
79
+ },
80
+ { desc: 'hash separator, 2 decimal places, rounded to nearest 1',
81
+ dimType: 0,
82
+ inputValue: 12.3456789,
83
+ expectedValue: '12#00',
84
+ DIMDSEP: '#',
85
+ DIMDEC: 2,
86
+ DIMADEC: 2,
87
+ DIMRND: 1,
88
+ },
89
+ { desc: 'comma separator, 2 decimal places, rounded to nearest 1',
90
+ dimType: 0,
91
+ inputValue: 0.23456,
92
+ expectedValue: '0,00',
93
+ DIMDSEP: ',',
94
+ DIMDEC: 2,
95
+ DIMADEC: 2,
96
+ DIMRND: 1,
97
+ },
98
+ { desc: 'comma separator, 2 decimal places, rounded to nearest 0.25',
99
+ dimType: 0,
100
+ inputValue: 0.23456,
101
+ expectedValue: '0,25',
102
+ DIMDSEP: ',',
103
+ DIMDEC: 2,
104
+ DIMADEC: 2,
105
+ DIMRND: 0.25,
106
+ },
107
+ { desc: 'Angular dimension, comma separator, 2 decimal places, rounded to nearest 0.25',
108
+ dimType: 2,
109
+ inputValue: 0.23457,
110
+ expectedValue: '0,23°',
111
+ DIMDSEP: ',',
112
+ DIMDEC: 2,
113
+ DIMADEC: 2,
114
+ DIMRND: 0.25,
115
+ },
116
+ { desc: 'negative value, dot separator, 4 decimal places, rounded to nearest 2',
117
+ dimType: 0,
118
+ inputValue: -123.45678,
119
+ expectedValue: '124.0000',
120
+ DIMDSEP: '.',
121
+ DIMDEC: 4,
122
+ DIMADEC: 2,
123
+ DIMRND: 2,
124
+ },
125
+ { desc: 'negative value, dot separator, 4 decimal places, rounded to nearest 2, remove trailing zeros',
126
+ dimType: 0,
127
+ inputValue: -123.45678,
128
+ expectedValue: '124',
129
+ DIMDSEP: '.',
130
+ DIMDEC: 4,
131
+ DIMADEC: 2,
132
+ DIMRND: 2,
133
+ DIMZIN: 8,
134
+ },
135
+ ];
136
+
137
+ test.each(scenarios)('getDimensionValue formats to style - $desc', (scenario) => {
138
+ baseDim.dimType.setDimType(scenario.dimType);
139
+ // Mock getDimensionStyle to return specific rounding value
140
+ baseDim.getDimensionStyle = () => ({
141
+ getValue: (prop) => {
142
+ let returnValue = null;
143
+ if (prop === 'DIMDSEP') returnValue = scenario.DIMDSEP;
144
+ if (prop === 'DIMDEC') returnValue = scenario.DIMDEC;
145
+ if (prop === 'DIMRND') returnValue = scenario.DIMRND;
146
+ if (prop === 'DIMADEC') returnValue = scenario.DIMADEC;
147
+ if (prop === 'DIMZIN') returnValue = scenario.DIMZIN || 0;
148
+ return returnValue;
149
+ },
150
+ });
151
+ expect(baseDim.getDimensionValue(scenario.inputValue)).toBe(scenario.expectedValue);
152
+ });
153
+ });
154
+
155
+ test('suppressZeros', () => {
156
+ expect(baseDim.suppressZeros('012.3400', true, true)).toBe('12.34');
157
+ expect(baseDim.suppressZeros('012.3400', true, false)).toBe('12.3400');
158
+ expect(baseDim.suppressZeros('012.3400', false, true)).toBe('012.34');
159
+ expect(baseDim.suppressZeros('012.3400', false, false)).toBe('012.3400');
160
+ expect(baseDim.suppressZeros('0.050', true, true)).toBe('.05');
161
+ expect(baseDim.suppressZeros('0.0', true, true)).toBe('0');
162
+ });
163
+
164
+ test('constructor throws on invalid dimType', () => {
165
+ expect(() => new BaseDimension({ 70: 999 })).toThrow(/Invalid Dimension Type/);
166
+ });
167
+
168
+ test('getDimensionValue uses textOverride', () => {
169
+ baseDim.textOverride = 'foo <> bar';
170
+ expect(baseDim.getDimensionValue(10)).toBe('foo 10.0000 bar');
171
+ });
172
+
173
+ test('getDimensionText returns a Text object with correct values', () => {
174
+ const text = baseDim.getDimensionText(10, new Point(1, 2), Math.PI / 4);
175
+ expect(text).toBeInstanceOf(Text);
176
+ expect(text.height).toBe(0.18);
177
+ expect(text.points[0].x).toBe(1);
178
+ expect(text.points[0].y).toBe(2);
179
+ expect(typeof text.string).toBe('string');
180
+ });
181
+
182
+ test('getTextDirection flips angle in lower half', () => {
183
+ expect(baseDim.getTextDirection(Math.PI)).toBeCloseTo(Math.PI * 2);
184
+ expect(baseDim.getTextDirection(0)).toBe(0);
185
+ });
186
+
187
+ test('alignedOrOpposite returns true for aligned/opposite angles', () => {
188
+ expect(baseDim.alignedOrOpposite(0, 0)).toBe(true);
189
+ expect(baseDim.alignedOrOpposite(0, Math.PI)).toBe(true);
190
+ expect(baseDim.alignedOrOpposite(0, Math.PI / 2)).toBe(false);
191
+ });
192
+
193
+ // test('getDimensionStyle returns style object', () => {
194
+ // expect(baseDim.getDimensionStyle()).toBe(styleMock);
195
+ // });
196
+
197
+ test('getPointBySequence returns correct point', () => {
198
+ baseDim.points = [Object.assign(new Point(1, 2), { sequence: 10 }), Object.assign(new Point(3, 4), { sequence: 15 })];
199
+ expect(baseDim.getPointBySequence(baseDim.points, 15).x).toBe(3);
200
+ expect(baseDim.getPointBySequence(baseDim.points, 99)).toBeNull();
201
+ });
202
+
203
+ test('getArrowHead returns a Solid', () => {
204
+ const solid = baseDim.getArrowHead(new Point(0, 0), 0);
205
+ expect(solid).toBeDefined();
206
+ expect(solid.points.length).toBe(3);
207
+ });
208
+
209
+ test('getCentreMark returns lines for markStyle > 0', () => {
210
+ const lines = baseDim.getCentreMark(new Point(0, 0));
211
+ expect(Array.isArray(lines)).toBe(true);
212
+ expect(lines.length).toBeGreaterThan(0);
213
+ });
214
+
215
+
216
+ test('snaps returns empty array', () => {
217
+ expect(baseDim.snaps(new Point(0, 0), 1)).toEqual([]);
218
+ });
219
+
220
+ test('closestPoint delegates to block', () => {
221
+ baseDim.block = { closestPoint: () => 'foo' };
222
+ expect(baseDim.closestPoint(new Point(0, 0))).toBe('foo');
223
+ });
224
+
225
+ test('boundingBox delegates to block', () => {
226
+ baseDim.block = { boundingBox: () => 'box' };
227
+ expect(baseDim.boundingBox()).toBe('box');
228
+ });
229
+
230
+ test('within delegates to block', () => {
231
+ baseDim.block = { within: () => true };
232
+ expect(baseDim.within({})).toBe(true);
233
+ });
234
+
235
+ test('touched delegates to block', () => {
236
+ baseDim.block = { touched: () => false };
237
+ expect(baseDim.touched({})).toBe(false);
238
+ });
239
+ });
@@ -0,0 +1,203 @@
1
+ import { DiametricDimension } from '../../core/dimensions/diametricDimension.js';
2
+ import { Point } from '../../core/entities/point.js';
3
+ import { Arc } from '../../core/entities/arc.js';
4
+ import { File, withMockInput } from '../test-helpers/test-helpers.js';
5
+ import { Core } from '../../core/core/core.js';
6
+ import { DesignCore } from '../../core/designCore.js';
7
+ import { SingleSelection } from '../../core/lib/selectionManager.js';
8
+ import { Circle } from '../../core/entities/circle.js';
9
+ import { Polyline } from '../../core/entities/polyline.js';
10
+
11
+
12
+ // initialise core
13
+ new Core();
14
+
15
+ // Test cases for user input
16
+ const scenarios = [
17
+
18
+ { desc: 'Diametric dimension from circle selection - Text outside circle',
19
+ input: [new SingleSelection(0, new Point()), new Point(20, 0)],
20
+ selectedItems: [new Circle({ points: [new Point(0, 0), new Point(10, 0)] })],
21
+ expectedDimType: 3,
22
+ dimensionValue: 20,
23
+ dimensionEntities: 6,
24
+ },
25
+ { desc: 'Diametric dimension from circle selection - Text inside circle',
26
+ input: [new SingleSelection(0, new Point()), new Point(0, 0)],
27
+ selectedItems: [new Circle({ points: [new Point(0, 0), new Point(10, 0)] })],
28
+ expectedDimType: 3,
29
+ dimensionValue: 20,
30
+ dimensionEntities: 5,
31
+ },
32
+ { desc: 'Diametric dimension from arc selection',
33
+ input: [new SingleSelection(0, new Point()), new Point(20, 10)],
34
+ selectedItems: [new Arc({ points: [new Point(0, 0), new Point(20, 0), new Point(20, 20)] })],
35
+ expectedDimType: 3,
36
+ dimensionValue: 40,
37
+ dimensionEntities: 6,
38
+ },
39
+ { desc: 'Diametric dimension from polyline selection',
40
+ input: [new SingleSelection(0, new Point(30, 10)), new Point(30, 10)],
41
+ selectedItems: [new Polyline({ points: [new Point(0, 0), new Point(20, 0, 1), new Point(20, 20)] })],
42
+ expectedDimType: 3,
43
+ dimensionValue: 20,
44
+ dimensionEntities: 6,
45
+ },
46
+ ];
47
+
48
+ test.each(scenarios)('DiametricDimension.execute handles $desc', async (scenario) => {
49
+ const { input, selectedItems, expectedDimType, dimensionValue, dimensionEntities } = scenario;
50
+
51
+ await withMockInput(DesignCore.Scene, input, async () => {
52
+ const dim = new DiametricDimension();
53
+ await dim.execute();
54
+
55
+ expect(dim.dimType.getBaseDimType()).toBe(expectedDimType);
56
+ // get the text entities from the dimension block
57
+ const dimensionBlockEntities = dim.buildDimension();
58
+ expect(dimensionBlockEntities.length).toBe(dimensionEntities);
59
+
60
+ // check if the text value matches the expected dimension value
61
+ for (const entity of dimensionBlockEntities) {
62
+ if (entity.type === 'Text') {
63
+ // remove all none numberic characters except . and -
64
+ const numbersOnly = entity.string.replace(/[^0-9.-]+/g, '');
65
+ expect(Number(numbersOnly)).toBeCloseTo(dimensionValue);
66
+ expect(entity.string).toContain('Ø');
67
+ }
68
+ }
69
+ }, { selectedItems });
70
+ });
71
+
72
+ test('constructor sets default properties', () => {
73
+ const dim = new DiametricDimension();
74
+ expect(dim).toBeInstanceOf(DiametricDimension);
75
+ expect(dim.points).toBeDefined();
76
+ });
77
+
78
+
79
+ test('getPointsFromSelection returns correct sequenced points', () => {
80
+ const center = new Point(0, 0);
81
+ const textPos = new Point(10, 0);
82
+ // Mock item with getRadius
83
+ const item = { points: [center], getRadius: () => 10 };
84
+ const result = DiametricDimension.getPointsFromSelection([item], textPos);
85
+ expect(Array.isArray(result)).toBe(true);
86
+ expect(result.length).toBe(3);
87
+ expect(result[0].sequence).toBe(10); // center
88
+ expect(result[1].sequence).toBe(15); // radius point
89
+ expect(result[2].sequence).toBe(11); // text position
90
+ });
91
+
92
+ test('DiametricDimension.preview runs without error and calls createTempItem', () => {
93
+ const origCreateTempItem = DesignCore.Scene.tempEntities.create;
94
+ const origPointOnScene = DesignCore.Mouse.pointOnScene;
95
+ const origSeletionSet = DesignCore.Scene.selectionManager.selectionSet.selectionSet.length;
96
+
97
+ // Manual mock for createTempItem
98
+ const createTempItemCalls = [];
99
+ DesignCore.Scene.tempEntities.create = function(type, obj) {
100
+ createTempItemCalls.push([type, obj]);
101
+ };
102
+ // Manual mock for pointOnScene
103
+ DesignCore.Mouse.pointOnScene = function() {
104
+ return new Point(5, 5);
105
+ };
106
+ // Manual mock for selection set
107
+ DesignCore.Scene.selectionManager.selectionSet.selectionSet = [];
108
+
109
+ const points = [];
110
+
111
+ const Pt10 = new Point();
112
+ Pt10.sequence = 10;
113
+ points.push(Pt10);
114
+
115
+ const Pt15 = new Point(10, 0);
116
+ Pt15.sequence = 15;
117
+ points.push(Pt15);
118
+
119
+ // Test with no selection - no action
120
+ const dim1 = new DiametricDimension();
121
+ dim1.points = points;
122
+ expect(() => dim1.preview()).not.toThrow();
123
+ expect(createTempItemCalls.length).toBe(0);
124
+
125
+ // Test with selection (should call createTempItem with this.type)
126
+ const dim2 = new DiametricDimension();
127
+ dim2.points = points;
128
+ DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(1);
129
+ expect(() => dim2.preview()).not.toThrow();
130
+ expect(createTempItemCalls.some((call) => call[0] === dim2.type)).toBe(true);
131
+
132
+ // Restore
133
+ DesignCore.Scene.tempEntities.create = origCreateTempItem;
134
+ DesignCore.Mouse.pointOnScene = origPointOnScene;
135
+ DesignCore.Scene.selectionManager.selectionSet.selectionSet.length = origSeletionSet;
136
+ });
137
+
138
+ test('Test DiametricDimension.dxf', () => {
139
+ const points = [];
140
+
141
+ const Pt10 = new Point();
142
+ Pt10.sequence = 10;
143
+ points.push(Pt10);
144
+
145
+ const Pt11 = new Point(20, 0);
146
+ Pt11.sequence = 11;
147
+ points.push(Pt11);
148
+
149
+ const Pt15 = new Point(10, 0);
150
+ Pt15.sequence = 15;
151
+ points.push(Pt15);
152
+
153
+ points.push(Pt10, Pt11, Pt15);
154
+
155
+ const dimension = new DiametricDimension({ points: points, handle: '1' });
156
+ let file = new File();
157
+ dimension.dxf(file);
158
+ // console.log(file.contents);
159
+
160
+ const dxfString = `0
161
+ DIMENSION
162
+ 5
163
+ 1
164
+ 100
165
+ AcDbEntity
166
+ 100
167
+ AcDbDimension
168
+ 8
169
+ 0
170
+ 10
171
+ 0
172
+ 20
173
+ 0
174
+ 30
175
+ 0.0
176
+ 11
177
+ 20
178
+ 21
179
+ 0
180
+ 31
181
+ 0.0
182
+ 70
183
+ 3
184
+ 3
185
+ STANDARD
186
+ 100
187
+ AcDbDiametricDimension
188
+ 15
189
+ 10
190
+ 25
191
+ 0
192
+ 35
193
+ 0.0
194
+ `;
195
+
196
+ expect(file.contents).toEqual(dxfString);
197
+
198
+ // create new entity from entity data to ensure all props are loaded
199
+ const newDimension = new DiametricDimension(dimension);
200
+ file = new File();
201
+ newDimension.dxf(file);
202
+ expect(file.contents).toEqual(dxfString);
203
+ });