@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
|
@@ -16,7 +16,7 @@ import { DimType } from '../properties/dimType.js';
|
|
|
16
16
|
* Base Dimension Entity Class
|
|
17
17
|
* @extends Entity
|
|
18
18
|
*/
|
|
19
|
-
export class
|
|
19
|
+
export class DimensionBase extends Entity {
|
|
20
20
|
/**
|
|
21
21
|
* Create a Base Dimension
|
|
22
22
|
* @param {Array} data
|
|
@@ -148,9 +148,9 @@ export class BaseDimension extends Entity {
|
|
|
148
148
|
|
|
149
149
|
if (data.hasOwnProperty('71')) {
|
|
150
150
|
// DXF Groupcode 71 - Attachment Point
|
|
151
|
-
// 1 = Top left; 2 = Top
|
|
152
|
-
// 4 = Middle left; 5 = Middle
|
|
153
|
-
// 7 = Bottom left; 8 = Bottom
|
|
151
|
+
// 1 = Top left; 2 = Top centre; 3 = Top right
|
|
152
|
+
// 4 = Middle left; 5 = Middle centre; 6 = Middle right
|
|
153
|
+
// 7 = Bottom left; 8 = Bottom centre; 9 = Bottom right
|
|
154
154
|
const err = 'Groupcode 71 not implemented';
|
|
155
155
|
Logging.instance.debug(`${this.type} - ${err}`);
|
|
156
156
|
}
|
|
@@ -301,7 +301,7 @@ export class BaseDimension extends Entity {
|
|
|
301
301
|
const textHeight = this.getDimensionStyle().getValue('DIMTXT');
|
|
302
302
|
// set the text height
|
|
303
303
|
text.setProperty(Property.Names.HEIGHT, textHeight);
|
|
304
|
-
// Always set text horizontal alignment to
|
|
304
|
+
// Always set text horizontal alignment to centre
|
|
305
305
|
text.setProperty(Property.Names.HORIZONTALALIGNMENT, 1);
|
|
306
306
|
// Always set text vertical alignment to middle
|
|
307
307
|
text.setProperty(Property.Names.VERTICALALIGNMENT, 2);
|
|
@@ -391,19 +391,19 @@ export class BaseDimension extends Entity {
|
|
|
391
391
|
|
|
392
392
|
/**
|
|
393
393
|
* Get the geometry for the centre mark
|
|
394
|
-
* @param {Point} point centre point for
|
|
395
|
-
* @return {Array} array of entities representing the
|
|
394
|
+
* @param {Point} point centre point for centre mark
|
|
395
|
+
* @return {Array} array of entities representing the centre mark
|
|
396
396
|
*/
|
|
397
397
|
getCentreMark(point) {
|
|
398
398
|
/*
|
|
399
399
|
* DIMCEN value defines the centre mark type and size
|
|
400
|
-
* 0 = No
|
|
401
|
-
* <0 =
|
|
402
|
-
* >0 =
|
|
400
|
+
* 0 = No centre marks or lines are drawn
|
|
401
|
+
* <0 = Centrelines are drawn
|
|
402
|
+
* >0 = Centre marks are drawn
|
|
403
403
|
*/
|
|
404
404
|
|
|
405
405
|
const centreMark = [];
|
|
406
|
-
// get the
|
|
406
|
+
// get the centre mark style
|
|
407
407
|
const markStyle = this.getDimensionStyle().getValue('DIMCENSTYL');
|
|
408
408
|
// get the centre mark size
|
|
409
409
|
const markSize = this.getDimensionStyle().getValue('DIMCENVALUE');
|
|
@@ -433,14 +433,14 @@ export class BaseDimension extends Entity {
|
|
|
433
433
|
/**
|
|
434
434
|
* Draw the entity
|
|
435
435
|
* @param {Object} renderer
|
|
436
|
-
* @return {Array} block
|
|
436
|
+
* @return {Array} block entities for the canvas to render recursively
|
|
437
437
|
*/
|
|
438
438
|
draw(renderer) {
|
|
439
|
-
if (this.block.
|
|
439
|
+
if (this.block.entities.length === 0) {
|
|
440
440
|
this.refresh();
|
|
441
441
|
}
|
|
442
442
|
|
|
443
|
-
return this.block.
|
|
443
|
+
return this.block.entities;
|
|
444
444
|
}
|
|
445
445
|
|
|
446
446
|
/**
|
|
@@ -490,18 +490,18 @@ export class BaseDimension extends Entity {
|
|
|
490
490
|
}
|
|
491
491
|
|
|
492
492
|
/**
|
|
493
|
-
*
|
|
493
|
+
* Refresh the dimension geometry
|
|
494
494
|
*/
|
|
495
495
|
refresh() {
|
|
496
496
|
const entities = this.buildDimension();
|
|
497
497
|
|
|
498
498
|
if (entities) {
|
|
499
|
-
this.block.
|
|
499
|
+
this.block.clearEntities();
|
|
500
500
|
|
|
501
501
|
entities.forEach((element) => {
|
|
502
502
|
// For colour BYBLOCK for dimensions
|
|
503
503
|
element.setProperty(Property.Names.COLOUR, 'BYBLOCK');
|
|
504
|
-
this.block.
|
|
504
|
+
this.block.addEntity(element);
|
|
505
505
|
});
|
|
506
506
|
}
|
|
507
507
|
}
|
|
@@ -3,7 +3,7 @@ import { Line } from '../entities/line.js';
|
|
|
3
3
|
import { Text } from '../entities/text.js';
|
|
4
4
|
import { Input, PromptOptions } from '../lib/inputManager.js';
|
|
5
5
|
import { Logging } from '../lib/logging.js';
|
|
6
|
-
import {
|
|
6
|
+
import { DimensionBase } from './dimensionBase.js';
|
|
7
7
|
import { Point } from '../entities/point.js';
|
|
8
8
|
|
|
9
9
|
import { DesignCore } from '../designCore.js';
|
|
@@ -13,9 +13,9 @@ import { RubberBand } from '../lib/auxiliary/rubberBand.js';
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Aligned Dimension Entity Class
|
|
16
|
-
* @extends
|
|
16
|
+
* @extends DimensionBase
|
|
17
17
|
*/
|
|
18
|
-
export class
|
|
18
|
+
export class LinearDimensionBase extends DimensionBase {
|
|
19
19
|
/**
|
|
20
20
|
* Create an Aligned Dimension
|
|
21
21
|
* @param {Array} data
|
|
@@ -62,7 +62,7 @@ export class BaseLinearDimension extends BaseDimension {
|
|
|
62
62
|
* Preview the entity during creation
|
|
63
63
|
*/
|
|
64
64
|
preview() {
|
|
65
|
-
if (this.points.length
|
|
65
|
+
if (this.points.length === 1) {
|
|
66
66
|
const mousePoint = DesignCore.Mouse.pointOnScene();
|
|
67
67
|
DesignCore.Scene.auxiliaryEntities.add(new RubberBand([this.points.at(0), mousePoint]));
|
|
68
68
|
}
|
|
@@ -190,7 +190,7 @@ export class BaseLinearDimension extends BaseDimension {
|
|
|
190
190
|
const outsideOffsetDirection = Pt11.distance(Pt13e) < Pt11.distance(Pt14e) ? reverseDimLineAngle : dimLineAngle;
|
|
191
191
|
|
|
192
192
|
switch (DIMJUST) {
|
|
193
|
-
case 0: // 0 =
|
|
193
|
+
case 0: // 0 = Centre-justified between extension lines
|
|
194
194
|
if (textOutSide) {
|
|
195
195
|
textPosition = midPoint.project(outsideOffsetDirection, outsideOffsetDistance);
|
|
196
196
|
}
|
|
@@ -237,7 +237,7 @@ export class BaseLinearDimension extends BaseDimension {
|
|
|
237
237
|
|
|
238
238
|
// DIMTAD - Text vertical position
|
|
239
239
|
switch (DIMTAD) {
|
|
240
|
-
case 0: // 0 =
|
|
240
|
+
case 0: // 0 = Centres the dimension text between the extension lines.
|
|
241
241
|
break;
|
|
242
242
|
case 1: // 1 = Places the dimension text above the dimension line except when the dimension line is not horizontal and text inside the extension lines is forced horizontal ( DIMTIH = 1).
|
|
243
243
|
textPosition = textPosition.project(textAboveDirection, textAboveDistance);
|
|
@@ -301,8 +301,8 @@ export class BaseLinearDimension extends BaseDimension {
|
|
|
301
301
|
dimLineTwoEnd = Pt14e;
|
|
302
302
|
}
|
|
303
303
|
// get the distance to extend the dimension line
|
|
304
|
-
// when text is vertically
|
|
305
|
-
// when text is not vertically
|
|
304
|
+
// when text is vertically centred trim the dimension line back from the text position
|
|
305
|
+
// when text is not vertically centred extend the dimension line beyond the text position by half the text width
|
|
306
306
|
const dimlineExtendDistance = textDimlineIntersection.isSame(textPosition) ? approxTextHalfWidth + DIMGAP : -approxTextHalfWidth;
|
|
307
307
|
|
|
308
308
|
if (Pt11.distance(Pt13e) < Pt11.distance(Pt14e)) {
|
|
@@ -314,7 +314,7 @@ export class BaseLinearDimension extends BaseDimension {
|
|
|
314
314
|
}
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
-
// split the dimension line when the text is
|
|
317
|
+
// split the dimension line when the text is centred vertically
|
|
318
318
|
if (textIsOnInternalDimLine) {
|
|
319
319
|
dimLineOneEnd = dimLineOneEnd.project(reverseDimLineAngle, approxTextWidth * 0.6);
|
|
320
320
|
dimLineTwoEnd = dimLineTwoEnd.project(dimLineAngle, approxTextWidth * 0.6);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
|
|
2
2
|
import { DXFFile } from '../lib/dxf/dxfFile.js';
|
|
3
|
-
import {
|
|
3
|
+
import { CircularDimensionBase } from './circularDimensionBase.js';
|
|
4
4
|
import { Property } from '../properties/property.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Radial Dimension Entity Class
|
|
8
|
-
* @extends
|
|
8
|
+
* @extends CircularDimensionBase
|
|
9
9
|
*/
|
|
10
|
-
export class RadialDimension extends
|
|
10
|
+
export class RadialDimension extends CircularDimensionBase {
|
|
11
11
|
/**
|
|
12
12
|
* Create a Radial Dimension
|
|
13
13
|
* @param {Array} data
|
|
@@ -31,17 +31,17 @@ export class RadialDimension extends BaseCircularDimension {
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* Get sequenced points from user selection
|
|
34
|
-
* @param {any}
|
|
34
|
+
* @param {any} entities
|
|
35
35
|
* @param {Point} textPos
|
|
36
36
|
* @return {Array} array of points
|
|
37
37
|
*/
|
|
38
|
-
static getPointsFromSelection(
|
|
39
|
-
const
|
|
38
|
+
static getPointsFromSelection(entities, textPos) {
|
|
39
|
+
const entity = entities[0];
|
|
40
40
|
const Pt11 = textPos;
|
|
41
41
|
Pt11.sequence = 11;
|
|
42
|
-
const Pt10 =
|
|
42
|
+
const Pt10 = entity.points[0]; // Centre
|
|
43
43
|
Pt10.sequence = 10;
|
|
44
|
-
const Pt15 = Pt10.project(Pt10.angle(Pt11),
|
|
44
|
+
const Pt15 = Pt10.project(Pt10.angle(Pt11), entity.getRadius());// Radius
|
|
45
45
|
Pt15.sequence = 15;
|
|
46
46
|
|
|
47
47
|
const points = [Pt10, Pt15, Pt11];
|
|
@@ -4,7 +4,7 @@ import { Input, PromptOptions } from '../lib/inputManager.js';
|
|
|
4
4
|
import { Logging } from '../lib/logging.js';
|
|
5
5
|
import { DXFFile } from '../lib/dxf/dxfFile.js';
|
|
6
6
|
import { Point } from '../entities/point.js';
|
|
7
|
-
import {
|
|
7
|
+
import { LinearDimensionBase } from './linearDimensionBase.js';
|
|
8
8
|
|
|
9
9
|
import { DesignCore } from '../designCore.js';
|
|
10
10
|
import { Property } from '../properties/property.js';
|
|
@@ -13,9 +13,9 @@ import { RubberBand } from '../lib/auxiliary/rubberBand.js';
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Rotated Dimension Entity Class
|
|
16
|
-
* @extends
|
|
16
|
+
* @extends LinearDimensionBase
|
|
17
17
|
*/
|
|
18
|
-
export class RotatedDimension extends
|
|
18
|
+
export class RotatedDimension extends LinearDimensionBase {
|
|
19
19
|
/**
|
|
20
20
|
* Create an Rotated Dimension
|
|
21
21
|
* @param {Array} data
|
|
@@ -77,20 +77,20 @@ export class RotatedDimension extends BaseLinearDimension {
|
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
79
|
* Get sequenced points from user selection
|
|
80
|
-
* @param {any}
|
|
80
|
+
* @param {any} entities
|
|
81
81
|
* @param {Point} textPos
|
|
82
82
|
* @param {number} angle - rotation angle in degrees (default 0 = horizontal)
|
|
83
83
|
* @return {Array} array of points
|
|
84
84
|
*/
|
|
85
|
-
static getPointsFromSelection(
|
|
85
|
+
static getPointsFromSelection(entities, textPos, angle = 0) {
|
|
86
86
|
const points = [];
|
|
87
|
-
const
|
|
87
|
+
const entity = entities[0];
|
|
88
88
|
|
|
89
|
-
const Pt13 =
|
|
89
|
+
const Pt13 = entity.points[0];
|
|
90
90
|
Pt13.sequence = 13;
|
|
91
91
|
points.push(Pt13);
|
|
92
92
|
|
|
93
|
-
const Pt14 =
|
|
93
|
+
const Pt14 = entity.points[1];
|
|
94
94
|
Pt14.sequence = 14;
|
|
95
95
|
points.push(Pt14);
|
|
96
96
|
|
package/core/entities/arc.js
CHANGED
|
@@ -27,7 +27,7 @@ export class Arc extends Entity {
|
|
|
27
27
|
constructor(data) {
|
|
28
28
|
super(data);
|
|
29
29
|
|
|
30
|
-
// If only the
|
|
30
|
+
// If only the centre point is present, project start/end from named scalar properties.
|
|
31
31
|
// Full-points data (post-execute or post-fromDxf) skips this block entirely.
|
|
32
32
|
if (data && this.points.length < 2) {
|
|
33
33
|
const radius = data.radius ?? 1;
|
|
@@ -73,8 +73,8 @@ export class Arc extends Entity {
|
|
|
73
73
|
* @return {Object}
|
|
74
74
|
*/
|
|
75
75
|
static fromDxf(data) {
|
|
76
|
-
const
|
|
77
|
-
if (!
|
|
76
|
+
const centre = data.points?.[0];
|
|
77
|
+
if (!centre) return data;
|
|
78
78
|
// validate required group codes for points-based arc representation are present
|
|
79
79
|
if (data[40] === undefined || data[50] === undefined || data[51] === undefined) return data;
|
|
80
80
|
|
|
@@ -82,9 +82,9 @@ export class Arc extends Entity {
|
|
|
82
82
|
return {
|
|
83
83
|
...data,
|
|
84
84
|
points: [
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
centre,
|
|
86
|
+
centre.project(Utils.degrees2radians(data[50] ?? 0), radius),
|
|
87
|
+
centre.project(Utils.degrees2radians(data[51] ?? 0), radius),
|
|
88
88
|
],
|
|
89
89
|
direction: data[73] ?? 1,
|
|
90
90
|
};
|
|
@@ -116,16 +116,16 @@ export class Arc extends Entity {
|
|
|
116
116
|
|
|
117
117
|
let pt2;
|
|
118
118
|
while (true) {
|
|
119
|
-
DesignCore.Scene.inputManager.inputPoint = pt; // polar/ortho tracks from
|
|
119
|
+
DesignCore.Scene.inputManager.inputPoint = pt; // polar/ortho tracks from centre on each attempt
|
|
120
120
|
const op2 = new PromptOptions(`${Strings.Input.END} ${Strings.Strings.OR} ${Strings.Input.ANGLE}`, [Input.Type.POINT, Input.Type.NUMBER]);
|
|
121
121
|
pt2 = await DesignCore.Scene.inputManager.requestInput(op2);
|
|
122
122
|
if (pt2 === undefined) return;
|
|
123
123
|
|
|
124
124
|
if (Input.getType(pt2) === Input.Type.POINT) {
|
|
125
|
-
// Must not be same as
|
|
126
|
-
const
|
|
125
|
+
// Must not be same as centre or start
|
|
126
|
+
const centre = this.points[0];
|
|
127
127
|
const start = this.points[1];
|
|
128
|
-
if (pt2.isSame?.(
|
|
128
|
+
if (pt2.isSame?.(centre) || pt2.isSame?.(start)) {
|
|
129
129
|
DesignCore.Core.notify(`${this.type} - ${Strings.Error.INVALIDPOINT}`);
|
|
130
130
|
continue;
|
|
131
131
|
}
|
|
@@ -193,8 +193,8 @@ export class Arc extends Entity {
|
|
|
193
193
|
if (this.points.length >= 2) {
|
|
194
194
|
const mousePoint = DesignCore.Mouse.pointOnScene();
|
|
195
195
|
// const points = [...this.points, mousePoint];
|
|
196
|
-
const
|
|
197
|
-
const endPoint =
|
|
196
|
+
const centre = this.points[0];
|
|
197
|
+
const endPoint = centre.project(centre.angle(mousePoint), this.getProperty(Property.Names.RADIUS));
|
|
198
198
|
if (endPoint.isSame(this.points[1])) return;
|
|
199
199
|
const points = [...this.points, endPoint];
|
|
200
200
|
|
|
@@ -210,22 +210,22 @@ export class Arc extends Entity {
|
|
|
210
210
|
|
|
211
211
|
/**
|
|
212
212
|
* Infer arc direction from three points using cross product
|
|
213
|
-
* @param {Point}
|
|
213
|
+
* @param {Point} centre
|
|
214
214
|
* @param {Point} start
|
|
215
215
|
* @param {Point} end
|
|
216
216
|
* @return {number} 1 for ccw, -1 for cw
|
|
217
217
|
*/
|
|
218
|
-
static #inferDirection(
|
|
218
|
+
static #inferDirection(centre, start, end) {
|
|
219
219
|
// All points must be defined and distinct
|
|
220
|
-
if (!
|
|
220
|
+
if (!centre || !start || !end) {
|
|
221
221
|
return 1; // Default to counterclockwise
|
|
222
222
|
}
|
|
223
|
-
if (
|
|
223
|
+
if (centre.isSame?.(start) || centre.isSame?.(end) || start.isSame?.(end)) {
|
|
224
224
|
return 1;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
const v1 = start.subtract(
|
|
228
|
-
const v2 = end.subtract(
|
|
227
|
+
const v1 = start.subtract(centre);
|
|
228
|
+
const v2 = end.subtract(centre);
|
|
229
229
|
const cross = v1.cross(v2);
|
|
230
230
|
const direction = cross > 0 ? 1 : -1;
|
|
231
231
|
return direction;
|
|
@@ -346,8 +346,8 @@ export class Arc extends Entity {
|
|
|
346
346
|
* @return {Arc}
|
|
347
347
|
*/
|
|
348
348
|
fromPolylinePoints(points) {
|
|
349
|
-
const
|
|
350
|
-
this.points = [
|
|
349
|
+
const centre = points[0].bulgeCentrePoint(points[1]);
|
|
350
|
+
this.points = [centre, new Point(points[0].x, points[0].y), new Point(points.at(-1).x, points.at(-1).y)];
|
|
351
351
|
return this;
|
|
352
352
|
}
|
|
353
353
|
|
|
@@ -415,9 +415,9 @@ export class Arc extends Entity {
|
|
|
415
415
|
closestPoint(P) {
|
|
416
416
|
const startPoint = this.points[1];
|
|
417
417
|
const endPoint = this.points[2];
|
|
418
|
-
const
|
|
418
|
+
const centrePoint = this.points[0];
|
|
419
419
|
|
|
420
|
-
const pnt = P.closestPointOnArc(startPoint, endPoint,
|
|
420
|
+
const pnt = P.closestPointOnArc(startPoint, endPoint, centrePoint, this.getProperty(Property.Names.DIRECTION));
|
|
421
421
|
|
|
422
422
|
if (pnt !== null) {
|
|
423
423
|
const distance = P.distance(pnt);
|
package/core/entities/arctext.js
CHANGED
|
@@ -25,7 +25,7 @@ export class ArcAlignedCharacter {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* @param {string} character - text character
|
|
28
|
-
* @param {Point} position -
|
|
28
|
+
* @param {Point} position - centre mid point of character
|
|
29
29
|
* @param {number} angle - in radians
|
|
30
30
|
* @param {number} height - character height
|
|
31
31
|
* @param {number} width - character width
|
|
@@ -192,10 +192,10 @@ export class ArcAlignedText extends Entity {
|
|
|
192
192
|
dxfCode: 46,
|
|
193
193
|
});
|
|
194
194
|
|
|
195
|
-
// ensure points array has at least one point - the arc
|
|
195
|
+
// ensure points array has at least one point - the arc centre
|
|
196
196
|
if (!this.points.length) {
|
|
197
197
|
this.points = [];
|
|
198
|
-
this.points.push(new Point(0, 0)); //
|
|
198
|
+
this.points.push(new Point(0, 0)); // centre point
|
|
199
199
|
}
|
|
200
200
|
|
|
201
201
|
// DXF Groupcode 50 - Start Angle in degrees
|
|
@@ -225,7 +225,7 @@ export class ArcAlignedText extends Entity {
|
|
|
225
225
|
dxfCode: 71,
|
|
226
226
|
options: () => [{ display: 'Outward', value: 1 }, { display: 'Inward', value: 2 }],
|
|
227
227
|
});
|
|
228
|
-
// DXF Groupcode 72 - 1 = fit to arc, 2 = left align, 3 = right align, 4 =
|
|
228
|
+
// DXF Groupcode 72 - 1 = fit to arc, 2 = left align, 3 = right align, 4 = centre
|
|
229
229
|
this.properties.add(Property.Names.TEXTALIGNMENT, {
|
|
230
230
|
type: Property.Type.LIST,
|
|
231
231
|
value: Property.loadValue([data?.textAlignment, data?.[72]], 4),
|
|
@@ -302,7 +302,7 @@ export class ArcAlignedText extends Entity {
|
|
|
302
302
|
|
|
303
303
|
const selection = await DesignCore.Scene.inputManager.requestInput(op);
|
|
304
304
|
if (selection === undefined) return;
|
|
305
|
-
selectedArc = DesignCore.Scene.entities.get(selection.
|
|
305
|
+
selectedArc = DesignCore.Scene.entities.get(selection.selectedEntityIndex);
|
|
306
306
|
|
|
307
307
|
if (selectedArc instanceof Arc === false) {
|
|
308
308
|
const msg = `${this.type} - ${Strings.Error.INVALIDTYPE}: ${selectedArc.type}`;
|
|
@@ -464,7 +464,7 @@ export class ArcAlignedText extends Entity {
|
|
|
464
464
|
|
|
465
465
|
let string = str.slice(); // make a copy of the string
|
|
466
466
|
|
|
467
|
-
// 1 = fit to arc, 2 = left align, 3 = right align, 4 =
|
|
467
|
+
// 1 = fit to arc, 2 = left align, 3 = right align, 4 = centre
|
|
468
468
|
if (textAlignment === 3) { // right align
|
|
469
469
|
// start at the arc start position and create the text cw around the arc
|
|
470
470
|
stringStartPoint = this.points[0].project(this.startAngle() + startOffsetAngle, radialDistance);
|
|
@@ -492,8 +492,8 @@ export class ArcAlignedText extends Entity {
|
|
|
492
492
|
// build per-character widths for the final (possibly reversed) string
|
|
493
493
|
const charWidths = [...string].map((ch) => Text.getApproximateWidth(ch, height));
|
|
494
494
|
|
|
495
|
-
// build cumulative arc angle offsets from the string start position to each character
|
|
496
|
-
// step between adjacent
|
|
495
|
+
// build cumulative arc angle offsets from the string start position to each character centre
|
|
496
|
+
// step between adjacent centres is the average of their two half-widths plus spacing
|
|
497
497
|
const charOffsetAngles = [0];
|
|
498
498
|
if (textAlignment === 1) { // fit to arc
|
|
499
499
|
if (string.length === 1) {
|
|
@@ -512,7 +512,7 @@ export class ArcAlignedText extends Entity {
|
|
|
512
512
|
charOffsetAngles.push(charOffsetAngles[i] + this.linearToAngular(step * 0.5, radialDistance));
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
-
if (textAlignment === 4) { //
|
|
515
|
+
if (textAlignment === 4) { // centre
|
|
516
516
|
const arcMidPoint = this.points[0].project(this.arcMidAngle(this.startAngle(), this.endAngle()), radialDistance);
|
|
517
517
|
stringStartPoint = arcMidPoint.rotate(this.points[0], charOffsetAngles.at(-1) * 0.5);
|
|
518
518
|
}
|
|
@@ -568,9 +568,9 @@ export class ArcAlignedText extends Entity {
|
|
|
568
568
|
file.writeGroupCode('2', style?.font);
|
|
569
569
|
file.writeGroupCode('3', '');
|
|
570
570
|
file.writeGroupCode('7', this.getProperty(Property.Names.STYLENAME)); // Test style name
|
|
571
|
-
file.writeGroupCode('10', this.points[0].x); // x of arc
|
|
572
|
-
file.writeGroupCode('20', this.points[0].y); // y of arc
|
|
573
|
-
file.writeGroupCode('30', '0.0'); // z of arc
|
|
571
|
+
file.writeGroupCode('10', this.points[0].x); // x of arc centre
|
|
572
|
+
file.writeGroupCode('20', this.points[0].y); // y of arc centre
|
|
573
|
+
file.writeGroupCode('30', '0.0'); // z of arc centre
|
|
574
574
|
file.writeGroupCode('40', this.getProperty(Property.Names.RADIUS));
|
|
575
575
|
file.writeGroupCode('41', this.getProperty(Property.Names.WIDTHFACTOR));
|
|
576
576
|
file.writeGroupCode('42', this.getProperty(Property.Names.HEIGHT));
|
|
@@ -607,7 +607,7 @@ export class ArcAlignedText extends Entity {
|
|
|
607
607
|
snaps(mousePoint, delta) {
|
|
608
608
|
const snaps = [];
|
|
609
609
|
|
|
610
|
-
snaps.push(new SnapPoint(this.points[0], SnapPoint.Type.CENTRE)); // arc
|
|
610
|
+
snaps.push(new SnapPoint(this.points[0], SnapPoint.Type.CENTRE)); // arc centre
|
|
611
611
|
|
|
612
612
|
const ArcAlignedCharacters = this.getArcAlignedCharacters();
|
|
613
613
|
for (const arcAlignedChar of ArcAlignedCharacters) {
|
package/core/entities/circle.js
CHANGED
|
@@ -35,7 +35,7 @@ export class Circle extends Entity {
|
|
|
35
35
|
dxfCode: 40,
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
// Named scalar radius (internal API / named prop) — projects points[1] from
|
|
38
|
+
// Named scalar radius (internal API / named prop) — projects points[1] from centre.
|
|
39
39
|
// Full-points data (post-execute or post-fromDxf) skips this.
|
|
40
40
|
if (data?.radius !== undefined && this.points.length < 2) {
|
|
41
41
|
this.setRadius(data.radius);
|
|
@@ -61,11 +61,11 @@ export class Circle extends Entity {
|
|
|
61
61
|
* @return {Object}
|
|
62
62
|
*/
|
|
63
63
|
static fromDxf(data) {
|
|
64
|
-
const
|
|
65
|
-
if (!
|
|
64
|
+
const centre = data.points?.[0];
|
|
65
|
+
if (!centre || data[40] === undefined) return data;
|
|
66
66
|
return {
|
|
67
67
|
...data,
|
|
68
|
-
points: [
|
|
68
|
+
points: [centre, centre.project(0, data[40])],
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
71
|
|
|
@@ -205,9 +205,9 @@ export class Circle extends Entity {
|
|
|
205
205
|
*/
|
|
206
206
|
fromPolylinePoints(points) {
|
|
207
207
|
if (points.length >= 3 && points[0].isSame(points.at(-1))) {
|
|
208
|
-
const
|
|
209
|
-
const radius =
|
|
210
|
-
this.points = [
|
|
208
|
+
const centre = points[0].bulgeCentrePoint(points[1]);
|
|
209
|
+
const radius = centre.distance(points[0]);
|
|
210
|
+
this.points = [centre, centre.project(0, radius)];
|
|
211
211
|
return this;
|
|
212
212
|
}
|
|
213
213
|
const arc = DesignCore.CommandManager.createNew('Arc', this);
|
package/core/entities/hatch.js
CHANGED
|
@@ -141,7 +141,7 @@ export class Hatch extends Entity {
|
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
const
|
|
144
|
+
const centrePoint = bb.centrePoint;
|
|
145
145
|
const bbXLength = bb.xLength;
|
|
146
146
|
const bbYLength = bb.yLength;
|
|
147
147
|
const s = this.getProperty(Property.Names.SCALE);
|
|
@@ -175,8 +175,8 @@ export class Hatch extends Entity {
|
|
|
175
175
|
|
|
176
176
|
// World-space anchor for this family: bounding-box centre shifted by the
|
|
177
177
|
// pattern line's origin offset (scaled to match the hatch scale).
|
|
178
|
-
const cx =
|
|
179
|
-
const cy =
|
|
178
|
+
const cx = centrePoint.x + patternLine.xOrigin * s;
|
|
179
|
+
const cy = centrePoint.y + patternLine.yOrigin * s;
|
|
180
180
|
|
|
181
181
|
// Bounding-box half-extents in pattern-local (unscaled) space.
|
|
182
182
|
const halfW = bbXLength / (2 * s);
|
|
@@ -390,13 +390,13 @@ export class Hatch extends Entity {
|
|
|
390
390
|
// 10 - X; 20 - Y; 40 - Radius; 50 - Start Angle; 51 - End Angle; 73 - Is Counter Clockwise
|
|
391
391
|
const shapeData = { points: [] };
|
|
392
392
|
|
|
393
|
-
const
|
|
394
|
-
if (
|
|
393
|
+
const centrePoint = points.shift();
|
|
394
|
+
if (centrePoint.sequence !== undefined && centrePoint.sequence !== 10) {
|
|
395
395
|
const msg = 'Invalid point sequence';
|
|
396
396
|
const err = (`${this.type} - ${msg}`);
|
|
397
397
|
throw Error(err);
|
|
398
398
|
}
|
|
399
|
-
shapeData.points.push(
|
|
399
|
+
shapeData.points.push(centrePoint);
|
|
400
400
|
shapeData.radius = this.getDataValue(data, 40);
|
|
401
401
|
shapeData.startAngle = this.getDataValue(data, 50);
|
|
402
402
|
shapeData.endAngle = this.getDataValue(data, 51);
|
|
@@ -482,8 +482,8 @@ export class Hatch extends Entity {
|
|
|
482
482
|
const result = await DesignCore.Scene.inputManager.requestInput(op);
|
|
483
483
|
if (result === undefined) return;
|
|
484
484
|
|
|
485
|
-
const
|
|
486
|
-
const boundary = this.processSelection(
|
|
485
|
+
const selectedEntities = DesignCore.Scene.selectionManager.selectedEntities.slice(0);
|
|
486
|
+
const boundary = this.processSelection(selectedEntities);
|
|
487
487
|
|
|
488
488
|
if (boundary.length) {
|
|
489
489
|
this.setProperty(Property.Names.CHILDENTITIES, boundary);
|
|
@@ -506,8 +506,8 @@ export class Hatch extends Entity {
|
|
|
506
506
|
* Preview the entity during creation
|
|
507
507
|
*/
|
|
508
508
|
preview() {
|
|
509
|
-
const
|
|
510
|
-
const shapes = this.processSelection(
|
|
509
|
+
const selectedEntities = DesignCore.Scene.selectionManager.selectedEntities.slice(0);
|
|
510
|
+
const shapes = this.processSelection(selectedEntities);
|
|
511
511
|
if (shapes.length) {
|
|
512
512
|
DesignCore.Scene.previewEntities.create(this.type, { points: this.points, childEntities: shapes }); // childEntities is passed as plain data here, not via getProperty
|
|
513
513
|
}
|
|
@@ -515,31 +515,31 @@ export class Hatch extends Entity {
|
|
|
515
515
|
|
|
516
516
|
/**
|
|
517
517
|
* Convert the selection to boundary items
|
|
518
|
-
* @param {Array}
|
|
518
|
+
* @param {Array} selectedEntities
|
|
519
519
|
* @return {Array} - Array of boundary items
|
|
520
520
|
*/
|
|
521
|
-
processSelection(
|
|
521
|
+
processSelection(selectedEntities) {
|
|
522
522
|
const selectedchildEntities = [];
|
|
523
523
|
|
|
524
524
|
let iterationPoints = [];
|
|
525
525
|
|
|
526
526
|
// track the last index count to make sure the loop is closed
|
|
527
|
-
let lastIndexCount =
|
|
527
|
+
let lastIndexCount = selectedEntities.length + 1;
|
|
528
528
|
|
|
529
|
-
while (
|
|
530
|
-
if (
|
|
529
|
+
while (selectedEntities.length) {
|
|
530
|
+
if (selectedEntities.length === lastIndexCount) {
|
|
531
531
|
return [];
|
|
532
532
|
}
|
|
533
533
|
|
|
534
|
-
lastIndexCount =
|
|
534
|
+
lastIndexCount = selectedEntities.length;
|
|
535
535
|
|
|
536
|
-
for (let i = 0; i <
|
|
537
|
-
// no points collected - get the first index from selected
|
|
536
|
+
for (let i = 0; i < selectedEntities.length; i++) {
|
|
537
|
+
// no points collected - get the first index from selected entities
|
|
538
538
|
|
|
539
|
-
const currentItem =
|
|
540
|
-
// if the item can't be converted to polyline points, remove from selected
|
|
539
|
+
const currentItem = selectedEntities[i];
|
|
540
|
+
// if the item can't be converted to polyline points, remove from selected entities and go again
|
|
541
541
|
if (typeof currentItem.toPolylinePoints === 'undefined' || currentItem.type === 'Text' || currentItem.type === 'ArcAlignedText') {
|
|
542
|
-
|
|
542
|
+
selectedEntities.splice(i, 1);
|
|
543
543
|
break;
|
|
544
544
|
}
|
|
545
545
|
|
|
@@ -575,8 +575,8 @@ export class Hatch extends Entity {
|
|
|
575
575
|
iterationPoints.push(...currentPoints);
|
|
576
576
|
}
|
|
577
577
|
|
|
578
|
-
// remove the index from selected
|
|
579
|
-
|
|
578
|
+
// remove the index from selected entities
|
|
579
|
+
selectedEntities = selectedEntities.filter((index) => index !== selectedEntities[i]);
|
|
580
580
|
|
|
581
581
|
if (iterationPoints.at(0).isSame(iterationPoints.at(-1))) {
|
|
582
582
|
const shape = new Polyline();
|
|
@@ -635,7 +635,7 @@ export class Hatch extends Entity {
|
|
|
635
635
|
}
|
|
636
636
|
|
|
637
637
|
// Draw the boundary outline when hovered or selected.
|
|
638
|
-
const isSelected = DesignCore.Scene.selectionManager.
|
|
638
|
+
const isSelected = DesignCore.Scene.selectionManager.selectedEntities.includes(this);
|
|
639
639
|
const isHovered = DesignCore.Scene.hoverEntities.indexOf(this) !== -1;
|
|
640
640
|
if (isSelected || isHovered) {
|
|
641
641
|
renderer.setDash([], 0);
|
|
@@ -774,7 +774,7 @@ export class Hatch extends Entity {
|
|
|
774
774
|
const intersect = Intersection.intersectPolylinePolyline(polyline, line);
|
|
775
775
|
const intersects = intersect.points.length;
|
|
776
776
|
// P is inside shape if there is a odd number of intersects
|
|
777
|
-
if (Math.abs(intersects % 2)
|
|
777
|
+
if (Math.abs(intersects % 2) === 1) {
|
|
778
778
|
return true;
|
|
779
779
|
}
|
|
780
780
|
}
|
|
@@ -850,11 +850,11 @@ export class Hatch extends Entity {
|
|
|
850
850
|
const theta = ang - this.points[0].angle(this.points.at(-1));
|
|
851
851
|
|
|
852
852
|
if (theta !== 0) {
|
|
853
|
-
// set rotation
|
|
854
|
-
const
|
|
853
|
+
// set rotation centre
|
|
854
|
+
const centre = this.points[0];
|
|
855
855
|
// apply rotation to child entities points
|
|
856
856
|
hatchChildren.forEach((child) => {
|
|
857
|
-
const rotatedPoints = child.points.map((p) => new Point(p.x, p.y, p.bulge, p.sequence).rotate(
|
|
857
|
+
const rotatedPoints = child.points.map((p) => new Point(p.x, p.y, p.bulge, p.sequence).rotate(centre, theta));
|
|
858
858
|
child.setProperty(Property.Names.POINTS, rotatedPoints);
|
|
859
859
|
});
|
|
860
860
|
|