@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,30 @@
1
- import {Point} from './point.js';
2
- import {Utils} from '../lib/utils.js';
3
- import {Strings} from '../lib/strings.js';
4
- import {Entity} from './entity.js';
5
- import {Input, PromptOptions} from '../lib/inputManager.js';
6
- import {Logging} from '../lib/logging.js';
7
- import {DXFFile} from '../lib/dxf/dxfFile.js';
8
- import {BoundingBox} from '../lib/boundingBox.js';
9
-
10
- import {DesignCore} from '../designCore.js';
11
-
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 { DXFFile } from '../lib/dxf/dxfFile.js';
7
+ import { BoundingBox } from '../lib/boundingBox.js';
8
+ import { AddState, RemoveState, UpdateState } from '../lib/stateManager.js';
9
+
10
+ import { DesignCore } from '../designCore.js';
11
+ import { Utils } from '../lib/utils.js';
12
+
13
+
14
+ /**
15
+ * Line Entity Class
16
+ * @extends Entity
17
+ */
12
18
  export class Line extends Entity {
19
+ /**
20
+ * Create a Line Entity
21
+ * @param {Array} data
22
+ */
13
23
  constructor(data) {
14
24
  super(data);
15
25
 
16
26
  if (data) {
17
- if (data.points) {
27
+ if (data.hasOwnProperty('points')) {
18
28
  // clear points
19
29
  this.points = [];
20
30
 
@@ -26,31 +36,43 @@ export class Line extends Entity {
26
36
  }
27
37
  }
28
38
 
29
-
39
+ /**
40
+ * Register the command
41
+ * @return {Object}
42
+ * command = name of the command
43
+ * shortcut = shortcut for the command
44
+ * type = type to group command in toolbars (omitted if not shown)
45
+ */
30
46
  static register() {
31
- const command = {command: 'Line', shortcut: 'L', type: 'Entity'};
47
+ const command = { command: 'Line', shortcut: 'L', type: 'Entity' };
32
48
  return command;
33
49
  }
34
50
 
51
+ /**
52
+ * Execute method
53
+ * executes the workflow, requesting input required to create an entity
54
+ */
35
55
  async execute() {
36
56
  try {
37
57
  const op = new PromptOptions(Strings.Input.START, [Input.Type.POINT]);
38
58
  const pt1 = await DesignCore.Scene.inputManager.requestInput(op);
59
+ if (pt1 === undefined) return;
39
60
  this.points.push(pt1);
40
61
 
41
- let pt2;
42
- const op2 = new PromptOptions(Strings.Input.NEXTPOINT, [Input.Type.POINT, Input.Type.NUMBER]);
43
62
  while (true) {
44
- pt2 = await DesignCore.Scene.inputManager.requestInput(op2);
45
- if (Input.getType(pt2) === Input.Type.POINT) {
46
- this.points.push(pt2);
47
- } else if (Input.getType(pt2) === Input.Type.NUMBER) {
48
- const basePoint = this.points.at(-1);
49
- const angle = Utils.degrees2radians(DesignCore.Mouse.inputAngle());
50
- const point = basePoint.project(angle, pt2);
51
- this.points.push(point);
63
+ const canClose = this.points.length >= 3;
64
+ const options = canClose ? ['Close'] : [];
65
+ const op2 = new PromptOptions(Strings.Input.NEXTPOINT, [Input.Type.POINT, Input.Type.DYNAMIC], options);
66
+ const pt2 = await DesignCore.Scene.inputManager.requestInput(op2);
67
+ if (pt2 === undefined) break;
68
+
69
+ if (Input.getType(pt2) === Input.Type.STRING && pt2 === 'Close') {
70
+ this.points.push(pt1);
71
+ DesignCore.Scene.inputManager.executeCommand(this);
72
+ return;
52
73
  }
53
74
 
75
+ this.points.push(pt2);
54
76
  DesignCore.Scene.inputManager.actionCommand(this);
55
77
  }
56
78
  } catch (err) {
@@ -58,172 +80,193 @@ export class Line extends Entity {
58
80
  }
59
81
  }
60
82
 
83
+ /**
84
+ * Preview the entity during creation
85
+ */
61
86
  preview() {
62
87
  if (this.points.length >= 1) {
63
88
  const mousePoint = DesignCore.Mouse.pointOnScene();
64
89
  const points = [this.points.at(-1), mousePoint];
65
- DesignCore.Scene.createTempItem(this.type, {points: points});
90
+ DesignCore.Scene.tempEntities.create(this.type, { points: points });
66
91
  }
67
92
  }
68
93
 
94
+ /**
95
+ * Draw the entity
96
+ * @param {Object} ctx - context
97
+ * @param {number} scale
98
+ */
69
99
  draw(ctx, scale) {
70
100
  ctx.moveTo(this.points[0].x, this.points[0].y);
71
101
  ctx.lineTo(this.points[1].x, this.points[1].y);
72
102
  ctx.stroke();
73
103
  }
74
104
 
105
+ /**
106
+ * Write the entity to file in the dxf format
107
+ * @param {DXFFile} file
108
+ */
75
109
  dxf(file) {
76
110
  file.writeGroupCode('0', 'LINE');
77
- file.writeGroupCode('5', file.nextHandle(), DXFFile.Version.R2000); // Handle
111
+ file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
78
112
  file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
79
113
  file.writeGroupCode('100', 'AcDbLine', DXFFile.Version.R2000);
80
114
  file.writeGroupCode('8', this.layer);
115
+ file.writeGroupCode('6', this.lineType);
81
116
  file.writeGroupCode('10', this.points[0].x);
82
117
  file.writeGroupCode('20', this.points[0].y);
83
118
  file.writeGroupCode('30', '0.0');
84
119
  file.writeGroupCode('11', this.points[1].x);
85
120
  file.writeGroupCode('21', this.points[1].y);
86
121
  file.writeGroupCode('31', '0.0');
122
+ file.writeGroupCode('39', this.lineWidth);
87
123
  }
88
124
 
89
- trim(points) {
90
- function trimOneEnd(intersectPnts, line) {
91
- let originPoint;
92
- let destinationPoint;
93
- const validPoints = [];
94
-
95
- for (let i = 0; i < line.points.length; i++) {
96
- for (let j = 0; j < intersectPnts.length; j++) {
97
- if (betweenPoints(DesignCore.Mouse.pointOnScene(), [intersectPnts[j], line.points[i]], false)) {
98
- if (Math.round(intersectPnts[j].distance(line.points[i]) * 100) / 100 < Math.round(line.points[0].distance(line.points[1]) * 100) / 100) {
99
- originPoint = i;
100
- validPoints.push(j);
101
- }
102
- }
103
- }
104
- }
105
-
106
- if (typeof validPoints !== 'undefined') {
107
- let dist = Number.POSITIVE_INFINITY;
108
-
109
- for (let j = 0; j < validPoints.length; j++) {
110
- if (line.points[originPoint].distance(intersectPnts[validPoints[j]]) < dist) {
111
- dist = line.points[originPoint].distance(intersectPnts[validPoints[j]]);
112
- destinationPoint = validPoints[j];
113
- }
114
- }
115
- }
125
+ /**
126
+ * Return a list of points representing a polyline version of this entity
127
+ * @return {Array}
128
+ */
129
+ toPolylinePoints() {
130
+ return this.points;
131
+ }
116
132
 
117
- if (typeof destinationPoint !== 'undefined') {
118
- line.points[originPoint] = intersectPnts[destinationPoint];
119
- }
120
- }
133
+ /**
134
+ * Set entity points from a polyline point representation
135
+ * @param {Array} points
136
+ */
137
+ fromPolylinePoints(points) {
138
+ this.points = [new Point(points[0].x, points[0].y), new Point(points[1].x, points[1].y)];
139
+ }
121
140
 
122
- function trimBetween(pnts, line) {
123
- const a = Math.round(line.points[0].distance(pnts[0]));
124
- const b = Math.round(line.points[0].distance(pnts[1]));
125
- const c = Math.round(line.points[1].distance(pnts[0]));
126
- const d = Math.round(line.points[1].distance(pnts[1]));
127
-
128
- if (a === 0 && d === 0 || b === 0 && c === 0) {
129
- } else {
130
- const data = {
131
- points: [pnts[a < b ? 1 : 0], line.points[1]],
132
- colour: line.colour,
133
- layer: line.layer,
134
- lineWidth: line.lineWidth,
135
- };
136
-
137
- DesignCore.Scene.addItem('Line', data);
138
-
139
- if (a < b) {
140
- line.points[1] = pnts[0];
141
- } else {
142
- line.points[1] = pnts[1];
143
- }
144
- }
141
+ /**
142
+ * Trim the entity
143
+ * @param {Array} intersections
144
+ * @return {Array} - array of state changes
145
+ */
146
+ trim(intersections) {
147
+ // array to hold state changes
148
+ const stateChanges = [];
149
+
150
+ if (intersections?.length === 0 || !intersections) {
151
+ return stateChanges;
145
152
  }
146
153
 
147
- function betweenPoints(mousePnt, pntsArray, returnPoints) {
148
- for (let i = 0; i < pntsArray.length - 1; i++) {
149
- const a = pntsArray[i].distance(mousePnt);
150
- const b = pntsArray[i + 1].distance(mousePnt);
151
- const c = pntsArray[i].distance(pntsArray[i + 1]);
152
-
153
- if (Math.round(a + b) === Math.round(c)) {
154
- if (returnPoints) {
155
- return [pntsArray[i], pntsArray[i + 1]];
154
+ // get the mouse position
155
+ const mousePosition = DesignCore.Mouse.pointOnScene();
156
+ // get the point on the line closest to the mouse
157
+ const pointOnLine = mousePosition.closestPointOnLine(this.points[0], this.points[1]);
158
+ // remove any intersections that are at the end points of the line
159
+ intersections = intersections.filter((p) => !p.isSame(this.points[0]) && !p.isSame(this.points[1]));
160
+
161
+ Utils.sortPointsByDistance(intersections, this.points[0]);
162
+
163
+ // Add line points to the start and the end of the point array
164
+ const testPoints = [this.points[0], ...intersections, this.points[1]];
165
+
166
+ // Test if mouse position is between two intersection points
167
+ if (testPoints.length > 1) {
168
+ for (let i = 0; i < testPoints.length - 1; i++) {
169
+ const startPoint = testPoints[i];
170
+ const endPoint = testPoints[i + 1];
171
+
172
+ // check if the mouse is between startPoint and endPoint
173
+ if (pointOnLine.isOnLine(startPoint, endPoint)) {
174
+ const newPoints = [];
175
+
176
+ for (const p of testPoints) {
177
+ const inOriginalLine = this.points.indexOf(p) !== -1;
178
+ const inIntersections = intersections.indexOf(p) !== -1;
179
+
180
+ // Keep points which:
181
+ // - The mouse is between are intersections
182
+ // - The mouse is not between and in this line
183
+ const isBetween = p.isSame(startPoint) || p.isSame(endPoint);
184
+ if ((isBetween && inIntersections) || (!isBetween && inOriginalLine)) {
185
+ newPoints.push(p);
186
+ }
156
187
  }
157
188
 
158
- return true;
189
+ if (newPoints.length % 2 === 0) {
190
+ // Add lines for each point pair
191
+ for (let j = 0; j < newPoints.length; j += 2) {
192
+ const line = Utils.cloneObject(this);
193
+ line.points = [newPoints[j], newPoints[j + 1]];
194
+ const addState = new AddState(line);
195
+ stateChanges.push(addState);
196
+ }
197
+ }
198
+ // Remove the existing line
199
+ const removeState = new RemoveState(this);
200
+ stateChanges.push(removeState);
159
201
  }
160
202
  }
161
203
  }
162
204
 
163
- if (points.length > 1) {
164
- // is the mouse between two points
165
- const pnts = betweenPoints(DesignCore.Mouse.pointOnScene(), points, true);
205
+ return stateChanges;
206
+ }
166
207
 
167
- if (typeof pnts !== 'undefined') {
168
- trimBetween(pnts, this);
169
- } else {
170
- trimOneEnd(points, this);
171
- }
172
- } else {
173
- trimOneEnd(points, this);
208
+ /**
209
+ * Extend the entity
210
+ * @param {Array} intersections
211
+ * @return {Array} - array of state changes
212
+ */
213
+ extend(intersections) {
214
+ // array to hold state changes
215
+ const stateChanges = [];
216
+
217
+ if (intersections?.length === 0 || !intersections) {
218
+ return stateChanges;
174
219
  }
175
- }
176
220
 
177
- extend(points) {
178
221
  let originPoint;
179
- let destinationPoint;
180
-
181
222
  // Find which end is closer to the mouse
182
- // ToDo: Pass the mouse location in rather than needing a ref to core.
183
223
  if (this.points[0].distance(DesignCore.Mouse.pointOnScene()) < this.points[1].distance(DesignCore.Mouse.pointOnScene())) {
184
224
  originPoint = 0;
185
225
  } else {
186
226
  originPoint = 1;
187
227
  }
188
228
 
189
- // check if any of the points are valid
190
- const validPoints = [];
229
+ Utils.sortPointsByDistance(intersections, this.points[originPoint]);
191
230
 
192
- for (let i = 0; i < points.length; i++) {
193
- if (Math.round(this.points[originPoint].angle(points[i])) === Math.round(this.points[originPoint ? 0 : 1].angle(this.points[originPoint]))) {
194
- // if the destination point is different than the origin add it to the array of valid points
195
- if (Math.round(this.points[originPoint].distance(points[i])) !== 0) {
196
- validPoints.push(i);
197
- }
198
- }
199
- }
231
+ const endPoint = this.points[originPoint];
232
+ const adjacentPoint = this.points[1 - originPoint];
200
233
 
201
- if (validPoints.length > 1) {
202
- let dist = Number.POSITIVE_INFINITY;
234
+ // Find the closest intersection that lies beyond the endpoint
235
+ const direction = endPoint.subtract(adjacentPoint);
236
+ const newEndPoint = intersections.find((p) => {
237
+ if (p.isSame(endPoint)) return false;
238
+ if (p.subtract(endPoint).dot(direction) <= 0) return false;
239
+ if (adjacentPoint.distance(p) <= adjacentPoint.distance(endPoint)) return false;
240
+ return true;
241
+ });
203
242
 
204
- for (let j = 0; j < validPoints.length; j++) {
205
- if (this.points[originPoint].distance(points[validPoints[j]]) < dist) {
206
- dist = this.points[originPoint].distance(points[validPoints[j]]);
207
- destinationPoint = validPoints[j];
208
- }
209
- }
210
- } else if (validPoints.length === 1) {
211
- // only one valid point
212
- destinationPoint = validPoints[0];
243
+ if (!newEndPoint) {
244
+ return stateChanges;
213
245
  }
214
246
 
215
- if (destinationPoint !== undefined) {
216
- this.points[originPoint] = points[destinationPoint];
247
+ const newPoints = [];
248
+ if (originPoint === 0) {
249
+ newPoints.push(newEndPoint, this.points[1]);
250
+ } else {
251
+ newPoints.push(this.points[0], newEndPoint);
217
252
  }
218
- }
219
253
 
220
- intersectPoints() {
221
- return {
222
- start: this.points[0],
223
- end: this.points[1],
224
- };
254
+ if (newPoints[0].isSame(this.points[0]) && newPoints[1].isSame(this.points[1])) {
255
+ // No change
256
+ return stateChanges;
257
+ }
258
+
259
+ // update the line
260
+ const addState = new UpdateState(this, { points: newPoints });
261
+ stateChanges.push(addState);
262
+
263
+ return stateChanges;
225
264
  }
226
265
 
266
+ /**
267
+ * Get the length of a line
268
+ * @return {number}
269
+ */
227
270
  length() {
228
271
  const A = (this.points[0].x - this.points[1].x);
229
272
  const B = (this.points[0].y - this.points[1].y);
@@ -234,11 +277,21 @@ export class Line extends Entity {
234
277
  return dist;
235
278
  }
236
279
 
280
+ /**
281
+ * Get the lines mid point
282
+ * @return {Point}
283
+ */
237
284
  midPoint() {
238
285
  const midPoint = this.points[0].midPoint(this.points[1]);
239
286
  return midPoint;
240
287
  }
241
288
 
289
+ /**
290
+ * Get snap points
291
+ * @param {Point} mousePoint
292
+ * @param {number} delta
293
+ * @return {Array} - array of snap points
294
+ */
242
295
  snaps(mousePoint, delta) {
243
296
  const snaps = [];
244
297
 
@@ -264,6 +317,11 @@ export class Line extends Entity {
264
317
  return snaps;
265
318
  }
266
319
 
320
+ /**
321
+ * Get closest point on entity
322
+ * @param {Point} P
323
+ * @return {Array} - [Point, distance]
324
+ */
267
325
  closestPoint(P) {
268
326
  const pnt = P.closestPointOnLine(this.points[0], this.points[1]);
269
327
  if (pnt === null) {
@@ -274,6 +332,10 @@ export class Line extends Entity {
274
332
  return [pnt, distance];
275
333
  }
276
334
 
335
+ /**
336
+ * Return boundingbox for entity
337
+ * @return {BoundingBox}
338
+ */
277
339
  boundingBox() {
278
340
  return BoundingBox.lineBoundingBox(this.points[0], this.points[1]);
279
341
  }
@@ -1,62 +1,39 @@
1
- import {Logging} from '../lib/logging.js';
2
- import {BasePolyline} from './basePolyline.js';
1
+ import { Logging } from '../lib/logging.js';
2
+ import { BasePolyline } from './basePolyline.js';
3
+ import { Polyline } from './polyline.js';
3
4
 
5
+ /**
6
+ * LWPolyline Entity Class
7
+ * @extends BasePolyline
8
+ */
4
9
  export class Lwpolyline extends BasePolyline {
10
+ /**
11
+ * Create an LW Polyline
12
+ * @param {Array} data
13
+ */
5
14
  constructor(data) {
6
15
  super(data);
7
16
 
8
17
  if (data) {
9
- if (data[90]) {
18
+ if (data.hasOwnProperty('90')) {
10
19
  // DXF Groupcode 90 - Number of vertices
11
20
  if (this.points.length !== data[90]) {
12
21
  Logging.instance.error(`LWPOLYLINE Vertices Count`);
13
22
  }
14
23
  }
15
24
  }
25
+ return new Polyline(data);
16
26
  }
17
27
 
28
+ /**
29
+ * Register the command
30
+ * @return {Object}
31
+ * command = name of the command
32
+ * shortcut = shortcut for the command
33
+ * type = type to group command in toolbars (omitted if not shown)
34
+ */
18
35
  static register() {
19
- const command = {command: 'Lwpolyline'};
36
+ const command = { command: 'Lwpolyline' };
20
37
  return command;
21
38
  }
22
-
23
- // dxf
24
- // R12 doesn't support Lwpolyline
25
- // output as polyline definition by default from super class
26
- /*
27
- dxf() {
28
- let pointData = '';
29
- this.points.forEach((point) => {
30
- pointData = pointData.concat(
31
- '\n', '10', // X
32
- '\n', point.x,
33
- '\n', '20', // Y
34
- '\n', point.y,
35
- '\n', '30', // Z
36
- '\n', '0',
37
- '\n', '42', // bulge
38
- '\n', point.bulge,
39
- );
40
- });
41
-
42
- const dxfitem = '';
43
- const data = dxfitem.concat(
44
- '0',
45
- '\n', 'LWPOLYLINE',
46
- // "\n", "5", //HANDLE
47
- // "\n", "DA",
48
- '\n', '8', // LAYERNAME
49
- '\n', this.layer,
50
- '\n', '39', // Line Width
51
- '\n', this.lineWidth,
52
- '\n', '70', // Flags
53
- '\n', this.flags,
54
- '\n', '90', // Vertex count
55
- '\n', this.points.length,
56
- pointData,
57
-
58
- );
59
- return data;
60
- }
61
- */
62
39
  }