@design-core/core 0.0.1 → 0.0.3
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 +14 -7
- package/.github/workflows/DesignCoreQA.yml +3 -1
- package/README.md +11 -4
- package/TODO.md +19 -0
- package/core/core/core.js +49 -42
- package/core/designCore.js +61 -2
- package/core/dimensions/alignedDimension.js +142 -0
- package/core/dimensions/angularDimension.js +550 -0
- package/core/dimensions/baseCircularDimension.js +244 -0
- package/core/dimensions/baseDimension.js +558 -0
- package/core/dimensions/baseLinearDimension.js +371 -0
- package/core/dimensions/diametricDimension.js +82 -0
- package/core/dimensions/dimension.js +298 -0
- package/core/dimensions/linearDimension.js +29 -0
- package/core/dimensions/radialDimension.js +78 -0
- package/core/dimensions/rotatedDimension.js +167 -0
- package/core/entities/arc.js +314 -60
- package/core/entities/arctext.js +642 -0
- package/core/entities/basePolyline.js +553 -94
- package/core/entities/circle.js +181 -54
- package/core/entities/entity.js +154 -74
- package/core/entities/hatch.js +807 -0
- package/core/entities/insert.js +200 -39
- package/core/entities/line.js +196 -134
- package/core/entities/lwpolyline.js +21 -44
- package/core/entities/point.js +194 -29
- package/core/entities/polyline.js +54 -7
- package/core/entities/rectangle.js +43 -13
- package/core/entities/solid.js +43 -6
- package/core/entities/text.js +324 -181
- package/core/lib/boundingBox.js +73 -13
- package/core/lib/canvas.js +256 -65
- package/core/lib/clipboard.js +198 -0
- package/core/lib/colour.js +144 -0
- package/core/lib/colours.js +367 -301
- package/core/lib/commandLine.js +16 -28
- package/core/lib/commandManager.js +115 -58
- package/core/lib/constants.js +23 -0
- package/core/lib/dxf/dxf.js +249 -34
- package/core/lib/dxf/dxfFile.js +23 -38
- package/core/lib/dxf/dxfIterator.js +17 -5
- package/core/lib/dxf/dxfRead.js +23 -7
- package/core/lib/dxf/dxfWrite.js +39 -129
- package/core/lib/dxf/handleManager.js +97 -0
- package/core/lib/dxf/sections/blocks.js +16 -2
- package/core/lib/dxf/sections/entities.js +17 -3
- package/core/lib/dxf/sections/header.js +10 -1
- package/core/lib/dxf/sections/objects.js +36 -0
- package/core/lib/dxf/sections/section.js +43 -5
- package/core/lib/dxf/sections/tables.js +17 -3
- package/core/lib/entityManager.js +178 -0
- package/core/lib/fileio.js +14 -4
- package/core/lib/headers.js +229 -0
- package/core/lib/input.js +46 -0
- package/core/lib/inputManager.js +199 -194
- package/core/lib/intersect.js +341 -468
- package/core/lib/logging.js +25 -1
- package/core/lib/matrix.js +6 -8
- package/core/lib/mouse.js +24 -79
- package/core/lib/patterns.js +690 -0
- package/core/lib/promptOptions.js +133 -0
- package/core/lib/scene.js +71 -174
- package/core/lib/selectionManager.js +74 -48
- package/core/lib/selectionWindow.js +24 -10
- package/core/lib/settings.js +18 -11
- package/core/lib/snapping.js +129 -21
- package/core/lib/stateManager.js +288 -0
- package/core/lib/strings.js +57 -5
- package/core/lib/utils.js +95 -11
- package/core/objects/dictionary.js +43 -0
- package/core/objects/dictionaryManager.js +80 -0
- package/core/properties/dimType.js +117 -0
- package/core/properties/flags.js +66 -0
- package/core/properties/property.js +26 -0
- package/core/properties/propertyManager.js +65 -19
- package/core/tables/appId.js +31 -0
- package/core/tables/appIdManager.js +44 -0
- package/core/tables/block.js +323 -0
- package/core/tables/blockManager.js +48 -0
- package/core/tables/blockRecord.js +29 -0
- package/core/tables/blockRecordManager.js +37 -0
- package/core/tables/dimStyle.js +627 -0
- package/core/tables/dimStyleManager.js +187 -0
- package/core/tables/endblk.js +28 -0
- package/core/tables/layer.js +219 -0
- package/core/tables/layerManager.js +47 -0
- package/core/tables/ltype.js +85 -0
- package/core/tables/ltypeManager.js +65 -0
- package/core/tables/style.js +145 -0
- package/core/tables/styleManager.js +55 -0
- package/core/tables/styleManagerBase.js +110 -0
- package/core/tables/tableManagerBase.js +354 -0
- package/core/tables/ucs.js +28 -0
- package/core/tables/ucsManager.js +44 -0
- package/core/tables/view.js +28 -0
- package/core/tables/viewManager.js +44 -0
- package/core/tables/vport.js +70 -0
- package/core/tables/vportManager.js +65 -0
- package/core/tools/chamfer.js +343 -0
- package/core/tools/chamferFilletBase.js +162 -0
- package/core/tools/copy.js +68 -40
- package/core/tools/copybase.js +65 -0
- package/core/tools/copyclip.js +59 -0
- package/core/tools/cornerEntity.js +138 -0
- package/core/tools/cutclip.js +72 -0
- package/core/tools/distance.js +37 -9
- package/core/tools/erase.js +43 -13
- package/core/tools/explode.js +117 -0
- package/core/tools/extend.js +71 -32
- package/core/tools/fillet.js +336 -0
- package/core/tools/identify.js +33 -6
- package/core/tools/matchProp.js +106 -0
- package/core/tools/mirror.js +141 -0
- package/core/tools/move.js +65 -32
- package/core/tools/offset.js +321 -0
- package/core/tools/pan.js +54 -0
- package/core/tools/pasteclip.js +93 -0
- package/core/tools/purge.js +90 -0
- package/core/tools/rotate.js +105 -70
- package/core/tools/scale.js +166 -0
- package/core/tools/tool.js +14 -4
- package/core/tools/trim.js +71 -32
- package/core/tools/zoom.js +152 -0
- package/package.json +3 -305
- package/test/dimensions/alignedDimension.test.js +211 -0
- package/test/dimensions/angularDimension.test.js +243 -0
- package/test/dimensions/baseDimension.test.js +239 -0
- package/test/dimensions/diametricDimension.test.js +203 -0
- package/test/dimensions/dimension.test.js +102 -0
- package/test/dimensions/radialDimension.test.js +203 -0
- package/test/dimensions/rotatedDimension.test.js +224 -0
- package/test/entities/arc.test.js +463 -41
- package/test/entities/arctext.test.js +329 -0
- package/test/entities/basePolyline.test.js +459 -10
- package/test/entities/circle.test.js +312 -7
- package/test/entities/entity.test.js +28 -9
- package/test/entities/hatch.test.js +606 -0
- package/test/entities/insert.test.js +90 -0
- package/test/entities/line.test.js +182 -6
- package/test/entities/point.test.js +375 -37
- package/test/entities/solid.test.js +156 -0
- package/test/entities/text.test.js +533 -7
- package/test/integration/exportIntegration.reference.dxf +1706 -0
- package/test/integration/exportIntegration.test.js +186 -0
- package/test/integration/importExportIntegration.test.js +126 -0
- package/test/integration/intersectionIntegration.test.js +880 -0
- package/test/integration/userInputIntegration.reference.dxf +1410 -0
- package/test/integration/userInputIntegration.test.js +269 -0
- package/test/lib/boundingBox.test.js +26 -2
- package/test/lib/canvas.test.js +613 -5
- package/test/lib/clipboard.test.js +70 -0
- package/test/lib/colour.test.js +114 -0
- package/test/lib/colours.test.js +63 -18
- package/test/lib/commandLine.test.js +159 -22
- package/test/lib/commandManager.test.js +4 -4
- package/test/lib/constants.test.js +9 -0
- package/test/lib/dxf/dxfFile.test.js +6 -2
- package/test/lib/dxf/dxfIterator.test.js +1 -1
- package/test/lib/dxf/dxfWrite.test.js +173 -0
- package/test/lib/dxf/handleManager.test.js +137 -0
- package/test/lib/dxf/sections/blocks.test.js +5 -5
- package/test/lib/dxf/sections/entities.test.js +4 -4
- package/test/lib/dxf/sections/header.test.js +18 -4
- package/test/lib/dxf/sections/objects.test.js +132 -0
- package/test/lib/dxf/sections/section.test.js +29 -29
- package/test/lib/dxf/sections/tables.test.js +3 -3
- package/test/lib/entityManager.test.js +163 -0
- package/test/lib/headers.test.js +233 -0
- package/test/lib/inputManager.test.js +1144 -5
- package/test/lib/intersect.test.js +454 -331
- package/test/lib/logging.test.js +1 -1
- package/test/lib/matrix.test.js +1 -1
- package/test/lib/mouse.test.js +327 -4
- package/test/lib/patterns.test.js +105 -0
- package/test/lib/promptOptions.test.js +179 -0
- package/test/lib/scene.test.js +16 -52
- package/test/lib/selectionManager.test.js +17 -5
- package/test/lib/settings.test.js +111 -5
- package/test/lib/snapping.test.js +142 -4
- package/test/lib/stateManager.test.js +155 -0
- package/test/lib/utils.test.js +81 -1
- package/test/objects/dictionary.test.js +81 -0
- package/test/objects/dictionaryManager.test.js +34 -0
- package/test/properties/dimType.test.js +62 -0
- package/test/properties/flags.test.js +164 -0
- package/test/properties/property.test.js +13 -0
- package/test/properties/propertyManager.test.js +10 -11
- package/test/tables/appId.test.js +46 -0
- package/test/tables/appIdManager.test.js +72 -0
- package/test/tables/block.test.js +157 -0
- package/test/tables/blockManager.test.js +52 -0
- package/test/tables/blockRecord.test.js +39 -0
- package/test/tables/blockRecordManager.test.js +60 -0
- package/test/tables/dimstyle.test.js +72 -0
- package/test/tables/endblk.test.js +30 -0
- package/test/tables/layer.test.js +95 -0
- package/test/tables/layerManager.test.js +172 -0
- package/test/{styles → tables}/ltype.test.js +7 -7
- package/test/{styles → tables}/ltypeManager.test.js +2 -2
- package/test/tables/style.test.js +44 -0
- package/test/tables/stylemanagerbase.test.js +220 -0
- package/test/tables/tableManagerBase.test.js +194 -0
- package/test/tables/ucs.test.js +37 -0
- package/test/tables/ucsManager.test.js +48 -0
- package/test/tables/view.test.js +37 -0
- package/test/tables/viewManager.test.js +48 -0
- package/test/tables/vport.test.js +117 -0
- package/test/tables/vportManager.test.js +54 -0
- package/test/test-helpers/test-helpers.js +66 -0
- package/test/tools/chamfer.test.js +970 -0
- package/test/tools/chamferFilletBase.test.js +446 -0
- package/test/tools/copy.test.js +22 -14
- package/test/tools/copybase.test.js +93 -0
- package/test/tools/copyclip.test.js +92 -0
- package/test/tools/cornerEntity.test.js +201 -0
- package/test/tools/cutclip.test.js +94 -0
- package/test/tools/distance.test.js +140 -18
- package/test/tools/erase.test.js +12 -12
- package/test/tools/explode.test.js +45 -0
- package/test/tools/extend.test.js +326 -44
- package/test/tools/fillet.test.js +831 -0
- package/test/tools/identify.test.js +115 -16
- package/test/tools/matchProp.test.js +84 -0
- package/test/tools/mirror.test.js +475 -0
- package/test/tools/move.test.js +75 -19
- package/test/tools/offset.test.js +748 -0
- package/test/tools/pan.test.js +72 -0
- package/test/tools/pasteclip.test.js +100 -0
- package/test/tools/purge.test.js +89 -0
- package/test/tools/rotate.test.js +89 -23
- package/test/tools/scale.test.js +529 -0
- package/test/tools/trim.test.js +419 -84
- package/test/tools/zoom.test.js +504 -0
- package/core/entities/alignedDimension.js +0 -279
- package/core/entities/angularDimension.js +0 -194
- package/core/entities/baseDimension.js +0 -227
- package/core/entities/block.js +0 -247
- package/core/entities/diametricDimension.js +0 -133
- package/core/entities/dimension.js +0 -202
- package/core/entities/radialDimension.js +0 -126
- package/core/styles/dimStyle.js +0 -719
- package/core/styles/dimStyleManager.js +0 -47
- package/core/styles/layer.js +0 -133
- package/core/styles/layerManager.js +0 -40
- package/core/styles/ltype.js +0 -86
- package/core/styles/ltypeManager.js +0 -50
- package/core/styles/style.js +0 -158
- package/core/styles/styleManager.js +0 -43
- package/core/styles/styleManagerBase.js +0 -299
- package/test/entities/block.test.js +0 -22
- package/test/styles/dimstyle.test.js +0 -19
- package/test/styles/layerManager.test.js +0 -150
- package/test/styles/style.test.js +0 -33
- package/test/styles/stylemanagerbase.test.js +0 -219
package/core/entities/arc.js
CHANGED
|
@@ -1,28 +1,38 @@
|
|
|
1
|
-
import {Point} from './point.js';
|
|
2
|
-
import {Utils} from '../lib/utils.js';
|
|
3
|
-
import {Strings} from '../lib/strings.js';
|
|
4
|
-
import {Entity} from './entity.js';
|
|
5
|
-
import {Input, PromptOptions} from '../lib/inputManager.js';
|
|
6
|
-
import {Logging} from '../lib/logging.js';
|
|
7
|
-
import {DXFFile} from '../lib/dxf/dxfFile.js';
|
|
8
|
-
import {BoundingBox} from '../lib/boundingBox.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { Point } from './point.js';
|
|
2
|
+
import { Utils } from '../lib/utils.js';
|
|
3
|
+
import { Strings } from '../lib/strings.js';
|
|
4
|
+
import { Entity } from './entity.js';
|
|
5
|
+
import { Input, PromptOptions } from '../lib/inputManager.js';
|
|
6
|
+
import { Logging } from '../lib/logging.js';
|
|
7
|
+
import { DXFFile } from '../lib/dxf/dxfFile.js';
|
|
8
|
+
import { BoundingBox } from '../lib/boundingBox.js';
|
|
9
|
+
import { AddState, RemoveState } from '../lib/stateManager.js';
|
|
10
|
+
|
|
11
|
+
import { DesignCore } from '../designCore.js';
|
|
12
|
+
import { Property } from '../properties/property.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Arc Entity Class
|
|
16
|
+
* @extends Entity
|
|
17
|
+
* */
|
|
13
18
|
export class Arc extends Entity {
|
|
19
|
+
/**
|
|
20
|
+
* Create an Arc Entity
|
|
21
|
+
* @param {Array} data
|
|
22
|
+
*/
|
|
14
23
|
constructor(data) {
|
|
15
24
|
super(data);
|
|
16
25
|
this.radius = 1;
|
|
17
26
|
|
|
18
|
-
// direction: - ccw > 0, cw
|
|
27
|
+
// direction: - ccw > 0, cw <= 0
|
|
28
|
+
// default to 1 - counter clockwise
|
|
19
29
|
Object.defineProperty(this, 'direction', {
|
|
20
30
|
value: 1,
|
|
21
31
|
writable: true,
|
|
22
32
|
});
|
|
23
33
|
|
|
24
34
|
if (data) {
|
|
25
|
-
if (data.points || data
|
|
35
|
+
if (data.hasOwnProperty('points') || data.hasOwnProperty('40')) {
|
|
26
36
|
// DXF Groupcode 40 - Radius
|
|
27
37
|
// get the radius from the points or the incoming dxf groupcode
|
|
28
38
|
const radius = this.points[1] ? this.points[0].distance(this.points[1]) : data[40];
|
|
@@ -32,52 +42,106 @@ export class Arc extends Entity {
|
|
|
32
42
|
}
|
|
33
43
|
}
|
|
34
44
|
|
|
35
|
-
if (data.hasOwnProperty('startAngle') || data
|
|
45
|
+
if (data.hasOwnProperty('startAngle') || data.hasOwnProperty('50')) {
|
|
36
46
|
// DXF Groupcode 50 - Start Angle
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
|
|
48
|
+
const angle = Property.loadValue([data.startAngle, data[50]], 0);
|
|
49
|
+
const projectionAngle = Utils.degrees2radians(angle);
|
|
50
|
+
this.points[1] = this.points[0].project(projectionAngle, this.radius);
|
|
39
51
|
}
|
|
40
52
|
|
|
41
|
-
if (data.hasOwnProperty('endAngle') || data
|
|
53
|
+
if (data.hasOwnProperty('endAngle') || data.hasOwnProperty('51')) {
|
|
42
54
|
// DXF Groupcode 51 - End Angle
|
|
43
|
-
const angle =
|
|
44
|
-
|
|
55
|
+
const angle = Property.loadValue([data.endAngle, data[51]], 0);
|
|
56
|
+
const projectionAngle = Utils.degrees2radians(angle);
|
|
57
|
+
this.points[2] = this.points[0].project(projectionAngle, this.radius);
|
|
45
58
|
}
|
|
46
59
|
|
|
47
|
-
if (data.hasOwnProperty('direction')) {
|
|
60
|
+
if (data.hasOwnProperty('direction') || data.hasOwnProperty('73')) {
|
|
48
61
|
// No DXF Groupcode - Arc Direction
|
|
49
|
-
|
|
50
|
-
this.direction = direction;
|
|
62
|
+
this.direction = Property.loadValue([data.direction, data[73]], 1);
|
|
51
63
|
}
|
|
52
64
|
}
|
|
53
65
|
}
|
|
54
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Register the command
|
|
69
|
+
* @return {Object}
|
|
70
|
+
* command = name of the command
|
|
71
|
+
* shortcut = shortcut for the command
|
|
72
|
+
* type = type to group command in toolbars (omitted if not shown)
|
|
73
|
+
*/
|
|
55
74
|
static register() {
|
|
56
|
-
const command = {command: 'Arc', shortcut: 'A', type: 'Entity'};
|
|
75
|
+
const command = { command: 'Arc', shortcut: 'A', type: 'Entity' };
|
|
57
76
|
return command;
|
|
58
77
|
}
|
|
59
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Execute method
|
|
81
|
+
* executes the workflow, requesting input required to create an entity
|
|
82
|
+
*/
|
|
60
83
|
async execute() {
|
|
61
84
|
try {
|
|
62
85
|
const op = new PromptOptions(Strings.Input.CENTER, [Input.Type.POINT]);
|
|
63
86
|
const pt = await DesignCore.Scene.inputManager.requestInput(op);
|
|
87
|
+
if (pt === undefined) return;
|
|
64
88
|
this.points.push(pt);
|
|
65
89
|
|
|
66
90
|
const op1 = new PromptOptions(Strings.Input.START, [Input.Type.POINT]);
|
|
67
91
|
const pt1 = await DesignCore.Scene.inputManager.requestInput(op1);
|
|
92
|
+
if (pt1 === undefined) return;
|
|
68
93
|
this.points.push(pt1);
|
|
69
94
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
95
|
+
let pt2;
|
|
96
|
+
while (true) {
|
|
97
|
+
const op2 = new PromptOptions(`${Strings.Input.END} ${Strings.Strings.OR} ${Strings.Input.ANGLE}`, [Input.Type.POINT, Input.Type.NUMBER]);
|
|
98
|
+
pt2 = await DesignCore.Scene.inputManager.requestInput(op2);
|
|
99
|
+
if (pt2 === undefined) return;
|
|
100
|
+
|
|
101
|
+
if (Input.getType(pt2) === Input.Type.POINT) {
|
|
102
|
+
// Must not be same as center or start
|
|
103
|
+
const center = this.points[0];
|
|
104
|
+
const start = this.points[1];
|
|
105
|
+
if (pt2.isSame?.(center) || pt2.isSame?.(start)) {
|
|
106
|
+
DesignCore.Core.notify(`${this.type} - ${Strings.Error.INVALIDPOINT}`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
this.points.push(pt2);
|
|
110
|
+
// Infer arc direction using cross product if we have 3 points
|
|
111
|
+
if (this.points.length === 3) {
|
|
112
|
+
this.direction = Arc.#inferDirection(this.points[0], this.points[1], this.points[2]);
|
|
113
|
+
// Check total angle > 1 degree
|
|
114
|
+
if (Math.abs(this.totalAngle) <= 1) {
|
|
115
|
+
this.points.pop(); // Remove invalid end point
|
|
116
|
+
DesignCore.Core.notify(`${this.type} - ${Strings.Error.INVALIDNUMBER}: ${Strings.Error.MINVALUE}`);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
break;
|
|
121
|
+
} else if (Input.getType(pt2) === Input.Type.NUMBER) {
|
|
122
|
+
// Must be a valid angle in (0, 360]
|
|
123
|
+
const angleValue = Number(pt2);
|
|
124
|
+
if (!Number.isFinite(angleValue) || Math.abs(angleValue) <= 0 || Math.abs(angleValue) > 360) {
|
|
125
|
+
DesignCore.Core.notify(`${this.type} - ${Strings.Error.INVALIDNUMBER}`);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const basePoint = this.points.at(0);
|
|
129
|
+
const startPoint = this.points.at(1);
|
|
130
|
+
const angle = Utils.degrees2radians(angleValue);
|
|
131
|
+
const point = startPoint.rotate(basePoint, angle);
|
|
132
|
+
this.points.push(point);
|
|
133
|
+
// Set direction based on sign of angle
|
|
134
|
+
this.direction = angle >= 0 ? 1 : -1;
|
|
135
|
+
// Check total angle > 1 degree
|
|
136
|
+
if (Math.abs(this.totalAngle) <= 1) {
|
|
137
|
+
this.points.pop(); // Remove invalid end point
|
|
138
|
+
DesignCore.Core.notify(`${this.type} - ${Strings.Error.INVALIDNUMBER}: ${Strings.Error.MINVALUE}`);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
} else {
|
|
143
|
+
DesignCore.Core.notify(`${this.type} - ${Strings.Error.INPUT}`);
|
|
144
|
+
}
|
|
81
145
|
}
|
|
82
146
|
|
|
83
147
|
DesignCore.Scene.inputManager.executeCommand(this);
|
|
@@ -86,71 +150,258 @@ export class Arc extends Entity {
|
|
|
86
150
|
}
|
|
87
151
|
}
|
|
88
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Preview the entity during creation
|
|
155
|
+
*/
|
|
89
156
|
preview() {
|
|
90
157
|
if (this.points.length >= 1) {
|
|
91
158
|
const mousePoint = DesignCore.Mouse.pointOnScene();
|
|
92
159
|
const points = [this.points.at(0), mousePoint];
|
|
93
|
-
DesignCore.Scene.
|
|
160
|
+
DesignCore.Scene.tempEntities.create('Line', { points: points });
|
|
94
161
|
}
|
|
95
162
|
|
|
96
163
|
if (this.points.length >= 2) {
|
|
97
164
|
const mousePoint = DesignCore.Mouse.pointOnScene();
|
|
98
165
|
const points = [...this.points, mousePoint];
|
|
99
|
-
|
|
166
|
+
|
|
167
|
+
// Infer direction for preview, so it matches what will be created
|
|
168
|
+
let direction = 1;
|
|
169
|
+
if (points.length === 3) {
|
|
170
|
+
direction = Arc.#inferDirection(points[0], points[1], points[2]);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
DesignCore.Scene.tempEntities.create(this.type, { points: points, direction: direction });
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Infer arc direction from three points using cross product
|
|
179
|
+
* @param {Point} center
|
|
180
|
+
* @param {Point} start
|
|
181
|
+
* @param {Point} end
|
|
182
|
+
* @return {number} 1 for ccw, -1 for cw
|
|
183
|
+
*/
|
|
184
|
+
static #inferDirection(center, start, end) {
|
|
185
|
+
// All points must be defined and distinct
|
|
186
|
+
if (!center || !start || !end) {
|
|
187
|
+
return 1; // Default to counterclockwise
|
|
188
|
+
}
|
|
189
|
+
if (center.isSame?.(start) || center.isSame?.(end) || start.isSame?.(end)) {
|
|
190
|
+
return 1;
|
|
100
191
|
}
|
|
192
|
+
|
|
193
|
+
const v1 = start.subtract(center);
|
|
194
|
+
const v2 = end.subtract(center);
|
|
195
|
+
const cross = v1.cross(v2);
|
|
196
|
+
const direction = cross > 0 ? 1 : -1;
|
|
197
|
+
return direction;
|
|
101
198
|
}
|
|
102
199
|
|
|
200
|
+
/**
|
|
201
|
+
* Arc start angle
|
|
202
|
+
* @return {number} start angle in radians
|
|
203
|
+
*/
|
|
103
204
|
startAngle() {
|
|
104
205
|
return this.points[0].angle(this.points[1]);
|
|
105
206
|
}
|
|
106
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Arc end angle
|
|
210
|
+
* @return {number} end angle in radians
|
|
211
|
+
*/
|
|
107
212
|
endAngle() {
|
|
108
|
-
|
|
213
|
+
const endAngle = this.points[0].angle(this.points[2]);
|
|
214
|
+
return endAngle;
|
|
109
215
|
}
|
|
110
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Calculate the angle between the start and end of the arc
|
|
219
|
+
* Clockwise returns positive angle
|
|
220
|
+
* Counter clockwise returns negative
|
|
221
|
+
* @return {number} angle in degrees
|
|
222
|
+
*/
|
|
223
|
+
get totalAngle() {
|
|
224
|
+
let startAngle = this.startAngle();
|
|
225
|
+
let endAngle = this.endAngle();
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
if (this.direction > 0) {
|
|
229
|
+
if (startAngle > endAngle || startAngle === endAngle) {
|
|
230
|
+
endAngle += (Math.PI * 2);
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
startAngle += (Math.PI * 2);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const totalAngle = (startAngle - endAngle);
|
|
237
|
+
return Utils.radians2degrees(totalAngle);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Get Arc radius
|
|
242
|
+
* @return {number} - arc radius
|
|
243
|
+
*/
|
|
111
244
|
getRadius() {
|
|
112
245
|
return this.radius;
|
|
113
246
|
}
|
|
114
247
|
|
|
248
|
+
/**
|
|
249
|
+
* Draw the entity
|
|
250
|
+
* @param {Object} ctx - context
|
|
251
|
+
* @param {number} scale
|
|
252
|
+
*/
|
|
115
253
|
draw(ctx, scale) {
|
|
116
|
-
ctx.arc(this.points[0].x, this.points[0].y, this.radius, this.startAngle(), this.endAngle());
|
|
254
|
+
ctx.arc(this.points[0].x, this.points[0].y, this.radius, this.direction > 0 ? this.startAngle() : this.endAngle(), this.direction > 0 ? this.endAngle() : this.startAngle());
|
|
117
255
|
ctx.stroke();
|
|
118
256
|
}
|
|
119
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Write the entity to file in the dxf format
|
|
260
|
+
* @param {DXFFile} file
|
|
261
|
+
*/
|
|
120
262
|
dxf(file) {
|
|
121
263
|
file.writeGroupCode('0', 'ARC');
|
|
122
|
-
file.writeGroupCode('5',
|
|
264
|
+
file.writeGroupCode('5', this.handle, DXFFile.Version.R2000); // Handle
|
|
123
265
|
file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
|
|
124
266
|
file.writeGroupCode('100', 'AcDbCircle', DXFFile.Version.R2000);
|
|
125
267
|
file.writeGroupCode('8', this.layer); // LAYERNAME
|
|
268
|
+
file.writeGroupCode('6', this.lineType); // LINETYPE
|
|
126
269
|
file.writeGroupCode('10', this.points[0].x); // X
|
|
127
270
|
file.writeGroupCode('20', this.points[0].y); // Y
|
|
128
271
|
file.writeGroupCode('30', '0.0'); // Z
|
|
272
|
+
file.writeGroupCode('39', this.lineWidth); // Line Width
|
|
129
273
|
file.writeGroupCode('40', this.radius); // Radius
|
|
130
274
|
file.writeGroupCode('100', 'AcDbArc', DXFFile.Version.R2000);
|
|
131
|
-
file.writeGroupCode('50', Utils.radians2degrees(this.startAngle())); // Start Angle
|
|
132
|
-
file.writeGroupCode('51', Utils.radians2degrees(this.endAngle())); // End Angle
|
|
275
|
+
file.writeGroupCode('50', Utils.radians2degrees(this.direction > 0 ? this.startAngle() : this.endAngle())); // Start Angle
|
|
276
|
+
file.writeGroupCode('51', Utils.radians2degrees(this.direction > 0 ? this.endAngle() : this.startAngle())); // End Angle
|
|
133
277
|
}
|
|
134
278
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
279
|
+
/**
|
|
280
|
+
* Return a list of points representing a polyline version of this entity
|
|
281
|
+
* @return {Array}
|
|
282
|
+
*/
|
|
283
|
+
toPolylinePoints() {
|
|
284
|
+
// counter clockwise bulge = +ve, clockwise bulge = -ve,
|
|
285
|
+
// ccw arc = 0, clockwise arc = 1
|
|
286
|
+
|
|
287
|
+
// If the arc forms a complete circle
|
|
288
|
+
// Split into two separate polyline arcs
|
|
289
|
+
if (Math.abs(this.totalAngle) === 360) {
|
|
290
|
+
const startPoint = this.points[0].project(0, this.radius);
|
|
291
|
+
startPoint.bulge = 1;
|
|
292
|
+
const endPoint = this.points[0].project(0, -this.radius);
|
|
293
|
+
endPoint.bulge = 1;
|
|
294
|
+
const closurePoint = this.points[0].project(0, this.radius);
|
|
295
|
+
return [startPoint, endPoint, closurePoint];
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const startPoint = this.points[0].project(this.startAngle(), this.radius);
|
|
299
|
+
const bulge = Math.tan(Utils.degrees2radians(-this.totalAngle % 360) / 4);
|
|
300
|
+
startPoint.bulge = bulge;
|
|
301
|
+
const endPoint = this.points[0].project(this.endAngle(), this.radius);
|
|
302
|
+
return [startPoint, endPoint];
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Set entity points from a polyline point representation
|
|
307
|
+
* @param {Array} points
|
|
308
|
+
*/
|
|
309
|
+
fromPolylinePoints(points) {
|
|
310
|
+
const center = points[0].bulgeCentrePoint(points[1]);
|
|
311
|
+
const radius = center.distance(points[0]);
|
|
312
|
+
this.points = [center, new Point(points[0].x, points[0].y), new Point(points[1].x, points[1].y)];
|
|
313
|
+
this.radius = radius;
|
|
143
314
|
}
|
|
144
315
|
|
|
316
|
+
/**
|
|
317
|
+
* Trim the entity
|
|
318
|
+
* @param {Array} intersections
|
|
319
|
+
* @return {Array} - array of state changes
|
|
320
|
+
*/
|
|
321
|
+
trim(intersections) {
|
|
322
|
+
// array to hold state changes
|
|
323
|
+
const stateChanges = [];
|
|
324
|
+
|
|
325
|
+
if (intersections?.length === 0 || !intersections) {
|
|
326
|
+
return stateChanges;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// get the mouse position
|
|
330
|
+
const mousePosition = DesignCore.Mouse.pointOnScene();
|
|
331
|
+
// get the point on the arc closest to the mouse
|
|
332
|
+
const pointOnArc = mousePosition.closestPointOnArc(this.points[1], this.points[2], this.points[0], this.direction);
|
|
333
|
+
// remove any intersections that are at the end points of the arc
|
|
334
|
+
intersections = intersections.filter((p) => !p.isSame(this.points[1]) && !p.isSame(this.points[2]));
|
|
335
|
+
// sort intersection points by distance to start point
|
|
336
|
+
Utils.sortPointsOnArc(intersections, this.points[1], this.points[2], this.points[0], this.direction);
|
|
337
|
+
// Add arc points to the start and the end of the point array
|
|
338
|
+
const testPoints = [this.points[1], ...intersections, this.points[2]];
|
|
339
|
+
|
|
340
|
+
// Test if mouse position is between two intersection points
|
|
341
|
+
if (testPoints.length > 1) {
|
|
342
|
+
for (let i = 0; i < testPoints.length - 1; i++) {
|
|
343
|
+
const startPoint = testPoints[i];
|
|
344
|
+
const endPoint = testPoints[i + 1];
|
|
345
|
+
|
|
346
|
+
// check if the mouse is between startPoint and endPoint
|
|
347
|
+
if (pointOnArc.isOnArc(startPoint, endPoint, this.points[0], this.direction)) {
|
|
348
|
+
// Store new entity points
|
|
349
|
+
const newPoints = [];
|
|
350
|
+
|
|
351
|
+
for (const p of testPoints) {
|
|
352
|
+
const inOriginalArc = this.points.indexOf(p) !== -1;
|
|
353
|
+
const inIntersections = intersections.indexOf(p) !== -1;
|
|
354
|
+
|
|
355
|
+
// Keep points which:
|
|
356
|
+
// - The mouse is between are intersections
|
|
357
|
+
// - The mouse is not between and in this arc
|
|
358
|
+
const isBetween = p.isSame(startPoint) || p.isSame(endPoint);
|
|
359
|
+
if ((isBetween && inIntersections) || (!isBetween && inOriginalArc)) {
|
|
360
|
+
newPoints.push(p);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (newPoints.length % 2 === 0) {
|
|
365
|
+
// Add arcs for each point pair
|
|
366
|
+
for (let j = 0; j < newPoints.length; j += 2) {
|
|
367
|
+
const arc = Utils.cloneObject(this);
|
|
368
|
+
arc.points = [this.points[0], newPoints[j], newPoints[j + 1]];
|
|
369
|
+
const addState = new AddState(arc);
|
|
370
|
+
stateChanges.push(addState);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (stateChanges.length > 0) {
|
|
375
|
+
// Remove the existing arc
|
|
376
|
+
const removeState = new RemoveState(this);
|
|
377
|
+
stateChanges.push(removeState);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return stateChanges;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Get snap points
|
|
388
|
+
* @param {Point} mousePoint
|
|
389
|
+
* @param {number} delta
|
|
390
|
+
* @return {Array} - array of snap points
|
|
391
|
+
*/
|
|
145
392
|
snaps(mousePoint, delta) {
|
|
146
393
|
const snaps = [];
|
|
147
394
|
|
|
148
395
|
if (DesignCore.Settings.endsnap) {
|
|
149
396
|
// Speed this up by generating the proper start and end points when the arc is initialised
|
|
150
|
-
const startPoint = new Point(
|
|
151
|
-
this.points[0].
|
|
152
|
-
|
|
153
|
-
|
|
397
|
+
const startPoint = new Point(
|
|
398
|
+
this.points[0].x + (this.radius * Math.cos(this.startAngle())),
|
|
399
|
+
this.points[0].y + (this.radius * Math.sin(this.startAngle())),
|
|
400
|
+
);
|
|
401
|
+
const endPoint = new Point(
|
|
402
|
+
this.points[0].x + (this.radius * Math.cos(this.endAngle())),
|
|
403
|
+
this.points[0].y + (this.radius * Math.sin(this.endAngle())),
|
|
404
|
+
);
|
|
154
405
|
|
|
155
406
|
snaps.push(startPoint, endPoint);
|
|
156
407
|
}
|
|
@@ -169,17 +420,20 @@ export class Arc extends Entity {
|
|
|
169
420
|
}
|
|
170
421
|
}
|
|
171
422
|
|
|
172
|
-
|
|
173
423
|
return snaps;
|
|
174
424
|
}
|
|
175
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Get closest point on entity
|
|
428
|
+
* @param {Point} P
|
|
429
|
+
* @return {Array} - [Point, distance]
|
|
430
|
+
*/
|
|
176
431
|
closestPoint(P) {
|
|
177
432
|
const startPoint = this.points[1];
|
|
178
433
|
const endPoint = this.points[2];
|
|
179
434
|
const centerPoint = this.points[0];
|
|
180
|
-
|
|
181
|
-
const
|
|
182
|
-
const pnt = P.closestPointOnArc(startPoint, endPoint, centerPoint, direction);
|
|
435
|
+
|
|
436
|
+
const pnt = P.closestPointOnArc(startPoint, endPoint, centerPoint, this.direction);
|
|
183
437
|
|
|
184
438
|
if (pnt !== null) {
|
|
185
439
|
const distance = P.distance(pnt);
|
|
@@ -191,8 +445,8 @@ export class Arc extends Entity {
|
|
|
191
445
|
}
|
|
192
446
|
|
|
193
447
|
/**
|
|
194
|
-
* Return boundingbox
|
|
195
|
-
* @
|
|
448
|
+
* Return boundingbox for entity
|
|
449
|
+
* @return {BoundingBox}
|
|
196
450
|
*/
|
|
197
451
|
boundingBox() {
|
|
198
452
|
return BoundingBox.arcBoundingBox(this.points[0], this.points[1], this.points[2], this.direction);
|