@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,43 @@
1
- import {Core} from '../../core/core/core.js';
2
- import {Point} from '../../core/entities/point.js';
3
- import {Extend} from '../../core/tools/extend.js';
1
+ import { Core } from '../../core/core/core.js';
2
+ import { Point } from '../../core/entities/point.js';
3
+ import { Extend } from '../../core/tools/extend.js';
4
+ import { SingleSelection } from '../../core/lib/selectionManager.js';
5
+ import { expect, jest } from '@jest/globals';
6
+ import { withMockInput } from '../test-helpers/test-helpers.js';
4
7
 
5
8
  const core = new Core();
6
9
 
10
+ // Test cases for user input
11
+ const inputScenarios = [
12
+
13
+ { desc: 'Trim selection',
14
+ inputs: [new SingleSelection(1, new Point())],
15
+ },
16
+ ];
17
+
18
+ test.each(inputScenarios)('Trim.execute handles $desc', async (scenario) => {
19
+ const { inputs } = scenario;
20
+ const actionSpy = jest.fn();
21
+
22
+ // clear all scene entities
23
+ core.scene.clear();
24
+ // create line
25
+ core.scene.addItem('Line', { points: [new Point(), new Point(10, 0)] });
26
+ // create circle
27
+ core.scene.addItem('Circle', { points: [new Point(), new Point(10, 0)] });
28
+ // select line
29
+ core.scene.selectionManager.selectionSet.selectionSet.push(0);
30
+
31
+ await withMockInput(core.scene, inputs, async () => {
32
+ const extend = new Extend();
33
+ await extend.execute();
34
+
35
+ expect(extend.selectedBoundaryItems[0]).toEqual(core.scene.entities.get(0));
36
+ expect(extend.selectedItem).toBe(core.scene.entities.get(1));
37
+ expect(actionSpy).toHaveBeenCalled();
38
+ }, { extraMethods: { actionCommand: () => actionSpy() } });
39
+ });
40
+
7
41
  test('Test Extend.action', () => {
8
42
  const lineOneStart = new Point(100, 0);
9
43
  const lineOneEnd = new Point(100, 100);
@@ -24,29 +58,31 @@ test('Test Extend.action', () => {
24
58
  * perpendicular lines
25
59
  * Extend end from horizontal line
26
60
  */
61
+ // clear all scene entities
62
+ core.scene.clear();
27
63
  // Add items to scene
28
- core.scene.addItem('Line', {points: [lineOneStart, lineOneEnd]});
29
- core.scene.addItem('Line', {points: [lineTwoStart, lineTwoEnd]});
64
+ core.scene.addItem('Line', { points: [lineOneStart, lineOneEnd] });
65
+ core.scene.addItem('Line', { points: [lineTwoStart, lineTwoEnd] });
30
66
  // Select boundary item
31
- core.scene.selectionManager.addToSelectionSet(0);
32
- // select item to Extend
33
- extend.selectedIndex = 1;
67
+ extend.selectedBoundaryItems = [core.scene.entities.get(0)];
68
+ // select item to trim
69
+ extend.selectedItem = core.scene.entities.get(1);
34
70
  // set mouse location - required for Extend
35
71
  core.mouse.setPosFromScenePoint(new Point(40, 50));
36
72
  // Perform Extend
37
73
  extend.action();
38
74
 
39
75
  // line one
40
- expect(core.scene.items[0].points[0].x).toBe(lineOneStart.x);
41
- expect(core.scene.items[0].points[0].y).toBe(lineOneStart.y);
42
- expect(core.scene.items[0].points[1].x).toBe(lineOneEnd.x);
43
- expect(core.scene.items[0].points[1].y).toBe(lineOneEnd.y);
76
+ expect(core.scene.entities.get(0).points[0].x).toBe(lineOneStart.x);
77
+ expect(core.scene.entities.get(0).points[0].y).toBe(lineOneStart.y);
78
+ expect(core.scene.entities.get(0).points[1].x).toBe(lineOneEnd.x);
79
+ expect(core.scene.entities.get(0).points[1].y).toBe(lineOneEnd.y);
44
80
 
45
81
  // line two
46
- expect(core.scene.items[1].points[0].x).toBe(lineTwoStart.x);
47
- expect(core.scene.items[1].points[0].y).toBe(lineTwoStart.y);
48
- expect(core.scene.items[1].points[1].x).toBe(100);
49
- expect(core.scene.items[1].points[1].y).toBe(lineTwoEnd.y);
82
+ expect(core.scene.entities.get(1).points[0].x).toBe(lineTwoStart.x);
83
+ expect(core.scene.entities.get(1).points[0].y).toBe(lineTwoStart.y);
84
+ expect(core.scene.entities.get(1).points[1].x).toBe(100);
85
+ expect(core.scene.entities.get(1).points[1].y).toBe(lineTwoEnd.y);
50
86
 
51
87
  /**
52
88
  * Extend test two
@@ -55,30 +91,30 @@ test('Test Extend.action', () => {
55
91
  */
56
92
 
57
93
  // clear scene items
58
- core.scene.items = [];
94
+ core.scene.clear();
59
95
  // Add items to scene
60
- core.scene.addItem('Line', {points: [lineTwoStart, lineTwoEnd]});
61
- core.scene.addItem('Line', {points: [lineThreeStart, lineThreeEnd]});
96
+ core.scene.addItem('Line', { points: [lineTwoStart, lineTwoEnd] });
97
+ core.scene.addItem('Line', { points: [lineThreeStart, lineThreeEnd] });
62
98
  // Select boundary item
63
- core.scene.selectionManager.addToSelectionSet(0);
64
- // select item to Extend
65
- extend.selectedIndex = 1;
99
+ extend.selectedBoundaryItems = [core.scene.entities.get(0)];
100
+ // select item to extend
101
+ extend.selectedItem = core.scene.entities.get(1);
66
102
  // set mouse location - required for Extend
67
103
  core.mouse.setPosFromScenePoint(new Point(0, 20));
68
104
  // Perform Extend
69
105
  extend.action();
70
106
 
71
107
  // line one
72
- expect(core.scene.items[0].points[0].x).toBe(lineTwoStart.x);
73
- expect(core.scene.items[0].points[0].y).toBe(lineTwoStart.y);
74
- expect(core.scene.items[0].points[1].x).toBe(lineTwoEnd.x);
75
- expect(core.scene.items[0].points[1].y).toBe(lineTwoEnd.y);
108
+ expect(core.scene.entities.get(0).points[0].x).toBe(lineTwoStart.x);
109
+ expect(core.scene.entities.get(0).points[0].y).toBe(lineTwoStart.y);
110
+ expect(core.scene.entities.get(0).points[1].x).toBe(lineTwoEnd.x);
111
+ expect(core.scene.entities.get(0).points[1].y).toBe(lineTwoEnd.y);
76
112
 
77
113
  // line two
78
- expect(core.scene.items[1].points[0].x).toBe(lineThreeStart.x);
79
- expect(core.scene.items[1].points[0].y).toBe(lineThreeStart.y);
80
- expect(core.scene.items[1].points[1].x).toBe(lineThreeEnd.x);
81
- expect(core.scene.items[1].points[1].y).toBe(50);
114
+ expect(core.scene.entities.get(1).points[0].x).toBe(lineThreeStart.x);
115
+ expect(core.scene.entities.get(1).points[0].y).toBe(lineThreeStart.y);
116
+ expect(core.scene.entities.get(1).points[1].x).toBe(lineThreeEnd.x);
117
+ expect(core.scene.entities.get(1).points[1].y).toBe(50);
82
118
 
83
119
  /**
84
120
  * Extend test three
@@ -86,28 +122,274 @@ test('Test Extend.action', () => {
86
122
  * trim end from crossing line
87
123
  */
88
124
  // clear scene items
89
- core.scene.items = [];
125
+ core.scene.clear();
90
126
  // Add items to scene
91
- core.scene.addItem('Line', {points: [lineOneStart, lineOneEnd]});
92
- core.scene.addItem('Line', {points: [crossingLineStart, crossingLineEnd]});
127
+ core.scene.addItem('Line', { points: [lineOneStart, lineOneEnd] });
128
+ core.scene.addItem('Line', { points: [crossingLineStart, crossingLineEnd] });
93
129
  // Select boundary item
94
- core.scene.selectionManager.addToSelectionSet(0);
95
- // select item to Extend
96
- extend.selectedIndex = 1;
130
+ extend.selectedBoundaryItems = [core.scene.entities.get(0)];
131
+ // select item to extend
132
+ extend.selectedItem = core.scene.entities.get(1);
97
133
  // set mouse location - required for Extend
98
134
  core.mouse.setPosFromScenePoint(new Point(35, 35));
99
135
  // Perform Extend
100
136
  extend.action();
101
137
 
102
138
  // line one
103
- expect(core.scene.items[0].points[0].x).toBe(lineOneStart.x);
104
- expect(core.scene.items[0].points[0].y).toBe(lineOneStart.y);
105
- expect(core.scene.items[0].points[1].x).toBe(lineOneEnd.x);
106
- expect(core.scene.items[0].points[1].y).toBe(lineOneEnd.y);
139
+ expect(core.scene.entities.get(0).points[0].x).toBe(lineOneStart.x);
140
+ expect(core.scene.entities.get(0).points[0].y).toBe(lineOneStart.y);
141
+ expect(core.scene.entities.get(0).points[1].x).toBe(lineOneEnd.x);
142
+ expect(core.scene.entities.get(0).points[1].y).toBe(lineOneEnd.y);
107
143
 
108
144
  // line two
109
- expect(core.scene.items[1].points[0].x).toBe(crossingLineStart.x);
110
- expect(core.scene.items[1].points[0].y).toBe(crossingLineStart.y);
111
- expect(core.scene.items[1].points[1].x).toBe(100);
112
- expect(core.scene.items[1].points[1].y).toBe(100);
145
+ expect(core.scene.entities.get(1).points[0].x).toBe(crossingLineStart.x);
146
+ expect(core.scene.entities.get(1).points[0].y).toBe(crossingLineStart.y);
147
+ expect(core.scene.entities.get(1).points[1].x).toBe(100);
148
+ expect(core.scene.entities.get(1).points[1].y).toBe(100);
149
+ });
150
+
151
+ test('Test Extend.action line - endpoint coincident with intersection', () => {
152
+ // Line from (0,50) to (25,50)
153
+ // Zig-zag boundary polyline crossing at x=50, x=100, x=150, x=200
154
+ // Successive extends should step through each crossing
155
+
156
+ const extend = new Extend();
157
+ core.scene.clear();
158
+
159
+ core.scene.addItem('Line', { points: [new Point(0, 50), new Point(25, 50)] });
160
+ core.scene.addItem('Lwpolyline', { points: [
161
+ new Point(50, 0), new Point(50, 100), new Point(100, 100),
162
+ new Point(100, 0), new Point(150, 0), new Point(150, 100),
163
+ new Point(200, 100), new Point(200, 0),
164
+ ] });
165
+
166
+ const boundary = core.scene.entities.get(1);
167
+ const line = core.scene.entities.get(0);
168
+
169
+ const expected = [50, 100, 150, 200];
170
+ for (const ex of expected) {
171
+ extend.selectedBoundaryItems = [boundary];
172
+ extend.selectedItem = line;
173
+ core.mouse.setPosFromScenePoint(new Point(line.points[1].x - 5, 50));
174
+ extend.action();
175
+ expect(line.points[1].x).toBe(ex);
176
+ expect(line.points[1].y).toBe(50);
177
+ }
178
+ });
179
+
180
+ test('Test Extend.action polyline - endpoint coincident with intersection', () => {
181
+ // Polyline from (0,0) to (50,50)
182
+ // Boundary line from (100,0) to (100,100)
183
+ // Endpoint is already at (50,50) (coincident with first intersection)
184
+ // Expected: polyline extends to (100,100)
185
+
186
+ const extend = new Extend();
187
+ core.scene.clear();
188
+
189
+ core.scene.addItem('Lwpolyline', { points: [new Point(0, 0), new Point(50, 50)] });
190
+ core.scene.addItem('Line', { points: [new Point(100, 0), new Point(100, 100)] });
191
+
192
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
193
+ extend.selectedItem = core.scene.entities.get(0);
194
+ core.mouse.setPosFromScenePoint(new Point(45, 45));
195
+ extend.action();
196
+
197
+ const polyline = core.scene.entities.get(0);
198
+ expect(polyline.points[1].x).toBe(100);
199
+ expect(polyline.points[1].y).toBe(100);
200
+ });
201
+
202
+ test('Test Extend.action polyline - 2-point polyline extend start', () => {
203
+ // 2-point polyline from (50,0) to (100,0)
204
+ // Boundary line at x=0
205
+ // Mouse near (50,0) - the start of the polyline
206
+ // Expected: first point extended to (0,0)
207
+
208
+ const extend = new Extend();
209
+ core.scene.clear();
210
+
211
+ core.scene.addItem('Lwpolyline', { points: [new Point(50, 0), new Point(100, 0)] });
212
+ core.scene.addItem('Line', { points: [new Point(0, -50), new Point(0, 50)] });
213
+
214
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
215
+ extend.selectedItem = core.scene.entities.get(0);
216
+ core.mouse.setPosFromScenePoint(new Point(55, 0));
217
+ extend.action();
218
+
219
+ const polyline = core.scene.entities.get(0);
220
+ expect(polyline.points[0].x).toBe(0);
221
+ expect(polyline.points[0].y).toBe(0);
222
+ expect(polyline.points[1].x).toBe(100);
223
+ expect(polyline.points[1].y).toBe(0);
224
+ });
225
+
226
+ test('Test Extend.action polyline - extend end segment', () => {
227
+ // Polyline from (0,0) to (50,0) to (75,0)
228
+ // Vertical boundary line at x=100
229
+ // Mouse near (75,0) - the end of the polyline
230
+ // Expected: last point extended to (100,0)
231
+
232
+ const extend = new Extend();
233
+ core.scene.clear();
234
+
235
+ core.scene.addItem('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0), new Point(75, 0)] });
236
+ core.scene.addItem('Line', { points: [new Point(100, -50), new Point(100, 50)] });
237
+
238
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
239
+ extend.selectedItem = core.scene.entities.get(0);
240
+ core.mouse.setPosFromScenePoint(new Point(80, 0));
241
+ extend.action();
242
+
243
+ const polyline = core.scene.entities.get(0);
244
+ expect(polyline.points.length).toBe(3);
245
+ expect(polyline.points[0].x).toBe(0);
246
+ expect(polyline.points[0].y).toBe(0);
247
+ expect(polyline.points[1].x).toBe(50);
248
+ expect(polyline.points[1].y).toBe(0);
249
+ expect(polyline.points[2].x).toBe(100);
250
+ expect(polyline.points[2].y).toBe(0);
251
+ });
252
+
253
+ test('Test Extend.action polyline - extend start segment', () => {
254
+ // Polyline from (25,0) to (50,0) to (100,0)
255
+ // Vertical boundary line at x=0
256
+ // Mouse near (25,0) - the start of the polyline
257
+ // Expected: first point extended to (0,0)
258
+
259
+ const extend = new Extend();
260
+ core.scene.clear();
261
+
262
+ core.scene.addItem('Lwpolyline', { points: [new Point(25, 0), new Point(50, 0), new Point(100, 0)] });
263
+ core.scene.addItem('Line', { points: [new Point(0, -50), new Point(0, 50)] });
264
+
265
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
266
+ extend.selectedItem = core.scene.entities.get(0);
267
+ core.mouse.setPosFromScenePoint(new Point(20, 0));
268
+ extend.action();
269
+
270
+ const polyline = core.scene.entities.get(0);
271
+ expect(polyline.points.length).toBe(3);
272
+ expect(polyline.points[0].x).toBe(0);
273
+ expect(polyline.points[0].y).toBe(0);
274
+ expect(polyline.points[1].x).toBe(50);
275
+ expect(polyline.points[1].y).toBe(0);
276
+ expect(polyline.points[2].x).toBe(100);
277
+ expect(polyline.points[2].y).toBe(0);
278
+ });
279
+
280
+ test('Test Extend.action polyline - reject arc end segment', () => {
281
+ // Polyline: (0,0) -> straight -> (50,0) with bulge=1 -> arc -> (100,0)
282
+ // Vertical boundary line at x=125
283
+ // Mouse near (100,0) - the end of the polyline (arc segment)
284
+ // Expected: no extension, polyline unchanged
285
+
286
+ const extend = new Extend();
287
+ core.scene.clear();
288
+
289
+ core.scene.addItem('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0, 1), new Point(100, 0)] });
290
+ core.scene.addItem('Line', { points: [new Point(125, -50), new Point(125, 50)] });
291
+
292
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
293
+ extend.selectedItem = core.scene.entities.get(0);
294
+ core.mouse.setPosFromScenePoint(new Point(100, 0));
295
+ extend.action();
296
+
297
+ // Polyline should be unchanged
298
+ const polyline = core.scene.entities.get(0);
299
+ expect(polyline.points.length).toBe(3);
300
+ expect(polyline.points[0].x).toBe(0);
301
+ expect(polyline.points[0].y).toBe(0);
302
+ expect(polyline.points[1].x).toBe(50);
303
+ expect(polyline.points[1].y).toBe(0);
304
+ expect(polyline.points[2].x).toBe(100);
305
+ expect(polyline.points[2].y).toBe(0);
306
+ });
307
+
308
+ test('Test Extend.action polyline - reject intersection behind endpoint', () => {
309
+ // Polyline from (50,0) to (75,0) to (100,0)
310
+ // Boundary line at x=25 (behind the start)
311
+ // Mouse near (100,0) - the end of the polyline
312
+ // The boundary is behind the end, so no extension should occur
313
+
314
+ const extend = new Extend();
315
+ core.scene.clear();
316
+
317
+ core.scene.addItem('Lwpolyline', { points: [new Point(50, 0), new Point(75, 0), new Point(100, 0)] });
318
+ core.scene.addItem('Line', { points: [new Point(25, -50), new Point(25, 50)] });
319
+
320
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
321
+ extend.selectedItem = core.scene.entities.get(0);
322
+ core.mouse.setPosFromScenePoint(new Point(95, 0));
323
+ extend.action();
324
+
325
+ // Polyline should be unchanged - intersection is behind the endpoint
326
+ const polyline = core.scene.entities.get(0);
327
+ expect(polyline.points[2].x).toBe(100);
328
+ expect(polyline.points[2].y).toBe(0);
329
+ });
330
+
331
+ test('Test Extend.action polyline - reject shortening intersection', () => {
332
+ // Polyline from (0,0) to (50,0) to (100,0)
333
+ // Boundary line at x=75 (between adjacent and endpoint)
334
+ // Mouse near (100,0) - the end of the polyline
335
+ // Intersection is in the correct direction but would shorten the polyline
336
+
337
+ const extend = new Extend();
338
+ core.scene.clear();
339
+
340
+ core.scene.addItem('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0), new Point(100, 0)] });
341
+ core.scene.addItem('Line', { points: [new Point(75, -50), new Point(75, 50)] });
342
+
343
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
344
+ extend.selectedItem = core.scene.entities.get(0);
345
+ core.mouse.setPosFromScenePoint(new Point(95, 0));
346
+ extend.action();
347
+
348
+ // Polyline should be unchanged - intersection would shorten it
349
+ const polyline = core.scene.entities.get(0);
350
+ expect(polyline.points[2].x).toBe(100);
351
+ expect(polyline.points[2].y).toBe(0);
352
+ });
353
+
354
+ test('Test Extend.action polyline - extend with arc start segment', () => {
355
+ // Polyline: bulge=1 arc -> (50,0) -> straight -> (100,0)
356
+ // Boundary at x=125, mouse near (100,0)
357
+ // The mouse is near the end (line segment), not the arc start
358
+ // Should extend the line segment end
359
+
360
+ const extend = new Extend();
361
+ core.scene.clear();
362
+
363
+ core.scene.addItem('Lwpolyline', { points: [new Point(0, 0, 1), new Point(50, 0), new Point(100, 0)] });
364
+ core.scene.addItem('Line', { points: [new Point(125, -50), new Point(125, 50)] });
365
+
366
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
367
+ extend.selectedItem = core.scene.entities.get(0);
368
+ core.mouse.setPosFromScenePoint(new Point(110, 0));
369
+ extend.action();
370
+
371
+ const polyline = core.scene.entities.get(0);
372
+ expect(polyline.points[2].x).toBe(125);
373
+ expect(polyline.points[2].y).toBe(0);
374
+ });
375
+
376
+ test('Test Extend.action polyline - no intersections', () => {
377
+ // Polyline from (0,0) to (50,0)
378
+ // Boundary line parallel to polyline (no intersection possible)
379
+ // Expected: no extension
380
+
381
+ const extend = new Extend();
382
+ core.scene.clear();
383
+
384
+ core.scene.addItem('Lwpolyline', { points: [new Point(0, 0), new Point(50, 0)] });
385
+ core.scene.addItem('Line', { points: [new Point(0, 50), new Point(100, 50)] });
386
+
387
+ extend.selectedBoundaryItems = [core.scene.entities.get(1)];
388
+ extend.selectedItem = core.scene.entities.get(0);
389
+ core.mouse.setPosFromScenePoint(new Point(45, 0));
390
+ extend.action();
391
+
392
+ const polyline = core.scene.entities.get(0);
393
+ expect(polyline.points[0].x).toBe(0);
394
+ expect(polyline.points[1].x).toBe(50);
113
395
  });