@design-core/core 0.0.7 → 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/.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 +28 -28
- package/core/entities/insert.js +5 -5
- 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 +6 -4
- 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/property.js +1 -1
- package/core/properties/propertyManager.js +37 -37
- package/core/tables/block.js +48 -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 +321 -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 +39 -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/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/propertyManager.test.js +22 -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 +5 -5
|
@@ -102,11 +102,11 @@ export class PdfRenderer extends RendererBase {
|
|
|
102
102
|
if (!p.bulge) {
|
|
103
103
|
this.#emit(`${this.#fmt(next.x)} ${this.#fmt(next.y)} l`);
|
|
104
104
|
} else {
|
|
105
|
-
const
|
|
105
|
+
const centre = p.bulgeCentrePoint(next);
|
|
106
106
|
const radius = p.bulgeRadius(next);
|
|
107
|
-
const startAngle =
|
|
107
|
+
const startAngle = centre.angle(p);
|
|
108
108
|
const sweepAngle = p.bulgeAngle();
|
|
109
|
-
for (const curve of this.#arcToBezier(
|
|
109
|
+
for (const curve of this.#arcToBezier(centre, radius, startAngle, sweepAngle)) {
|
|
110
110
|
this.#emit(`${this.#fmt(curve.cp1x)} ${this.#fmt(curve.cp1y)} ${this.#fmt(curve.cp2x)} ${this.#fmt(curve.cp2y)} ${this.#fmt(curve.x)} ${this.#fmt(curve.y)} c`);
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -321,13 +321,13 @@ export class PdfRenderer extends RendererBase {
|
|
|
321
321
|
/**
|
|
322
322
|
* Approximate a circular arc as one or more PDF cubic Bezier curves.
|
|
323
323
|
* Arcs larger than 90° are split into ≤90° segments for accuracy.
|
|
324
|
-
* @param {Point}
|
|
324
|
+
* @param {Point} centre - arc centre
|
|
325
325
|
* @param {number} radius - arc radius
|
|
326
326
|
* @param {number} startAngle - angle from positive x-axis to arc start (radians)
|
|
327
327
|
* @param {number} sweepAngle - signed sweep: positive = CCW, negative = CW (radians)
|
|
328
328
|
* @return {Array<{cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number}>}
|
|
329
329
|
*/
|
|
330
|
-
#arcToBezier(
|
|
330
|
+
#arcToBezier(centre, radius, startAngle, sweepAngle) {
|
|
331
331
|
// Number of ≤90° segments needed to keep Bezier error below ~0.03%
|
|
332
332
|
const steps = Math.max(1, Math.ceil(Math.abs(sweepAngle) / (Math.PI / 2)));
|
|
333
333
|
// Signed angle of each segment (negative for CW arcs)
|
|
@@ -340,8 +340,8 @@ export class PdfRenderer extends RendererBase {
|
|
|
340
340
|
const a1 = startAngle + i * stepAngle;
|
|
341
341
|
const a2 = a1 + stepAngle;
|
|
342
342
|
// Points on the circle at the segment start and end angles
|
|
343
|
-
const p1 =
|
|
344
|
-
const p2 =
|
|
343
|
+
const p1 = centre.project(a1, radius);
|
|
344
|
+
const p2 = centre.project(a2, radius);
|
|
345
345
|
// Control points are offset from p1/p2 along the tangent direction by radius*tangentScale.
|
|
346
346
|
// Tangent at p1 (CCW) is a1 + π/2; tangent at p2 (CW, pointing back) is a2 - π/2.
|
|
347
347
|
// tangentScale is signed, so CW arcs (negative sweepAngle) automatically reverse the offset.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* correction.
|
|
12
12
|
*
|
|
13
13
|
* Transform helpers (applyTransform, save, restore) are called by canvas.js
|
|
14
|
-
* when processing container entities (Insert,
|
|
14
|
+
* when processing container entities (Insert, DimensionBase) that return a
|
|
15
15
|
* child list from draw().
|
|
16
16
|
*/
|
|
17
17
|
export class RendererBase {
|
package/core/lib/scene.js
CHANGED
|
@@ -75,7 +75,7 @@ export class Scene {
|
|
|
75
75
|
* @param {number} index - integer of item to replace
|
|
76
76
|
* @return {number} - index of created item
|
|
77
77
|
*/
|
|
78
|
-
|
|
78
|
+
addEntity(type, data, index) {
|
|
79
79
|
// TODO: validate data is valid for type
|
|
80
80
|
if (!data) {
|
|
81
81
|
throw Error('Input data missing');
|
|
@@ -13,7 +13,7 @@ export class SingleSelection {
|
|
|
13
13
|
* @param {Point} point
|
|
14
14
|
*/
|
|
15
15
|
constructor(index, point) {
|
|
16
|
-
this.
|
|
16
|
+
this.selectedEntityIndex = index;
|
|
17
17
|
this.selectedPoint = point;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -41,24 +41,24 @@ export class SelectionSet {
|
|
|
41
41
|
export class SelectionManager {
|
|
42
42
|
/** Create a SelectionManager */
|
|
43
43
|
constructor() {
|
|
44
|
-
this.selectionSet = new SelectionSet(); // store a list of selected
|
|
45
|
-
this.
|
|
44
|
+
this.selectionSet = new SelectionSet(); // store a list of selected entities indices
|
|
45
|
+
this.selectedEntities = []; // store a copy of selected entities
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* Reset the selection state
|
|
50
50
|
*/
|
|
51
51
|
reset() {
|
|
52
|
-
this.
|
|
52
|
+
this.selectedEntities = [];
|
|
53
53
|
this.selectionSet = new SelectionSet();
|
|
54
54
|
this.selectionSetChanged();
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
|
-
* Remove the last selection from the selected
|
|
58
|
+
* Remove the last selection from the selected entities
|
|
59
59
|
*/
|
|
60
60
|
removeLastSelection() {
|
|
61
|
-
this.
|
|
61
|
+
this.selectedEntities.pop();
|
|
62
62
|
this.selectionSet.removeLastSelection();
|
|
63
63
|
this.selectionSetChanged();
|
|
64
64
|
}
|
|
@@ -157,19 +157,19 @@ export class SelectionManager {
|
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
|
-
* Remove the item at index from the selectionSet and
|
|
160
|
+
* Remove the item at index from the selectionSet and selectedEntities
|
|
161
161
|
* @param {number} index - index of the item
|
|
162
162
|
*/
|
|
163
163
|
removeFromSelectionSet(index) {
|
|
164
164
|
const itemIndex = this.selectionSet.selectionSet.indexOf(index);
|
|
165
165
|
if (itemIndex !== -1) {
|
|
166
166
|
this.selectionSet.selectionSet.splice(itemIndex, 1);
|
|
167
|
-
this.
|
|
167
|
+
this.selectedEntities.splice(itemIndex, 1);
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
/**
|
|
172
|
-
* Add the item at index to the selectionSet and
|
|
172
|
+
* Add the item at index to the selectionSet and selectedEntities
|
|
173
173
|
* @param {number} index
|
|
174
174
|
*/
|
|
175
175
|
addToSelectionSet(index) {
|
|
@@ -179,28 +179,28 @@ export class SelectionManager {
|
|
|
179
179
|
// only store selections once
|
|
180
180
|
if (this.selectionSet.selectionSet.indexOf(index) === -1) {
|
|
181
181
|
this.selectionSet.selectionSet.push(index);
|
|
182
|
-
this.
|
|
182
|
+
this.addToSelectedEntities(index);
|
|
183
183
|
}
|
|
184
184
|
}
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
|
-
* Duplicate the item at index and add to
|
|
187
|
+
* Duplicate the item at index and add to selectedEntities
|
|
188
188
|
* @param {number} index
|
|
189
189
|
*/
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
this.
|
|
190
|
+
addToSelectedEntities(index) {
|
|
191
|
+
const copyOfItem = Utils.cloneObject(DesignCore.Scene.entities.get(index));
|
|
192
|
+
this.selectedEntities.push(copyOfItem);
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
/**
|
|
196
|
-
* Reload the
|
|
196
|
+
* Reload the selectedEntities
|
|
197
197
|
* This is required following changes to selected item properties
|
|
198
198
|
*/
|
|
199
|
-
|
|
200
|
-
this.
|
|
199
|
+
reloadSelectedEntities() {
|
|
200
|
+
this.selectedEntities = [];
|
|
201
201
|
|
|
202
202
|
for (let i = 0; i < this.selectionSet.selectionSet.length; i++) {
|
|
203
|
-
this.
|
|
203
|
+
this.addToSelectedEntities(this.selectionSet.selectionSet[i]);
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
DesignCore.Core.canvas.requestPaint();
|
package/core/lib/utils.js
CHANGED
|
@@ -47,26 +47,26 @@ export class Utils {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
* Sort points around an arc
|
|
50
|
+
* Sort points around an arc centre by angular position.
|
|
51
51
|
* Mutates the points array.
|
|
52
52
|
*
|
|
53
53
|
* @param {Array} points - array of points
|
|
54
54
|
* @param {Point} startPoint - arc start point
|
|
55
55
|
* @param {Point} endPoint - arc end point
|
|
56
|
-
* @param {Point}
|
|
56
|
+
* @param {Point} centrePoint - arc centre point
|
|
57
57
|
* @param {number} direction - arc direction (ccw >0, cw <=0)
|
|
58
58
|
*
|
|
59
59
|
*/
|
|
60
|
-
static sortPointsOnArc(points, startPoint, endPoint,
|
|
60
|
+
static sortPointsOnArc(points, startPoint, endPoint, centrePoint, direction = 1) {
|
|
61
61
|
if (!Array.isArray(points)) return;
|
|
62
62
|
|
|
63
|
-
const refAngle = direction > 0 ?
|
|
63
|
+
const refAngle = direction > 0 ? centrePoint.angle(startPoint) : centrePoint.angle(endPoint);
|
|
64
64
|
const twoPi = Math.PI * 2;
|
|
65
65
|
const normalize = (ang) => ((ang % twoPi) + twoPi) % twoPi;
|
|
66
66
|
|
|
67
67
|
// map points to angles
|
|
68
68
|
const mapped = points.map((point) => {
|
|
69
|
-
const angle = Math.atan2(point.y -
|
|
69
|
+
const angle = Math.atan2(point.y - centrePoint.y, point.x - centrePoint.x);
|
|
70
70
|
const normalizedAngle = normalize(angle - refAngle);
|
|
71
71
|
return { point, normalizedAngle };
|
|
72
72
|
});
|
|
@@ -78,7 +78,7 @@ export class Property {
|
|
|
78
78
|
SCALE: 'scale',
|
|
79
79
|
STRING: 'string',
|
|
80
80
|
STYLENAME: 'styleName',
|
|
81
|
-
// ──
|
|
81
|
+
// ── PolylineBase ──────────────────────────────────────────────────────────
|
|
82
82
|
CLOSED: 'closed',
|
|
83
83
|
// ── Hatch ─────────────────────────────────────────────────────────────────
|
|
84
84
|
CHILDENTITIES: 'childEntities',
|
|
@@ -28,81 +28,81 @@ export class PropertyManager {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* Set
|
|
31
|
+
* Set entity properties
|
|
32
32
|
* @param {string} property
|
|
33
33
|
* @param {any} newPropertyValue
|
|
34
|
-
* @param {string}
|
|
34
|
+
* @param {string} entityType
|
|
35
35
|
*/
|
|
36
|
-
|
|
36
|
+
setEntityProperties(property, newPropertyValue, entityType='All') {
|
|
37
37
|
const stateChanges = [];
|
|
38
38
|
for (let i = 0; i < DesignCore.Scene.selectionManager.selectionSet.selectionSet.length; i++) {
|
|
39
39
|
const index = DesignCore.Scene.selectionManager.selectionSet.selectionSet[i];
|
|
40
40
|
|
|
41
|
-
const
|
|
41
|
+
const entity = DesignCore.Scene.entities.get(index);
|
|
42
42
|
|
|
43
|
-
// check if the
|
|
44
|
-
if (
|
|
43
|
+
// check if the entity is of the selected type
|
|
44
|
+
if (entityType !== 'All' && entity.type !== entityType) {
|
|
45
45
|
continue;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
// check if the
|
|
49
|
-
if (!
|
|
48
|
+
// check if the entity has the selected property
|
|
49
|
+
if (!entity.properties?.has(property)) {
|
|
50
50
|
continue;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const currentValue =
|
|
53
|
+
const currentValue = entity.getProperty(property);
|
|
54
54
|
|
|
55
55
|
if (typeof (currentValue) !== typeof (newPropertyValue)) {
|
|
56
56
|
DesignCore.Core.notify(Strings.Error.INPUT);
|
|
57
57
|
} else {
|
|
58
|
-
// update the
|
|
58
|
+
// update the entity property
|
|
59
59
|
const update = {};
|
|
60
60
|
update[property] = newPropertyValue;
|
|
61
|
-
const stateChange = new UpdateState(
|
|
61
|
+
const stateChange = new UpdateState(entity, update);
|
|
62
62
|
stateChanges.push(stateChange);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
DesignCore.Scene.commit(stateChanges);
|
|
66
|
-
DesignCore.Scene.selectionManager.
|
|
66
|
+
DesignCore.Scene.selectionManager.reloadSelectedEntities();
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
70
70
|
* Get the types of items selected
|
|
71
71
|
* @return {Array}
|
|
72
72
|
*/
|
|
73
|
-
|
|
74
|
-
// Loop through the items and get a list of
|
|
75
|
-
const
|
|
73
|
+
getEntityTypes() {
|
|
74
|
+
// Loop through the items and get a list of entity types.
|
|
75
|
+
const entityTypes = [];
|
|
76
76
|
|
|
77
77
|
if (DesignCore.Scene.selectionManager.selectionSet.selectionSet.length > 0) {
|
|
78
78
|
for (let i = 0; i < DesignCore.Scene.selectionManager.selectionSet.selectionSet.length; i++) {
|
|
79
|
-
const
|
|
80
|
-
const
|
|
79
|
+
const entity = DesignCore.Scene.entities.get(DesignCore.Scene.selectionManager.selectionSet.selectionSet[i]);
|
|
80
|
+
const entityType = entity.type;
|
|
81
81
|
|
|
82
|
-
if (
|
|
83
|
-
|
|
82
|
+
if (entityTypes.indexOf(entityType, 0) === -1) {
|
|
83
|
+
entityTypes.push(entityType);
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// if there is more that one type add an option for all
|
|
88
|
-
if (
|
|
89
|
-
|
|
88
|
+
if (entityTypes.length > 1) {
|
|
89
|
+
entityTypes.unshift('All');
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
return
|
|
93
|
+
return entityTypes;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/**
|
|
97
|
-
* Get a list of common
|
|
98
|
-
* @param {string}
|
|
97
|
+
* Get a list of common properties
|
|
98
|
+
* @param {string} entityType
|
|
99
99
|
* @return {Array}
|
|
100
100
|
*/
|
|
101
|
-
|
|
101
|
+
getEntityProperties(entityType) {
|
|
102
102
|
// Loop through the items and get a list of common properties.
|
|
103
103
|
|
|
104
|
-
// check for valid
|
|
105
|
-
if (
|
|
104
|
+
// check for valid entityType and selectionSet
|
|
105
|
+
if (entityType === undefined || entityType === null || DesignCore.Scene.selectionManager.selectionSet.selectionSet.length <= 0) {
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -114,8 +114,8 @@ export class PropertyManager {
|
|
|
114
114
|
});
|
|
115
115
|
|
|
116
116
|
// get a subset of the selectionSet
|
|
117
|
-
if (
|
|
118
|
-
subset = subset.filter((el) => el.type ===
|
|
117
|
+
if (entityType !== 'All') {
|
|
118
|
+
subset = subset.filter((el) => el.type === entityType);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
const propertiesList = [];
|
|
@@ -138,14 +138,14 @@ export class PropertyManager {
|
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
140
|
* Get the Property descriptor for a named property from a representative selected entity.
|
|
141
|
-
* @param {string}
|
|
141
|
+
* @param {string} entityType
|
|
142
142
|
* @param {string} property
|
|
143
143
|
* @return {Property|undefined}
|
|
144
144
|
*/
|
|
145
|
-
|
|
145
|
+
getEntityPropertyDefinition(entityType, property) {
|
|
146
146
|
const index = DesignCore.Scene.selectionManager.selectionSet.selectionSet.find((i) => {
|
|
147
|
-
const
|
|
148
|
-
return (
|
|
147
|
+
const entity = DesignCore.Scene.entities.get(i);
|
|
148
|
+
return (entityType === 'All' || entity.type === entityType) && entity.properties?.has(property);
|
|
149
149
|
});
|
|
150
150
|
if (index === undefined) return undefined;
|
|
151
151
|
return DesignCore.Scene.entities.get(index).properties.definition(property);
|
|
@@ -153,23 +153,23 @@ export class PropertyManager {
|
|
|
153
153
|
|
|
154
154
|
/**
|
|
155
155
|
* Get a list the property values
|
|
156
|
-
* @param {string}
|
|
156
|
+
* @param {string} entityType
|
|
157
157
|
* @param {string} property
|
|
158
158
|
* @return {Array}
|
|
159
159
|
*/
|
|
160
|
-
|
|
160
|
+
getEntityPropertyValue(entityType, property) {
|
|
161
161
|
// Loop through the items and get a list the property values
|
|
162
162
|
const propertiesValueList = [];
|
|
163
163
|
if (DesignCore.Scene.selectionManager.selectionSet.selectionSet.length > 0) {
|
|
164
164
|
for (let i = 0; i < DesignCore.Scene.selectionManager.selectionSet.selectionSet.length; i++) {
|
|
165
|
-
if (DesignCore.Scene.entities.get(DesignCore.Scene.selectionManager.selectionSet.selectionSet[i]).type ===
|
|
165
|
+
if (DesignCore.Scene.entities.get(DesignCore.Scene.selectionManager.selectionSet.selectionSet[i]).type === entityType || entityType === 'All') {
|
|
166
166
|
const entity = DesignCore.Scene.entities.get(DesignCore.Scene.selectionManager.selectionSet.selectionSet[i]);
|
|
167
167
|
propertiesValueList.push(entity.getProperty(property));
|
|
168
168
|
}
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
// Check if every
|
|
172
|
+
// Check if every entity in the selection set has the same value for the property
|
|
173
173
|
if (propertiesValueList.every((prop) => {
|
|
174
174
|
return prop === propertiesValueList[0];
|
|
175
175
|
})) {
|
package/core/tables/block.js
CHANGED
|
@@ -8,9 +8,11 @@ import { Input, PromptOptions } from '../lib/inputManager.js';
|
|
|
8
8
|
import { Flags } from '../properties/flags.js';
|
|
9
9
|
import { Property } from '../properties/property.js';
|
|
10
10
|
import { AddState, RemoveState } from '../lib/stateManager.js';
|
|
11
|
+
import { Logging } from '../lib/logging.js';
|
|
12
|
+
import { Utils } from '../lib/utils.js';
|
|
11
13
|
|
|
12
14
|
import { DesignCore } from '../designCore.js';
|
|
13
|
-
|
|
15
|
+
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Block Entity Class
|
|
@@ -36,7 +38,7 @@ export class Block extends Entity {
|
|
|
36
38
|
writable: true,
|
|
37
39
|
});
|
|
38
40
|
|
|
39
|
-
Object.defineProperty(this, '
|
|
41
|
+
Object.defineProperty(this, 'entities', {
|
|
40
42
|
value: [],
|
|
41
43
|
writable: true,
|
|
42
44
|
});
|
|
@@ -47,8 +49,8 @@ export class Block extends Entity {
|
|
|
47
49
|
this.name = data.name || data[2];
|
|
48
50
|
}
|
|
49
51
|
|
|
50
|
-
if (data.hasOwnProperty('
|
|
51
|
-
this.
|
|
52
|
+
if (data.hasOwnProperty('entities')) {
|
|
53
|
+
this.entities = data.entities;
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
if (data.hasOwnProperty('flags') || data.hasOwnProperty('70')) {
|
|
@@ -114,21 +116,21 @@ export class Block extends Entity {
|
|
|
114
116
|
// array to hold state changes
|
|
115
117
|
const stateChanges = [];
|
|
116
118
|
|
|
117
|
-
// move selected
|
|
119
|
+
// move selected entities from scene to block
|
|
118
120
|
selections.forEach((index) => {
|
|
119
|
-
const
|
|
120
|
-
// remove
|
|
121
|
-
const
|
|
122
|
-
// assign a fresh handle — the block
|
|
123
|
-
|
|
124
|
-
// adjust the
|
|
121
|
+
const entity = DesignCore.Scene.entities.get(index);
|
|
122
|
+
// remove entity from scene
|
|
123
|
+
const copyOfEntity = Utils.cloneObject(entity);
|
|
124
|
+
// assign a fresh handle — the block entity is a new entity distinct from the scene entity
|
|
125
|
+
copyOfEntity.setProperty('handle', DesignCore.HandleManager.next());
|
|
126
|
+
// adjust the entity's points to reflect the insert point
|
|
125
127
|
const delta = new Point(-insertPoint.x, -insertPoint.y);
|
|
126
|
-
if (
|
|
127
|
-
const points =
|
|
128
|
-
|
|
128
|
+
if (copyOfEntity.points?.length) {
|
|
129
|
+
const points = copyOfEntity.points.map((p) => new Point(p.x, p.y, p.bulge, p.sequence).add(delta));
|
|
130
|
+
copyOfEntity.setProperty('points', points);
|
|
129
131
|
}
|
|
130
|
-
block.
|
|
131
|
-
const stateChangeRemove = new RemoveState(
|
|
132
|
+
block.entities.push(copyOfEntity);
|
|
133
|
+
const stateChangeRemove = new RemoveState(entity);
|
|
132
134
|
stateChanges.push(stateChangeRemove);
|
|
133
135
|
});
|
|
134
136
|
|
|
@@ -175,8 +177,8 @@ export class Block extends Entity {
|
|
|
175
177
|
file.writeGroupCode('3', this.name); // Name again
|
|
176
178
|
file.writeGroupCode('1', '');
|
|
177
179
|
|
|
178
|
-
for (let i = 0; i < this.
|
|
179
|
-
this.
|
|
180
|
+
for (let i = 0; i < this.entities.length; i++) {
|
|
181
|
+
this.entities[i].dxf(file);
|
|
180
182
|
}
|
|
181
183
|
|
|
182
184
|
const endblk = new EndBlock({ handle: this.endblkHandle });
|
|
@@ -184,18 +186,18 @@ export class Block extends Entity {
|
|
|
184
186
|
}
|
|
185
187
|
|
|
186
188
|
/**
|
|
187
|
-
* Clear
|
|
189
|
+
* Clear entities from the block
|
|
188
190
|
*/
|
|
189
|
-
|
|
190
|
-
this.
|
|
191
|
+
clearEntities() {
|
|
192
|
+
this.entities = [];
|
|
191
193
|
}
|
|
192
194
|
|
|
193
195
|
/**
|
|
194
|
-
* Add an
|
|
195
|
-
* @param {Object}
|
|
196
|
+
* Add an entity to the block
|
|
197
|
+
* @param {Object} entity
|
|
196
198
|
*/
|
|
197
|
-
|
|
198
|
-
this.
|
|
199
|
+
addEntity(entity) {
|
|
200
|
+
this.entities.push(entity);
|
|
199
201
|
}
|
|
200
202
|
|
|
201
203
|
/**
|
|
@@ -207,15 +209,15 @@ export class Block extends Entity {
|
|
|
207
209
|
snaps(mousePoint, delta) {
|
|
208
210
|
const snaps = [];
|
|
209
211
|
|
|
210
|
-
if (!this.
|
|
212
|
+
if (!this.entities.length) {
|
|
211
213
|
// nothing to draw
|
|
212
214
|
return snaps;
|
|
213
215
|
}
|
|
214
216
|
|
|
215
|
-
for (let
|
|
216
|
-
// collect the child
|
|
217
|
-
const
|
|
218
|
-
snaps.push(...
|
|
217
|
+
for (let entity = 0; entity < this.entities.length; entity++) {
|
|
218
|
+
// collect the child entity snaps
|
|
219
|
+
const entitySnaps = this.entities[entity].snaps(mousePoint, delta);
|
|
220
|
+
snaps.push(...entitySnaps);
|
|
219
221
|
}
|
|
220
222
|
|
|
221
223
|
return snaps;
|
|
@@ -230,19 +232,19 @@ export class Block extends Entity {
|
|
|
230
232
|
let distance = Infinity;
|
|
231
233
|
let minPnt = P;
|
|
232
234
|
|
|
233
|
-
if (!this.
|
|
235
|
+
if (!this.entities.length) {
|
|
234
236
|
// nothing to draw
|
|
235
237
|
return [minPnt, distance];
|
|
236
238
|
}
|
|
237
239
|
|
|
238
|
-
for (let idx = 0; idx < this.
|
|
239
|
-
const
|
|
240
|
-
const
|
|
241
|
-
const
|
|
240
|
+
for (let idx = 0; idx < this.entities.length; idx++) {
|
|
241
|
+
const entityClosestPoint = this.entities[idx].closestPoint(P);
|
|
242
|
+
const entityPnt = entityClosestPoint[0];
|
|
243
|
+
const entityDist = entityClosestPoint[1];
|
|
242
244
|
|
|
243
|
-
if (
|
|
244
|
-
distance =
|
|
245
|
-
minPnt =
|
|
245
|
+
if (entityDist < distance) {
|
|
246
|
+
distance = entityDist;
|
|
247
|
+
minPnt = entityPnt;
|
|
246
248
|
}
|
|
247
249
|
}
|
|
248
250
|
|
|
@@ -259,13 +261,13 @@ export class Block extends Entity {
|
|
|
259
261
|
let ymin = Infinity;
|
|
260
262
|
let ymax = -Infinity;
|
|
261
263
|
|
|
262
|
-
for (let idx = 0; idx < this.
|
|
263
|
-
const
|
|
264
|
+
for (let idx = 0; idx < this.entities.length; idx++) {
|
|
265
|
+
const entityBoundingBox = this.entities[idx].boundingBox();
|
|
264
266
|
|
|
265
|
-
xmin = Math.min(xmin,
|
|
266
|
-
xmax = Math.max(xmax,
|
|
267
|
-
ymin = Math.min(ymin,
|
|
268
|
-
ymax = Math.max(ymax,
|
|
267
|
+
xmin = Math.min(xmin, entityBoundingBox.xMin);
|
|
268
|
+
xmax = Math.max(xmax, entityBoundingBox.xMax);
|
|
269
|
+
ymin = Math.min(ymin, entityBoundingBox.yMin);
|
|
270
|
+
ymax = Math.max(ymax, entityBoundingBox.yMax);
|
|
269
271
|
}
|
|
270
272
|
|
|
271
273
|
const topLeft = new Point(xmin, ymax);
|
|
@@ -280,8 +282,8 @@ export class Block extends Entity {
|
|
|
280
282
|
* @return {boolean} true if touched
|
|
281
283
|
*/
|
|
282
284
|
touched(selection) {
|
|
283
|
-
for (let idx = 0; idx < this.
|
|
284
|
-
const touched = this.
|
|
285
|
+
for (let idx = 0; idx < this.entities.length; idx++) {
|
|
286
|
+
const touched = this.entities[idx].touched(selection);
|
|
285
287
|
if (touched) {
|
|
286
288
|
return true;
|
|
287
289
|
}
|
package/core/tables/dimStyle.js
CHANGED
|
@@ -321,11 +321,11 @@ export class DimStyle {
|
|
|
321
321
|
this.DIMTMOVE = Property.loadValue([data.DIMTMOVE, data[279]], 0);
|
|
322
322
|
|
|
323
323
|
// DXF Groupcode 280 - Horizontal dimension text position:
|
|
324
|
-
// 0 = Above dimension line and
|
|
324
|
+
// 0 = Above dimension line and centre-justified between extension lines
|
|
325
325
|
// 1 = Above dimension line and next to first extension line
|
|
326
326
|
// 2 = Above dimension line and next to second extension line
|
|
327
|
-
// 3 = Above and
|
|
328
|
-
// 4 = Above and
|
|
327
|
+
// 3 = Above and centre-justified to first extension line
|
|
328
|
+
// 4 = Above and centre-justified to second extension line
|
|
329
329
|
this.DIMJUST = Property.loadValue([data.DIMJUST, data[280]], 0);
|
|
330
330
|
|
|
331
331
|
// DXF Groupcode 281 - Suppression of first extension line:
|
|
@@ -506,7 +506,7 @@ export class DimStyle {
|
|
|
506
506
|
}
|
|
507
507
|
|
|
508
508
|
/**
|
|
509
|
-
* get the DIMCEN property for the
|
|
509
|
+
* get the DIMCEN property for the centre mark size
|
|
510
510
|
* @return {Number} DIMCEN value
|
|
511
511
|
* This uses two internal values to define the DIMCEN property
|
|
512
512
|
* DIMCENSTYL & DIMCENVALUE
|
|
@@ -604,7 +604,7 @@ export class DimStyle {
|
|
|
604
604
|
file.writeGroupCode('275', this.DIMAUNIT, DXFFile.Version.R13);
|
|
605
605
|
file.writeGroupCode('276', this.DIMFRAC, DXFFile.Version.R2000);
|
|
606
606
|
file.writeGroupCode('277', this.DIMLUNIT, DXFFile.Version.R2000);
|
|
607
|
-
// file.writeGroupCode('278', this.DIMDSEP, DXFFile.Version.R14)); - TODO: AutoCAD uses a
|
|
607
|
+
// file.writeGroupCode('278', this.DIMDSEP, DXFFile.Version.R14)); - TODO: AutoCAD uses a numerical description
|
|
608
608
|
file.writeGroupCode('279', this.DIMTMOVE, DXFFile.Version.R2000);
|
|
609
609
|
file.writeGroupCode('280', this.DIMJUST, DXFFile.Version.R13);
|
|
610
610
|
file.writeGroupCode('281', this.DIMSD1 ? 1 : 0, DXFFile.Version.R13); // convert bool to int
|
|
@@ -48,7 +48,7 @@ export class LTypeManager extends StyleManagerBase {
|
|
|
48
48
|
*/
|
|
49
49
|
dxf(file) {
|
|
50
50
|
// Create table data for ltype styles
|
|
51
|
-
// The LTYPE Table must
|
|
51
|
+
// The LTYPE Table must precede the LAYER table
|
|
52
52
|
file.writeGroupCode('0', 'TABLE');
|
|
53
53
|
file.writeGroupCode('2', 'LTYPE');
|
|
54
54
|
file.writeGroupCode('5', this.handle, DXFFile.Version.R2000);
|
package/core/tables/vport.js
CHANGED
|
@@ -12,9 +12,9 @@ export class VPort {
|
|
|
12
12
|
this.handle = Property.loadValue([data?.handle, data?.[5]]);
|
|
13
13
|
// DXF Groupcode 2 - Name
|
|
14
14
|
this.name = Property.loadValue([data?.name, data?.[2]], '*ACTIVE');
|
|
15
|
-
// DXF Groupcode 12 - View
|
|
15
|
+
// DXF Groupcode 12 - View centre X
|
|
16
16
|
this.viewCenterX = Property.loadValue([data?.viewCenterX, data?.[12]], 0);
|
|
17
|
-
// DXF Groupcode 22 - View
|
|
17
|
+
// DXF Groupcode 22 - View centre Y
|
|
18
18
|
this.viewCenterY = Property.loadValue([data?.viewCenterY, data?.[22]], 0);
|
|
19
19
|
// DXF Groupcode 40 - VPort height
|
|
20
20
|
this.height = Property.loadValue([data?.height, data?.[40]], 0);
|
package/core/tools/chamfer.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Logging } from '../lib/logging.js';
|
|
|
6
6
|
import { Utils } from '../lib/utils.js';
|
|
7
7
|
import { Point } from '../entities/point.js';
|
|
8
8
|
import { Line } from '../entities/line.js';
|
|
9
|
-
import {
|
|
9
|
+
import { PolylineBase } from '../entities/polylineBase.js';
|
|
10
10
|
import { AddState } from '../lib/stateManager.js';
|
|
11
11
|
import { Colour } from '../lib/colour.js';
|
|
12
12
|
|
|
@@ -98,9 +98,9 @@ export class Chamfer extends ChamferFilletBase {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
// input1 is a selection — validate and store first entity
|
|
101
|
-
const firstEntity = DesignCore.Scene.entities.get(input1.
|
|
101
|
+
const firstEntity = DesignCore.Scene.entities.get(input1.selectedEntityIndex);
|
|
102
102
|
DesignCore.Scene.selectionManager.removeLastSelection();
|
|
103
|
-
if (!(firstEntity instanceof Line) && !(firstEntity instanceof
|
|
103
|
+
if (!(firstEntity instanceof Line) && !(firstEntity instanceof PolylineBase)) {
|
|
104
104
|
DesignCore.Core.notify(`${firstEntity.type} - ${Strings.Message.NOCHAMFER}`);
|
|
105
105
|
continue;
|
|
106
106
|
}
|
|
@@ -112,16 +112,16 @@ export class Chamfer extends ChamferFilletBase {
|
|
|
112
112
|
const input2 = await DesignCore.Scene.inputManager.requestInput(op2);
|
|
113
113
|
if (input2 === undefined) return;
|
|
114
114
|
|
|
115
|
-
const candidate = DesignCore.Scene.entities.get(input2.
|
|
115
|
+
const candidate = DesignCore.Scene.entities.get(input2.selectedEntityIndex);
|
|
116
116
|
DesignCore.Scene.selectionManager.removeLastSelection();
|
|
117
|
-
if (!(candidate instanceof Line) && !(candidate instanceof
|
|
117
|
+
if (!(candidate instanceof Line) && !(candidate instanceof PolylineBase)) {
|
|
118
118
|
DesignCore.Core.notify(`${this.type} - ${candidate.type} ${Strings.Message.NOCHAMFER}`);
|
|
119
119
|
continue;
|
|
120
120
|
}
|
|
121
121
|
if (!this.secondPick.setPick(candidate, input2.selectedPoint, `${Strings.Strings.ARC} - ${Strings.Message.NOCHAMFER}`)) continue;
|
|
122
122
|
// If both selections are the same polyline, segments must be consecutive
|
|
123
123
|
// or they must be the open-end segments of an open polyline.
|
|
124
|
-
if (candidate === firstEntity && firstEntity instanceof
|
|
124
|
+
if (candidate === firstEntity && firstEntity instanceof PolylineBase) {
|
|
125
125
|
const isConsecutive = firstEntity.areConsecutiveSegments(this.firstPick.segmentIndex, this.secondPick.segmentIndex);
|
|
126
126
|
const lastIdx = firstEntity.points.length - 1;
|
|
127
127
|
const isOpenEnds = !firstEntity.flags.hasFlag(1) &&
|