@design-core/core 0.0.7 → 51.1.0
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.
- package/.github/workflows/DesignCoreQA.yml +3 -0
- package/core/designCore.js +1 -1
- package/core/dimensions/alignedDimension.js +7 -7
- package/core/dimensions/angularDimension.js +32 -32
- package/core/dimensions/{baseCircularDimension.js → circularDimensionBase.js} +19 -19
- package/core/dimensions/diametricDimension.js +10 -10
- package/core/dimensions/dimension.js +42 -42
- package/core/dimensions/{baseDimension.js → dimensionBase.js} +17 -17
- package/core/dimensions/{baseLinearDimension.js → linearDimensionBase.js} +9 -9
- package/core/dimensions/radialDimension.js +8 -8
- package/core/dimensions/rotatedDimension.js +8 -8
- package/core/entities/arc.js +22 -22
- package/core/entities/arctext.js +13 -13
- package/core/entities/circle.js +7 -7
- package/core/entities/hatch.js +210 -40
- package/core/entities/insert.js +11 -6
- package/core/entities/point.js +19 -19
- package/core/entities/polyline.js +3 -3
- package/core/entities/{basePolyline.js → polylineBase.js} +18 -18
- package/core/entities/text.js +4 -4
- package/core/lib/boundingBox.js +11 -11
- package/core/lib/canvas.js +13 -6
- package/core/lib/clipboard.js +2 -2
- package/core/lib/dxf/dxf.js +11 -11
- package/core/lib/dxf/dxfIterator.js +2 -2
- package/core/lib/entityManager.js +19 -19
- package/core/lib/inputManager.js +1 -1
- package/core/lib/matrix.js +1 -1
- package/core/lib/patterns.js +1 -1
- package/core/lib/polylineUtils.js +9 -9
- package/core/lib/renderers/cairoRenderer.js +5 -5
- package/core/lib/renderers/canvasRenderer.js +4 -4
- package/core/lib/renderers/pdfRenderer.js +7 -7
- package/core/lib/renderers/rendererBase.js +1 -1
- package/core/lib/scene.js +1 -1
- package/core/lib/selectionManager.js +18 -18
- package/core/lib/utils.js +5 -5
- package/core/properties/entityProperties.js +2 -1
- package/core/properties/flags.js +12 -0
- package/core/properties/property.js +8 -3
- package/core/properties/propertyManager.js +52 -37
- package/core/tables/block.js +50 -46
- package/core/tables/dimStyle.js +5 -5
- package/core/tables/ltypeManager.js +1 -1
- package/core/tables/vport.js +2 -2
- package/core/tools/chamfer.js +6 -6
- package/core/tools/chamferFilletBase.js +4 -4
- package/core/tools/copy.js +8 -8
- package/core/tools/copybase.js +3 -3
- package/core/tools/copyclip.js +3 -3
- package/core/tools/cornerEntity.js +2 -2
- package/core/tools/cutclip.js +3 -3
- package/core/tools/explode.js +6 -6
- package/core/tools/extend.js +13 -13
- package/core/tools/fillet.js +6 -6
- package/core/tools/matchProp.js +1 -1
- package/core/tools/mirror.js +11 -11
- package/core/tools/move.js +5 -5
- package/core/tools/offset.js +29 -29
- package/core/tools/purge.js +10 -10
- package/core/tools/rotate.js +16 -16
- package/core/tools/scale.js +6 -6
- package/core/tools/trim.js +15 -15
- package/cspell.json +323 -0
- package/package.json +1 -1
- package/test/dimensions/alignedDimension.test.js +3 -3
- package/test/dimensions/angularDimension.test.js +7 -7
- package/test/dimensions/diametricDimension.test.js +9 -9
- package/test/dimensions/dimension.test.js +12 -12
- package/test/dimensions/{baseDimension.test.js → dimensionBase.test.js} +12 -12
- package/test/dimensions/{baseLinearDimension.test.js → linearDimensionBase.test.js} +7 -7
- package/test/dimensions/radialDimension.test.js +9 -9
- package/test/dimensions/rotatedDimension.test.js +4 -4
- package/test/entities/arc.test.js +10 -10
- package/test/entities/arctext.test.js +6 -6
- package/test/entities/circle.test.js +18 -18
- package/test/entities/hatch.test.js +362 -39
- package/test/entities/insert.test.js +9 -9
- package/test/entities/point.test.js +3 -3
- package/test/entities/{basePolyline.test.js → polylineBase.test.js} +131 -62
- package/test/entities/text.test.js +19 -19
- package/test/integration/exportIntegration.test.js +3 -3
- package/test/integration/userInputIntegration.test.js +5 -5
- package/test/lib/boundingBox.test.js +3 -3
- package/test/lib/canvas.test.js +9 -9
- package/test/lib/clipboard.test.js +73 -0
- package/test/lib/inputManager.test.js +4 -4
- package/test/lib/scene.test.js +9 -9
- package/test/lib/selectionManager.test.js +3 -3
- package/test/lib/snapping.test.js +1 -1
- package/test/properties/flags.test.js +24 -0
- package/test/properties/propertyManager.test.js +93 -22
- package/test/renderers/pdfRenderer.test.js +2 -2
- package/test/tables/block.test.js +63 -14
- package/test/tables/layerManager.test.js +2 -2
- package/test/test-helpers/hatchGridRenderer.js +3 -3
- package/test/test-helpers/test-helpers.js +6 -6
- package/test/tools/chamfer.test.js +60 -60
- package/test/tools/chamferFilletBase.test.js +36 -36
- package/test/tools/copy.test.js +6 -6
- package/test/tools/copybase.test.js +2 -2
- package/test/tools/copyclip.test.js +2 -2
- package/test/tools/cornerEntity.test.js +8 -8
- package/test/tools/cutclip.test.js +2 -2
- package/test/tools/erase.test.js +6 -6
- package/test/tools/explode.test.js +2 -2
- package/test/tools/extend.test.js +84 -84
- package/test/tools/fillet.test.js +62 -62
- package/test/tools/matchProp.test.js +6 -6
- package/test/tools/mirror.test.js +26 -26
- package/test/tools/move.test.js +7 -7
- package/test/tools/offset.test.js +65 -65
- package/test/tools/purge.test.js +4 -4
- package/test/tools/rotate.test.js +10 -10
- package/test/tools/scale.test.js +28 -28
- package/test/tools/trim.test.js +109 -109
- package/test/tools/zoom.test.js +15 -17
|
@@ -14,7 +14,7 @@ const inputScenarios = [
|
|
|
14
14
|
desc: 'offset line to the left by distance 5',
|
|
15
15
|
entityType: 'Line',
|
|
16
16
|
entityData: { points: [new Point(0, 0), new Point(10, 0)] },
|
|
17
|
-
inputs: [5, {
|
|
17
|
+
inputs: [5, { selectedEntityIndex: 0 }, new Point(5, 5)],
|
|
18
18
|
checkIndex: 1,
|
|
19
19
|
expectedPoints: [new Point(0, 5), new Point(10, 5)],
|
|
20
20
|
},
|
|
@@ -22,7 +22,7 @@ const inputScenarios = [
|
|
|
22
22
|
desc: 'offset line to the right by distance 5',
|
|
23
23
|
entityType: 'Line',
|
|
24
24
|
entityData: { points: [new Point(0, 0), new Point(10, 0)] },
|
|
25
|
-
inputs: [5, {
|
|
25
|
+
inputs: [5, { selectedEntityIndex: 0 }, new Point(5, -5)],
|
|
26
26
|
checkIndex: 1,
|
|
27
27
|
expectedPoints: [new Point(0, -5), new Point(10, -5)],
|
|
28
28
|
},
|
|
@@ -30,7 +30,7 @@ const inputScenarios = [
|
|
|
30
30
|
desc: 'offset circle outward by distance 5',
|
|
31
31
|
entityType: 'Circle',
|
|
32
32
|
entityData: { points: [new Point(0, 0), new Point(10, 0)] },
|
|
33
|
-
inputs: [5, {
|
|
33
|
+
inputs: [5, { selectedEntityIndex: 0 }, new Point(20, 0)],
|
|
34
34
|
checkIndex: 1,
|
|
35
35
|
checkRadius: 15,
|
|
36
36
|
},
|
|
@@ -38,7 +38,7 @@ const inputScenarios = [
|
|
|
38
38
|
desc: 'offset circle inward by distance 3',
|
|
39
39
|
entityType: 'Circle',
|
|
40
40
|
entityData: { points: [new Point(0, 0), new Point(10, 0)] },
|
|
41
|
-
inputs: [3, {
|
|
41
|
+
inputs: [3, { selectedEntityIndex: 0 }, new Point(5, 0)],
|
|
42
42
|
checkIndex: 1,
|
|
43
43
|
checkRadius: 7,
|
|
44
44
|
},
|
|
@@ -46,7 +46,7 @@ const inputScenarios = [
|
|
|
46
46
|
desc: 'offset arc outward by distance 5',
|
|
47
47
|
entityType: 'Arc',
|
|
48
48
|
entityData: { points: [new Point(0, 0), new Point(10, 0), new Point(0, 10)] },
|
|
49
|
-
inputs: [5, {
|
|
49
|
+
inputs: [5, { selectedEntityIndex: 0 }, new Point(20, 0)],
|
|
50
50
|
checkIndex: 1,
|
|
51
51
|
checkRadius: 15,
|
|
52
52
|
},
|
|
@@ -58,7 +58,7 @@ test.each(inputScenarios)('Offset.execute handles $desc', async (scenario) => {
|
|
|
58
58
|
core.scene.clear();
|
|
59
59
|
core.scene.selectionManager.reset();
|
|
60
60
|
|
|
61
|
-
core.scene.
|
|
61
|
+
core.scene.addEntity(entityType, entityData);
|
|
62
62
|
|
|
63
63
|
const origInputManager = core.scene.inputManager;
|
|
64
64
|
let callCount = 0;
|
|
@@ -100,7 +100,7 @@ test('Offset.execute - cancel at distance prompt does not offset', async () => {
|
|
|
100
100
|
core.scene.clear();
|
|
101
101
|
core.scene.selectionManager.reset();
|
|
102
102
|
|
|
103
|
-
core.scene.
|
|
103
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
104
104
|
|
|
105
105
|
const origInputManager = core.scene.inputManager;
|
|
106
106
|
core.scene.inputManager = {
|
|
@@ -121,7 +121,7 @@ test('Offset.execute - cancel at entity selection does not offset', async () =>
|
|
|
121
121
|
core.scene.clear();
|
|
122
122
|
core.scene.selectionManager.reset();
|
|
123
123
|
|
|
124
|
-
core.scene.
|
|
124
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
125
125
|
|
|
126
126
|
const origInputManager = core.scene.inputManager;
|
|
127
127
|
let callCount = 0;
|
|
@@ -148,11 +148,11 @@ test('Offset.execute - cancel at side point does not offset', async () => {
|
|
|
148
148
|
core.scene.clear();
|
|
149
149
|
core.scene.selectionManager.reset();
|
|
150
150
|
|
|
151
|
-
core.scene.
|
|
151
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
152
152
|
|
|
153
153
|
const origInputManager = core.scene.inputManager;
|
|
154
154
|
let callCount = 0;
|
|
155
|
-
const inputs = [5, {
|
|
155
|
+
const inputs = [5, { selectedEntityIndex: 0 }]; // distance + selection, then undefined
|
|
156
156
|
core.scene.inputManager = {
|
|
157
157
|
requestInput: async () => {
|
|
158
158
|
if (callCount < inputs.length) {
|
|
@@ -167,8 +167,8 @@ test('Offset.execute - cancel at side point does not offset', async () => {
|
|
|
167
167
|
await offset.execute();
|
|
168
168
|
|
|
169
169
|
expect(core.scene.entities.count()).toBe(1);
|
|
170
|
-
//
|
|
171
|
-
expect(offset.
|
|
170
|
+
// selectedEntity must be cleared so a stale action() call cannot create an unintended entity
|
|
171
|
+
expect(offset.selectedEntity).toBeNull();
|
|
172
172
|
|
|
173
173
|
core.scene.inputManager = origInputManager;
|
|
174
174
|
});
|
|
@@ -177,14 +177,14 @@ test('Offset.execute - entity count increases by one per offset', async () => {
|
|
|
177
177
|
core.scene.clear();
|
|
178
178
|
core.scene.selectionManager.reset();
|
|
179
179
|
|
|
180
|
-
core.scene.
|
|
181
|
-
core.scene.
|
|
180
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
181
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
182
182
|
|
|
183
183
|
const entityCount = core.scene.entities.count();
|
|
184
184
|
|
|
185
185
|
const origInputManager = core.scene.inputManager;
|
|
186
186
|
let callCount = 0;
|
|
187
|
-
const inputs = [5, {
|
|
187
|
+
const inputs = [5, { selectedEntityIndex: 0 }, new Point(5, 5)];
|
|
188
188
|
core.scene.inputManager = {
|
|
189
189
|
requestInput: async () => {
|
|
190
190
|
if (callCount < inputs.length) {
|
|
@@ -210,10 +210,10 @@ test('Test Offset.action - offset line perpendicular', () => {
|
|
|
210
210
|
core.scene.clear();
|
|
211
211
|
core.scene.selectionManager.reset();
|
|
212
212
|
|
|
213
|
-
core.scene.
|
|
213
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
214
214
|
|
|
215
215
|
const offset = new Offset();
|
|
216
|
-
offset.
|
|
216
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
217
217
|
core.scene.headers.offsetDistance = 5;
|
|
218
218
|
offset.points = [new Point(5, 5)]; // side point above line
|
|
219
219
|
|
|
@@ -232,10 +232,10 @@ test('Test Offset.action - offset vertical line', () => {
|
|
|
232
232
|
core.scene.clear();
|
|
233
233
|
core.scene.selectionManager.reset();
|
|
234
234
|
|
|
235
|
-
core.scene.
|
|
235
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
236
236
|
|
|
237
237
|
const offset = new Offset();
|
|
238
|
-
offset.
|
|
238
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
239
239
|
core.scene.headers.offsetDistance = 3;
|
|
240
240
|
offset.points = [new Point(5, 5)]; // side point to the right
|
|
241
241
|
|
|
@@ -252,10 +252,10 @@ test('Test Offset.action - offset circle outward', () => {
|
|
|
252
252
|
core.scene.clear();
|
|
253
253
|
core.scene.selectionManager.reset();
|
|
254
254
|
|
|
255
|
-
core.scene.
|
|
255
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
256
256
|
|
|
257
257
|
const offset = new Offset();
|
|
258
|
-
offset.
|
|
258
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
259
259
|
core.scene.headers.offsetDistance = 5;
|
|
260
260
|
offset.points = [new Point(20, 0)]; // outside the circle
|
|
261
261
|
|
|
@@ -275,10 +275,10 @@ test('Test Offset.action - offset circle inward', () => {
|
|
|
275
275
|
core.scene.clear();
|
|
276
276
|
core.scene.selectionManager.reset();
|
|
277
277
|
|
|
278
|
-
core.scene.
|
|
278
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
279
279
|
|
|
280
280
|
const offset = new Offset();
|
|
281
|
-
offset.
|
|
281
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
282
282
|
core.scene.headers.offsetDistance = 3;
|
|
283
283
|
offset.points = [new Point(5, 0)]; // inside the circle
|
|
284
284
|
|
|
@@ -294,10 +294,10 @@ test('Test Offset.action - offset circle inward returns null when radius would b
|
|
|
294
294
|
core.scene.clear();
|
|
295
295
|
core.scene.selectionManager.reset();
|
|
296
296
|
|
|
297
|
-
core.scene.
|
|
297
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
298
298
|
|
|
299
299
|
const offset = new Offset();
|
|
300
|
-
offset.
|
|
300
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
301
301
|
core.scene.headers.offsetDistance = 15; // larger than radius
|
|
302
302
|
offset.points = [new Point(5, 0)]; // inside
|
|
303
303
|
|
|
@@ -311,14 +311,14 @@ test('Test Offset.action - offset arc outward preserves angles', () => {
|
|
|
311
311
|
core.scene.clear();
|
|
312
312
|
core.scene.selectionManager.reset();
|
|
313
313
|
|
|
314
|
-
const
|
|
315
|
-
const start =
|
|
316
|
-
const end =
|
|
314
|
+
const centre = new Point(0, 0);
|
|
315
|
+
const start = centre.project(0, 10); // radius 10
|
|
316
|
+
const end = centre.project(Math.PI / 2, 10);
|
|
317
317
|
|
|
318
|
-
core.scene.
|
|
318
|
+
core.scene.addEntity('Arc', { points: [centre, start, end] });
|
|
319
319
|
|
|
320
320
|
const offset = new Offset();
|
|
321
|
-
offset.
|
|
321
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
322
322
|
core.scene.headers.offsetDistance = 5;
|
|
323
323
|
offset.points = [new Point(20, 0)]; // outside
|
|
324
324
|
|
|
@@ -330,8 +330,8 @@ test('Test Offset.action - offset arc outward preserves angles', () => {
|
|
|
330
330
|
expect(newRadius).toBeCloseTo(15);
|
|
331
331
|
|
|
332
332
|
// Start and end angles should be preserved
|
|
333
|
-
const originalStartAngle =
|
|
334
|
-
const originalEndAngle =
|
|
333
|
+
const originalStartAngle = centre.angle(start);
|
|
334
|
+
const originalEndAngle = centre.angle(end);
|
|
335
335
|
const newStartAngle = newArc.points[0].angle(newArc.points[1]);
|
|
336
336
|
const newEndAngle = newArc.points[0].angle(newArc.points[2]);
|
|
337
337
|
expect(newStartAngle).toBeCloseTo(originalStartAngle);
|
|
@@ -342,10 +342,10 @@ test('Test Offset.action - unsupported entity type does not create new entity',
|
|
|
342
342
|
core.scene.clear();
|
|
343
343
|
core.scene.selectionManager.reset();
|
|
344
344
|
|
|
345
|
-
core.scene.
|
|
345
|
+
core.scene.addEntity('Rectangle', { points: [new Point(0, 0), new Point(10, 10)] });
|
|
346
346
|
|
|
347
347
|
const offset = new Offset();
|
|
348
|
-
offset.
|
|
348
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
349
349
|
core.scene.headers.offsetDistance = 5;
|
|
350
350
|
offset.points = [new Point(20, 20)];
|
|
351
351
|
|
|
@@ -397,7 +397,7 @@ test('Test Offset.getThroughDistance - circle', () => {
|
|
|
397
397
|
|
|
398
398
|
test('Test Offset.getThroughDistance - arc uses same radial distance as circle', () => {
|
|
399
399
|
const offset = new Offset();
|
|
400
|
-
// Arc:
|
|
400
|
+
// Arc: centre (0,0), radius 10
|
|
401
401
|
const entity = new Arc({ points: [new Point(0, 0), new Point(10, 0), new Point(0, 10)] });
|
|
402
402
|
|
|
403
403
|
// Point inside the arc radius
|
|
@@ -409,7 +409,7 @@ test('Test Offset.getThroughDistance - arc uses same radial distance as circle',
|
|
|
409
409
|
test('Test Offset.getThroughDistance - polyline uses closestPoint distance', () => {
|
|
410
410
|
core.scene.clear();
|
|
411
411
|
core.scene.selectionManager.reset();
|
|
412
|
-
core.scene.
|
|
412
|
+
core.scene.addEntity('Polyline', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
413
413
|
const entity = core.scene.entities.get(0);
|
|
414
414
|
|
|
415
415
|
const offset = new Offset();
|
|
@@ -426,13 +426,13 @@ test('Test Offset.getThroughDistance - unsupported entity returns 0', () => {
|
|
|
426
426
|
|
|
427
427
|
// ─── action edge cases ────────────────────────────────────────────────────────
|
|
428
428
|
|
|
429
|
-
test('Test Offset.action - returns early when
|
|
429
|
+
test('Test Offset.action - returns early when selectedEntity is null', () => {
|
|
430
430
|
core.scene.clear();
|
|
431
431
|
core.scene.selectionManager.reset();
|
|
432
|
-
core.scene.
|
|
432
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
433
433
|
|
|
434
434
|
const offset = new Offset();
|
|
435
|
-
offset.
|
|
435
|
+
offset.selectedEntity = null;
|
|
436
436
|
core.scene.headers.offsetDistance = 5;
|
|
437
437
|
offset.action();
|
|
438
438
|
|
|
@@ -442,10 +442,10 @@ test('Test Offset.action - returns early when selectedItem is null', () => {
|
|
|
442
442
|
test('Test Offset.action - returns early when offsetDistance is 0', () => {
|
|
443
443
|
core.scene.clear();
|
|
444
444
|
core.scene.selectionManager.reset();
|
|
445
|
-
core.scene.
|
|
445
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
446
446
|
|
|
447
447
|
const offset = new Offset();
|
|
448
|
-
offset.
|
|
448
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
449
449
|
core.scene.headers.offsetDistance = 0;
|
|
450
450
|
offset.points = [new Point(5, 5)];
|
|
451
451
|
offset.action();
|
|
@@ -459,7 +459,7 @@ test('Test Offset.getOffsetPoints - arc inward offset shrinks radius', () => {
|
|
|
459
459
|
const offset = new Offset();
|
|
460
460
|
const entity = new Arc({ points: [new Point(0, 0), new Point(10, 0), new Point(0, 10)] });
|
|
461
461
|
|
|
462
|
-
// sidePoint inside the arc (between
|
|
462
|
+
// sidePoint inside the arc (between centre and circumference)
|
|
463
463
|
const result = offset.getOffsetPoints(entity, new Point(5, 0), 3);
|
|
464
464
|
|
|
465
465
|
expect(result).not.toBeNull();
|
|
@@ -538,7 +538,7 @@ test('Test Offset.getOffsetPolylinePoints - closed rectangle offset outward', ()
|
|
|
538
538
|
test('Test Offset.getOffsetPolylinePoints - arc segment (bulge) offset outward grows radius', () => {
|
|
539
539
|
const offset = new Offset();
|
|
540
540
|
// CW semicircle (bulge=-1) from (0,0) to (10,0): traces the TOP half through (5,5)
|
|
541
|
-
//
|
|
541
|
+
// centre=(5,0), radius=5
|
|
542
542
|
const start = new Point(0, 0, -1); // bulge=-1 → CW, arc goes upward
|
|
543
543
|
const end = new Point(10, 0);
|
|
544
544
|
const points = [start, end];
|
|
@@ -577,7 +577,7 @@ test('Offset.findJunction - parallel line/line falls back to midpoint', () => {
|
|
|
577
577
|
|
|
578
578
|
test('Offset.findJunction - arc/line returns circle-line intersection', () => {
|
|
579
579
|
const offset = new Offset();
|
|
580
|
-
// Arc: A=(-5,0) B=(5,0) bulge=1 →
|
|
580
|
+
// Arc: A=(-5,0) B=(5,0) bulge=1 → centre (0,0), radius 5 via bulgeCentrePoint
|
|
581
581
|
// Line: vertical at x=3 → circle intersects at (3,4) and (3,-4)
|
|
582
582
|
const seg = { A: new Point(-5, 0), B: new Point(5, 0), bulge: 1 };
|
|
583
583
|
const nextSeg = { A: new Point(3, 5), B: new Point(3, 10), bulge: 0 };
|
|
@@ -601,7 +601,7 @@ test('Offset.findJunction - line/arc returns line-circle intersection', () => {
|
|
|
601
601
|
|
|
602
602
|
test('Offset.findJunction - arc/arc returns circle-circle intersection', () => {
|
|
603
603
|
const offset = new Offset();
|
|
604
|
-
// Circle 1: A=(-4,0) B=(4,0) bulge=1 →
|
|
604
|
+
// Circle 1: A=(-4,0) B=(4,0) bulge=1 → centre (0,0), radius 4 via bulgeCentrePoint
|
|
605
605
|
// Circle 2: A=(0,4) B=(6,4) bulge=1 → center (3,4), radius 3 via bulgeCentrePoint
|
|
606
606
|
// Intersections: (0,4) and (96/25, 28/25)
|
|
607
607
|
const seg = { A: new Point(-4, 0), B: new Point(4, 0), bulge: 1 };
|
|
@@ -629,7 +629,7 @@ test('Offset.findJunction - non-intersecting arc/arc falls back to midpoint', ()
|
|
|
629
629
|
test('Offset.execute - single preselection skips entity selection prompt', async () => {
|
|
630
630
|
core.scene.clear();
|
|
631
631
|
core.scene.selectionManager.reset();
|
|
632
|
-
core.scene.
|
|
632
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
633
633
|
// Preselect the entity
|
|
634
634
|
core.scene.selectionManager.addToSelectionSet(0);
|
|
635
635
|
|
|
@@ -658,8 +658,8 @@ test('Offset.execute - single preselection skips entity selection prompt', async
|
|
|
658
658
|
test('Offset.execute - multi-preselection clears selection and prompts', async () => {
|
|
659
659
|
core.scene.clear();
|
|
660
660
|
core.scene.selectionManager.reset();
|
|
661
|
-
core.scene.
|
|
662
|
-
core.scene.
|
|
661
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
662
|
+
core.scene.addEntity('Line', { points: [new Point(0, 5), new Point(10, 5)] });
|
|
663
663
|
// Preselect two entities
|
|
664
664
|
core.scene.selectionManager.addToSelectionSet(0);
|
|
665
665
|
core.scene.selectionManager.addToSelectionSet(1);
|
|
@@ -667,7 +667,7 @@ test('Offset.execute - multi-preselection clears selection and prompts', async (
|
|
|
667
667
|
const origInputManager = core.scene.inputManager;
|
|
668
668
|
let callCount = 0;
|
|
669
669
|
// After clearing, distance + selection + side-point
|
|
670
|
-
const inputs = [5, {
|
|
670
|
+
const inputs = [5, { selectedEntityIndex: 0 }, new Point(5, 5)];
|
|
671
671
|
const offset = new Offset();
|
|
672
672
|
core.scene.inputManager = {
|
|
673
673
|
requestInput: async () => {
|
|
@@ -691,7 +691,7 @@ test('Offset.execute - multi-preselection clears selection and prompts', async (
|
|
|
691
691
|
test('Offset.execute - distance <= 0 notifies and does not offset', async () => {
|
|
692
692
|
core.scene.clear();
|
|
693
693
|
core.scene.selectionManager.reset();
|
|
694
|
-
core.scene.
|
|
694
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
695
695
|
|
|
696
696
|
const notifySpy = jest.spyOn(core, 'notify').mockImplementation(() => {});
|
|
697
697
|
|
|
@@ -715,12 +715,12 @@ test('Offset.execute - distance <= 0 notifies and does not offset', async () =>
|
|
|
715
715
|
test('Offset.execute - Through mode offsets entity to the through point distance', async () => {
|
|
716
716
|
core.scene.clear();
|
|
717
717
|
core.scene.selectionManager.reset();
|
|
718
|
-
core.scene.
|
|
718
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
719
719
|
|
|
720
720
|
const origInputManager = core.scene.inputManager;
|
|
721
721
|
let callCount = 0;
|
|
722
722
|
// 'Through' → select entity at index 0 → through point at (5, 7) → undefined exits loop
|
|
723
|
-
const inputs = ['Through', {
|
|
723
|
+
const inputs = ['Through', { selectedEntityIndex: 0 }, new Point(5, 7)];
|
|
724
724
|
|
|
725
725
|
const offset = new Offset();
|
|
726
726
|
core.scene.inputManager = {
|
|
@@ -758,20 +758,20 @@ test('Offset.register returns correct metadata', () => {
|
|
|
758
758
|
|
|
759
759
|
// ─── preview ──────────────────────────────────────────────────────────────────
|
|
760
760
|
|
|
761
|
-
test('Offset.preview does not add preview entity when
|
|
761
|
+
test('Offset.preview does not add preview entity when selectedEntity is null', () => {
|
|
762
762
|
core.scene.clear();
|
|
763
763
|
DesignCore.Scene.previewEntities.clear();
|
|
764
764
|
core.scene.headers.offsetDistance = 5;
|
|
765
765
|
|
|
766
766
|
const offset = new Offset();
|
|
767
|
-
offset.
|
|
767
|
+
offset.selectedEntity = null;
|
|
768
768
|
expect(() => offset.preview()).not.toThrow();
|
|
769
769
|
expect(DesignCore.Scene.previewEntities.count()).toBe(0);
|
|
770
770
|
});
|
|
771
771
|
|
|
772
772
|
test('Offset.preview does not add preview entity when offsetDistance is 0', () => {
|
|
773
773
|
core.scene.clear();
|
|
774
|
-
core.scene.
|
|
774
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
775
775
|
DesignCore.Scene.previewEntities.clear();
|
|
776
776
|
core.scene.headers.offsetDistance = 0;
|
|
777
777
|
|
|
@@ -779,7 +779,7 @@ test('Offset.preview does not add preview entity when offsetDistance is 0', () =
|
|
|
779
779
|
DesignCore.Mouse.pointOnScene = () => new Point(5, 5);
|
|
780
780
|
|
|
781
781
|
const offset = new Offset();
|
|
782
|
-
offset.
|
|
782
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
783
783
|
offset.preview();
|
|
784
784
|
|
|
785
785
|
DesignCore.Mouse.pointOnScene = savedPointOnScene;
|
|
@@ -788,7 +788,7 @@ test('Offset.preview does not add preview entity when offsetDistance is 0', () =
|
|
|
788
788
|
|
|
789
789
|
test('Offset.preview adds entity to previewEntities for a valid line', () => {
|
|
790
790
|
core.scene.clear();
|
|
791
|
-
core.scene.
|
|
791
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
792
792
|
DesignCore.Scene.previewEntities.clear();
|
|
793
793
|
core.scene.headers.offsetDistance = 5;
|
|
794
794
|
|
|
@@ -796,7 +796,7 @@ test('Offset.preview adds entity to previewEntities for a valid line', () => {
|
|
|
796
796
|
DesignCore.Mouse.pointOnScene = () => new Point(5, 5);
|
|
797
797
|
|
|
798
798
|
const offset = new Offset();
|
|
799
|
-
offset.
|
|
799
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
800
800
|
offset.preview();
|
|
801
801
|
|
|
802
802
|
DesignCore.Mouse.pointOnScene = savedPointOnScene;
|
|
@@ -811,10 +811,10 @@ test('Test Offset.action - offset open Lwpolyline', () => {
|
|
|
811
811
|
core.scene.selectionManager.reset();
|
|
812
812
|
|
|
813
813
|
// L-shape: (0,0) → (10,0) → (10,10)
|
|
814
|
-
core.scene.
|
|
814
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10)] });
|
|
815
815
|
|
|
816
816
|
const offset = new Offset();
|
|
817
|
-
offset.
|
|
817
|
+
offset.selectedEntity = core.scene.entities.get(0);
|
|
818
818
|
core.scene.headers.offsetDistance = 1;
|
|
819
819
|
offset.points = [new Point(5, 2)]; // above the bottom segment → offset upward/left
|
|
820
820
|
|
|
@@ -833,7 +833,7 @@ test('Test Offset.action - offset closed Lwpolyline outward', () => {
|
|
|
833
833
|
core.scene.selectionManager.reset();
|
|
834
834
|
|
|
835
835
|
// Closed square: 5 points where first === last → constructor sets flag=1
|
|
836
|
-
core.scene.
|
|
836
|
+
core.scene.addEntity('Lwpolyline', {
|
|
837
837
|
points: [new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10), new Point(0, 0)],
|
|
838
838
|
});
|
|
839
839
|
|
|
@@ -841,7 +841,7 @@ test('Test Offset.action - offset closed Lwpolyline outward', () => {
|
|
|
841
841
|
expect(polyline.flags.hasFlag(1)).toBe(true); // confirm closed
|
|
842
842
|
|
|
843
843
|
const offset = new Offset();
|
|
844
|
-
offset.
|
|
844
|
+
offset.selectedEntity = polyline;
|
|
845
845
|
core.scene.headers.offsetDistance = 1;
|
|
846
846
|
offset.points = [new Point(-5, 5)]; // outside the left edge
|
|
847
847
|
|
|
@@ -883,13 +883,13 @@ test('Offset.execute - Through mode offsets circle to the through point', async
|
|
|
883
883
|
core.scene.clear();
|
|
884
884
|
core.scene.selectionManager.reset();
|
|
885
885
|
|
|
886
|
-
// Circle:
|
|
887
|
-
core.scene.
|
|
886
|
+
// Circle: centre (0,0), radius 10
|
|
887
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
888
888
|
|
|
889
889
|
const origInputManager = core.scene.inputManager;
|
|
890
890
|
let callCount = 0;
|
|
891
891
|
// Through → select circle → through point at (15,0) → undefined exits loop
|
|
892
|
-
const inputs = ['Through', {
|
|
892
|
+
const inputs = ['Through', { selectedEntityIndex: 0 }, new Point(15, 0)];
|
|
893
893
|
|
|
894
894
|
const offset = new Offset();
|
|
895
895
|
core.scene.inputManager = {
|
package/test/tools/purge.test.js
CHANGED
|
@@ -29,10 +29,10 @@ beforeEach(() => {
|
|
|
29
29
|
|
|
30
30
|
const data = { points: [point1, point2], layer: 'layerWithItems', lineType: 'ltypeWithItems' };
|
|
31
31
|
|
|
32
|
-
DesignCore.Scene.
|
|
33
|
-
DesignCore.Scene.
|
|
34
|
-
DesignCore.Scene.
|
|
35
|
-
DesignCore.Scene.
|
|
32
|
+
DesignCore.Scene.addEntity('Insert', { blockName: 'blockWithItems' });
|
|
33
|
+
DesignCore.Scene.addEntity('Line', data);
|
|
34
|
+
DesignCore.Scene.addEntity('Circle', data);
|
|
35
|
+
DesignCore.Scene.addEntity('Text', data);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
test('Test purge.action', () => {
|
|
@@ -49,7 +49,7 @@ test.each(inputScenarios)('Rotate.execute handles $desc', async (scenario) => {
|
|
|
49
49
|
// create line
|
|
50
50
|
const pointOne = new Point(10, 0);
|
|
51
51
|
const pointTwo = new Point(20, 0);
|
|
52
|
-
core.scene.
|
|
52
|
+
core.scene.addEntity('Line', { points: [pointOne, pointTwo] });
|
|
53
53
|
|
|
54
54
|
// select line
|
|
55
55
|
core.scene.selectionManager.addToSelectionSet(0);
|
|
@@ -78,12 +78,12 @@ test.each(inputScenarios)('Rotate.execute handles $desc', async (scenario) => {
|
|
|
78
78
|
|
|
79
79
|
test('Test Rotate.action', () => {
|
|
80
80
|
// Add items to scene
|
|
81
|
-
core.scene.
|
|
82
|
-
core.scene.
|
|
83
|
-
core.scene.
|
|
84
|
-
core.scene.
|
|
85
|
-
core.scene.
|
|
86
|
-
core.scene.
|
|
81
|
+
core.scene.addEntity('Line', { points: [new Point(10, 0), new Point(20, 0)] });
|
|
82
|
+
core.scene.addEntity('Circle', { points: [new Point(10, 0), new Point(20, 0)] });
|
|
83
|
+
core.scene.addEntity('Polyline', { points: [new Point(10, 0), new Point(20, 0)] });
|
|
84
|
+
core.scene.addEntity('Arc', { points: [new Point(10, 0), new Point(10, 10), new Point(0, 10)] });
|
|
85
|
+
core.scene.addEntity('Rectangle', { points: [new Point(10, 0), new Point(0, 10)] });
|
|
86
|
+
core.scene.addEntity('Text', { points: [new Point(10, 0), new Point(0, 10)], height: 10, rotation: 0, string: 'text test' });
|
|
87
87
|
|
|
88
88
|
// Add items to selection set
|
|
89
89
|
for (let i = 0; i < core.scene.entities.count(); i++) {
|
|
@@ -132,7 +132,7 @@ test('Test Rotate.action', () => {
|
|
|
132
132
|
}
|
|
133
133
|
});
|
|
134
134
|
|
|
135
|
-
test('Rotate.execute with reference - resets inputPoint to rotation
|
|
135
|
+
test('Rotate.execute with reference - resets inputPoint to rotation centre', async () => {
|
|
136
136
|
const origInputManager = core.scene.inputManager;
|
|
137
137
|
|
|
138
138
|
const basePoint = new Point(10, 0);
|
|
@@ -149,14 +149,14 @@ test('Rotate.execute with reference - resets inputPoint to rotation center', asy
|
|
|
149
149
|
core.scene.inputManager = mockInputManager;
|
|
150
150
|
|
|
151
151
|
core.scene.clear();
|
|
152
|
-
core.scene.
|
|
152
|
+
core.scene.addEntity('Line', { points: [new Point(10, 0), new Point(20, 0)] });
|
|
153
153
|
core.scene.selectionManager.addToSelectionSet(0);
|
|
154
154
|
|
|
155
155
|
const rotate = new Rotate();
|
|
156
156
|
await rotate.execute();
|
|
157
157
|
|
|
158
158
|
// After the reference sequence completes, inputPoint must be reset to the
|
|
159
|
-
// rotation
|
|
159
|
+
// rotation centre (points[0]) so the tracking line uses the correct origin.
|
|
160
160
|
expect(mockInputManager.inputPoint).toEqual(basePoint);
|
|
161
161
|
|
|
162
162
|
core.scene.inputManager = origInputManager;
|