@design-core/core 0.0.6 → 50.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/.eslintrc.json +4 -0
- package/.github/workflows/DesignCoreQA.yml +3 -0
- package/TODO.md +49 -6
- package/core/core/core.js +0 -3
- package/core/designCore.js +1 -1
- package/core/dimensions/alignedDimension.js +12 -11
- package/core/dimensions/angularDimension.js +38 -37
- package/core/dimensions/{baseCircularDimension.js → circularDimensionBase.js} +22 -21
- package/core/dimensions/diametricDimension.js +14 -13
- package/core/dimensions/dimension.js +62 -55
- package/core/dimensions/{baseDimension.js → dimensionBase.js} +73 -107
- package/core/dimensions/{baseLinearDimension.js → linearDimensionBase.js} +15 -14
- package/core/dimensions/radialDimension.js +12 -11
- package/core/dimensions/rotatedDimension.js +20 -19
- package/core/entities/arc.js +123 -156
- package/core/entities/arctext.js +222 -184
- package/core/entities/circle.js +77 -99
- package/core/entities/entity.js +114 -93
- package/core/entities/hatch.js +346 -273
- package/core/entities/insert.js +68 -83
- package/core/entities/line.js +21 -142
- package/core/entities/lwpolyline.js +16 -11
- package/core/entities/point.js +19 -19
- package/core/entities/polyline.js +7 -7
- package/core/entities/{basePolyline.js → polylineBase.js} +47 -299
- package/core/entities/rectangle.js +3 -1
- package/core/entities/solid.js +6 -15
- package/core/entities/text.js +190 -201
- package/core/lib/auxiliary/rubberBand.js +32 -0
- package/core/lib/auxiliary/selectionWindow.js +63 -0
- package/core/lib/auxiliary/snapPoint.js +113 -0
- package/core/lib/auxiliary/trackingLine.js +76 -0
- package/core/lib/boundingBox.js +11 -11
- package/core/lib/canvas.js +232 -168
- package/core/lib/clipboard.js +9 -3
- package/core/lib/colour.js +16 -0
- package/core/lib/commandLine.js +1 -6
- package/core/lib/commandManager.js +18 -8
- package/core/lib/constants.js +28 -0
- package/core/lib/dxf/dxf.js +15 -14
- package/core/lib/dxf/dxfIterator.js +2 -2
- package/core/lib/entityManager.js +33 -26
- package/core/lib/inputManager.js +36 -12
- package/core/lib/intersect.js +25 -0
- package/core/lib/matrix.js +1 -1
- package/core/lib/patterns.js +9 -2
- package/core/lib/plotOptions.js +67 -0
- package/core/lib/polylineUtils.js +75 -0
- package/core/lib/renderers/cairoRenderer.js +371 -0
- package/core/lib/renderers/canvasRenderer.js +315 -0
- package/core/lib/renderers/pdfRenderer.js +366 -0
- package/core/lib/renderers/rendererBase.js +284 -0
- package/core/lib/renderers/svgRenderer.js +343 -0
- package/core/lib/scene.js +28 -6
- package/core/lib/selectionManager.js +20 -20
- package/core/lib/settings.js +4 -2
- package/core/lib/snapping.js +4 -191
- package/core/lib/stateManager.js +30 -1
- package/core/lib/utils.js +26 -7
- package/core/properties/entityProperties.js +104 -0
- package/core/properties/property.js +106 -2
- package/core/properties/propertyManager.js +60 -44
- package/core/tables/block.js +50 -81
- package/core/tables/dimStyle.js +5 -5
- package/core/tables/endblk.js +1 -1
- package/core/tables/layer.js +8 -0
- package/core/tables/ltypeManager.js +1 -1
- package/core/tables/styleManagerBase.js +3 -2
- package/core/tables/tableManagerBase.js +8 -3
- package/core/tables/vport.js +2 -2
- package/core/tools/chamfer.js +117 -143
- package/core/tools/chamferFilletBase.js +138 -37
- package/core/tools/copy.js +11 -11
- 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 +7 -7
- package/core/tools/extend.js +138 -25
- package/core/tools/fillet.js +92 -189
- package/core/tools/matchProp.js +3 -12
- package/core/tools/mirror.js +15 -14
- package/core/tools/move.js +8 -8
- package/core/tools/offset.js +31 -33
- package/core/tools/pasteclip.js +1 -1
- package/core/tools/purge.js +10 -10
- package/core/tools/rotate.js +19 -16
- package/core/tools/scale.js +7 -7
- package/core/tools/trim.js +271 -29
- package/core/tools/zoom.js +1 -1
- package/cspell.json +321 -0
- package/jest.config.js +6 -0
- package/package.json +5 -3
- package/test/dimensions/alignedDimension.test.js +17 -10
- package/test/dimensions/angularDimension.test.js +13 -13
- package/test/dimensions/diametricDimension.test.js +15 -15
- package/test/dimensions/dimension.test.js +12 -12
- package/test/dimensions/{baseDimension.test.js → dimensionBase.test.js} +73 -12
- package/test/dimensions/linearDimensionBase.test.js +62 -0
- package/test/dimensions/radialDimension.test.js +15 -15
- package/test/dimensions/rotatedDimension.test.js +18 -11
- package/test/entities/arc.test.js +83 -86
- package/test/entities/arctext.test.js +184 -57
- package/test/entities/circle.test.js +68 -96
- package/test/entities/entity.test.js +42 -8
- package/test/entities/hatch.test.js +569 -96
- package/test/entities/insert.test.js +99 -4
- package/test/entities/line.test.js +15 -41
- package/test/entities/lwpolyline.test.js +104 -0
- package/test/entities/point.test.js +3 -3
- package/test/entities/polyline.test.js +11 -0
- package/test/entities/{basePolyline.test.js → polylineBase.test.js} +192 -57
- package/test/entities/rectangle.test.js +11 -0
- package/test/entities/solid.test.js +1 -1
- package/test/entities/text.test.js +302 -77
- package/test/integration/exportIntegration.reference.dxf +9 -9
- package/test/integration/exportIntegration.test.js +5 -5
- package/test/integration/intersectionIntegration.test.js +4 -5
- package/test/integration/pdfRendererIntegration.reference.pdf +17709 -0
- package/test/integration/pdfRendererIntegration.test.js +61 -0
- package/test/integration/svgRendererIntegration.reference.svg +3343 -0
- package/test/integration/svgRendererIntegration.test.js +61 -0
- package/test/integration/userInputIntegration.reference.dxf +1165 -105
- package/test/integration/userInputIntegration.test.js +239 -132
- package/test/lib/boundingBox.test.js +3 -3
- package/test/lib/canvas.test.js +744 -125
- package/test/lib/constants.test.js +27 -0
- package/test/lib/entityManager.test.js +4 -4
- package/test/lib/inputManager.test.js +81 -20
- package/test/lib/intersect.test.js +83 -0
- package/test/lib/plotOptions.test.js +179 -0
- package/test/lib/rubberBand.test.js +84 -0
- package/test/lib/scene.test.js +9 -9
- package/test/lib/selectionManager.test.js +3 -3
- package/test/lib/settings.test.js +5 -6
- package/test/lib/snapping.test.js +72 -130
- package/test/lib/stateManager.test.js +7 -7
- package/test/lib/utils.test.js +36 -2
- package/test/properties/entityProperties.test.js +132 -0
- package/test/properties/property.test.js +53 -0
- package/test/properties/propertyManager.test.js +25 -25
- package/test/renderers/canvasRenderer.test.js +317 -0
- package/test/renderers/pdfRenderer.test.js +271 -0
- package/test/renderers/rendererBase.test.js +213 -0
- package/test/renderers/svgRenderer.test.js +326 -0
- package/test/tables/block.test.js +92 -13
- package/test/tables/endblk.test.js +2 -2
- package/test/tables/layer.test.js +30 -0
- package/test/tables/layerManager.test.js +2 -2
- package/test/test-helpers/hatchGridRenderer.js +180 -0
- package/test/test-helpers/test-helpers.js +158 -6
- package/test/tools/chamfer.test.js +273 -51
- package/test/tools/chamferFilletBase.test.js +125 -36
- package/test/tools/copy.test.js +8 -8
- 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 +5 -5
- package/test/tools/extend.test.js +373 -42
- package/test/tools/fillet.test.js +230 -49
- package/test/tools/matchProp.test.js +11 -11
- package/test/tools/mirror.test.js +39 -39
- package/test/tools/move.test.js +7 -7
- package/test/tools/offset.test.js +222 -55
- package/test/tools/pasteclip.test.js +5 -5
- package/test/tools/purge.test.js +4 -4
- package/test/tools/rotate.test.js +39 -9
- package/test/tools/scale.test.js +33 -33
- package/test/tools/trim.test.js +579 -53
- package/test/tools/zoom.test.js +12 -12
- package/core/lib/selectionWindow.js +0 -83
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@design-core/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "50.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"eslint": "^8.26.0",
|
|
10
10
|
"eslint-config-google": "^0.14.0",
|
|
11
11
|
"eslint-config-standard": "^17.0.0",
|
|
12
|
-
"eslint-plugin-import": "^2.
|
|
12
|
+
"eslint-plugin-import": "^2.32.0",
|
|
13
13
|
"eslint-plugin-n": "^15.3.0",
|
|
14
14
|
"eslint-plugin-promise": "^6.1.1",
|
|
15
15
|
"jest": "^29.7.0"
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"description": "2D CAD Library",
|
|
18
18
|
"exports": {
|
|
19
19
|
".": "./core/core/core.js",
|
|
20
|
-
"./designCore.js": "./core/designCore.js"
|
|
20
|
+
"./designCore.js": "./core/designCore.js",
|
|
21
|
+
"./property.js": "./core/properties/property.js",
|
|
22
|
+
"./canvasRenderer.js": "./core/lib/renderers/canvasRenderer.js"
|
|
21
23
|
},
|
|
22
24
|
"directories": {
|
|
23
25
|
"test": "test"
|
|
@@ -13,14 +13,14 @@ const scenarios = [
|
|
|
13
13
|
|
|
14
14
|
{ desc: 'Aligned dimension from point selection',
|
|
15
15
|
input: [new Point(), new Point(10, 0), new Point(5, 5)],
|
|
16
|
-
|
|
16
|
+
selectedEntities: [],
|
|
17
17
|
expectedDimType: 1,
|
|
18
18
|
dimensionValue: 10,
|
|
19
19
|
},
|
|
20
20
|
];
|
|
21
21
|
|
|
22
22
|
test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
|
|
23
|
-
const { input,
|
|
23
|
+
const { input, selectedEntities, expectedDimType, dimensionValue } = scenario;
|
|
24
24
|
|
|
25
25
|
await withMockInput(DesignCore.Scene, input, async () => {
|
|
26
26
|
const dim = new AlignedDimension();
|
|
@@ -34,10 +34,10 @@ test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
|
|
|
34
34
|
// check if the text value matches the expected dimension value
|
|
35
35
|
for (const entity of dimensionBlockEntities) {
|
|
36
36
|
if (entity.type === 'Text') {
|
|
37
|
-
expect(Number(entity.string)).toBeCloseTo(dimensionValue);
|
|
37
|
+
expect(Number(entity.getProperty('string'))).toBeCloseTo(dimensionValue);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
}, {
|
|
40
|
+
}, { selectedEntities });
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
test('constructor sets default properties', () => {
|
|
@@ -104,23 +104,29 @@ describe('AlignedDimension.getPointsFromSelection', () => {
|
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
test('AlignedDimension.preview runs without error and calls createTempItem', () => {
|
|
107
|
-
const
|
|
107
|
+
const origAddAux = DesignCore.Scene.auxiliaryEntities.add;
|
|
108
|
+
const origCreateTempItem = DesignCore.Scene.previewEntities.create;
|
|
108
109
|
const origPointOnScene = DesignCore.Mouse.pointOnScene;
|
|
109
110
|
// Manual mock for createTempItem
|
|
110
111
|
const createTempItemCalls = [];
|
|
111
|
-
DesignCore.Scene.
|
|
112
|
+
DesignCore.Scene.previewEntities.create = function(type, obj) {
|
|
112
113
|
createTempItemCalls.push([type, obj]);
|
|
113
114
|
};
|
|
115
|
+
// Manual mock for auxiliaryEntities.add
|
|
116
|
+
const addAuxCalls = [];
|
|
117
|
+
DesignCore.Scene.auxiliaryEntities.add = function(item) {
|
|
118
|
+
addAuxCalls.push(item);
|
|
119
|
+
};
|
|
114
120
|
// Manual mock for pointOnScene
|
|
115
121
|
DesignCore.Mouse.pointOnScene = function() {
|
|
116
122
|
return new Point(5, 5);
|
|
117
123
|
};
|
|
118
124
|
|
|
119
|
-
// Test with 1 point (should
|
|
125
|
+
// Test with 1 point (should add a RubberBand to auxiliaryEntities)
|
|
120
126
|
const dim1 = new AlignedDimension();
|
|
121
127
|
dim1.points = [new Point(0, 0)];
|
|
122
128
|
expect(() => dim1.preview()).not.toThrow();
|
|
123
|
-
expect(
|
|
129
|
+
expect(addAuxCalls.length).toBeGreaterThanOrEqual(1);
|
|
124
130
|
|
|
125
131
|
// Test with >1 point (should call createTempItem with this.type)
|
|
126
132
|
const dim2 = new AlignedDimension();
|
|
@@ -129,7 +135,8 @@ test('AlignedDimension.preview runs without error and calls createTempItem', ()
|
|
|
129
135
|
expect(createTempItemCalls.some((call) => call[0] === dim2.type)).toBe(true);
|
|
130
136
|
|
|
131
137
|
// Restore
|
|
132
|
-
DesignCore.Scene.
|
|
138
|
+
DesignCore.Scene.auxiliaryEntities.add = origAddAux;
|
|
139
|
+
DesignCore.Scene.previewEntities.create = origCreateTempItem;
|
|
133
140
|
DesignCore.Mouse.pointOnScene = origPointOnScene;
|
|
134
141
|
});
|
|
135
142
|
|
|
@@ -204,7 +211,7 @@ AcDbAlignedDimension
|
|
|
204
211
|
expect(file.contents).toEqual(dxfString);
|
|
205
212
|
|
|
206
213
|
// create new entity from entity data to ensure all props are loaded
|
|
207
|
-
const newDimension = new AlignedDimension(dimension);
|
|
214
|
+
const newDimension = new AlignedDimension({ handle: dimension.getProperty('handle'), points: dimension.points, ...dimension });
|
|
208
215
|
file = new File();
|
|
209
216
|
newDimension.dxf(file);
|
|
210
217
|
expect(file.contents).toEqual(dxfString);
|
|
@@ -18,35 +18,35 @@ const scenarios = [
|
|
|
18
18
|
|
|
19
19
|
{ desc: 'Angular dimension from line selection - 45 degrees',
|
|
20
20
|
input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, 5)],
|
|
21
|
-
|
|
21
|
+
selectedEntities: [new Line({ points: [new Point(0, 0), new Point(10, 0)] }), new Line({ points: [new Point(0, 0), new Point(10, 10)] })],
|
|
22
22
|
expectedDimType: 2,
|
|
23
23
|
dimensionValue: 45,
|
|
24
24
|
dimensionEntities: 5,
|
|
25
25
|
},
|
|
26
26
|
{ desc: 'Angular dimension from line selection - 135 degrees',
|
|
27
27
|
input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(-5, 5)],
|
|
28
|
-
|
|
28
|
+
selectedEntities: [new Line({ points: [new Point(0, 0), new Point(10, 0)] }), new Line({ points: [new Point(0, 0), new Point(10, 10)] })],
|
|
29
29
|
expectedDimType: 2,
|
|
30
30
|
dimensionValue: 135,
|
|
31
31
|
dimensionEntities: 6,
|
|
32
32
|
},
|
|
33
33
|
{ desc: 'Angular dimension from line selection - 45 degrees',
|
|
34
34
|
input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(-5, -5)],
|
|
35
|
-
|
|
35
|
+
selectedEntities: [new Line({ points: [new Point(0, 0), new Point(10, 0)] }), new Line({ points: [new Point(0, 0), new Point(10, 10)] })],
|
|
36
36
|
expectedDimType: 2,
|
|
37
37
|
dimensionValue: 45,
|
|
38
38
|
dimensionEntities: 7,
|
|
39
39
|
},
|
|
40
40
|
{ desc: 'Angular dimension from line selection - 135 degrees',
|
|
41
41
|
input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, -5)],
|
|
42
|
-
|
|
42
|
+
selectedEntities: [new Line({ points: [new Point(0, 0), new Point(10, 0)] }), new Line({ points: [new Point(0, 0), new Point(10, 10)] })],
|
|
43
43
|
expectedDimType: 2,
|
|
44
44
|
dimensionValue: 135,
|
|
45
45
|
dimensionEntities: 6,
|
|
46
46
|
},
|
|
47
47
|
{ desc: 'Angular dimension from polyline selection - 45 degrees',
|
|
48
48
|
input: [new SingleSelection(0, new Point(5, 0)), new SingleSelection(1, new Point(5, 5)), new Point(5, 5)],
|
|
49
|
-
|
|
49
|
+
selectedEntities: [new Polyline({ points: [new Point(0, 0), new Point(10, 0)] }), new Polyline({ points: [new Point(0, 0), new Point(10, 10)] })],
|
|
50
50
|
expectedDimType: 2,
|
|
51
51
|
dimensionValue: 45,
|
|
52
52
|
dimensionEntities: 5,
|
|
@@ -54,7 +54,7 @@ const scenarios = [
|
|
|
54
54
|
];
|
|
55
55
|
|
|
56
56
|
test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
|
|
57
|
-
const { input,
|
|
57
|
+
const { input, selectedEntities, expectedDimType, dimensionValue, dimensionEntities } = scenario;
|
|
58
58
|
|
|
59
59
|
await withMockInput(DesignCore.Scene, input, async () => {
|
|
60
60
|
const dim = new AngularDimension();
|
|
@@ -69,12 +69,12 @@ test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
|
|
|
69
69
|
for (const entity of dimensionBlockEntities) {
|
|
70
70
|
if (entity.type === 'Text') {
|
|
71
71
|
// remove all non-numeric characters except . and -
|
|
72
|
-
const numbersOnly = entity.string.replace(/[^0-9.-]+/g, '');
|
|
72
|
+
const numbersOnly = entity.getProperty('string').replace(/[^0-9.-]+/g, '');
|
|
73
73
|
expect(Number(numbersOnly)).toBeCloseTo(dimensionValue);
|
|
74
|
-
expect(entity.string).toContain('°');
|
|
74
|
+
expect(entity.getProperty('string')).toContain('°');
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
-
}, {
|
|
77
|
+
}, { selectedEntities });
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
test('constructor sets default properties', () => {
|
|
@@ -100,11 +100,11 @@ test('getPointsFromSelection returns correct sequenced points', () => {
|
|
|
100
100
|
});
|
|
101
101
|
|
|
102
102
|
test('AngularDimension.preview runs without error and calls createTempItem', () => {
|
|
103
|
-
const origCreateTempItem = DesignCore.Scene.
|
|
103
|
+
const origCreateTempItem = DesignCore.Scene.previewEntities.create;
|
|
104
104
|
const origPointOnScene = DesignCore.Mouse.pointOnScene;
|
|
105
105
|
// Manual mock for createTempItem
|
|
106
106
|
const createTempItemCalls = [];
|
|
107
|
-
DesignCore.Scene.
|
|
107
|
+
DesignCore.Scene.previewEntities.create = function(type, obj) {
|
|
108
108
|
createTempItemCalls.push([type, obj]);
|
|
109
109
|
};
|
|
110
110
|
// Manual mock for pointOnScene
|
|
@@ -138,7 +138,7 @@ test('AngularDimension.preview runs without error and calls createTempItem', ()
|
|
|
138
138
|
expect(createTempItemCalls.some((call) => call[0] === dim2.type)).toBe(true);
|
|
139
139
|
|
|
140
140
|
// Restore
|
|
141
|
-
DesignCore.Scene.
|
|
141
|
+
DesignCore.Scene.previewEntities.create = origCreateTempItem;
|
|
142
142
|
DesignCore.Mouse.pointOnScene = origPointOnScene;
|
|
143
143
|
});
|
|
144
144
|
|
|
@@ -234,7 +234,7 @@ AcDb2LineAngularDimension
|
|
|
234
234
|
expect(file.contents).toEqual(dxfString);
|
|
235
235
|
|
|
236
236
|
// create new entity from entity data to ensure all props are loaded
|
|
237
|
-
const newDimension = new AngularDimension(dimension);
|
|
237
|
+
const newDimension = new AngularDimension({ handle: dimension.getProperty('handle'), points: dimension.points, ...dimension });
|
|
238
238
|
file = new File();
|
|
239
239
|
newDimension.dxf(file);
|
|
240
240
|
expect(file.contents).toEqual(dxfString);
|
|
@@ -17,28 +17,28 @@ const scenarios = [
|
|
|
17
17
|
|
|
18
18
|
{ desc: 'Diametric dimension from circle selection - Text outside circle',
|
|
19
19
|
input: [new SingleSelection(0, new Point()), new Point(20, 0)],
|
|
20
|
-
|
|
20
|
+
selectedEntities: [new Circle({ points: [new Point(0, 0), new Point(10, 0)] })],
|
|
21
21
|
expectedDimType: 3,
|
|
22
22
|
dimensionValue: 20,
|
|
23
23
|
dimensionEntities: 6,
|
|
24
24
|
},
|
|
25
25
|
{ desc: 'Diametric dimension from circle selection - Text inside circle',
|
|
26
26
|
input: [new SingleSelection(0, new Point()), new Point(0, 0)],
|
|
27
|
-
|
|
27
|
+
selectedEntities: [new Circle({ points: [new Point(0, 0), new Point(10, 0)] })],
|
|
28
28
|
expectedDimType: 3,
|
|
29
29
|
dimensionValue: 20,
|
|
30
30
|
dimensionEntities: 5,
|
|
31
31
|
},
|
|
32
32
|
{ desc: 'Diametric dimension from arc selection',
|
|
33
33
|
input: [new SingleSelection(0, new Point()), new Point(20, 10)],
|
|
34
|
-
|
|
34
|
+
selectedEntities: [new Arc({ points: [new Point(0, 0), new Point(20, 0), new Point(20, 20)] })],
|
|
35
35
|
expectedDimType: 3,
|
|
36
36
|
dimensionValue: 40,
|
|
37
37
|
dimensionEntities: 6,
|
|
38
38
|
},
|
|
39
39
|
{ desc: 'Diametric dimension from polyline selection',
|
|
40
40
|
input: [new SingleSelection(0, new Point(30, 10)), new Point(30, 10)],
|
|
41
|
-
|
|
41
|
+
selectedEntities: [new Polyline({ points: [new Point(0, 0), new Point(20, 0, 1), new Point(20, 20)] })],
|
|
42
42
|
expectedDimType: 3,
|
|
43
43
|
dimensionValue: 20,
|
|
44
44
|
dimensionEntities: 6,
|
|
@@ -46,7 +46,7 @@ const scenarios = [
|
|
|
46
46
|
];
|
|
47
47
|
|
|
48
48
|
test.each(scenarios)('DiametricDimension.execute handles $desc', async (scenario) => {
|
|
49
|
-
const { input,
|
|
49
|
+
const { input, selectedEntities, expectedDimType, dimensionValue, dimensionEntities } = scenario;
|
|
50
50
|
|
|
51
51
|
await withMockInput(DesignCore.Scene, input, async () => {
|
|
52
52
|
const dim = new DiametricDimension();
|
|
@@ -61,12 +61,12 @@ test.each(scenarios)('DiametricDimension.execute handles $desc', async (scenario
|
|
|
61
61
|
for (const entity of dimensionBlockEntities) {
|
|
62
62
|
if (entity.type === 'Text') {
|
|
63
63
|
// remove all none numberic characters except . and -
|
|
64
|
-
const numbersOnly = entity.string.replace(/[^0-9.-]+/g, '');
|
|
64
|
+
const numbersOnly = entity.getProperty('string').replace(/[^0-9.-]+/g, '');
|
|
65
65
|
expect(Number(numbersOnly)).toBeCloseTo(dimensionValue);
|
|
66
|
-
expect(entity.string).toContain('Ø');
|
|
66
|
+
expect(entity.getProperty('string')).toContain('Ø');
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
-
}, {
|
|
69
|
+
}, { selectedEntities });
|
|
70
70
|
});
|
|
71
71
|
|
|
72
72
|
test('constructor sets default properties', () => {
|
|
@@ -77,26 +77,26 @@ test('constructor sets default properties', () => {
|
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
test('getPointsFromSelection returns correct sequenced points', () => {
|
|
80
|
-
const
|
|
80
|
+
const centre = new Point(0, 0);
|
|
81
81
|
const textPos = new Point(10, 0);
|
|
82
82
|
// Mock item with getRadius
|
|
83
|
-
const item = { points: [
|
|
83
|
+
const item = { points: [centre], getRadius: () => 10 };
|
|
84
84
|
const result = DiametricDimension.getPointsFromSelection([item], textPos);
|
|
85
85
|
expect(Array.isArray(result)).toBe(true);
|
|
86
86
|
expect(result.length).toBe(3);
|
|
87
|
-
expect(result[0].sequence).toBe(10); //
|
|
87
|
+
expect(result[0].sequence).toBe(10); // centre
|
|
88
88
|
expect(result[1].sequence).toBe(15); // radius point
|
|
89
89
|
expect(result[2].sequence).toBe(11); // text position
|
|
90
90
|
});
|
|
91
91
|
|
|
92
92
|
test('DiametricDimension.preview runs without error and calls createTempItem', () => {
|
|
93
|
-
const origCreateTempItem = DesignCore.Scene.
|
|
93
|
+
const origCreateTempItem = DesignCore.Scene.previewEntities.create;
|
|
94
94
|
const origPointOnScene = DesignCore.Mouse.pointOnScene;
|
|
95
95
|
const origSeletionSet = DesignCore.Scene.selectionManager.selectionSet.selectionSet.length;
|
|
96
96
|
|
|
97
97
|
// Manual mock for createTempItem
|
|
98
98
|
const createTempItemCalls = [];
|
|
99
|
-
DesignCore.Scene.
|
|
99
|
+
DesignCore.Scene.previewEntities.create = function(type, obj) {
|
|
100
100
|
createTempItemCalls.push([type, obj]);
|
|
101
101
|
};
|
|
102
102
|
// Manual mock for pointOnScene
|
|
@@ -130,7 +130,7 @@ test('DiametricDimension.preview runs without error and calls createTempItem', (
|
|
|
130
130
|
expect(createTempItemCalls.some((call) => call[0] === dim2.type)).toBe(true);
|
|
131
131
|
|
|
132
132
|
// Restore
|
|
133
|
-
DesignCore.Scene.
|
|
133
|
+
DesignCore.Scene.previewEntities.create = origCreateTempItem;
|
|
134
134
|
DesignCore.Mouse.pointOnScene = origPointOnScene;
|
|
135
135
|
DesignCore.Scene.selectionManager.selectionSet.selectionSet.length = origSeletionSet;
|
|
136
136
|
});
|
|
@@ -196,7 +196,7 @@ AcDbDiametricDimension
|
|
|
196
196
|
expect(file.contents).toEqual(dxfString);
|
|
197
197
|
|
|
198
198
|
// create new entity from entity data to ensure all props are loaded
|
|
199
|
-
const newDimension = new DiametricDimension(dimension);
|
|
199
|
+
const newDimension = new DiametricDimension({ handle: dimension.getProperty('handle'), points: dimension.points, ...dimension });
|
|
200
200
|
file = new File();
|
|
201
201
|
newDimension.dxf(file);
|
|
202
202
|
expect(file.contents).toEqual(dxfString);
|
|
@@ -18,61 +18,61 @@ const scenarios = [
|
|
|
18
18
|
|
|
19
19
|
{ desc: 'Rotated dimension from line selection',
|
|
20
20
|
input: [new SingleSelection(0, new Point()), new Point(5, 5)],
|
|
21
|
-
|
|
21
|
+
selectedEntities: [new Line({ points: [new Point(), new Point(10, 0)] })],
|
|
22
22
|
expectedDimType: 0,
|
|
23
23
|
},
|
|
24
24
|
{ desc: 'Aligned dimension from line selection',
|
|
25
25
|
input: [new SingleSelection(0, new Point()), new Point(6.5, 3.5)],
|
|
26
|
-
|
|
26
|
+
selectedEntities: [new Line({ points: [new Point(), new Point(10, 10)] })],
|
|
27
27
|
expectedDimType: 1,
|
|
28
28
|
},
|
|
29
29
|
{ desc: 'Rotated dimension from point selection',
|
|
30
30
|
input: [new Point(), new Point(10, 0), new Point(5, 5)],
|
|
31
|
-
|
|
31
|
+
selectedEntities: [],
|
|
32
32
|
expectedDimType: 0,
|
|
33
33
|
},
|
|
34
34
|
{ desc: 'Diametric dimension from circle selection',
|
|
35
35
|
input: [new SingleSelection(0, new Point()), new Point(20, 10)],
|
|
36
|
-
|
|
36
|
+
selectedEntities: [new Circle({ points: [new Point(), new Point(10, 0)] })],
|
|
37
37
|
expectedDimType: 3,
|
|
38
38
|
},
|
|
39
39
|
{ desc: 'Radial dimension from arc selection',
|
|
40
40
|
input: [new SingleSelection(0, new Point()), new Point(20, 10)],
|
|
41
|
-
|
|
41
|
+
selectedEntities: [new Arc({ points: [new Point(), new Point(10, 0), new Point(10, 10)] })],
|
|
42
42
|
expectedDimType: 4,
|
|
43
43
|
},
|
|
44
44
|
{ desc: 'Angular dimension from line selection',
|
|
45
45
|
input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, 5)],
|
|
46
|
-
|
|
46
|
+
selectedEntities: [new Line({ points: [new Point(), new Point(10, 0)] }), new Line({ points: [new Point(), new Point(10, 10)] })],
|
|
47
47
|
expectedDimType: 2,
|
|
48
48
|
},
|
|
49
49
|
{ desc: 'Aligned dimension from polyline selection',
|
|
50
50
|
input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, 5)],
|
|
51
|
-
|
|
51
|
+
selectedEntities: [new Polyline({ points: [new Point(), new Point(10, 0)] })],
|
|
52
52
|
expectedDimType: 1,
|
|
53
53
|
},
|
|
54
54
|
{ desc: 'Radial dimension from polyline selection',
|
|
55
55
|
input: [new SingleSelection(0, new Point(16, 5)), new Point(20, 5)],
|
|
56
|
-
|
|
56
|
+
selectedEntities: [new Polyline({ points: [new Point(), new Point(10, 0, 1), new Point(10, 10)] })],
|
|
57
57
|
expectedDimType: 4,
|
|
58
58
|
},
|
|
59
59
|
{ desc: 'Angular dimension from polyline selection',
|
|
60
60
|
input: [new SingleSelection(0, new Point(5, 0)), new SingleSelection(1, new Point(5, 5)), new Point(5, 5)],
|
|
61
|
-
|
|
61
|
+
selectedEntities: [new Polyline({ points: [new Point(), new Point(10, 0)] }), new Polyline({ points: [new Point(), new Point(10, 10)] })],
|
|
62
62
|
expectedDimType: 2,
|
|
63
63
|
},
|
|
64
64
|
|
|
65
65
|
];
|
|
66
66
|
|
|
67
67
|
test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
|
|
68
|
-
const { input,
|
|
68
|
+
const { input, selectedEntities, expectedDimType } = scenario;
|
|
69
69
|
|
|
70
70
|
await withMockInput(DesignCore.Scene, input, async () => {
|
|
71
71
|
const dim = new Dimension();
|
|
72
72
|
await dim.execute();
|
|
73
73
|
|
|
74
74
|
expect(dim.dimType.getBaseDimType()).toBe(expectedDimType);
|
|
75
|
-
}, {
|
|
75
|
+
}, { selectedEntities });
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
test('constructor instantiates correct dimension type', () => {
|
|
@@ -95,7 +95,7 @@ test('get linear dimension type', () => {
|
|
|
95
95
|
|
|
96
96
|
test('preview calls createTempItem with correct args', () => {
|
|
97
97
|
const dim = new Dimension({ 70: 1 });
|
|
98
|
-
dim.
|
|
98
|
+
dim.selectedEntities = [1];
|
|
99
99
|
dim.points = [{}, {}];
|
|
100
100
|
// Should not throw
|
|
101
101
|
expect(() => dim.preview()).not.toThrow();
|
|
@@ -1,26 +1,28 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DimensionBase } from '../../core/dimensions/dimensionBase.js';
|
|
2
2
|
import { Point } from '../../core/entities/point.js';
|
|
3
3
|
import { Core } from '../../core/core/core.js';
|
|
4
4
|
import { Text } from '../../core/entities/text.js';
|
|
5
|
+
import { Line } from '../../core/entities/line.js';
|
|
6
|
+
import { jest } from '@jest/globals';
|
|
5
7
|
// import { DimType } from '../../core/properties/dimType.js';
|
|
6
8
|
|
|
7
9
|
// initialise core
|
|
8
10
|
new Core();
|
|
9
11
|
|
|
10
|
-
describe('
|
|
12
|
+
describe('DimensionBase', () => {
|
|
11
13
|
let baseDim;
|
|
12
14
|
|
|
13
15
|
beforeEach(() => {
|
|
14
|
-
baseDim = new
|
|
16
|
+
baseDim = new DimensionBase({});
|
|
15
17
|
baseDim.points = [new Point(1, 2, 0), new Point(3, 4, 0)];
|
|
16
18
|
});
|
|
17
19
|
|
|
18
20
|
test('constructor sets default properties', () => {
|
|
19
|
-
expect(baseDim.textOverride).toBe('');
|
|
20
|
-
expect(baseDim.blockName).toBe('');
|
|
21
|
-
expect(baseDim.dimensionStyle).toBe('STANDARD');
|
|
22
|
-
expect(baseDim.leaderLength).toBe(0);
|
|
23
|
-
expect(baseDim.linearDimAngle).toBe(0);
|
|
21
|
+
expect(baseDim.getProperty('textOverride')).toBe('');
|
|
22
|
+
expect(baseDim.getProperty('blockName')).toBe('');
|
|
23
|
+
expect(baseDim.getProperty('dimensionStyle')).toBe('STANDARD');
|
|
24
|
+
expect(baseDim.getProperty('leaderLength')).toBe(0);
|
|
25
|
+
expect(baseDim.getProperty('linearDimAngle')).toBe(0);
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
test('getDimensionValue formats values by dimension type', () => {
|
|
@@ -162,21 +164,21 @@ describe('BaseDimension', () => {
|
|
|
162
164
|
});
|
|
163
165
|
|
|
164
166
|
test('constructor throws on invalid dimType', () => {
|
|
165
|
-
expect(() => new
|
|
167
|
+
expect(() => new DimensionBase({ 70: 999 })).toThrow(/Invalid Dimension Type/);
|
|
166
168
|
});
|
|
167
169
|
|
|
168
170
|
test('getDimensionValue uses textOverride', () => {
|
|
169
|
-
baseDim.textOverride
|
|
171
|
+
baseDim.setProperty('textOverride', 'foo <> bar');
|
|
170
172
|
expect(baseDim.getDimensionValue(10)).toBe('foo 10.0000 bar');
|
|
171
173
|
});
|
|
172
174
|
|
|
173
175
|
test('getDimensionText returns a Text object with correct values', () => {
|
|
174
176
|
const text = baseDim.getDimensionText(10, new Point(1, 2), Math.PI / 4);
|
|
175
177
|
expect(text).toBeInstanceOf(Text);
|
|
176
|
-
expect(text.height).toBe(0.18);
|
|
178
|
+
expect(text.getProperty('height')).toBe(0.18);
|
|
177
179
|
expect(text.points[0].x).toBe(1);
|
|
178
180
|
expect(text.points[0].y).toBe(2);
|
|
179
|
-
expect(typeof text.string).toBe('string');
|
|
181
|
+
expect(typeof text.getProperty('string')).toBe('string');
|
|
180
182
|
});
|
|
181
183
|
|
|
182
184
|
test('getTextDirection flips angle in lower half', () => {
|
|
@@ -236,4 +238,63 @@ describe('BaseDimension', () => {
|
|
|
236
238
|
baseDim.block = { touched: () => false };
|
|
237
239
|
expect(baseDim.touched({})).toBe(false);
|
|
238
240
|
});
|
|
241
|
+
|
|
242
|
+
describe('draw()', () => {
|
|
243
|
+
/**
|
|
244
|
+
* Return a DimensionBase with a stubbed buildDimension() that produces one Line.
|
|
245
|
+
* @return {DimensionBase}
|
|
246
|
+
*/
|
|
247
|
+
function makeDim() {
|
|
248
|
+
const dim = new DimensionBase({});
|
|
249
|
+
dim.points = [new Point(0, 0), new Point(10, 0)];
|
|
250
|
+
dim.buildDimension = jest.fn(() => {
|
|
251
|
+
return [new Line({ points: [new Point(0, 0), new Point(10, 0)] })];
|
|
252
|
+
});
|
|
253
|
+
return dim;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
test('draw() returns the block items array', () => {
|
|
257
|
+
const dim = makeDim();
|
|
258
|
+
const result = dim.draw({});
|
|
259
|
+
expect(result).toBe(dim.block.entities);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test('draw() calls refresh() (via buildDimension) when block is empty', () => {
|
|
263
|
+
const dim = makeDim();
|
|
264
|
+
expect(dim.block.entities).toHaveLength(0);
|
|
265
|
+
dim.draw({});
|
|
266
|
+
expect(dim.buildDimension).toHaveBeenCalledTimes(1);
|
|
267
|
+
expect(dim.block.entities.length).toBeGreaterThan(0);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test('draw() does not call refresh() when block already has items', () => {
|
|
271
|
+
const dim = makeDim();
|
|
272
|
+
// pre-populate the block
|
|
273
|
+
dim.block.addEntity(new Line({ points: [new Point(0, 0), new Point(1, 1)] }));
|
|
274
|
+
dim.draw({});
|
|
275
|
+
expect(dim.buildDimension).not.toHaveBeenCalled();
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test('draw() returns populated items after initial refresh', () => {
|
|
279
|
+
const dim = makeDim();
|
|
280
|
+
const items = dim.draw({});
|
|
281
|
+
expect(items).toBeInstanceOf(Array);
|
|
282
|
+
expect(items.length).toBeGreaterThan(0);
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test('draw() returns same array reference on repeated calls', () => {
|
|
286
|
+
const dim = makeDim();
|
|
287
|
+
const first = dim.draw({});
|
|
288
|
+
const second = dim.draw({});
|
|
289
|
+
expect(first).toBe(second);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test('draw() block items have BYBLOCK colour after refresh', () => {
|
|
293
|
+
const dim = makeDim();
|
|
294
|
+
dim.draw({});
|
|
295
|
+
for (const item of dim.block.entities) {
|
|
296
|
+
expect(item.entityColour.aci).toBe(0); // BYBLOCK = ACI 0
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
});
|
|
239
300
|
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { AlignedDimension } from '../../core/dimensions/alignedDimension.js';
|
|
2
|
+
import { LinearDimensionBase } from '../../core/dimensions/linearDimensionBase.js';
|
|
3
|
+
import { Point } from '../../core/entities/point.js';
|
|
4
|
+
import { DesignCore } from '../../core/designCore.js';
|
|
5
|
+
import { Core } from '../../core/core/core.js';
|
|
6
|
+
|
|
7
|
+
// initialise core
|
|
8
|
+
new Core();
|
|
9
|
+
|
|
10
|
+
// ─── constructor ─────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
test('LinearDimensionBase can be instantiated', () => {
|
|
13
|
+
const dim = new LinearDimensionBase();
|
|
14
|
+
expect(dim).toBeInstanceOf(LinearDimensionBase);
|
|
15
|
+
expect(dim.points).toBeDefined();
|
|
16
|
+
expect(Array.isArray(dim.points)).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// ─── preview ─────────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
test('LinearDimensionBase.preview - 0 points does nothing', () => {
|
|
22
|
+
const dim = new AlignedDimension();
|
|
23
|
+
DesignCore.Scene.auxiliaryEntities.clear();
|
|
24
|
+
DesignCore.Scene.previewEntities.clear();
|
|
25
|
+
|
|
26
|
+
expect(() => dim.preview()).not.toThrow();
|
|
27
|
+
expect(DesignCore.Scene.auxiliaryEntities.count()).toBe(0);
|
|
28
|
+
expect(DesignCore.Scene.previewEntities.count()).toBe(0);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('LinearDimensionBase.preview - 1 point adds RubberBand to auxiliaryEntities', () => {
|
|
32
|
+
const dim = new AlignedDimension();
|
|
33
|
+
dim.points = [new Point(0, 0)];
|
|
34
|
+
|
|
35
|
+
const origAdd = DesignCore.Scene.auxiliaryEntities.add;
|
|
36
|
+
const added = [];
|
|
37
|
+
DesignCore.Scene.auxiliaryEntities.add = (item) => added.push(item);
|
|
38
|
+
DesignCore.Scene.previewEntities.clear();
|
|
39
|
+
|
|
40
|
+
expect(() => dim.preview()).not.toThrow();
|
|
41
|
+
expect(added.length).toBeGreaterThanOrEqual(1);
|
|
42
|
+
expect(DesignCore.Scene.previewEntities.count()).toBe(0);
|
|
43
|
+
|
|
44
|
+
DesignCore.Scene.auxiliaryEntities.add = origAdd;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('LinearDimensionBase.preview - >1 points creates temp entity', () => {
|
|
48
|
+
const dim = new AlignedDimension();
|
|
49
|
+
dim.points = [new Point(0, 0), new Point(10, 0)];
|
|
50
|
+
|
|
51
|
+
const origCreate = DesignCore.Scene.previewEntities.create;
|
|
52
|
+
const created = [];
|
|
53
|
+
DesignCore.Scene.previewEntities.create = (type, data) => created.push({ type, data });
|
|
54
|
+
DesignCore.Scene.auxiliaryEntities.clear();
|
|
55
|
+
|
|
56
|
+
expect(() => dim.preview()).not.toThrow();
|
|
57
|
+
expect(created.length).toBeGreaterThanOrEqual(1);
|
|
58
|
+
expect(created[0].type).toBe(dim.type);
|
|
59
|
+
expect(DesignCore.Scene.auxiliaryEntities.count()).toBe(0);
|
|
60
|
+
|
|
61
|
+
DesignCore.Scene.previewEntities.create = origCreate;
|
|
62
|
+
});
|