@design-core/core 0.0.2 → 0.0.4

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 +5 -4
  4. package/TODO.md +19 -0
  5. package/core/core/core.js +52 -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 -5
  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,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
+ });
@@ -0,0 +1,102 @@
1
+ import { Dimension } from '../../core/dimensions/dimension.js';
2
+ import { DiametricDimension } from '../../core/dimensions/diametricDimension.js';
3
+ import { Circle } from '../../core/entities/circle.js';
4
+ import { Point } from '../../core/entities/point.js';
5
+ import { Line } from '../../core/entities/line.js';
6
+ import { Arc } from '../../core/entities/arc.js';
7
+ import { Polyline } from '../../core/entities/polyline.js';
8
+ import { Core } from '../../core/core/core.js';
9
+ import { DesignCore } from '../../core/designCore.js';
10
+ import { SingleSelection } from '../../core/lib/selectionManager.js';
11
+ import { withMockInput } from '../test-helpers/test-helpers.js';
12
+
13
+ // initialise core
14
+ new Core();
15
+
16
+ // Test cases for user input
17
+ const scenarios = [
18
+
19
+ { desc: 'Rotated dimension from line selection',
20
+ input: [new SingleSelection(0, new Point()), new Point(5, 5)],
21
+ selectedItems: [new Line({ points: [new Point(), new Point(10, 0)] })],
22
+ expectedDimType: 0,
23
+ },
24
+ { desc: 'Aligned dimension from line selection',
25
+ input: [new SingleSelection(0, new Point()), new Point(6.5, 3.5)],
26
+ selectedItems: [new Line({ points: [new Point(), new Point(10, 10)] })],
27
+ expectedDimType: 1,
28
+ },
29
+ { desc: 'Rotated dimension from point selection',
30
+ input: [new Point(), new Point(10, 0), new Point(5, 5)],
31
+ selectedItems: [],
32
+ expectedDimType: 0,
33
+ },
34
+ { desc: 'Diametric dimension from circle selection',
35
+ input: [new SingleSelection(0, new Point()), new Point(20, 10)],
36
+ selectedItems: [new Circle({ points: [new Point(), new Point(10, 0)] })],
37
+ expectedDimType: 3,
38
+ },
39
+ { desc: 'Radial dimension from arc selection',
40
+ input: [new SingleSelection(0, new Point()), new Point(20, 10)],
41
+ selectedItems: [new Arc({ points: [new Point(), new Point(10, 0), new Point(10, 10)] })],
42
+ expectedDimType: 4,
43
+ },
44
+ { desc: 'Angular dimension from line selection',
45
+ input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, 5)],
46
+ selectedItems: [new Line({ points: [new Point(), new Point(10, 0)] }), new Line({ points: [new Point(), new Point(10, 10)] })],
47
+ expectedDimType: 2,
48
+ },
49
+ { desc: 'Aligned dimension from polyline selection',
50
+ input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, 5)],
51
+ selectedItems: [new Polyline({ points: [new Point(), new Point(10, 0)] })],
52
+ expectedDimType: 1,
53
+ },
54
+ { desc: 'Radial dimension from polyline selection',
55
+ input: [new SingleSelection(0, new Point(16, 5)), new Point(20, 5)],
56
+ selectedItems: [new Polyline({ points: [new Point(), new Point(10, 0, 1), new Point(10, 10)] })],
57
+ expectedDimType: 4,
58
+ },
59
+ { desc: 'Angular dimension from polyline selection',
60
+ input: [new SingleSelection(0, new Point(5, 0)), new SingleSelection(1, new Point(5, 5)), new Point(5, 5)],
61
+ selectedItems: [new Polyline({ points: [new Point(), new Point(10, 0)] }), new Polyline({ points: [new Point(), new Point(10, 10)] })],
62
+ expectedDimType: 2,
63
+ },
64
+
65
+ ];
66
+
67
+ test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
68
+ const { input, selectedItems, expectedDimType } = scenario;
69
+
70
+ await withMockInput(DesignCore.Scene, input, async () => {
71
+ const dim = new Dimension();
72
+ await dim.execute();
73
+
74
+ expect(dim.dimType.getBaseDimType()).toBe(expectedDimType);
75
+ }, { selectedItems });
76
+ });
77
+
78
+ test('constructor instantiates correct dimension type', () => {
79
+ const data = { 70: 3, 2: 'blockName' };
80
+ const dim = new Dimension(data);
81
+ expect(dim instanceof DiametricDimension).toBe(true);
82
+ });
83
+
84
+ test('register returns command object', () => {
85
+ expect(Dimension.register()).toEqual({ command: 'Dimension', shortcut: 'DIM' });
86
+ });
87
+
88
+ test('get linear dimension type', () => {
89
+ const dim = new Dimension();
90
+ expect(dim.getLinearDimensionType(new Point(0, 0), new Point(10, 0), new Point(5, 5))).toBe(0);
91
+ expect(dim.getLinearDimensionType(new Point(0, 0), new Point(10, 10), new Point(7.5, 2.5))).toBe(1);
92
+ expect(dim.getLinearDimensionType(new Point(0, 0), new Point(10, 10), new Point(12.5, 8.5))).toBe(0);
93
+ });
94
+
95
+
96
+ test('preview calls createTempItem with correct args', () => {
97
+ const dim = new Dimension({ 70: 1 });
98
+ dim.selectedItems = [1];
99
+ dim.points = [{}, {}];
100
+ // Should not throw
101
+ expect(() => dim.preview()).not.toThrow();
102
+ });