@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/lib/strings.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* String Class
|
|
4
|
+
* Holds common strings for consistency and translation
|
|
5
|
+
*/
|
|
1
6
|
export class Strings {
|
|
2
|
-
// Error Strings
|
|
7
|
+
// Error Strings
|
|
3
8
|
static Error = {
|
|
4
9
|
ERROR: 'Error',
|
|
5
|
-
FILEOPEN: 'Error
|
|
6
|
-
INPUT: '
|
|
10
|
+
FILEOPEN: 'Error Opening File',
|
|
11
|
+
INPUT: 'Invalid Input',
|
|
7
12
|
INVALIDFILE: 'Invalid File',
|
|
8
13
|
INVALIDDXFFORMAT: 'Invalid DXF Format',
|
|
9
14
|
INVALIDPOINT: 'Invalid Point Data',
|
|
@@ -11,6 +16,15 @@ export class Strings {
|
|
|
11
16
|
INVALIDNUMBER: 'Invalid Number',
|
|
12
17
|
INVALIDTYPE: 'Invalid Type',
|
|
13
18
|
INVALIDINTERSECTTYPE: 'Invalid Intersect Type',
|
|
19
|
+
SELECTION: 'Invalid Selection',
|
|
20
|
+
PARALLELLINES: 'Parallel Lines',
|
|
21
|
+
RADIUSTOOLARGE: 'Radius too large',
|
|
22
|
+
INVALIDCLIPBOARD: 'Invalid Clipboard Data',
|
|
23
|
+
INVALIDBOUNDARY: 'Invalid Boundary Item',
|
|
24
|
+
NONZERO: 'Value must be positive and nonzero',
|
|
25
|
+
MINVALUE: 'Value is too small',
|
|
26
|
+
MAXVALUE: 'Value is too large',
|
|
27
|
+
ZEROLENGTH: 'Cannot define a zero length line',
|
|
14
28
|
};
|
|
15
29
|
|
|
16
30
|
// Warning Strings
|
|
@@ -27,19 +41,43 @@ export class Strings {
|
|
|
27
41
|
CSTYLEDELETE: 'Currently selected style cannot be deleted',
|
|
28
42
|
CANNOTBEDELETED: 'cannot be deleted',
|
|
29
43
|
CANNOTBERENAMED: 'cannot be renamed',
|
|
44
|
+
CANNOTBEACTIONED: 'cannot be actioned',
|
|
45
|
+
COMPLETED: 'completed',
|
|
46
|
+
NOUNDO: 'No actions to undo',
|
|
47
|
+
NOREDO: 'No actions to redo',
|
|
48
|
+
NOTRIM: 'cannot be trimmed',
|
|
49
|
+
NOEXTEND: 'cannot be extended',
|
|
50
|
+
NOFILLET: 'cannot be filleted',
|
|
51
|
+
NOCHAMFER: 'cannot be chamfered',
|
|
52
|
+
NONCONSECUTIVESEGMENTS: 'segments must be consecutive',
|
|
53
|
+
NOTIMPLEMENTED: 'Not Implemented',
|
|
30
54
|
};
|
|
31
55
|
|
|
32
56
|
// Strings
|
|
33
57
|
static Strings = {
|
|
58
|
+
ARC: 'Arc',
|
|
34
59
|
LENGTH: 'Length',
|
|
35
60
|
LINE: 'Line',
|
|
36
61
|
VARIES: 'Varies',
|
|
62
|
+
AND: 'and',
|
|
63
|
+
OR: 'or',
|
|
64
|
+
ITEMS: 'item(s)',
|
|
65
|
+
ADDED: 'added',
|
|
66
|
+
REMOVED: 'removed',
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// colours
|
|
70
|
+
static Colour = {
|
|
71
|
+
BYLAYER: 'ByLayer',
|
|
72
|
+
BYBLOCK: 'ByBlock',
|
|
37
73
|
};
|
|
38
74
|
|
|
39
75
|
// Unicode Symbols
|
|
40
76
|
static Symbol = {
|
|
41
|
-
DIAMETER: '\
|
|
77
|
+
DIAMETER: '\u00D8',
|
|
42
78
|
DEGREE: '\u00B0',
|
|
79
|
+
RADIUS: 'R',
|
|
80
|
+
DELTA: '\u0394',
|
|
43
81
|
};
|
|
44
82
|
|
|
45
83
|
// Input Strings
|
|
@@ -50,17 +88,31 @@ export class Strings {
|
|
|
50
88
|
START: 'Specify start point',
|
|
51
89
|
END: 'Specify end point',
|
|
52
90
|
POINT: 'Specify a point',
|
|
53
|
-
DIMENSION: 'Specify dimension
|
|
91
|
+
DIMENSION: 'Specify dimension position',
|
|
92
|
+
CLOSE: 'Close',
|
|
54
93
|
NEXTPOINT: 'Specify next point',
|
|
55
94
|
RADIUS: 'Specify radius',
|
|
95
|
+
DIAMETER: 'Specify diameter',
|
|
56
96
|
POSITION: 'Specify position',
|
|
57
97
|
HEIGHT: 'Specify height',
|
|
58
98
|
STRING: 'Specify text',
|
|
99
|
+
NAME: 'Specify name',
|
|
59
100
|
OPTION: 'Specify option',
|
|
60
101
|
ANGLE: 'Specify angle',
|
|
61
102
|
ROTATION: 'Specify rotation angle',
|
|
62
103
|
DESTINATION: 'Specify destination',
|
|
104
|
+
DISTANCE: 'Specify offset distance',
|
|
105
|
+
SIDE: 'Specify point on side to offset',
|
|
106
|
+
THROUGHPOINT: 'Specify through point',
|
|
63
107
|
SELECT: 'Select object',
|
|
64
108
|
SELECTIONSET: 'Select Items',
|
|
109
|
+
SOURCE: 'Select source object',
|
|
110
|
+
DESTINATIONSET: 'Select destination object(s)',
|
|
111
|
+
MIRRORFIRST: 'Specify first point of mirror line',
|
|
112
|
+
MIRRORSECOND: 'Specify second point of mirror line',
|
|
113
|
+
ERASESOURCE: 'Erase source objects?',
|
|
114
|
+
SCALEFACTOR: 'Specify scale factor',
|
|
115
|
+
REFERENCELENGTH: 'Specify reference length',
|
|
116
|
+
NEWLENGTH: 'Specify new length',
|
|
65
117
|
};
|
|
66
118
|
};
|
package/core/lib/utils.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
import { Logging } from './logging.js';
|
|
3
|
+
import { Constants } from './constants.js';
|
|
4
|
+
|
|
5
|
+
/** Utils Class */
|
|
1
6
|
export class Utils {
|
|
2
7
|
/**
|
|
3
8
|
* Convert degrees to radians
|
|
4
9
|
* @param {number} degrees
|
|
5
|
-
* @
|
|
10
|
+
* @return {number} angle in radians
|
|
6
11
|
*/
|
|
7
12
|
static degrees2radians(degrees) {
|
|
8
13
|
return degrees * Math.PI / 180;
|
|
@@ -11,7 +16,7 @@ export class Utils {
|
|
|
11
16
|
/**
|
|
12
17
|
* Convert radians to degrees
|
|
13
18
|
* @param {number} radians
|
|
14
|
-
* @
|
|
19
|
+
* @return {number} angle in degrees
|
|
15
20
|
*/
|
|
16
21
|
static radians2degrees(radians) {
|
|
17
22
|
return radians * 180 / Math.PI;
|
|
@@ -20,19 +25,71 @@ export class Utils {
|
|
|
20
25
|
/**
|
|
21
26
|
* Round to 5 decimal places
|
|
22
27
|
* @param {number} number
|
|
23
|
-
* @
|
|
28
|
+
* @return {number} rounded number
|
|
24
29
|
*/
|
|
25
30
|
static round(number) {
|
|
26
|
-
return Number(number.toFixed(
|
|
31
|
+
return Number(Number(number).toFixed(Constants.Precision.DECIMALPLACES));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Sort points by distance to reference point
|
|
36
|
+
* note this mutates the points array
|
|
37
|
+
* @param {Array} points
|
|
38
|
+
* @param {Point} refPoint
|
|
39
|
+
*/
|
|
40
|
+
static sortPointsByDistance(points, refPoint) {
|
|
41
|
+
points.sort((a, b) => {
|
|
42
|
+
const da = (a.x - refPoint.x) ** 2 + (a.y - refPoint.y) ** 2;
|
|
43
|
+
const db = (b.x - refPoint.x) ** 2 + (b.y - refPoint.y) ** 2;
|
|
44
|
+
return da - db; // nearest first
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Sort points around an arc center by angular position.
|
|
50
|
+
* Mutates the points array.
|
|
51
|
+
*
|
|
52
|
+
* @param {Array} points - array of points
|
|
53
|
+
* @param {Point} startPoint - arc start point
|
|
54
|
+
* @param {Point} endPoint - arc end point
|
|
55
|
+
* @param {Point} centerPoint - arc center point
|
|
56
|
+
* @param {number} direction - arc direction (ccw >0, cw <=0)
|
|
57
|
+
*
|
|
58
|
+
*/
|
|
59
|
+
static sortPointsOnArc(points, startPoint, endPoint, centerPoint, direction = 1) {
|
|
60
|
+
if (!Array.isArray(points)) return;
|
|
61
|
+
|
|
62
|
+
const refAngle = direction > 0 ? centerPoint.angle(startPoint) : centerPoint.angle(endPoint);
|
|
63
|
+
const twoPi = Math.PI * 2;
|
|
64
|
+
const normalize = (ang) => ((ang % twoPi) + twoPi) % twoPi;
|
|
65
|
+
|
|
66
|
+
// map points to angles
|
|
67
|
+
const mapped = points.map((point) => {
|
|
68
|
+
const angle = Math.atan2(point.y - centerPoint.y, point.x - centerPoint.x);
|
|
69
|
+
const normalizedAngle = normalize(angle - refAngle);
|
|
70
|
+
return { point, normalizedAngle };
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// sort by angle
|
|
74
|
+
mapped.sort((u, v) => u.normalizedAngle - v.normalizedAngle);
|
|
75
|
+
|
|
76
|
+
// direction: - ccw > 0, cw <= 0
|
|
77
|
+
if (direction <= 0) mapped.reverse();
|
|
78
|
+
|
|
79
|
+
// write back into original array (preserve Point instances)
|
|
80
|
+
for (let i = 0; i < mapped.length; i++) {
|
|
81
|
+
points[i] = mapped[i].point;
|
|
82
|
+
}
|
|
27
83
|
}
|
|
28
84
|
|
|
29
85
|
/**
|
|
30
86
|
* Deep clone object
|
|
31
|
-
* @param {
|
|
32
|
-
* @
|
|
87
|
+
* @param {Object} obj - object to clone
|
|
88
|
+
* @return {Object} - new cloned object
|
|
33
89
|
*/
|
|
34
90
|
static cloneObject(obj) {
|
|
35
91
|
// deep clone obj and all its attributes
|
|
92
|
+
|
|
36
93
|
if (obj === null || typeof obj !== 'object') {
|
|
37
94
|
return obj;
|
|
38
95
|
}
|
|
@@ -42,19 +99,46 @@ export class Utils {
|
|
|
42
99
|
|
|
43
100
|
for (const key of Reflect.ownKeys(obj)) {
|
|
44
101
|
const value = obj[key];
|
|
45
|
-
|
|
102
|
+
try {
|
|
103
|
+
if (Array.isArray(value)) {
|
|
104
|
+
clone[key] = value.map((v) => this.cloneObject(v));
|
|
105
|
+
} else if (value && typeof value === 'object' && typeof value !== 'function') {
|
|
106
|
+
clone[key] = this.cloneObject(value);
|
|
107
|
+
} else {
|
|
108
|
+
clone[key] = value;
|
|
109
|
+
}
|
|
110
|
+
} catch (e) {
|
|
111
|
+
const err = 'Utils.cloneObject - Could not clone property';
|
|
112
|
+
Logging.instance.warn(`${err}:${key} - ${e}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Clear handle so a fresh unique handle is assigned when added to the scene
|
|
117
|
+
if (clone.handle !== undefined) {
|
|
118
|
+
clone.handle = undefined;
|
|
46
119
|
}
|
|
47
120
|
|
|
48
121
|
return clone;
|
|
49
122
|
}
|
|
50
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Calculate area of triangle given 3 points
|
|
126
|
+
* @param {Point} p1
|
|
127
|
+
* @param {Point} p2
|
|
128
|
+
* @param {Point} p3
|
|
129
|
+
* @return {number} area of triangle
|
|
130
|
+
*/
|
|
131
|
+
static areaOfTriangle(p1, p2, p3) {
|
|
132
|
+
return Math.abs((p1.x * (p2.y - p3.y) + p2.x * (p3.y - p1.y) + p3.x * (p1.y - p2.y)) / 2.0);
|
|
133
|
+
}
|
|
134
|
+
|
|
51
135
|
/**
|
|
52
136
|
* Returns a levenshtein edit distance to the input strings
|
|
53
137
|
* The distance represents the minimum number of character edits required to change one string into the other.
|
|
54
138
|
* a lower number suggests the strings are more similar and value of 0 means they are the same.
|
|
55
139
|
* @param {string} a
|
|
56
140
|
* @param {string} b
|
|
57
|
-
* @
|
|
141
|
+
* @return {number} levenshtein edit distance
|
|
58
142
|
* inspired by https://gist.github.com/andrei-m/982927
|
|
59
143
|
*/
|
|
60
144
|
static getLevenshteinDistance(a, b) {
|
|
@@ -67,9 +151,9 @@ export class Utils {
|
|
|
67
151
|
m[0][j] = j;
|
|
68
152
|
if (j === 0) continue;
|
|
69
153
|
m[i][j] = b.charAt(i - 1) == a.charAt(j - 1) ? m[i - 1][j - 1] : Math.min(
|
|
70
|
-
m[i-1][j-1] + 1,
|
|
71
|
-
m[i][j-1] + 1,
|
|
72
|
-
m[i-1][j] + 1,
|
|
154
|
+
m[i - 1][j - 1] + 1,
|
|
155
|
+
m[i][j - 1] + 1,
|
|
156
|
+
m[i - 1][j] + 1,
|
|
73
157
|
);
|
|
74
158
|
}
|
|
75
159
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DXFFile } from '../lib/dxf/dxfFile.js';
|
|
2
|
+
import { Property } from '../properties/property.js';
|
|
3
|
+
|
|
4
|
+
/** Dictionary Class */
|
|
5
|
+
export class Dictionary {
|
|
6
|
+
/**
|
|
7
|
+
* Create a Dictionary
|
|
8
|
+
* @param {Object} data
|
|
9
|
+
*/
|
|
10
|
+
constructor(data) {
|
|
11
|
+
// DXF Groupcode 5 - Handle
|
|
12
|
+
this.handle = Property.loadValue([data?.handle, data?.[5]]);
|
|
13
|
+
this.name = Property.loadValue([data?.name, data?.[3]], '');
|
|
14
|
+
this.duplicateRecordCloning = Property.loadValue([data?.duplicateRecordCloning, data?.[281]], 1);
|
|
15
|
+
this.entries = Property.loadValue([data?.entries], []);
|
|
16
|
+
|
|
17
|
+
// Build entries from DXF group codes 3 (name) and 350 (handle)
|
|
18
|
+
if (!this.entries.length && data?.[3] !== undefined && data?.[350] !== undefined) {
|
|
19
|
+
const names = Array.isArray(data[3]) ? data[3] : [data[3]];
|
|
20
|
+
const handles = Array.isArray(data[350]) ? data[350] : [data[350]];
|
|
21
|
+
|
|
22
|
+
for (let i = 0; i < names.length && i < handles.length; i++) {
|
|
23
|
+
this.entries.push({ 'name': names[i], 'handle': handles[i] });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Write the item to file in the dxf format
|
|
30
|
+
* @param {DXFFile} file
|
|
31
|
+
*/
|
|
32
|
+
dxf(file) {
|
|
33
|
+
file.writeGroupCode('0', 'DICTIONARY', DXFFile.Version.R2000);
|
|
34
|
+
file.writeGroupCode('5', this.handle, DXFFile.Version.R2000);
|
|
35
|
+
file.writeGroupCode('100', 'AcDbDictionary', DXFFile.Version.R2000);
|
|
36
|
+
file.writeGroupCode('281', this.duplicateRecordCloning.toString(), DXFFile.Version.R2000);
|
|
37
|
+
|
|
38
|
+
for (let i = 0; i < this.entries.length; i++) {
|
|
39
|
+
file.writeGroupCode('3', this.entries[i].name, DXFFile.Version.R2000);
|
|
40
|
+
file.writeGroupCode('350', this.entries[i].handle, DXFFile.Version.R2000);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Dictionary } from './dictionary.js';
|
|
2
|
+
import { DesignCore } from '../designCore.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* DictionaryManager Class
|
|
6
|
+
* Manages DXF dictionary objects for the OBJECTS section
|
|
7
|
+
*/
|
|
8
|
+
export class DictionaryManager {
|
|
9
|
+
/** Create a DictionaryManager */
|
|
10
|
+
constructor() {
|
|
11
|
+
this.addStandardItems();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Create the standard dictionary items
|
|
16
|
+
*/
|
|
17
|
+
addStandardItems() {
|
|
18
|
+
// ACAD_GROUP: child dictionary that stores named entity groups (selections)
|
|
19
|
+
this.groupDictionary = new Dictionary({
|
|
20
|
+
'name': 'ACAD_GROUP',
|
|
21
|
+
'handle': DesignCore.HandleManager.next(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Root dictionary with entry pointing to ACAD_GROUP
|
|
25
|
+
this.rootDictionary = new Dictionary({
|
|
26
|
+
'handle': DesignCore.HandleManager.next(),
|
|
27
|
+
'entries': [{ 'name': 'ACAD_GROUP', 'handle': this.groupDictionary.handle }],
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Clear all dictionary items
|
|
33
|
+
*/
|
|
34
|
+
clearItems() {
|
|
35
|
+
this.groupDictionary = undefined;
|
|
36
|
+
this.rootDictionary = undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Add a dictionary item from parsed DXF data
|
|
41
|
+
* @param {Object} data - parsed DICTIONARY object
|
|
42
|
+
*/
|
|
43
|
+
addItem(data) {
|
|
44
|
+
const dictionary = new Dictionary(data);
|
|
45
|
+
DesignCore.HandleManager.checkHandle(dictionary.handle);
|
|
46
|
+
|
|
47
|
+
if (!this.rootDictionary) {
|
|
48
|
+
// The first dictionary is the root dictionary
|
|
49
|
+
this.rootDictionary = dictionary;
|
|
50
|
+
// Only keep entries for dictionaries that Design manages
|
|
51
|
+
const groupEntry = this.rootDictionary.entries.find((entry) => entry.name === 'ACAD_GROUP');
|
|
52
|
+
this.rootDictionary.entries = groupEntry ? [groupEntry] : [];
|
|
53
|
+
} else if (!this.groupDictionary) {
|
|
54
|
+
// Check if this dictionary is the ACAD_GROUP child
|
|
55
|
+
const groupEntry = this.rootDictionary.entries[0];
|
|
56
|
+
if (groupEntry && dictionary.handle === groupEntry.handle) {
|
|
57
|
+
dictionary.name = groupEntry.name;
|
|
58
|
+
this.groupDictionary = dictionary;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Ensure standard dictionary items exist
|
|
65
|
+
*/
|
|
66
|
+
checkItems() {
|
|
67
|
+
if (!this.rootDictionary || !this.groupDictionary) {
|
|
68
|
+
this.addStandardItems();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Write the dictionaries to file in the dxf format
|
|
74
|
+
* @param {DXFFile} file
|
|
75
|
+
*/
|
|
76
|
+
dxf(file) {
|
|
77
|
+
this.rootDictionary.dxf(file);
|
|
78
|
+
this.groupDictionary.dxf(file);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
|
|
2
|
+
/** DimType Class */
|
|
3
|
+
export class DimType {
|
|
4
|
+
/** Create DimType
|
|
5
|
+
* @param {number} dimType - dxf dimType value
|
|
6
|
+
*/
|
|
7
|
+
constructor(dimType=0) {
|
|
8
|
+
// 0 = Rotated, horizontal, or vertical;
|
|
9
|
+
// 1 = Aligned;
|
|
10
|
+
// 2 = Angular;
|
|
11
|
+
// 3 = Diameter;
|
|
12
|
+
// 4 = Radius;
|
|
13
|
+
// 5 = Angular 3 point;
|
|
14
|
+
// 6 = Ordinate;
|
|
15
|
+
// 32 = Indicates that the block reference (group code 2) is referenced by this dimension only
|
|
16
|
+
// 64 = Ordinate type. This is a bit value (bit 7) used only with integer value 6. If set, ordinate is X-type; if not set, ordinate is Y-type
|
|
17
|
+
// 128 = This is a bit value (bit 8) added to the other group 70 values if the dimension text
|
|
18
|
+
|
|
19
|
+
this.dimType = 0;
|
|
20
|
+
this.blockReference = true; // dimType bit 32 - dimension uses a block
|
|
21
|
+
this.xTypeOrdinate = false; // dimType bit 64 - ordinate is X-type
|
|
22
|
+
this.userPositionedText = false; // dimType bit 128 - text is user positioned
|
|
23
|
+
|
|
24
|
+
this.setDimType(dimType);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Check if dimension type is valid
|
|
28
|
+
* @param {number} dimType
|
|
29
|
+
* @return {boolean} true if valid dimension type
|
|
30
|
+
*/
|
|
31
|
+
static isValidDimensionType(dimType) {
|
|
32
|
+
// get the base type
|
|
33
|
+
const baseType = DimType.getBaseType(dimType);
|
|
34
|
+
// check if base type is valid
|
|
35
|
+
return baseType >= 0 && baseType <= 6;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
/** Get Base Type
|
|
40
|
+
* @param {number} dimType
|
|
41
|
+
* @return {number} base dimension type
|
|
42
|
+
*/
|
|
43
|
+
static getBaseType(dimType) {
|
|
44
|
+
// sort the type temporarily
|
|
45
|
+
let baseType = Number(dimType);
|
|
46
|
+
// strip off the bit values
|
|
47
|
+
if ((baseType & 128) !== 0) {
|
|
48
|
+
baseType -= 128;
|
|
49
|
+
};
|
|
50
|
+
if ((baseType & 64) !== 0) {
|
|
51
|
+
baseType -= 64;
|
|
52
|
+
};
|
|
53
|
+
if ((baseType & 32) !== 0) {
|
|
54
|
+
baseType -= 32;
|
|
55
|
+
};
|
|
56
|
+
// return base type
|
|
57
|
+
return baseType;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Get Dimension Type without any flags
|
|
62
|
+
* @return {number}
|
|
63
|
+
*/
|
|
64
|
+
getBaseDimType() {
|
|
65
|
+
return this.dimType;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get Dimension Type with flags
|
|
70
|
+
* @return {number}
|
|
71
|
+
*/
|
|
72
|
+
getDimType() {
|
|
73
|
+
let dimType = this.dimType;
|
|
74
|
+
if (this.blockReference) {
|
|
75
|
+
dimType += 32;
|
|
76
|
+
}
|
|
77
|
+
if (this.xTypeOrdinate) {
|
|
78
|
+
dimType += 64;
|
|
79
|
+
}
|
|
80
|
+
if (this.userPositionedText) {
|
|
81
|
+
dimType += 128;
|
|
82
|
+
}
|
|
83
|
+
return dimType;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Set Dimension Type
|
|
88
|
+
* @param {number} dimType
|
|
89
|
+
*/
|
|
90
|
+
setDimType(dimType) {
|
|
91
|
+
// handle invalid input
|
|
92
|
+
if (!DimType.isValidDimensionType(dimType)) {
|
|
93
|
+
dimType = 0; // default to 0 if invalid
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
this.dimType = DimType.getBaseType(dimType);
|
|
97
|
+
this.blockReference = (dimType & 32) !== 0;
|
|
98
|
+
this.xTypeOrdinate = (dimType & 64) !== 0;
|
|
99
|
+
this.userPositionedText = (dimType & 128) !== 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Check if the dimension has a block reference
|
|
104
|
+
* @return {boolean} true if the dimension has a block reference
|
|
105
|
+
*/
|
|
106
|
+
hasBlockReference() {
|
|
107
|
+
return this.blockReference;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Check if the dimension text is user positioned
|
|
112
|
+
* @return {boolean} true if the dimension text is user positioned
|
|
113
|
+
*/
|
|
114
|
+
hasUserPositionedText() {
|
|
115
|
+
return this.userPositionedText;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** Flags Class */
|
|
2
|
+
export class Flags {
|
|
3
|
+
/** Create Flags */
|
|
4
|
+
constructor() {
|
|
5
|
+
/* flags - bit-coded values
|
|
6
|
+
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
|
|
7
|
+
0 0 0 1 0 0 1 1
|
|
8
|
+
*/
|
|
9
|
+
this.flags = 0;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Set the flag value
|
|
14
|
+
* @param {number} flagValue
|
|
15
|
+
*/
|
|
16
|
+
setFlagValue(flagValue) {
|
|
17
|
+
const value = Number(flagValue);
|
|
18
|
+
if (isNaN(value) === false) {
|
|
19
|
+
this.flags = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get the flag value
|
|
25
|
+
* @return {number} flags value
|
|
26
|
+
*/
|
|
27
|
+
getFlagValue() {
|
|
28
|
+
return this.flags;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get the backwards value
|
|
33
|
+
* @param {number} flagValue
|
|
34
|
+
* @return {boolean} true if flags contains the flagValue
|
|
35
|
+
*/
|
|
36
|
+
hasFlag(flagValue) {
|
|
37
|
+
// check if the flagValue is bitmasked in flags
|
|
38
|
+
// Bitwise AND (&) returns a value where each number has a 1 in the respective bit
|
|
39
|
+
/* Example
|
|
40
|
+
this.flags = 7 (01011)
|
|
41
|
+
flagValue = 3 (0011)
|
|
42
|
+
bits: 16 | 8 | 4 | 2 | 1
|
|
43
|
+
flags: 0 | 0 | 1 | 1 | 1
|
|
44
|
+
flagValue: 0 | 0 | 0 | 1 | 1
|
|
45
|
+
result: 0 | 0 | 0 | 1 | 1
|
|
46
|
+
decimal: 3
|
|
47
|
+
*/
|
|
48
|
+
return Boolean((this.flags & flagValue) === flagValue);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Set the flag value
|
|
53
|
+
* @param {number} flagValue
|
|
54
|
+
*/
|
|
55
|
+
addValue(flagValue) {
|
|
56
|
+
this.flags = (this.flags | Number(flagValue));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Remove the flag value
|
|
61
|
+
* @param {number} flagValue
|
|
62
|
+
*/
|
|
63
|
+
removeValue(flagValue) {
|
|
64
|
+
this.flags = (this.flags ^ (this.flags & flagValue));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Flags } from './flags.js';
|
|
2
|
+
|
|
3
|
+
/** Property Class */
|
|
4
|
+
export class Property {
|
|
5
|
+
/** Create property */
|
|
6
|
+
constructor() { }
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Parse the input values and return a value
|
|
10
|
+
* @param {Array} values - list of values
|
|
11
|
+
* @param {any} def - default value
|
|
12
|
+
* @return {any}
|
|
13
|
+
*/
|
|
14
|
+
static loadValue(values, def) {
|
|
15
|
+
// return any value in values
|
|
16
|
+
for (let i = 0; i < values.length; i++) {
|
|
17
|
+
if (values[i] !== undefined) {
|
|
18
|
+
// check if the value is a flags object
|
|
19
|
+
return (values[i] instanceof Flags) ? values[i].getFlagValue() : values[i];
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// no valid values, return the default value
|
|
24
|
+
return def;
|
|
25
|
+
}
|
|
26
|
+
}
|