@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
@@ -1,9 +1,14 @@
1
+
2
+ /**
3
+ * String Class
4
+ * Holds common strings for consistency and translation
5
+ */
1
6
  export class Strings {
2
- // Error Strings
7
+ // Error Strings
3
8
  static Error = {
4
9
  ERROR: 'Error',
5
- FILEOPEN: 'Error opening file',
6
- INPUT: 'Incorrect input',
10
+ FILEOPEN: 'Error Opening File',
11
+ INPUT: 'Invalid Input',
7
12
  INVALIDFILE: 'Invalid File',
8
13
  INVALIDDXFFORMAT: 'Invalid DXF Format',
9
14
  INVALIDPOINT: 'Invalid Point Data',
@@ -11,6 +16,15 @@ export class Strings {
11
16
  INVALIDNUMBER: 'Invalid Number',
12
17
  INVALIDTYPE: 'Invalid Type',
13
18
  INVALIDINTERSECTTYPE: 'Invalid Intersect Type',
19
+ SELECTION: 'Invalid Selection',
20
+ PARALLELLINES: 'Parallel Lines',
21
+ RADIUSTOOLARGE: 'Radius too large',
22
+ INVALIDCLIPBOARD: 'Invalid Clipboard Data',
23
+ INVALIDBOUNDARY: 'Invalid Boundary Item',
24
+ NONZERO: 'Value must be positive and nonzero',
25
+ MINVALUE: 'Value is too small',
26
+ MAXVALUE: 'Value is too large',
27
+ ZEROLENGTH: 'Cannot define a zero length line',
14
28
  };
15
29
 
16
30
  // Warning Strings
@@ -27,19 +41,43 @@ export class Strings {
27
41
  CSTYLEDELETE: 'Currently selected style cannot be deleted',
28
42
  CANNOTBEDELETED: 'cannot be deleted',
29
43
  CANNOTBERENAMED: 'cannot be renamed',
44
+ CANNOTBEACTIONED: 'cannot be actioned',
45
+ COMPLETED: 'completed',
46
+ NOUNDO: 'No actions to undo',
47
+ NOREDO: 'No actions to redo',
48
+ NOTRIM: 'cannot be trimmed',
49
+ NOEXTEND: 'cannot be extended',
50
+ NOFILLET: 'cannot be filleted',
51
+ NOCHAMFER: 'cannot be chamfered',
52
+ NONCONSECUTIVESEGMENTS: 'segments must be consecutive',
53
+ NOTIMPLEMENTED: 'Not Implemented',
30
54
  };
31
55
 
32
56
  // Strings
33
57
  static Strings = {
58
+ ARC: 'Arc',
34
59
  LENGTH: 'Length',
35
60
  LINE: 'Line',
36
61
  VARIES: 'Varies',
62
+ AND: 'and',
63
+ OR: 'or',
64
+ ITEMS: 'item(s)',
65
+ ADDED: 'added',
66
+ REMOVED: 'removed',
67
+ };
68
+
69
+ // colours
70
+ static Colour = {
71
+ BYLAYER: 'ByLayer',
72
+ BYBLOCK: 'ByBlock',
37
73
  };
38
74
 
39
75
  // Unicode Symbols
40
76
  static Symbol = {
41
- DIAMETER: '\u2300',
77
+ DIAMETER: '\u00D8',
42
78
  DEGREE: '\u00B0',
79
+ RADIUS: 'R',
80
+ DELTA: '\u0394',
43
81
  };
44
82
 
45
83
  // Input Strings
@@ -50,17 +88,31 @@ export class Strings {
50
88
  START: 'Specify start point',
51
89
  END: 'Specify end point',
52
90
  POINT: 'Specify a point',
53
- DIMENSION: 'Specify dimension location',
91
+ DIMENSION: 'Specify dimension position',
92
+ CLOSE: 'Close',
54
93
  NEXTPOINT: 'Specify next point',
55
94
  RADIUS: 'Specify radius',
95
+ DIAMETER: 'Specify diameter',
56
96
  POSITION: 'Specify position',
57
97
  HEIGHT: 'Specify height',
58
98
  STRING: 'Specify text',
99
+ NAME: 'Specify name',
59
100
  OPTION: 'Specify option',
60
101
  ANGLE: 'Specify angle',
61
102
  ROTATION: 'Specify rotation angle',
62
103
  DESTINATION: 'Specify destination',
104
+ DISTANCE: 'Specify offset distance',
105
+ SIDE: 'Specify point on side to offset',
106
+ THROUGHPOINT: 'Specify through point',
63
107
  SELECT: 'Select object',
64
108
  SELECTIONSET: 'Select Items',
109
+ SOURCE: 'Select source object',
110
+ DESTINATIONSET: 'Select destination object(s)',
111
+ MIRRORFIRST: 'Specify first point of mirror line',
112
+ MIRRORSECOND: 'Specify second point of mirror line',
113
+ ERASESOURCE: 'Erase source objects?',
114
+ SCALEFACTOR: 'Specify scale factor',
115
+ REFERENCELENGTH: 'Specify reference length',
116
+ NEWLENGTH: 'Specify new length',
65
117
  };
66
118
  };
package/core/lib/utils.js CHANGED
@@ -1,8 +1,13 @@
1
+
2
+ import { Logging } from './logging.js';
3
+ import { Constants } from './constants.js';
4
+
5
+ /** Utils Class */
1
6
  export class Utils {
2
7
  /**
3
8
  * Convert degrees to radians
4
9
  * @param {number} degrees
5
- * @returns angle in radians
10
+ * @return {number} angle in radians
6
11
  */
7
12
  static degrees2radians(degrees) {
8
13
  return degrees * Math.PI / 180;
@@ -11,7 +16,7 @@ export class Utils {
11
16
  /**
12
17
  * Convert radians to degrees
13
18
  * @param {number} radians
14
- * @returns angle in degrees
19
+ * @return {number} angle in degrees
15
20
  */
16
21
  static radians2degrees(radians) {
17
22
  return radians * 180 / Math.PI;
@@ -20,19 +25,71 @@ export class Utils {
20
25
  /**
21
26
  * Round to 5 decimal places
22
27
  * @param {number} number
23
- * @returns rounded number
28
+ * @return {number} rounded number
24
29
  */
25
30
  static round(number) {
26
- return Number(number.toFixed(5));
31
+ return Number(Number(number).toFixed(Constants.Precision.DECIMALPLACES));
32
+ }
33
+
34
+ /**
35
+ * Sort points by distance to reference point
36
+ * note this mutates the points array
37
+ * @param {Array} points
38
+ * @param {Point} refPoint
39
+ */
40
+ static sortPointsByDistance(points, refPoint) {
41
+ points.sort((a, b) => {
42
+ const da = (a.x - refPoint.x) ** 2 + (a.y - refPoint.y) ** 2;
43
+ const db = (b.x - refPoint.x) ** 2 + (b.y - refPoint.y) ** 2;
44
+ return da - db; // nearest first
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Sort points around an arc center by angular position.
50
+ * Mutates the points array.
51
+ *
52
+ * @param {Array} points - array of points
53
+ * @param {Point} startPoint - arc start point
54
+ * @param {Point} endPoint - arc end point
55
+ * @param {Point} centerPoint - arc center point
56
+ * @param {number} direction - arc direction (ccw >0, cw <=0)
57
+ *
58
+ */
59
+ static sortPointsOnArc(points, startPoint, endPoint, centerPoint, direction = 1) {
60
+ if (!Array.isArray(points)) return;
61
+
62
+ const refAngle = direction > 0 ? centerPoint.angle(startPoint) : centerPoint.angle(endPoint);
63
+ const twoPi = Math.PI * 2;
64
+ const normalize = (ang) => ((ang % twoPi) + twoPi) % twoPi;
65
+
66
+ // map points to angles
67
+ const mapped = points.map((point) => {
68
+ const angle = Math.atan2(point.y - centerPoint.y, point.x - centerPoint.x);
69
+ const normalizedAngle = normalize(angle - refAngle);
70
+ return { point, normalizedAngle };
71
+ });
72
+
73
+ // sort by angle
74
+ mapped.sort((u, v) => u.normalizedAngle - v.normalizedAngle);
75
+
76
+ // direction: - ccw > 0, cw <= 0
77
+ if (direction <= 0) mapped.reverse();
78
+
79
+ // write back into original array (preserve Point instances)
80
+ for (let i = 0; i < mapped.length; i++) {
81
+ points[i] = mapped[i].point;
82
+ }
27
83
  }
28
84
 
29
85
  /**
30
86
  * Deep clone object
31
- * @param {objec} obj - object to clone
32
- * @returns - new cloned object
87
+ * @param {Object} obj - object to clone
88
+ * @return {Object} - new cloned object
33
89
  */
34
90
  static cloneObject(obj) {
35
91
  // deep clone obj and all its attributes
92
+
36
93
  if (obj === null || typeof obj !== 'object') {
37
94
  return obj;
38
95
  }
@@ -42,19 +99,46 @@ export class Utils {
42
99
 
43
100
  for (const key of Reflect.ownKeys(obj)) {
44
101
  const value = obj[key];
45
- clone[key] = value instanceof Object && typeof value !== 'function' ? this.cloneObject(value) : value;
102
+ try {
103
+ if (Array.isArray(value)) {
104
+ clone[key] = value.map((v) => this.cloneObject(v));
105
+ } else if (value && typeof value === 'object' && typeof value !== 'function') {
106
+ clone[key] = this.cloneObject(value);
107
+ } else {
108
+ clone[key] = value;
109
+ }
110
+ } catch (e) {
111
+ const err = 'Utils.cloneObject - Could not clone property';
112
+ Logging.instance.warn(`${err}:${key} - ${e}`);
113
+ }
114
+ }
115
+
116
+ // Clear handle so a fresh unique handle is assigned when added to the scene
117
+ if (clone.handle !== undefined) {
118
+ clone.handle = undefined;
46
119
  }
47
120
 
48
121
  return clone;
49
122
  }
50
123
 
124
+ /**
125
+ * Calculate area of triangle given 3 points
126
+ * @param {Point} p1
127
+ * @param {Point} p2
128
+ * @param {Point} p3
129
+ * @return {number} area of triangle
130
+ */
131
+ static areaOfTriangle(p1, p2, p3) {
132
+ return Math.abs((p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) / 2.0);
133
+ }
134
+
51
135
  /**
52
136
  * Returns a levenshtein edit distance to the input strings
53
137
  * The distance represents the minimum number of character edits required to change one string into the other.
54
138
  * a lower number suggests the strings are more similar and value of 0 means they are the same.
55
139
  * @param {string} a
56
140
  * @param {string} b
57
- * @returns {integer} levenshtein edit distance
141
+ * @return {number} levenshtein edit distance
58
142
  * inspired by https://gist.github.com/andrei-m/982927
59
143
  */
60
144
  static getLevenshteinDistance(a, b) {
@@ -67,9 +151,9 @@ export class Utils {
67
151
  m[0][j] = j;
68
152
  if (j === 0) continue;
69
153
  m[i][j] = b.charAt(i - 1) == a.charAt(j - 1) ? m[i - 1][j - 1] : Math.min(
70
- m[i-1][j-1] + 1,
71
- m[i][j-1] + 1,
72
- m[i-1][j] + 1,
154
+ m[i - 1][j - 1] + 1,
155
+ m[i][j - 1] + 1,
156
+ m[i - 1][j] + 1,
73
157
  );
74
158
  }
75
159
  }
@@ -0,0 +1,43 @@
1
+ import { DXFFile } from '../lib/dxf/dxfFile.js';
2
+ import { Property } from '../properties/property.js';
3
+
4
+ /** Dictionary Class */
5
+ export class Dictionary {
6
+ /**
7
+ * Create a Dictionary
8
+ * @param {Object} data
9
+ */
10
+ constructor(data) {
11
+ // DXF Groupcode 5 - Handle
12
+ this.handle = Property.loadValue([data?.handle, data?.[5]]);
13
+ this.name = Property.loadValue([data?.name, data?.[3]], '');
14
+ this.duplicateRecordCloning = Property.loadValue([data?.duplicateRecordCloning, data?.[281]], 1);
15
+ this.entries = Property.loadValue([data?.entries], []);
16
+
17
+ // Build entries from DXF group codes 3 (name) and 350 (handle)
18
+ if (!this.entries.length && data?.[3] !== undefined && data?.[350] !== undefined) {
19
+ const names = Array.isArray(data[3]) ? data[3] : [data[3]];
20
+ const handles = Array.isArray(data[350]) ? data[350] : [data[350]];
21
+
22
+ for (let i = 0; i < names.length && i < handles.length; i++) {
23
+ this.entries.push({ 'name': names[i], 'handle': handles[i] });
24
+ }
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Write the item to file in the dxf format
30
+ * @param {DXFFile} file
31
+ */
32
+ dxf(file) {
33
+ file.writeGroupCode('0', 'DICTIONARY', DXFFile.Version.R2000);
34
+ file.writeGroupCode('5', this.handle, DXFFile.Version.R2000);
35
+ file.writeGroupCode('100', 'AcDbDictionary', DXFFile.Version.R2000);
36
+ file.writeGroupCode('281', this.duplicateRecordCloning.toString(), DXFFile.Version.R2000);
37
+
38
+ for (let i = 0; i < this.entries.length; i++) {
39
+ file.writeGroupCode('3', this.entries[i].name, DXFFile.Version.R2000);
40
+ file.writeGroupCode('350', this.entries[i].handle, DXFFile.Version.R2000);
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,80 @@
1
+ import { Dictionary } from './dictionary.js';
2
+ import { DesignCore } from '../designCore.js';
3
+
4
+ /**
5
+ * DictionaryManager Class
6
+ * Manages DXF dictionary objects for the OBJECTS section
7
+ */
8
+ export class DictionaryManager {
9
+ /** Create a DictionaryManager */
10
+ constructor() {
11
+ this.addStandardItems();
12
+ }
13
+
14
+ /**
15
+ * Create the standard dictionary items
16
+ */
17
+ addStandardItems() {
18
+ // ACAD_GROUP: child dictionary that stores named entity groups (selections)
19
+ this.groupDictionary = new Dictionary({
20
+ 'name': 'ACAD_GROUP',
21
+ 'handle': DesignCore.HandleManager.next(),
22
+ });
23
+
24
+ // Root dictionary with entry pointing to ACAD_GROUP
25
+ this.rootDictionary = new Dictionary({
26
+ 'handle': DesignCore.HandleManager.next(),
27
+ 'entries': [{ 'name': 'ACAD_GROUP', 'handle': this.groupDictionary.handle }],
28
+ });
29
+ }
30
+
31
+ /**
32
+ * Clear all dictionary items
33
+ */
34
+ clearItems() {
35
+ this.groupDictionary = undefined;
36
+ this.rootDictionary = undefined;
37
+ }
38
+
39
+ /**
40
+ * Add a dictionary item from parsed DXF data
41
+ * @param {Object} data - parsed DICTIONARY object
42
+ */
43
+ addItem(data) {
44
+ const dictionary = new Dictionary(data);
45
+ DesignCore.HandleManager.checkHandle(dictionary.handle);
46
+
47
+ if (!this.rootDictionary) {
48
+ // The first dictionary is the root dictionary
49
+ this.rootDictionary = dictionary;
50
+ // Only keep entries for dictionaries that Design manages
51
+ const groupEntry = this.rootDictionary.entries.find((entry) => entry.name === 'ACAD_GROUP');
52
+ this.rootDictionary.entries = groupEntry ? [groupEntry] : [];
53
+ } else if (!this.groupDictionary) {
54
+ // Check if this dictionary is the ACAD_GROUP child
55
+ const groupEntry = this.rootDictionary.entries[0];
56
+ if (groupEntry && dictionary.handle === groupEntry.handle) {
57
+ dictionary.name = groupEntry.name;
58
+ this.groupDictionary = dictionary;
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Ensure standard dictionary items exist
65
+ */
66
+ checkItems() {
67
+ if (!this.rootDictionary || !this.groupDictionary) {
68
+ this.addStandardItems();
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Write the dictionaries to file in the dxf format
74
+ * @param {DXFFile} file
75
+ */
76
+ dxf(file) {
77
+ this.rootDictionary.dxf(file);
78
+ this.groupDictionary.dxf(file);
79
+ }
80
+ }
@@ -0,0 +1,117 @@
1
+
2
+ /** DimType Class */
3
+ export class DimType {
4
+ /** Create DimType
5
+ * @param {number} dimType - dxf dimType value
6
+ */
7
+ constructor(dimType=0) {
8
+ // 0 = Rotated, horizontal, or vertical;
9
+ // 1 = Aligned;
10
+ // 2 = Angular;
11
+ // 3 = Diameter;
12
+ // 4 = Radius;
13
+ // 5 = Angular 3 point;
14
+ // 6 = Ordinate;
15
+ // 32 = Indicates that the block reference (group code 2) is referenced by this dimension only
16
+ // 64 = Ordinate type. This is a bit value (bit 7) used only with integer value 6. If set, ordinate is X-type; if not set, ordinate is Y-type
17
+ // 128 = This is a bit value (bit 8) added to the other group 70 values if the dimension text
18
+
19
+ this.dimType = 0;
20
+ this.blockReference = true; // dimType bit 32 - dimension uses a block
21
+ this.xTypeOrdinate = false; // dimType bit 64 - ordinate is X-type
22
+ this.userPositionedText = false; // dimType bit 128 - text is user positioned
23
+
24
+ this.setDimType(dimType);
25
+ }
26
+
27
+ /** Check if dimension type is valid
28
+ * @param {number} dimType
29
+ * @return {boolean} true if valid dimension type
30
+ */
31
+ static isValidDimensionType(dimType) {
32
+ // get the base type
33
+ const baseType = DimType.getBaseType(dimType);
34
+ // check if base type is valid
35
+ return baseType >= 0 && baseType <= 6;
36
+ }
37
+
38
+
39
+ /** Get Base Type
40
+ * @param {number} dimType
41
+ * @return {number} base dimension type
42
+ */
43
+ static getBaseType(dimType) {
44
+ // sort the type temporarily
45
+ let baseType = Number(dimType);
46
+ // strip off the bit values
47
+ if ((baseType & 128) !== 0) {
48
+ baseType -= 128;
49
+ };
50
+ if ((baseType & 64) !== 0) {
51
+ baseType -= 64;
52
+ };
53
+ if ((baseType & 32) !== 0) {
54
+ baseType -= 32;
55
+ };
56
+ // return base type
57
+ return baseType;
58
+ }
59
+
60
+ /**
61
+ * Get Dimension Type without any flags
62
+ * @return {number}
63
+ */
64
+ getBaseDimType() {
65
+ return this.dimType;
66
+ }
67
+
68
+ /**
69
+ * Get Dimension Type with flags
70
+ * @return {number}
71
+ */
72
+ getDimType() {
73
+ let dimType = this.dimType;
74
+ if (this.blockReference) {
75
+ dimType += 32;
76
+ }
77
+ if (this.xTypeOrdinate) {
78
+ dimType += 64;
79
+ }
80
+ if (this.userPositionedText) {
81
+ dimType += 128;
82
+ }
83
+ return dimType;
84
+ }
85
+
86
+ /**
87
+ * Set Dimension Type
88
+ * @param {number} dimType
89
+ */
90
+ setDimType(dimType) {
91
+ // handle invalid input
92
+ if (!DimType.isValidDimensionType(dimType)) {
93
+ dimType = 0; // default to 0 if invalid
94
+ }
95
+
96
+ this.dimType = DimType.getBaseType(dimType);
97
+ this.blockReference = (dimType & 32) !== 0;
98
+ this.xTypeOrdinate = (dimType & 64) !== 0;
99
+ this.userPositionedText = (dimType & 128) !== 0;
100
+ }
101
+
102
+ /**
103
+ * Check if the dimension has a block reference
104
+ * @return {boolean} true if the dimension has a block reference
105
+ */
106
+ hasBlockReference() {
107
+ return this.blockReference;
108
+ }
109
+
110
+ /**
111
+ * Check if the dimension text is user positioned
112
+ * @return {boolean} true if the dimension text is user positioned
113
+ */
114
+ hasUserPositionedText() {
115
+ return this.userPositionedText;
116
+ }
117
+ }
@@ -0,0 +1,66 @@
1
+ /** Flags Class */
2
+ export class Flags {
3
+ /** Create Flags */
4
+ constructor() {
5
+ /* flags - bit-coded values
6
+ | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
7
+ 0 0 0 1 0 0 1 1
8
+ */
9
+ this.flags = 0;
10
+ }
11
+
12
+ /**
13
+ * Set the flag value
14
+ * @param {number} flagValue
15
+ */
16
+ setFlagValue(flagValue) {
17
+ const value = Number(flagValue);
18
+ if (isNaN(value) === false) {
19
+ this.flags = value;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Get the flag value
25
+ * @return {number} flags value
26
+ */
27
+ getFlagValue() {
28
+ return this.flags;
29
+ }
30
+
31
+ /**
32
+ * Get the backwards value
33
+ * @param {number} flagValue
34
+ * @return {boolean} true if flags contains the flagValue
35
+ */
36
+ hasFlag(flagValue) {
37
+ // check if the flagValue is bitmasked in flags
38
+ // Bitwise AND (&) returns a value where each number has a 1 in the respective bit
39
+ /* Example
40
+ this.flags = 7 (01011)
41
+ flagValue = 3 (0011)
42
+ bits: 16 | 8 | 4 | 2 | 1
43
+ flags: 0 | 0 | 1 | 1 | 1
44
+ flagValue: 0 | 0 | 0 | 1 | 1
45
+ result: 0 | 0 | 0 | 1 | 1
46
+ decimal: 3
47
+ */
48
+ return Boolean((this.flags & flagValue) === flagValue);
49
+ }
50
+
51
+ /**
52
+ * Set the flag value
53
+ * @param {number} flagValue
54
+ */
55
+ addValue(flagValue) {
56
+ this.flags = (this.flags | Number(flagValue));
57
+ }
58
+
59
+ /**
60
+ * Remove the flag value
61
+ * @param {number} flagValue
62
+ */
63
+ removeValue(flagValue) {
64
+ this.flags = (this.flags ^ (this.flags & flagValue));
65
+ }
66
+ }
@@ -0,0 +1,26 @@
1
+ import { Flags } from './flags.js';
2
+
3
+ /** Property Class */
4
+ export class Property {
5
+ /** Create property */
6
+ constructor() { }
7
+
8
+ /**
9
+ * Parse the input values and return a value
10
+ * @param {Array} values - list of values
11
+ * @param {any} def - default value
12
+ * @return {any}
13
+ */
14
+ static loadValue(values, def) {
15
+ // return any value in values
16
+ for (let i = 0; i < values.length; i++) {
17
+ if (values[i] !== undefined) {
18
+ // check if the value is a flags object
19
+ return (values[i] instanceof Flags) ? values[i].getFlagValue() : values[i];
20
+ }
21
+ };
22
+
23
+ // no valid values, return the default value
24
+ return def;
25
+ }
26
+ }