@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,550 @@
1
+
2
+ import { Utils } from '../lib/utils.js';
3
+ import { Strings } from '../lib/strings.js';
4
+ import { Arc } from '../entities/arc.js';
5
+ import { BasePolyline } from '../entities/basePolyline.js';
6
+ import { Line } from '../entities/line.js';
7
+ import { Input, PromptOptions } from '../lib/inputManager.js';
8
+ import { Logging } from '../lib/logging.js';
9
+ import { DXFFile } from '../lib/dxf/dxfFile.js';
10
+ import { BaseDimension } from './baseDimension.js';
11
+ import { Intersection } from '../lib/intersect.js';
12
+ import { Point } from '../entities/point.js';
13
+
14
+ import { Text } from '../entities/text.js'; // used to debug the dimension points
15
+
16
+ import { DesignCore } from '../designCore.js';
17
+
18
+ /**
19
+ * Angular Dimension Entity Class
20
+ * @extends BaseDimension
21
+ */
22
+ export class AngularDimension extends BaseDimension {
23
+ /**
24
+ * Create an Angular Dimension
25
+ * @param {Array} data
26
+ */
27
+ constructor(data) {
28
+ super(data);
29
+ this.dimType.setDimType(2); // Angular dimension
30
+ }
31
+
32
+ /**
33
+ * Register the command
34
+ * @return {Object}
35
+ * command = name of the command
36
+ * shortcut = shortcut for the command
37
+ * type = type to group command in toolbars (omitted if not shown)
38
+ */
39
+ static register() {
40
+ const command = { command: 'AngularDimension', shortcut: 'DIMANG' };
41
+ return command;
42
+ }
43
+
44
+ /**
45
+ * Execute method
46
+ * executes the workflow, requesting input required to create an entity
47
+ */
48
+ async execute() {
49
+ try {
50
+ this.dimensionStyle = DesignCore.DimStyleManager.getCstyle();
51
+ this.dimType.setDimType(2); // Angular dimension
52
+
53
+ let Pt10;
54
+ let Pt15;
55
+ let Pt13;
56
+ let Pt14;
57
+
58
+ while (!Pt10 && !Pt15) {
59
+ this.points = [];
60
+ DesignCore.Scene.selectionManager.reset();
61
+
62
+ const op = new PromptOptions(Strings.Input.SELECT, [Input.Type.SINGLESELECTION]);
63
+ const selection = await DesignCore.Scene.inputManager.requestInput(op);
64
+ let selectedItem = DesignCore.Scene.entities.get(selection.selectedItemIndex);
65
+
66
+ if ([Line, BasePolyline].some((entity) => selectedItem instanceof entity)) {
67
+ if (selectedItem instanceof BasePolyline) {
68
+ // get the segment closest to the mouse point
69
+ const segment = selectedItem.getClosestSegment(selection.selectedPoint);
70
+
71
+ if (segment instanceof Line) {
72
+ // update the selected item to be the polyline arc segment
73
+ selectedItem = segment;
74
+ }
75
+ }
76
+
77
+ if (selectedItem instanceof Line) {
78
+ Pt15 = selectedItem.points[0];
79
+ Pt15.sequence = 15;
80
+ this.points.push(Pt15);
81
+
82
+ Pt10 = selectedItem.points[1];
83
+ Pt10.sequence = 10;
84
+ this.points.push(Pt10);
85
+ }
86
+ }
87
+ }
88
+
89
+ while (!Pt13 && !Pt14) {
90
+ DesignCore.Scene.selectionManager.reset();
91
+ const op1 = new PromptOptions(Strings.Input.SELECT, [Input.Type.SINGLESELECTION]);
92
+ const selection2 = await DesignCore.Scene.inputManager.requestInput(op1);
93
+ let selectedItem = DesignCore.Scene.entities.get(selection2.selectedItemIndex);
94
+
95
+ if ([Line, BasePolyline].some((entity) => selectedItem instanceof entity)) {
96
+ if (selectedItem instanceof BasePolyline) {
97
+ // get the segment closest to the mouse point
98
+ const segment = selectedItem.getClosestSegment(selection2.selectedPoint);
99
+
100
+ if (segment instanceof Line) {
101
+ // update the selected item to be the polyline arc segment
102
+ selectedItem = segment;
103
+ }
104
+ }
105
+ if (selectedItem instanceof Line) {
106
+ Pt13 = selectedItem.points[0];
107
+ Pt13.sequence = 13;
108
+ this.points.push(Pt13);
109
+
110
+ Pt14 = selectedItem.points[1];
111
+ Pt14.sequence = 14;
112
+ this.points.push(Pt14);
113
+ }
114
+ }
115
+ }
116
+
117
+ const op2 = new PromptOptions(Strings.Input.START, [Input.Type.POINT]);
118
+ const Pt11 = await DesignCore.Scene.inputManager.requestInput(op2);
119
+
120
+ const tempLineOne = new Line({ points: [Pt15, Pt10] });
121
+ const tempLineTwo = new Line({ points: [Pt13, Pt14] });
122
+
123
+ this.points = AngularDimension.getPointsFromSelection([tempLineOne, tempLineTwo], Pt11);
124
+
125
+ DesignCore.Scene.inputManager.executeCommand(this);
126
+ } catch (err) {
127
+ Logging.instance.error(`${this.type} - ${err}`);
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Preview the entity during creation
133
+ */
134
+ preview() {
135
+ if (this.points.length >= 4) {
136
+ const Pt11 = DesignCore.Mouse.pointOnScene();
137
+ Pt11.sequence = 11;
138
+
139
+ const Pt15 = this.getPointBySequence(this.points, 15);
140
+ const Pt10 = this.getPointBySequence(this.points, 10);
141
+ const Pt13 = this.getPointBySequence(this.points, 13);
142
+ const Pt14 = this.getPointBySequence(this.points, 14);
143
+
144
+ const tempLineOne = new Line({ points: [Pt15, Pt10] });
145
+ const tempLineTwo = new Line({ points: [Pt13, Pt14] });
146
+
147
+ const points = AngularDimension.getPointsFromSelection([tempLineOne, tempLineTwo], Pt11);
148
+
149
+ DesignCore.Scene.tempEntities.create(this.type, { points: points, dimensionStyle: this.dimensionStyle });
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Get sequenced points from user selection
155
+ * @param {any} items
156
+ * @param {Point} textPos
157
+ * @return {Array} array of points
158
+ */
159
+ static getPointsFromSelection(items, textPos) {
160
+ // Transform the items into points
161
+ // Do nothing more than transform the items into points
162
+
163
+ const points = [];
164
+ const item1 = items[0];
165
+ const item2 = items[1];
166
+
167
+ const tempPt15 = item1.points[0];
168
+ const tempPt10 = item1.points[1];
169
+
170
+ const tempPt13 = item2.points[0];
171
+ const tempPt14 = item2.points[1];
172
+
173
+ // Check the lines intersect
174
+ const intersect = Intersection.intersectSegmentSegment(tempPt15, tempPt10, tempPt13, tempPt14, false, true);
175
+ const intersectPt = intersect.points[0];
176
+
177
+ if (intersectPt === undefined) {
178
+ const err = 'Invalid selection - undefined origin';
179
+ Logging.instance.warn(`${this.type} - ${err}`);
180
+ return;
181
+ }
182
+
183
+ const Pt15 = new Point(tempPt15.x, tempPt15.y);
184
+ Pt15.sequence = 15;
185
+ points.push(Pt15);
186
+
187
+ const Pt10 = new Point(tempPt10.x, tempPt10.y);
188
+ Pt10.sequence = 10;
189
+ points.push(Pt10);
190
+
191
+ const Pt13 = new Point(tempPt13.x, tempPt13.y);
192
+ Pt13.sequence = 13;
193
+ points.push(Pt13);
194
+
195
+ const Pt14 = new Point(tempPt14.x, tempPt14.y);
196
+ Pt14.sequence = 14;
197
+ points.push(Pt14);
198
+
199
+ // Add text position
200
+ const Pt11 = new Point(textPos.x, textPos.y);
201
+ Pt11.sequence = 11;
202
+ points.push(Pt11);
203
+
204
+ // Add arc defining point
205
+ // TODO: Pt16 should be 2/3 of the arc between pt10 and pt14
206
+ const Pt16 = new Point(textPos.x, textPos.y);
207
+ Pt16.sequence = 16;
208
+ points.push(Pt16);
209
+
210
+ return points;
211
+ }
212
+
213
+
214
+ /**
215
+ * Sort the dimension points
216
+ * @return {Array} - Array of points sorted in the order required for the angular dimension
217
+ */
218
+ sortDimensionPoints() {
219
+ // There are two definitions for angular dimensions;
220
+
221
+ // --------------------
222
+ // Type 2 - Angular Dimension
223
+ // --------------------
224
+ // Pt16 = Dimension line position
225
+ // Pt11 = Text position
226
+ // Pt13 = Additional extension line 1 start - Origin of dimension
227
+ // Pt14 = Additional extension line 1 end
228
+ // Pt15 = Additional extension line 2 start
229
+ // Pt10 = Additional extension line 2 end
230
+
231
+ // get the points by sequence
232
+ let tempPt15 = this.getPointBySequence(this.points, 15); // Pt15 is second line start point
233
+ let tempPt10 = this.getPointBySequence(this.points, 10); // Pt10 is the second line end point
234
+
235
+ let tempPt13 = this.getPointBySequence(this.points, 13); // Pt13 is the first line start point
236
+ let tempPt14 = this.getPointBySequence(this.points, 14); // Pt14 is the first line end point
237
+
238
+ // Check the lines intersect
239
+ const intersect = Intersection.intersectSegmentSegment(tempPt15, tempPt10, tempPt13, tempPt14, false, true);
240
+ const intersectPt = intersect.points[0];
241
+
242
+ if (tempPt10.distance(intersectPt) < tempPt15.distance(intersectPt)) {
243
+ const swapPt = tempPt10;
244
+ tempPt10 = tempPt15;
245
+ tempPt15 = swapPt;
246
+ }
247
+
248
+ if (tempPt14.distance(intersectPt) < tempPt13.distance(intersectPt)) {
249
+ const swapPt = tempPt13;
250
+ tempPt13 = tempPt14;
251
+ tempPt14 = swapPt;
252
+ }
253
+
254
+ // Ensure points are in CCW order
255
+ if (intersectPt.angle(tempPt10) < intersectPt.angle(tempPt14)) {
256
+ let swapPt = tempPt15;
257
+ tempPt15 = tempPt13;
258
+ tempPt13 = swapPt;
259
+
260
+ swapPt = tempPt10;
261
+ tempPt10 = tempPt14;
262
+ tempPt14 = swapPt;
263
+ }
264
+
265
+ const line1Angle = tempPt13.angle(tempPt14);
266
+ const line2Angle = tempPt15.angle(tempPt10);
267
+ const dimension = line2Angle - line1Angle;
268
+
269
+ // Ensure points are in CCW order
270
+ if (dimension > Math.PI) {
271
+ let swapPt = tempPt15;
272
+ tempPt15 = tempPt13;
273
+ tempPt13 = swapPt;
274
+
275
+ swapPt = tempPt10;
276
+ tempPt10 = tempPt14;
277
+ tempPt14 = swapPt;
278
+ }
279
+
280
+ const sortedPoints = [];
281
+ const Pt15 = new Point(tempPt15.x, tempPt15.y);
282
+ Pt15.sequence = 15;
283
+ sortedPoints.push(Pt15);
284
+
285
+ const Pt10 = new Point(tempPt10.x, tempPt10.y);
286
+ Pt10.sequence = 10;
287
+ sortedPoints.push(Pt10);
288
+
289
+ const Pt13 = new Point(tempPt13.x, tempPt13.y);
290
+ Pt13.sequence = 13;
291
+ sortedPoints.push(Pt13);
292
+
293
+ const Pt14 = new Point(tempPt14.x, tempPt14.y);
294
+ Pt14.sequence = 14;
295
+ sortedPoints.push(Pt14);
296
+
297
+ return sortedPoints;
298
+ }
299
+
300
+ /**
301
+ * Build the dimension
302
+ * @param {Object} style
303
+ * @return {Array} - Array of entities that compose the dimension
304
+ */
305
+ buildDimension() {
306
+ // Get sorted and sequenced points
307
+ const sortedPoints = this.sortDimensionPoints();
308
+ const Pt13 = this.getPointBySequence(sortedPoints, 13);
309
+ const Pt14 = this.getPointBySequence(sortedPoints, 14);
310
+ const Pt15 = this.getPointBySequence(sortedPoints, 15);
311
+ const Pt10 = this.getPointBySequence(sortedPoints, 10);
312
+ const Pt16 = this.getPointBySequence(this.points, 16);
313
+ const Pt11 = this.getPointBySequence(this.points, 11);
314
+
315
+ // Style values
316
+ const DIMTIH = this.getDimensionStyle().getValue('DIMTIH'); // Text inside horizontal alignment
317
+ const DIMTOH = this.getDimensionStyle().getValue('DIMTOH'); // Text outside horizontal alignment
318
+ const DIMASZ = this.getDimensionStyle().getValue('DIMASZ'); // Arrow size (used for extension line length)
319
+ const DIMTXT = this.getDimensionStyle().getValue('DIMTXT'); // Text size (used for estimated text width)
320
+ const DIMTAD = this.getDimensionStyle().getValue('DIMTAD'); // Text vertical position
321
+ const DIMEXE = this.getDimensionStyle().getValue('DIMEXE'); // Extend beyond dimension line distance
322
+ const DIMEXO = this.getDimensionStyle().getValue('DIMEXO'); // Offset from origin distance
323
+ const DIMJUST = this.getDimensionStyle().getValue('DIMJUST'); // Justification of the dimension text
324
+ const DIMGAP = this.getDimensionStyle().getValue('DIMGAP'); // Gap between dimension line and text
325
+ const DIMSE1 = this.getDimensionStyle().getValue('DIMSE1'); // Suppress first extension line
326
+ const DIMSE2 = this.getDimensionStyle().getValue('DIMSE2'); // Suppress second extension line
327
+ const DIMSD1 = this.getDimensionStyle().getValue('DIMSD1'); // Suppress first dimension line
328
+ const DIMSD2 = this.getDimensionStyle().getValue('DIMSD2'); // Suppress second dimension line
329
+
330
+ // Intersection and radius
331
+ const intersectPt = Intersection.intersectSegmentSegment(Pt15, Pt10, Pt13, Pt14, false, true).points[0];
332
+ const radius = intersectPt.distance(Pt16);
333
+
334
+ // check dimension is valid
335
+ if (radius === 0) {
336
+ return;
337
+ }
338
+
339
+ // Inline quadrant/arrow/line logic
340
+ const quadOneStart = Pt14;
341
+ const quadOneEnd = Pt10;
342
+ const quadTwoStart = Pt14.rotate(intersectPt, Math.PI);
343
+ const quadTwoEnd = Pt10.rotate(intersectPt, Math.PI);
344
+ let arrow1pos = intersectPt;
345
+ let arrow2pos = intersectPt;
346
+ let line1Extents = Pt14;
347
+ let line2Extents = Pt10;
348
+ if (Pt16.isOnArc(quadOneStart, quadOneEnd, intersectPt, 1)) {
349
+ arrow1pos = intersectPt.project(intersectPt.angle(quadOneStart), radius);
350
+ arrow2pos = intersectPt.project(intersectPt.angle(quadOneEnd), radius);
351
+ line1Extents = Pt14;
352
+ line2Extents = Pt10;
353
+ } else if (Pt16.isOnArc(quadOneEnd, quadTwoStart, intersectPt, 1)) {
354
+ arrow1pos = intersectPt.project(intersectPt.angle(quadOneEnd), radius);
355
+ arrow2pos = intersectPt.project(intersectPt.angle(quadTwoStart), radius);
356
+ line1Extents = Pt10;
357
+ line2Extents = Pt13;
358
+ } else if (Pt16.isOnArc(quadTwoStart, quadTwoEnd, intersectPt, 1)) {
359
+ arrow1pos = intersectPt.project(intersectPt.angle(quadTwoStart), radius);
360
+ arrow2pos = intersectPt.project(intersectPt.angle(quadTwoEnd), radius);
361
+ line1Extents = Pt13;
362
+ line2Extents = Pt15;
363
+ } else if (Pt16.isOnArc(quadTwoEnd, quadOneStart, intersectPt, 1)) {
364
+ arrow1pos = intersectPt.project(intersectPt.angle(quadTwoEnd), radius);
365
+ arrow2pos = intersectPt.project(intersectPt.angle(quadOneStart), radius);
366
+ line1Extents = Pt15;
367
+ line2Extents = Pt14;
368
+ }
369
+
370
+ const line1Angle = intersectPt.angle(arrow1pos);
371
+ const line2Angle = intersectPt.angle(arrow2pos);
372
+ let dimension = line2Angle - line1Angle;
373
+ if (dimension < 0) dimension += Math.PI * 2;
374
+
375
+ // Text and arc calculations
376
+ const approxTextWidth = Text.getApproximateWidth(this.getDimensionValue(Utils.radians2degrees(dimension)), DIMTXT) * 1.25;
377
+ const approxTextHalfWidth = approxTextWidth * 0.5;
378
+ const circumference = 2 * Math.PI * radius;
379
+ const radiansPerLengthUnit = (2 * Math.PI) / circumference;
380
+ const arcAdjustment = approxTextHalfWidth * radiansPerLengthUnit;
381
+ const arrowRadians = DIMASZ * radiansPerLengthUnit;
382
+ const textOutSide = (approxTextWidth * 1.5) * radiansPerLengthUnit >= dimension;
383
+ const arrowsOutside = arrowRadians * 3 >= dimension;
384
+ const horizontalText = (DIMTIH !== 0 && !textOutSide) || (DIMTOH !== 0 && textOutSide);
385
+
386
+ // Arc/text positions
387
+ const arcMiddle = intersectPt.project(intersectPt.angle(arrow1pos.midPoint(arrow2pos)), radius);
388
+ let textPosition = arcMiddle;
389
+ let textRotation = this.getTextDirection(horizontalText ? 0 : arrow1pos.angle(arrow2pos));
390
+ let textAboveDirection = textRotation + Math.PI / 2;
391
+ let textAboveDistance = DIMTXT * 0.5 + DIMGAP;
392
+ const outsideOffsetDirection = Pt11.distance(arrow1pos) < Pt11.distance(arrow2pos) ? -1 : 1;
393
+ const textPositionOffsetAngle = arrowRadians * 3;
394
+ const internalPositionAdjustmentAngle = dimension * 0.5 > textPositionOffsetAngle ? dimension * 0.5 - textPositionOffsetAngle : 0;
395
+ const externalPositionAdjustmentAngle = dimension * 0.5 + textPositionOffsetAngle;
396
+
397
+ // Text justification
398
+ switch (DIMJUST) {
399
+ case 0:
400
+ if (textOutSide) textPosition = arcMiddle.rotate(intersectPt, externalPositionAdjustmentAngle * outsideOffsetDirection);
401
+ break;
402
+ case 1:
403
+ if (textOutSide) {
404
+ textPosition = arcMiddle.rotate(intersectPt, externalPositionAdjustmentAngle * outsideOffsetDirection);
405
+ } else {
406
+ textPosition = arcMiddle.rotate(intersectPt, internalPositionAdjustmentAngle);
407
+ textRotation = this.getTextDirection(horizontalText ? 0 : (intersectPt.angle(textPosition) + Math.PI / 2));
408
+ }
409
+ break;
410
+ case 2:
411
+ if (textOutSide) {
412
+ textPosition = arcMiddle.rotate(intersectPt, (dimension * 0.5 + DIMASZ * 2 * radiansPerLengthUnit) * outsideOffsetDirection);
413
+ } else {
414
+ textPosition = arcMiddle.rotate(intersectPt, -internalPositionAdjustmentAngle);
415
+ textRotation = this.getTextDirection(horizontalText ? 0 : (intersectPt.angle(textPosition) + Math.PI / 2));
416
+ }
417
+ break;
418
+ case 3:
419
+ textPosition = arrow1pos.project(line1Angle, (approxTextHalfWidth + DIMEXE + DIMTXT));
420
+ textRotation = this.getTextDirection(line1Angle);
421
+ textAboveDirection = textRotation + Math.PI / 2;
422
+ break;
423
+ case 4:
424
+ textPosition = arrow2pos.project(line2Angle, (approxTextHalfWidth + DIMEXE + DIMTXT));
425
+ textRotation = this.getTextDirection(line2Angle);
426
+ textAboveDirection = textRotation + Math.PI / 2;
427
+ break;
428
+ }
429
+
430
+ // Text vertical position
431
+ const textAndDimlineAligned = this.alignedOrOpposite(textRotation, (intersectPt.angle(textPosition) + Math.PI / 2));
432
+ const textIsOnExtensionLine = textPosition.perpendicular(intersectPt, arrow1pos).isSame(textPosition) || textPosition.perpendicular(intersectPt, arrow2pos).isSame(textPosition);
433
+ if (!textAndDimlineAligned && !textIsOnExtensionLine) textAboveDistance = 0;
434
+ switch (DIMTAD) {
435
+ case 1:
436
+ case 2:
437
+ case 3:
438
+ textPosition = textPosition.project(textAboveDirection, textAboveDistance);
439
+ break;
440
+ case 4:
441
+ textPosition = textPosition.project(textAboveDirection, -textAboveDistance);
442
+ break;
443
+ }
444
+
445
+ // Add dimension text entity
446
+ const entities = [];
447
+ entities.push(this.getDimensionText(Utils.radians2degrees(dimension), textPosition, textRotation));
448
+
449
+ // Arc and arrow geometry
450
+ const textDimlineIntersection = intersectPt.project(intersectPt.angle(textPosition), radius);
451
+ const textIsOnDimLine = Utils.round(intersectPt.distance(textPosition)) === Utils.round(radius);
452
+ const textIsOnExtensionLineOne = textPosition.perpendicular(intersectPt, arrow1pos).isSame(textPosition);
453
+ const textIsOnExtensionLineTwo = textPosition.perpendicular(intersectPt, arrow2pos).isSame(textPosition);
454
+ const textAndExtlineOneAligned = this.alignedOrOpposite(textRotation, intersectPt.angle(arrow1pos));
455
+ const textAndExtlineTwoAligned = this.alignedOrOpposite(textRotation, intersectPt.angle(arrow2pos));
456
+
457
+ // Arrow heads
458
+ const arcOffset = radius - Math.sqrt(radius * radius - DIMASZ * DIMASZ);
459
+ const arcRotationOffset = Math.asin(arcOffset / DIMASZ);
460
+ const arrowRotation = arrowsOutside ? -Math.PI / 2 - arcRotationOffset : Math.PI / 2 + arcRotationOffset;
461
+ const arrowHead1 = this.getArrowHead(arrow1pos, intersectPt.angle(arrow1pos) + arrowRotation);
462
+ const arrowHead2 = this.getArrowHead(arrow2pos, intersectPt.angle(arrow2pos) - arrowRotation);
463
+
464
+ // Arc geometry
465
+ const arcStart = textIsOnDimLine ? textDimlineIntersection : arcMiddle;
466
+ const arcOneBase = arrowsOutside ? arrow1pos : !textOutSide ? arcStart : arcMiddle;
467
+ const arcOneRotation = arrowsOutside ? (-arrowRadians * 2) : ((textIsOnDimLine && !textOutSide) ? -arcAdjustment : 0);
468
+ const arcOneEnd = arcOneBase.rotate(intersectPt, arcOneRotation);
469
+ const arcOne = new Arc({ points: [intersectPt, arrow1pos, arcOneEnd], direction: arrowsOutside ? -1 : 1 });
470
+ if (!DIMSD1) {
471
+ entities.push(arrowHead1);
472
+ entities.push(arcOne);
473
+ }
474
+ const arcTwoBase = arrowsOutside ? arrow2pos : !textOutSide ? arcStart : arcMiddle;
475
+ const arcTwoRotation = arrowsOutside ? (arrowRadians * 2) : ((textIsOnDimLine && !textOutSide) ? arcAdjustment : 0);
476
+ const arcTwoEnd = arcTwoBase.rotate(intersectPt, arcTwoRotation);
477
+ const arcTwo = new Arc({ points: [intersectPt, arrow2pos, arcTwoEnd], direction: arrowsOutside ? 1 : -1 });
478
+ if (!DIMSD2) {
479
+ entities.push(arrowHead2);
480
+ entities.push(arcTwo);
481
+ }
482
+
483
+ // Extension lines
484
+ const extensionLineOneStart = intersectPt.project(intersectPt.angle(arrow1pos), intersectPt.distance(line1Extents) + DIMEXO);
485
+ let extensionLineOneEnd = intersectPt.project(intersectPt.angle(arrow1pos), radius + DIMEXE);
486
+ const extensionLineTwoStart = intersectPt.project(intersectPt.angle(arrow2pos), intersectPt.distance(line2Extents) + DIMEXO);
487
+ let extensionLineTwoEnd = intersectPt.project(intersectPt.angle(arrow2pos), radius + DIMEXE);
488
+ if (textPosition.distance(arrow1pos) < textPosition.distance(arrow2pos)) {
489
+ if (!textIsOnExtensionLineOne && textAndExtlineOneAligned && !textIsOnDimLine) {
490
+ const dist = extensionLineOneEnd.distance(textPosition.perpendicular(extensionLineOneStart, extensionLineOneEnd)) + approxTextHalfWidth;
491
+ extensionLineOneEnd = extensionLineOneEnd.project(extensionLineOneStart.angle(extensionLineOneEnd), dist);
492
+ }
493
+ } else {
494
+ if (!textIsOnExtensionLineTwo && textAndExtlineTwoAligned && !textIsOnDimLine) {
495
+ const dist = extensionLineTwoEnd.distance(textPosition.perpendicular(extensionLineTwoStart, extensionLineTwoEnd)) + approxTextHalfWidth;
496
+ extensionLineTwoEnd = extensionLineTwoEnd.project(extensionLineTwoStart.angle(extensionLineTwoEnd), dist);
497
+ }
498
+ }
499
+ if (radius > intersectPt.distance(line1Extents) + DIMEXE) {
500
+ const extensionLineOne = new Line({ points: [extensionLineOneStart, extensionLineOneEnd] });
501
+ if (!DIMSE1) entities.push(extensionLineOne);
502
+ }
503
+ if (radius > intersectPt.distance(line2Extents) + DIMEXE) {
504
+ const extensionLineTwo = new Line({ points: [extensionLineTwoStart, extensionLineTwoEnd] });
505
+ if (!DIMSE2) entities.push(extensionLineTwo);
506
+ }
507
+ return entities;
508
+ }
509
+
510
+ /**
511
+ * Write the entity to file in the dxf format
512
+ * @param {DXFFile} file
513
+ */
514
+ dxf(file) {
515
+ const Pt10 = this.getPointBySequence(this.points, 10);
516
+ const Pt11 = this.getPointBySequence(this.points, 11);
517
+ const Pt13 = this.getPointBySequence(this.points, 13);
518
+ const Pt14 = this.getPointBySequence(this.points, 14);
519
+ const Pt15 = this.getPointBySequence(this.points, 15);
520
+ const Pt16 = this.getPointBySequence(this.points, 16);
521
+
522
+ file.writeGroupCode('0', 'DIMENSION');
523
+ file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
524
+ file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
525
+ file.writeGroupCode('100', 'AcDbDimension', DXFFile.Version.R2000);
526
+ file.writeGroupCode('8', this.layer);
527
+ // file.writeGroupCode('2', this.blockName); // Block not required
528
+ file.writeGroupCode('10', Pt10.x); // X - Start of Dimension Line
529
+ file.writeGroupCode('20', Pt10.y); // Y
530
+ file.writeGroupCode('30', '0.0'); // Z
531
+ file.writeGroupCode('11', Pt11.x); // X - Text Midpoint
532
+ file.writeGroupCode('21', Pt11.y); // Y
533
+ file.writeGroupCode('31', '0.0'); // Z
534
+ file.writeGroupCode('70', this.dimType.getDimType()); // DIMENSION TYPE
535
+ file.writeGroupCode('3', this.dimensionStyle); // DIMENSION STYLE
536
+ file.writeGroupCode('100', 'AcDb2LineAngularDimension', DXFFile.Version.R2000);
537
+ file.writeGroupCode('13', Pt13.x); // X
538
+ file.writeGroupCode('23', Pt13.y); // Y
539
+ file.writeGroupCode('33', '0.0'); // Z
540
+ file.writeGroupCode('14', Pt14.x); // X
541
+ file.writeGroupCode('24', Pt14.y); // Y
542
+ file.writeGroupCode('34', '0.0'); // Z
543
+ file.writeGroupCode('15', Pt15.x); // X
544
+ file.writeGroupCode('25', Pt15.y); // Y
545
+ file.writeGroupCode('35', '0.0'); // Z
546
+ file.writeGroupCode('16', Pt16.x); // X
547
+ file.writeGroupCode('26', Pt16.y); // Y
548
+ file.writeGroupCode('36', '0.0'); // Z
549
+ }
550
+ }