@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
|
@@ -91,7 +91,7 @@ test('Test LayerManager.checkStyles', () => {
|
|
|
91
91
|
layer: newItemName,
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
core.scene.
|
|
94
|
+
core.scene.addEntity('Line', data);
|
|
95
95
|
|
|
96
96
|
layerManager.checkStyles();
|
|
97
97
|
const layers = layerManager.getItems();
|
|
@@ -115,7 +115,7 @@ test('Test LayerManager.checkItems', () => {
|
|
|
115
115
|
layer: newItemName,
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
-
core.scene.
|
|
118
|
+
core.scene.addEntity('Line', data);
|
|
119
119
|
|
|
120
120
|
layerManager.checkItems();
|
|
121
121
|
const layers = layerManager.getItems();
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
import { Core } from '../../core/core/core.js';
|
|
17
17
|
import { Hatch } from '../../core/entities/hatch.js';
|
|
18
|
-
import {
|
|
18
|
+
import { PolylineBase } from '../../core/entities/polylineBase.js';
|
|
19
19
|
import { Point } from '../../core/entities/point.js';
|
|
20
20
|
import { Text } from '../../core/entities/text.js';
|
|
21
21
|
|
|
@@ -136,7 +136,7 @@ export function buildHatchGrid(renderer) {
|
|
|
136
136
|
let outlinePoints;
|
|
137
137
|
|
|
138
138
|
if (i % 2 === 0) {
|
|
139
|
-
hatchBoundary = new
|
|
139
|
+
hatchBoundary = new PolylineBase({ points: [
|
|
140
140
|
new Point(cx - SHAPE_R, cy - SHAPE_R),
|
|
141
141
|
new Point(cx + SHAPE_R, cy - SHAPE_R),
|
|
142
142
|
new Point(cx + SHAPE_R, cy + SHAPE_R),
|
|
@@ -145,7 +145,7 @@ export function buildHatchGrid(renderer) {
|
|
|
145
145
|
outlinePoints = hatchBoundary.toPolylinePoints();
|
|
146
146
|
} else {
|
|
147
147
|
// Two exact semicircle arcs (bulge = 1) for clipping; polygon for visible outline
|
|
148
|
-
hatchBoundary = new
|
|
148
|
+
hatchBoundary = new PolylineBase({ points: [
|
|
149
149
|
new Point(cx + SHAPE_R, cy, 1),
|
|
150
150
|
new Point(cx - SHAPE_R, cy, 1),
|
|
151
151
|
] });
|
|
@@ -27,10 +27,10 @@ export class File {
|
|
|
27
27
|
* @param {Function} testFn - async function to run with the mock active
|
|
28
28
|
* @param {object} [options] - optional configuration
|
|
29
29
|
* @param {object} [options.extraMethods] - additional methods to add to the mock inputManager
|
|
30
|
-
* @param {Array} [options.
|
|
30
|
+
* @param {Array} [options.selectedEntities] - sequential values returned by entities.get
|
|
31
31
|
*/
|
|
32
32
|
export async function withMockInput(scene, inputs, testFn, options = {}) {
|
|
33
|
-
const { extraMethods = {},
|
|
33
|
+
const { extraMethods = {}, selectedEntities } = options;
|
|
34
34
|
const origInputManager = scene.inputManager;
|
|
35
35
|
let callCount = 0;
|
|
36
36
|
|
|
@@ -47,11 +47,11 @@ export async function withMockInput(scene, inputs, testFn, options = {}) {
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
let origGetItem;
|
|
50
|
-
if (
|
|
50
|
+
if (selectedEntities) {
|
|
51
51
|
origGetItem = scene.entities.get;
|
|
52
|
-
let
|
|
52
|
+
let selectedEntitiesCallCount = 0;
|
|
53
53
|
scene.entities.get = () => {
|
|
54
|
-
return
|
|
54
|
+
return selectedEntities[selectedEntitiesCallCount++];
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -59,7 +59,7 @@ export async function withMockInput(scene, inputs, testFn, options = {}) {
|
|
|
59
59
|
await testFn();
|
|
60
60
|
} finally {
|
|
61
61
|
scene.inputManager = origInputManager;
|
|
62
|
-
if (
|
|
62
|
+
if (selectedEntities) {
|
|
63
63
|
scene.entities.get = origGetItem;
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -21,7 +21,7 @@ test('Chamfer.register returns correct command object', () => {
|
|
|
21
21
|
|
|
22
22
|
test('Chamfer.action does nothing when entities are not set', () => {
|
|
23
23
|
core.scene.clear();
|
|
24
|
-
core.scene.
|
|
24
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
25
25
|
const countBefore = core.scene.entities.count();
|
|
26
26
|
|
|
27
27
|
const chamfer = new Chamfer();
|
|
@@ -32,8 +32,8 @@ test('Chamfer.action does nothing when entities are not set', () => {
|
|
|
32
32
|
|
|
33
33
|
test('Chamfer.action notifies when first entity type is not supported', () => {
|
|
34
34
|
core.scene.clear();
|
|
35
|
-
core.scene.
|
|
36
|
-
core.scene.
|
|
35
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
36
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
37
37
|
|
|
38
38
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
39
39
|
|
|
@@ -50,8 +50,8 @@ test('Chamfer.action notifies when first entity type is not supported', () => {
|
|
|
50
50
|
|
|
51
51
|
test('Chamfer.action notifies when second entity type is not supported', () => {
|
|
52
52
|
core.scene.clear();
|
|
53
|
-
core.scene.
|
|
54
|
-
core.scene.
|
|
53
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
54
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
55
55
|
|
|
56
56
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
57
57
|
|
|
@@ -68,8 +68,8 @@ test('Chamfer.action notifies when second entity type is not supported', () => {
|
|
|
68
68
|
|
|
69
69
|
test('Chamfer.action notifies for parallel lines', () => {
|
|
70
70
|
core.scene.clear();
|
|
71
|
-
core.scene.
|
|
72
|
-
core.scene.
|
|
71
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
72
|
+
core.scene.addEntity('Line', { points: [new Point(0, 5), new Point(10, 5)] });
|
|
73
73
|
|
|
74
74
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
75
75
|
|
|
@@ -90,8 +90,8 @@ test('Chamfer.action dist=0 trimMode=true trims both lines to intersection', ()
|
|
|
90
90
|
// Lines only touching when extended: horizontal (0,0)→(8,0), vertical (10,-10)→(10,-2)
|
|
91
91
|
// Infinite extensions meet at (10, 0).
|
|
92
92
|
core.scene.clear();
|
|
93
|
-
core.scene.
|
|
94
|
-
core.scene.
|
|
93
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(8, 0)] });
|
|
94
|
+
core.scene.addEntity('Line', { points: [new Point(10, -10), new Point(10, -2)] });
|
|
95
95
|
|
|
96
96
|
core.scene.headers.chamferDistanceA = 0;
|
|
97
97
|
core.scene.headers.chamferDistanceB = 0;
|
|
@@ -122,8 +122,8 @@ test('Chamfer.action dist=0 trimMode=true trims both lines to intersection', ()
|
|
|
122
122
|
|
|
123
123
|
test('Chamfer.action dist=0 trimMode=false makes no changes', () => {
|
|
124
124
|
core.scene.clear();
|
|
125
|
-
core.scene.
|
|
126
|
-
core.scene.
|
|
125
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(8, 0)] });
|
|
126
|
+
core.scene.addEntity('Line', { points: [new Point(10, -10), new Point(10, -2)] });
|
|
127
127
|
|
|
128
128
|
core.scene.headers.chamferDistanceA = 0;
|
|
129
129
|
core.scene.headers.chamferDistanceB = 0;
|
|
@@ -146,8 +146,8 @@ test('Chamfer.action distance method trimMode=true adds chamfer line and trims',
|
|
|
146
146
|
// Perpendicular L-corner at origin: horizontal (-10,0)→(0,0), vertical (0,0)→(0,10)
|
|
147
147
|
// Equal distances of 2 → chamfer endpoints at (-2,0) and (0,2)
|
|
148
148
|
core.scene.clear();
|
|
149
|
-
core.scene.
|
|
150
|
-
core.scene.
|
|
149
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
150
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
151
151
|
|
|
152
152
|
core.scene.headers.chamferDistanceA = 2;
|
|
153
153
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -191,8 +191,8 @@ test('Chamfer.action distance method trimMode=true adds chamfer line and trims',
|
|
|
191
191
|
test('Chamfer.action distance method asymmetric distances', () => {
|
|
192
192
|
// L-corner at origin, distA=3 along horizontal, distB=1 along vertical
|
|
193
193
|
core.scene.clear();
|
|
194
|
-
core.scene.
|
|
195
|
-
core.scene.
|
|
194
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
195
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
196
196
|
|
|
197
197
|
core.scene.headers.chamferDistanceA = 3;
|
|
198
198
|
core.scene.headers.chamferDistanceB = 1;
|
|
@@ -216,8 +216,8 @@ test('Chamfer.action distance method asymmetric distances', () => {
|
|
|
216
216
|
|
|
217
217
|
test('Chamfer.action distance method trimMode=false adds chamfer line only', () => {
|
|
218
218
|
core.scene.clear();
|
|
219
|
-
core.scene.
|
|
220
|
-
core.scene.
|
|
219
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
220
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
221
221
|
|
|
222
222
|
core.scene.headers.chamferDistanceA = 2;
|
|
223
223
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -245,8 +245,8 @@ test('Chamfer.action distance method trimMode=false adds chamfer line only', ()
|
|
|
245
245
|
test('Chamfer.action notifies when distance is too large for the segments', () => {
|
|
246
246
|
// Lines only 5 units long from intersection — distance 10 won't fit
|
|
247
247
|
core.scene.clear();
|
|
248
|
-
core.scene.
|
|
249
|
-
core.scene.
|
|
248
|
+
core.scene.addEntity('Line', { points: [new Point(-5, 0), new Point(0, 0)] });
|
|
249
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 5)] });
|
|
250
250
|
|
|
251
251
|
core.scene.headers.chamferDistanceA = 10;
|
|
252
252
|
core.scene.headers.chamferDistanceB = 10;
|
|
@@ -273,8 +273,8 @@ test('Chamfer.action angle method 45° on perpendicular lines matches distance m
|
|
|
273
273
|
// With perpendicular lines and 45°, the chamfer endpoint on line2 should also be 2 units
|
|
274
274
|
// from the intersection — matching a symmetric distance chamfer.
|
|
275
275
|
core.scene.clear();
|
|
276
|
-
core.scene.
|
|
277
|
-
core.scene.
|
|
276
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
277
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
278
278
|
|
|
279
279
|
core.scene.headers.chamferLength = 2;
|
|
280
280
|
core.scene.headers.chamferAngle = 45; // degrees
|
|
@@ -307,8 +307,8 @@ test('Chamfer.action notifies when click coincides with intersection', () => {
|
|
|
307
307
|
// L-corner at origin. Clicking firstClickPoint exactly at (0,0) makes
|
|
308
308
|
// firstClickDistance = 0, triggering the "Selected corner cannot be chamfered" guard.
|
|
309
309
|
core.scene.clear();
|
|
310
|
-
core.scene.
|
|
311
|
-
core.scene.
|
|
310
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
311
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
312
312
|
|
|
313
313
|
core.scene.headers.chamferDistanceA = 2;
|
|
314
314
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -333,8 +333,8 @@ test('Chamfer.action notifies when click coincides with intersection', () => {
|
|
|
333
333
|
|
|
334
334
|
test('Chamfer.action angle method notifies INVALIDNUMBER when angle is zero', () => {
|
|
335
335
|
core.scene.clear();
|
|
336
|
-
core.scene.
|
|
337
|
-
core.scene.
|
|
336
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
337
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
338
338
|
|
|
339
339
|
core.scene.headers.chamferLength = 2;
|
|
340
340
|
core.scene.headers.chamferAngle = 0; // alpha = 0 * π/180 = 0, fails alpha <= 0 guard
|
|
@@ -362,8 +362,8 @@ test('Chamfer.action angle method notifies PARALLELLINES when chamfer direction
|
|
|
362
362
|
// candidate1 = rotate(-1,0) by +π/2 = (0,-1); dot with secondClickUnit (0,1) = -1 < 0.
|
|
363
363
|
// candidate2 = rotate(-1,0) by -π/2 = (0, 1) → parallel to secondLineDirection (0,1) → cross = 0.
|
|
364
364
|
core.scene.clear();
|
|
365
|
-
core.scene.
|
|
366
|
-
core.scene.
|
|
365
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
366
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
367
367
|
|
|
368
368
|
core.scene.headers.chamferLength = 2;
|
|
369
369
|
core.scene.headers.chamferAngle = 90; // degrees
|
|
@@ -397,8 +397,8 @@ test('Chamfer.execute returns early when first input is undefined', async () =>
|
|
|
397
397
|
|
|
398
398
|
test('Chamfer.execute selects two lines and calls executeCommand', async () => {
|
|
399
399
|
core.scene.clear();
|
|
400
|
-
core.scene.
|
|
401
|
-
core.scene.
|
|
400
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
401
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
402
402
|
|
|
403
403
|
const executeCommandSpy = jest.fn();
|
|
404
404
|
|
|
@@ -544,7 +544,7 @@ test('Chamfer.execute sets chamferMode to true via Method=Angle option', async (
|
|
|
544
544
|
|
|
545
545
|
test('Chamfer.execute re-prompts and notifies when first selected entity is not a Line', async () => {
|
|
546
546
|
core.scene.clear();
|
|
547
|
-
core.scene.
|
|
547
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
548
548
|
|
|
549
549
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
550
550
|
|
|
@@ -563,8 +563,8 @@ test('Chamfer.execute re-prompts and notifies when first selected entity is not
|
|
|
563
563
|
|
|
564
564
|
test('Chamfer.execute re-prompts and notifies when second selected entity is not a Line', async () => {
|
|
565
565
|
core.scene.clear();
|
|
566
|
-
core.scene.
|
|
567
|
-
core.scene.
|
|
566
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(10, 0)] });
|
|
567
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
568
568
|
|
|
569
569
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
570
570
|
|
|
@@ -594,8 +594,8 @@ test('Chamfer.execute re-prompts and notifies when second selected entity is not
|
|
|
594
594
|
test('Chamfer.action dist>0 trimMode=true Line first + Lwpolyline second keepStart: chamfer embedded in polyline', () => {
|
|
595
595
|
// Click polyline near (-15,0) → segment 1. keepStart keeps the start portion.
|
|
596
596
|
core.scene.clear();
|
|
597
|
-
core.scene.
|
|
598
|
-
core.scene.
|
|
597
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
598
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-20, 0), new Point(-10, 0), new Point(0, 0), new Point(10, 0)] });
|
|
599
599
|
|
|
600
600
|
core.scene.headers.chamferDistanceA = 2;
|
|
601
601
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -635,8 +635,8 @@ test('Chamfer.action dist>0 trimMode=true Line first + Lwpolyline second keepSta
|
|
|
635
635
|
|
|
636
636
|
test('Chamfer.action dist>0 trimMode=true Lwpolyline first + Line second keepStart: same result with entities reversed', () => {
|
|
637
637
|
core.scene.clear();
|
|
638
|
-
core.scene.
|
|
639
|
-
core.scene.
|
|
638
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-20, 0), new Point(-10, 0), new Point(0, 0), new Point(10, 0)] });
|
|
639
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
640
640
|
|
|
641
641
|
core.scene.headers.chamferDistanceA = 2;
|
|
642
642
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -676,8 +676,8 @@ test('Chamfer.action dist>0 trimMode=true Line + Lwpolyline keepEnd: keeps end p
|
|
|
676
676
|
// Click polyline near (8,0) → segment 3 (right of intersection). keepEnd.
|
|
677
677
|
// polyChamfer = (2,0), lineChamfer = (0,2).
|
|
678
678
|
core.scene.clear();
|
|
679
|
-
core.scene.
|
|
680
|
-
core.scene.
|
|
679
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
680
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-20, 0), new Point(-10, 0), new Point(0, 0), new Point(10, 0)] });
|
|
681
681
|
|
|
682
682
|
core.scene.headers.chamferDistanceA = 2;
|
|
683
683
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -720,7 +720,7 @@ test('Chamfer.action dist>0 trimMode=true same Lwpolyline consecutive segments:
|
|
|
720
720
|
// Segment 1: (-10,0)→(0,0), Segment 2: (0,0)→(0,10). Corner at (0,0).
|
|
721
721
|
// dist=2 → chamfer at (-2,0) and (0,2).
|
|
722
722
|
core.scene.clear();
|
|
723
|
-
core.scene.
|
|
723
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-10, 0), new Point(0, 0), new Point(0, 10)] });
|
|
724
724
|
|
|
725
725
|
core.scene.headers.chamferDistanceA = 2;
|
|
726
726
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -763,7 +763,7 @@ test('Chamfer.action dist>0 trimMode=true same Lwpolyline open ends: separate ch
|
|
|
763
763
|
// dist=2, clicks at (-3,0) and (1,3):
|
|
764
764
|
// firstChamfer = (-1,0), secondChamfer = (1,2).
|
|
765
765
|
core.scene.clear();
|
|
766
|
-
core.scene.
|
|
766
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-5, 0), new Point(0, 0), new Point(1, 0), new Point(1, 5)] });
|
|
767
767
|
|
|
768
768
|
core.scene.headers.chamferDistanceA = 2;
|
|
769
769
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -809,7 +809,7 @@ test('Chamfer.action dist>0 trimMode=true closed Lwpolyline seg3+closing-seg: co
|
|
|
809
809
|
// Closing segment (idx=4) goes (0,10)→(0,0); seg 3 goes (10,10)→(0,10).
|
|
810
810
|
// Corner at (0,10) — chamfer dist=2 trims to (2,10) on seg3 and (0,8) on closing seg.
|
|
811
811
|
core.scene.clear();
|
|
812
|
-
core.scene.
|
|
812
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10)] });
|
|
813
813
|
const polyEntity = core.scene.entities.get(0);
|
|
814
814
|
polyEntity.flags.setFlagValue(1);
|
|
815
815
|
|
|
@@ -847,7 +847,7 @@ test('Chamfer.action dist>0 trimMode=true closed Lwpolyline closing-wrap (seg4+s
|
|
|
847
847
|
// Bug: old code had no closed-poly guard, so closing-wrap was treated as open-ends.
|
|
848
848
|
// Fix: closed poly must NOT enter the open-ends path → corner-splice at index 0.
|
|
849
849
|
core.scene.clear();
|
|
850
|
-
core.scene.
|
|
850
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10)] });
|
|
851
851
|
const polyEntity = core.scene.entities.get(0);
|
|
852
852
|
polyEntity.flags.setFlagValue(1);
|
|
853
853
|
|
|
@@ -892,7 +892,7 @@ test('Chamfer.action dist>0 trimMode=true closed Lwpolyline closing-wrap (seg4+s
|
|
|
892
892
|
test('Chamfer.action dist>0 trimMode=false closed Lwpolyline closing-wrap: standalone chamfer Line only', () => {
|
|
893
893
|
// Same square, closed, trimMode=false. No polyline mutation; only chamfer Line added.
|
|
894
894
|
core.scene.clear();
|
|
895
|
-
core.scene.
|
|
895
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10)] });
|
|
896
896
|
const polyEntity = core.scene.entities.get(0);
|
|
897
897
|
polyEntity.flags.setFlagValue(1);
|
|
898
898
|
|
|
@@ -922,7 +922,7 @@ test('Chamfer.action dist>0 trimMode=true open Lwpolyline seg1+lastIdx still tak
|
|
|
922
922
|
// Open 4-point polyline (no flags). Seg 1 and seg 3 (lastIdx=3) → open-ends path still fires.
|
|
923
923
|
// Regression guard: the closed-poly fix must not break the open-poly open-ends case.
|
|
924
924
|
core.scene.clear();
|
|
925
|
-
core.scene.
|
|
925
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-5, 0), new Point(0, 0), new Point(1, 0), new Point(1, 5)] });
|
|
926
926
|
const polyEntity = core.scene.entities.get(0);
|
|
927
927
|
// No flags set — open polyline
|
|
928
928
|
|
|
@@ -949,8 +949,8 @@ test('Chamfer.action dist>0 trimMode=true open Lwpolyline seg1+lastIdx still tak
|
|
|
949
949
|
|
|
950
950
|
test('Chamfer.action dist>0 trimMode=false Line + Lwpolyline: standalone chamfer Line added, entities unchanged', () => {
|
|
951
951
|
core.scene.clear();
|
|
952
|
-
core.scene.
|
|
953
|
-
core.scene.
|
|
952
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
953
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-20, 0), new Point(-10, 0), new Point(0, 0), new Point(10, 0)] });
|
|
954
954
|
|
|
955
955
|
core.scene.headers.chamferDistanceA = 2;
|
|
956
956
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -984,8 +984,8 @@ test('Chamfer.action dist>0 trimMode=false Line + Lwpolyline: standalone chamfer
|
|
|
984
984
|
test('Chamfer.action chamfer line inherits layer, lineWidth, lineType from first entity', () => {
|
|
985
985
|
// Perpendicular L-corner at origin; first entity on a non-default layer.
|
|
986
986
|
core.scene.clear();
|
|
987
|
-
core.scene.
|
|
988
|
-
core.scene.
|
|
987
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)], layer: 'walls', lineWidth: 5, lineType: 'DASHED' });
|
|
988
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
989
989
|
|
|
990
990
|
core.scene.headers.chamferDistanceA = 2;
|
|
991
991
|
core.scene.headers.chamferDistanceB = 2;
|
|
@@ -1014,7 +1014,7 @@ test('Chamfer.preview does not throw', () => {
|
|
|
1014
1014
|
|
|
1015
1015
|
test('Chamfer.preview returns early when findClosestItem returns undefined', () => {
|
|
1016
1016
|
core.scene.clear();
|
|
1017
|
-
core.scene.
|
|
1017
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
1018
1018
|
DesignCore.Scene.previewEntities.clear();
|
|
1019
1019
|
|
|
1020
1020
|
const chamfer = new Chamfer();
|
|
@@ -1031,8 +1031,8 @@ test('Chamfer.preview returns early when findClosestItem returns undefined', ()
|
|
|
1031
1031
|
|
|
1032
1032
|
test('Chamfer.preview adds chamfer line to previewEntities in no-trim mode', () => {
|
|
1033
1033
|
core.scene.clear();
|
|
1034
|
-
core.scene.
|
|
1035
|
-
core.scene.
|
|
1034
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
1035
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
1036
1036
|
DesignCore.Scene.previewEntities.clear();
|
|
1037
1037
|
|
|
1038
1038
|
core.scene.headers.chamferDistanceA = 2;
|
|
@@ -1054,8 +1054,8 @@ test('Chamfer.preview adds chamfer line to previewEntities in no-trim mode', ()
|
|
|
1054
1054
|
|
|
1055
1055
|
test('Chamfer.preview skips chamfer line in no-trim mode when distances are both 0 (sharp corner)', () => {
|
|
1056
1056
|
core.scene.clear();
|
|
1057
|
-
core.scene.
|
|
1058
|
-
core.scene.
|
|
1057
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
1058
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
1059
1059
|
DesignCore.Scene.previewEntities.clear();
|
|
1060
1060
|
|
|
1061
1061
|
core.scene.headers.chamferDistanceA = 0;
|
|
@@ -1077,8 +1077,8 @@ test('Chamfer.preview skips chamfer line in no-trim mode when distances are both
|
|
|
1077
1077
|
|
|
1078
1078
|
test('Chamfer.preview adds 5 entities to previewEntities in trim mode', () => {
|
|
1079
1079
|
core.scene.clear();
|
|
1080
|
-
core.scene.
|
|
1081
|
-
core.scene.
|
|
1080
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
1081
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
1082
1082
|
DesignCore.Scene.previewEntities.clear();
|
|
1083
1083
|
|
|
1084
1084
|
core.scene.headers.chamferDistanceA = 2;
|
|
@@ -1101,8 +1101,8 @@ test('Chamfer.preview adds 5 entities to previewEntities in trim mode', () => {
|
|
|
1101
1101
|
|
|
1102
1102
|
test('Chamfer.execute returns early when second-entity input is undefined (inner loop)', async () => {
|
|
1103
1103
|
core.scene.clear();
|
|
1104
|
-
core.scene.
|
|
1105
|
-
core.scene.
|
|
1104
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
1105
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
1106
1106
|
|
|
1107
1107
|
const executeCommandSpy = jest.fn();
|
|
1108
1108
|
await withMockInput(
|
|
@@ -1121,7 +1121,7 @@ test('Chamfer.execute notifies NONCONSECUTIVESEGMENTS for non-adjacent polyline
|
|
|
1121
1121
|
// 5-point polyline → 4 segments. Pick segment 1 (near -15,0) then segment 3 (near 5,0).
|
|
1122
1122
|
// Neither consecutive nor open-ends → NONCONSECUTIVESEGMENTS, then undefined to exit.
|
|
1123
1123
|
core.scene.clear();
|
|
1124
|
-
core.scene.
|
|
1124
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-20, 0), new Point(-10, 0), new Point(0, 0), new Point(10, 0), new Point(20, 0)] });
|
|
1125
1125
|
|
|
1126
1126
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
1127
1127
|
await withMockInput(
|
|
@@ -1169,8 +1169,8 @@ test('Chamfer.execute Trim→Trim keeps trimMode=true', async () => {
|
|
|
1169
1169
|
test('Chamfer.action angle method angle=180 notifies INVALIDNUMBER', () => {
|
|
1170
1170
|
// alpha = 180 * π/180 = π; checks alpha >= Math.PI → INVALIDNUMBER
|
|
1171
1171
|
core.scene.clear();
|
|
1172
|
-
core.scene.
|
|
1173
|
-
core.scene.
|
|
1172
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
1173
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
1174
1174
|
|
|
1175
1175
|
core.scene.headers.chamferLength = 2;
|
|
1176
1176
|
core.scene.headers.chamferAngle = 180;
|