@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,20 +1,27 @@
1
+ import { Utils } from '../lib/utils.js';
2
+ import { Constants } from '../lib/constants.js';
3
+
4
+ /** Point Entity Class */
1
5
  export class Point {
2
6
  /**
3
- * @param {Number} x
7
+ * Create a Point
8
+ * @param {number} x
4
9
  * @param {number} y
10
+ * @param {number} bulge
11
+ * @param {number} sequence - dxf group code sequence reference
5
12
  */
6
- constructor(x, y) {
13
+ constructor(x, y, bulge = 0, sequence) {
7
14
  this.type = this.constructor.name;
8
15
  this.x = 0;
9
16
  this.y = 0;
10
17
  // sequence holds a reference to the dxf group code sequence the point represents
11
18
  // 10, 20, 30;
12
19
  // 11, 21, 31;
13
- this.sequence;
20
+ this.sequence = sequence;
14
21
 
15
22
  // bulge value used for defining arcs in polylines
16
23
  // arc is ccw if positive
17
- this.bulge = 0;
24
+ this.bulge = bulge;
18
25
 
19
26
  if (x !== undefined) {
20
27
  this.x = x;
@@ -25,39 +32,44 @@ export class Point {
25
32
  /**
26
33
  * Add this to that
27
34
  * @param {Point} that
35
+ * @return {Point}
28
36
  */
29
37
  add(that) {
30
- return new Point(this.x + that.x, this.y + that.y);
38
+ return new Point(this.x + that.x, this.y + that.y, this.bulge, this.sequence);
31
39
  }
32
40
 
33
41
  /**
34
42
  * subtract that from this
35
43
  * @param {Point} that
44
+ * @return {Point}
36
45
  */
37
46
  subtract(that) {
38
- return new Point(this.x - that.x, this.y - that.y);
47
+ return new Point(this.x - that.x, this.y - that.y, this.bulge, this.sequence);
39
48
  };
40
49
 
41
50
  /**
42
51
  * Angle between this and that in radians
43
52
  * @param {Point} that
53
+ * @return {number}
44
54
  */
45
55
  angle(that) {
46
56
  const angle = Math.atan2((this.y - that.y), (this.x - that.x)) + Math.PI;
47
- return angle % (Math.PI*2);
57
+ return angle % (Math.PI * 2);
48
58
  }
49
59
 
50
60
 
51
61
  /**
52
62
  * Returns a deep clone of a point
63
+ * @return {Point}
53
64
  */
54
65
  clone() {
55
- return new Point(this.x, this.y);
66
+ return new Point(this.x, this.y, this.bulge, this.sequence);
56
67
  };
57
68
 
58
69
  /**
59
70
  * Returns distance between this and that
60
71
  * @param {Point} that
72
+ * @return {number}
61
73
  */
62
74
  distance(that) {
63
75
  return Math.sqrt((this.x - that.x) * (this.x - that.x) + (this.y - that.y) * (this.y - that.y));
@@ -66,26 +78,100 @@ export class Point {
66
78
 
67
79
  /**
68
80
  * Return dot product of this and that
81
+ * Measures how much two vectors point in the same direction.
82
+ * Equal to |this| * |that| * cos(angle between them).
83
+ * Positive: vectors point in the same direction (angle < 90°)
84
+ * Zero: vectors are perpendicular (angle = 90°)
85
+ * Negative: vectors point in opposite directions (angle > 90°)
69
86
  * @param {Point} that
87
+ * @return {number}
70
88
  */
71
89
  dot(that) {
72
90
  return this.x * that.x + this.y * that.y;
73
91
  };
74
92
 
93
+ /**
94
+ * Return 2D cross product of this and that
95
+ * Measures the signed area of the parallelogram formed by the two vectors.
96
+ * Equal to |this| * |that| * sin(angle from this to that).
97
+ * Positive: that is counter-clockwise from this
98
+ * Zero: vectors are parallel (or one is zero length)
99
+ * Negative: that is clockwise from this
100
+ * @param {Point} that
101
+ * @return {number}
102
+ */
103
+ cross(that) {
104
+ return this.x * that.y - this.y * that.x;
105
+ };
106
+
107
+ /**
108
+ * Return new point mirrored across the line defined by pt1 and pt2
109
+ * @param {Point} pt1 - first point on the mirror line
110
+ * @param {Point} pt2 - second point on the mirror line
111
+ * @return {Point}
112
+ */
113
+ mirror(pt1, pt2) {
114
+ if (pt1.isSame(pt2)) return this.clone();
115
+ const perp = this.perpendicular(pt1, pt2);
116
+ return new Point(2 * perp.x - this.x, 2 * perp.y - this.y, -this.bulge, this.sequence);
117
+ }
118
+
119
+ /**
120
+ * Return new point scaled from base by a scalar factor
121
+ * @param {Point} base
122
+ * @param {number} factor
123
+ * @return {Point}
124
+ */
125
+ scaleFrom(base, factor) {
126
+ const x = base.x + (this.x - base.x) * factor;
127
+ const y = base.y + (this.y - base.y) * factor;
128
+ return new Point(x, y, this.bulge, this.sequence);
129
+ }
130
+
75
131
  /**
76
132
  * Return new point rotated about centre by angle in radians
77
133
  * @param {Point} centre
78
- * @param {Number} angle - in radians
134
+ * @param {number} angle - in radians
135
+ * @return {Point}
79
136
  */
80
137
  rotate(centre, angle) {
81
138
  const x = centre.x + (this.x - centre.x) * Math.cos(angle) - (this.y - centre.y) * Math.sin(angle);
82
139
  const y = centre.y + (this.x - centre.x) * Math.sin(angle) + (this.y - centre.y) * Math.cos(angle);
83
- return new Point(x, y);
140
+ return new Point(x, y, this.bulge, this.sequence);
141
+ }
142
+
143
+ /**
144
+ * Return the length (magnitude) of this vector.
145
+ * @return {number}
146
+ */
147
+ length() {
148
+ return Math.sqrt(this.x ** 2 + this.y ** 2);
149
+ }
150
+
151
+ /**
152
+ * Return a new unit vector in the same direction as this.
153
+ * (Divides each component by the vector's magnitude.)
154
+ * @return {Point}
155
+ */
156
+ normalise() {
157
+ const len = this.length();
158
+ if (len < Constants.Tolerance.EPSILON) return new Point(0, 0);
159
+ return new Point(this.x / len, this.y / len);
160
+ }
161
+
162
+ /**
163
+ * Return a new point scaled by a scalar factor.
164
+ * @param {number} scalar
165
+ * @return {Point}
166
+ */
167
+ scale(scalar) {
168
+ return new Point(this.x * scalar, this.y * scalar);
84
169
  }
85
170
 
86
171
  /**
87
172
  * Return new point with minimum values for x and y from this and that
88
173
  * @param {Point} that
174
+ * @return {Point}
89
175
  */
90
176
  min(that) {
91
177
  return new Point(
@@ -97,6 +183,7 @@ export class Point {
97
183
  /**
98
184
  * Return new point with maximum values for x and y from this and that
99
185
  * @param {Point} that
186
+ * @return {Point}
100
187
  */
101
188
  max(that) {
102
189
  return new Point(
@@ -108,6 +195,7 @@ export class Point {
108
195
  /**
109
196
  * Return midpoint between this and that
110
197
  * @param {Point} that
198
+ * @return {Point}
111
199
  */
112
200
  midPoint(that) {
113
201
  // return point midway between this and that
@@ -123,7 +211,8 @@ export class Point {
123
211
  * Returns linear interpolation between this and that
124
212
  * e.g. t = 0.5 will return midpoint between this and that
125
213
  * @param {Point} that
126
- * @param {Number} t - ratio between 0 and 1
214
+ * @param {number} t - ratio between 0 and 1
215
+ * @return {Point}
127
216
  */
128
217
  lerp(that, t) {
129
218
  return new Point(
@@ -134,8 +223,9 @@ export class Point {
134
223
 
135
224
  /**
136
225
  * Return new point projected from this along angle by distance
137
- * @param {Number} angle - in radians
138
- * @param {Number} distance
226
+ * @param {number} angle - in radians
227
+ * @param {number} distance
228
+ * @return {Point}
139
229
  */
140
230
  project(angle, distance) {
141
231
  if (angle === 0) {
@@ -153,7 +243,7 @@ export class Point {
153
243
  * Find the closest point to this on the ray formed by Pt1 and Pt2
154
244
  * @param {Point} Pt1
155
245
  * @param {Point} Pt2
156
- * @returns the closest point on the ray
246
+ * @return {Point} the closest point on the ray
157
247
  */
158
248
  perpendicular(Pt1, Pt2) {
159
249
  const APx = this.x - Pt1.x;
@@ -162,6 +252,7 @@ export class Point {
162
252
  const ABy = Pt2.y - Pt1.y;
163
253
 
164
254
  const magAB2 = ABx * ABx + ABy * ABy;
255
+ if (magAB2 === 0) return new Point(Pt1.x, Pt1.y);
165
256
  const ABdotAP = ABx * APx + ABy * APy;
166
257
  const t = ABdotAP / magAB2;
167
258
 
@@ -173,17 +264,18 @@ export class Point {
173
264
  /**
174
265
  * Check if this is the same as that
175
266
  * @param {Point} that
267
+ * @return {boolean}
176
268
  */
177
269
  isSame(that) {
178
- if (this.x == that.x && this.y == that.y) return true;
270
+ if (Utils.round(this.x) == Utils.round(that.x) && Utils.round(this.y) == Utils.round(that.y)) return true;
179
271
  return false;
180
272
  }
181
273
 
182
274
  /**
183
275
  * Find the closest point on a line between start and end points
184
- * @param {*} startPoint
185
- * @param {*} endPoint
186
- * @returns the closest point on the line or null
276
+ * @param {Point} startPoint
277
+ * @param {Point} endPoint
278
+ * @return {Point} the closest point on the line
187
279
  */
188
280
  closestPointOnLine(startPoint, endPoint) {
189
281
  const pnt = this.perpendicular(startPoint, endPoint);
@@ -191,7 +283,13 @@ export class Point {
191
283
  return pnt;
192
284
  }
193
285
 
194
- return null;
286
+ // point is not perpendicular to the line
287
+ // closest point must be at the start or end
288
+ if (this.distance(startPoint) < this.distance(endPoint)) {
289
+ return startPoint;
290
+ } else {
291
+ return endPoint;
292
+ }
195
293
  }
196
294
 
197
295
  /**
@@ -200,9 +298,9 @@ export class Point {
200
298
  * @param {Point} endPoint
201
299
  * @param {Point} centerPoint
202
300
  * @param {number} direction - CCW if > 0
203
- * @returns the closest point on the arc or null
301
+ * @return {Point} the closest point on the arc or null
204
302
  */
205
- closestPointOnArc(startPoint, endPoint, centerPoint, direction=1) {
303
+ closestPointOnArc(startPoint, endPoint, centerPoint, direction = 0) {
206
304
  const length = this.distance(centerPoint);
207
305
  const radius = centerPoint.distance(startPoint);
208
306
 
@@ -229,14 +327,16 @@ export class Point {
229
327
  * @param {Point} endPoint
230
328
  * @param {Point} centerPoint
231
329
  * @param {number} direction - CCW if > 0
232
- * @returns true or false
330
+ * @return {Point} true or false
233
331
  */
234
- isOnArc(startPoint, endPoint, centerPoint, direction=1) {
332
+ isOnArc(startPoint, endPoint, centerPoint, direction = 0) {
333
+ // direction: ccw arc > 0, clockwise arc <= 0
235
334
  const snapAngle = centerPoint.angle(this);
236
335
  const startAngle = centerPoint.angle(startPoint);
237
336
  const endAngle = centerPoint.angle(endPoint);
238
337
 
239
338
  if (direction > 0) {
339
+ // Counter Clockwise Arc
240
340
  if (startAngle < endAngle) {
241
341
  if (snapAngle >= startAngle && snapAngle <= endAngle) {
242
342
  return true;
@@ -248,7 +348,8 @@ export class Point {
248
348
  return true;
249
349
  }
250
350
  }
251
- } else if (direction < 0) {
351
+ } else if (direction <= 0) {
352
+ // Clockwise Arc
252
353
  if (startAngle < endAngle) {
253
354
  if (snapAngle <= startAngle || snapAngle >= endAngle) {
254
355
  return true;
@@ -270,19 +371,51 @@ export class Point {
270
371
  * Determine if point is on line segment
271
372
  * @param {Point} startPoint
272
373
  * @param {Point} endPoint
273
- * @returns true or false
374
+ * @return {Point} true or false
274
375
  */
275
376
  isOnLine(startPoint, endPoint) {
276
377
  // check start -> point + point -> end equals start -> end
277
- if (startPoint.distance(this) + this.distance(endPoint) === startPoint.distance(endPoint)) {
378
+ if (Utils.round(startPoint.distance(this) + this.distance(endPoint)) === Utils.round(startPoint.distance(endPoint))) {
379
+ return true;
380
+ }
381
+ return false;
382
+ }
383
+
384
+ /**
385
+ * Check if point is inside rectangle defined by points A, B, C, D
386
+ * @param {Point} A - Bottom left rectangle corner
387
+ * @param {Point} B - Bottom right rectangle corner
388
+ * @param {Point} C - Top right rectangle corner
389
+ * @param {Point} D - Top left rectangle corner
390
+ * @return {boolean} - true if point is inside rectangle
391
+ */
392
+ isInRectangle(A, B, C, D) {
393
+ /* Calculate area of rectangle ABCD */
394
+ const rectangleArea = Utils.areaOfTriangle(A, B, C) + Utils.areaOfTriangle(A, C, D);
395
+
396
+ /* Calculate area of triangle PAB */
397
+ const A1 = Utils.areaOfTriangle(this, A, B);
398
+
399
+ /* Calculate area of triangle PBC */
400
+ const A2 = Utils.areaOfTriangle(this, B, C);
401
+
402
+ /* Calculate area of triangle PCD */
403
+ const A3 = Utils.areaOfTriangle(this, C, D);
404
+
405
+ /* Calculate area of triangle PAD */
406
+ const A4 = Utils.areaOfTriangle(this, A, D);
407
+
408
+ /* Check if sum of A1, A2, A3 and A4 is same as A */
409
+ if (Utils.round(rectangleArea) === Utils.round(A1 + A2 + A3 + A4)) {
278
410
  return true;
279
411
  }
412
+
280
413
  return false;
281
414
  }
282
415
 
283
416
  /**
284
417
  * Get the arc angle in radians from the bulge value
285
- * @returns arc angle in radians
418
+ * @return {Point} arc angle in radians
286
419
  */
287
420
  bulgeAngle() {
288
421
  return Math.atan(this.bulge) * 4;
@@ -290,6 +423,8 @@ export class Point {
290
423
 
291
424
  /**
292
425
  * Return the radius of the arc from the next point in the polyline
426
+ * @param {Point} nextPoint
427
+ * @return {number}
293
428
  */
294
429
  bulgeRadius(nextPoint) {
295
430
  if (this.bulge == 0) {
@@ -303,7 +438,7 @@ export class Point {
303
438
  /**
304
439
  * Returns apothem; the distance from arc center to cord midpoint
305
440
  * @param {Point} nextPoint
306
- * @returns apothem
441
+ * @return {number} apothem
307
442
  */
308
443
  apothem(nextPoint) {
309
444
  if (this.bulge == 0) {
@@ -317,7 +452,7 @@ export class Point {
317
452
  /**
318
453
  * Return the centre point of the arc
319
454
  * @param {Point} nextPoint
320
- * @returns Point
455
+ * @return {Point} Point
321
456
  */
322
457
  bulgeCentrePoint(nextPoint) {
323
458
  const midp = this.midPoint(nextPoint);
@@ -340,4 +475,34 @@ export class Point {
340
475
 
341
476
  return centre;
342
477
  }
478
+
479
+ /**
480
+ * Calculate the bulge for a partial arc segment
481
+ * @param {Point} nextPoint - segment end point
482
+ * @param {Point} splitPoint - point where the arc is split
483
+ * @param {boolean} afterSplit - if true, return bulge for the portion after the split point
484
+ * @return {number} - the partial bulge value
485
+ */
486
+ partialBulge(nextPoint, splitPoint, afterSplit = false) {
487
+ const center = this.bulgeCentrePoint(nextPoint);
488
+ const direction = this.bulge > 0 ? 1 : -1;
489
+
490
+ const startAngle = center.angle(this);
491
+ const endAngle = center.angle(nextPoint);
492
+ const splitAngle = center.angle(splitPoint);
493
+
494
+ let includedAngle;
495
+ if (afterSplit) {
496
+ // Angle from split point to end
497
+ includedAngle = (endAngle - splitAngle) * direction;
498
+ } else {
499
+ // Angle from start to split point
500
+ includedAngle = (splitAngle - startAngle) * direction;
501
+ }
502
+
503
+ // Normalise to 0..2PI
504
+ includedAngle = ((includedAngle % (2 * Math.PI)) + 2 * Math.PI) % (2 * Math.PI);
505
+
506
+ return Math.tan(includedAngle / 4) * direction;
507
+ }
343
508
  }
@@ -1,15 +1,24 @@
1
- import {BasePolyline} from './basePolyline.js';
2
- import {Point} from './point.js';
1
+ import { DXFFile } from '../lib/dxf/dxfFile.js';
2
+ import { BasePolyline } from './basePolyline.js';
3
+ import { Point } from './point.js';
3
4
 
5
+ /**
6
+ * Polyline Entity Class
7
+ * @extends BasePolyline
8
+ */
4
9
  export class Polyline extends BasePolyline {
10
+ /**
11
+ * Create a Polyline
12
+ * @param {Array} data
13
+ */
5
14
  constructor(data) {
6
15
  super(data);
7
16
 
8
17
  if (data) {
9
- if (data.children) {
10
- // remove any points
11
- // point data comes from the vertices
12
- if (data.points) {
18
+ if (data.hasOwnProperty('children')) {
19
+ // remove any points
20
+ // point data comes from the vertices
21
+ if (data.hasOwnProperty('points')) {
13
22
  this.points = [];
14
23
  }
15
24
 
@@ -28,8 +37,46 @@ export class Polyline extends BasePolyline {
28
37
  }
29
38
  }
30
39
 
40
+ /**
41
+ * Write the entity to file in the dxf format
42
+ * @param {DXFFile} file
43
+ */
44
+ dxf(file) {
45
+ if (file.version < DXFFile.Version.R2000) {
46
+ // POLYLINE/VERTEX/SEQEND format for R12
47
+ file.writeGroupCode('0', 'POLYLINE');
48
+ file.writeGroupCode('8', this.layer);
49
+ file.writeGroupCode('6', this.lineType);
50
+ file.writeGroupCode('66', 1); // vertices-follow flag
51
+ file.writeGroupCode('70', this.flags.getFlagValue());
52
+
53
+ for (let i = 0; i < this.points.length; i++) {
54
+ file.writeGroupCode('0', 'VERTEX');
55
+ file.writeGroupCode('8', this.layer);
56
+ file.writeGroupCode('10', this.points[i].x);
57
+ file.writeGroupCode('20', this.points[i].y);
58
+ file.writeGroupCode('30', '0.0');
59
+ file.writeGroupCode('42', this.points[i].bulge);
60
+ }
61
+
62
+ file.writeGroupCode('0', 'SEQEND');
63
+ file.writeGroupCode('8', this.layer);
64
+ return;
65
+ }
66
+
67
+ // Default to LWPOLYLINE output for R2000 and later
68
+ super.dxf(file);
69
+ }
70
+
71
+ /**
72
+ * Register the command
73
+ * @return {Object}
74
+ * command = name of the command
75
+ * shortcut = shortcut for the command
76
+ * type = type to group command in toolbars (omitted if not shown)
77
+ */
31
78
  static register() {
32
- const command = {command: 'Polyline', shortcut: 'PL', type: 'Entity'};
79
+ const command = { command: 'Polyline', shortcut: 'PL', type: 'Entity' };
33
80
  return command;
34
81
  }
35
82
  }
@@ -1,36 +1,57 @@
1
- import {Point} from './point.js';
2
- import {Strings} from '../lib/strings.js';
3
- import {Entity} from './entity.js';
4
- import {Input, PromptOptions} from '../lib/inputManager.js';
5
- import {Logging} from '../lib/logging.js';
6
- import {Polyline} from './polyline.js';
1
+ import { Point } from './point.js';
2
+ import { Strings } from '../lib/strings.js';
3
+ import { Entity } from './entity.js';
4
+ import { Input, PromptOptions } from '../lib/inputManager.js';
5
+ import { Logging } from '../lib/logging.js';
6
+ import { Polyline } from './polyline.js';
7
7
 
8
- import {DesignCore} from '../designCore.js';
8
+ import { DesignCore } from '../designCore.js';
9
9
 
10
+ /**
11
+ * Rectangle Entity Class
12
+ * @extends Entity
13
+ */
10
14
  export class Rectangle extends Entity {
15
+ /**
16
+ * Create a Rectangle
17
+ * @param {Array} data
18
+ */
11
19
  constructor(data) {
12
20
  super(data);
13
21
  // There is no DXF representation of a Rectangle
14
22
  // Convenience entity to create a polyline from two points
15
23
  }
16
24
 
25
+ /**
26
+ * Register the command
27
+ * @return {Object}
28
+ * command = name of the command
29
+ * shortcut = shortcut for the command
30
+ * type = type to group command in toolbars (omitted if not shown)
31
+ */
17
32
  static register() {
18
- const command = {command: 'Rectangle', shortcut: 'REC', type: 'Entity'};
33
+ const command = { command: 'Rectangle', shortcut: 'REC', type: 'Entity' };
19
34
  return command;
20
35
  }
21
36
 
37
+ /**
38
+ * Execute method
39
+ * executes the workflow, requesting input required to create an entity
40
+ */
22
41
  async execute() {
23
42
  try {
24
43
  const op = new PromptOptions(Strings.Input.START, [Input.Type.POINT]);
25
44
  const pt1 = await DesignCore.Scene.inputManager.requestInput(op);
45
+ if (pt1 === undefined) return;
26
46
  this.points.push(pt1);
27
47
 
28
48
  const op2 = new PromptOptions(Strings.Input.END, [Input.Type.POINT]);
29
49
  const pt2 = await DesignCore.Scene.inputManager.requestInput(op2);
50
+ if (pt2 === undefined) return;
30
51
  this.points.push(pt2);
31
52
 
32
53
  const points = this.rectPoints(this.points[0], this.points[1]);
33
- const polyline = new Polyline({points: points});
54
+ const polyline = new Polyline({ points: points });
34
55
 
35
56
  DesignCore.Scene.inputManager.executeCommand(polyline);
36
57
  } catch (err) {
@@ -38,20 +59,29 @@ export class Rectangle extends Entity {
38
59
  }
39
60
  }
40
61
 
62
+ /**
63
+ * Preview the entity during creation
64
+ */
41
65
  preview() {
42
66
  if (this.points.length >= 1) {
43
67
  const mousePoint = DesignCore.Mouse.pointOnScene();
44
68
  const points = this.rectPoints(this.points.at(-1), mousePoint);
45
- DesignCore.Scene.createTempItem('Polyline', {points: points});
69
+ DesignCore.Scene.tempEntities.create('Polyline', { points: points });
46
70
  }
47
71
  }
48
72
 
73
+ /**
74
+ * Get the rectangle points
75
+ * @param {Point} pt1
76
+ * @param {Point} pt2
77
+ * @return {Array} array of points for each corner
78
+ */
49
79
  rectPoints(pt1, pt2) {
50
80
  const points = [];
51
- points.push( new Point(pt1.x, pt1.y));
81
+ points.push(new Point(pt1.x, pt1.y));
52
82
  points.push(new Point(pt2.x, pt1.y));
53
- points.push( new Point(pt2.x, pt2.y));
54
- points.push( new Point(pt1.x, pt2.y));
83
+ points.push(new Point(pt2.x, pt2.y));
84
+ points.push(new Point(pt1.x, pt2.y));
55
85
  points.push(new Point(pt1.x, pt1.y));
56
86
  return points;
57
87
  }
@@ -1,12 +1,25 @@
1
- import {Entity} from './entity.js';
2
- import {DXFFile} from '../lib/dxf/dxfFile.js';
3
- import {BoundingBox} from '../lib/boundingBox.js';
1
+ import { Entity } from './entity.js';
2
+ import { DXFFile } from '../lib/dxf/dxfFile.js';
3
+ import { BoundingBox } from '../lib/boundingBox.js';
4
4
 
5
+ /**
6
+ * Solid Entity Class
7
+ * @extends Entity
8
+ */
5
9
  export class Solid extends Entity {
10
+ /**
11
+ * Create a Solid Entity
12
+ * @param {Array} data
13
+ */
6
14
  constructor(data) {
7
15
  super(data);
8
16
  }
9
17
 
18
+ /**
19
+ * Draw the entity
20
+ * @param {Object} ctx - context
21
+ * @param {number} scale
22
+ */
10
23
  draw(ctx, scale) {
11
24
  this.points.forEach((point, index) => {
12
25
  if (index == 0) {
@@ -20,9 +33,13 @@ export class Solid extends Entity {
20
33
  ctx.fill();
21
34
  }
22
35
 
36
+ /**
37
+ * Write the entity to file in the dxf format
38
+ * @param {DXFFile} file
39
+ */
23
40
  dxf(file) {
24
41
  file.writeGroupCode('0', 'SOLID');
25
- file.writeGroupCode('5', file.nextHandle(), DXFFile.Version.R2000); // Handle
42
+ file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
26
43
  file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
27
44
  file.writeGroupCode('100', 'AcDbTrace', DXFFile.Version.R2000);
28
45
  file.writeGroupCode('8', this.layer);
@@ -39,15 +56,35 @@ export class Solid extends Entity {
39
56
  file.writeGroupCode('32', '0.0');
40
57
 
41
58
  // If only three points are use to define the SOLID then the fourth points is the same as the third.
42
- file.writeGroupCode('13', this.points[3].x || this.points[2].x);
43
- file.writeGroupCode('23', this.points[3].y || this.points[2].x);
59
+ file.writeGroupCode('13', this.points.length > 3 ? this.points[3].x : this.points[2].x);
60
+ file.writeGroupCode('23', this.points.length > 3 ? this.points[3].y : this.points[2].x);
44
61
  file.writeGroupCode('33', '0.0');
45
62
  }
46
63
 
64
+ /**
65
+ * Get closest point on entity
66
+ * @param {Point} P
67
+ * @return {Array} - [Point, distance]
68
+ */
47
69
  closestPoint(P) {
48
70
  return [P, Infinity];
49
71
  }
50
72
 
73
+ /**
74
+ * Convert the entity to polyline points
75
+ * @return {Array} array of points representing the solid as a polyline
76
+ */
77
+ toPolylinePoints() {
78
+ const points = this.points.map((point) => point.clone());
79
+ // Close the shape
80
+ points.push(this.points[0].clone());
81
+ return points;
82
+ }
83
+
84
+ /**
85
+ * Return boundingbox for entity
86
+ * @return {BoundingBox}
87
+ */
51
88
  boundingBox() {
52
89
  return BoundingBox.fromPoints(this.points);
53
90
  }