@design-core/core 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +4 -0
- package/TODO.md +49 -6
- package/core/core/core.js +0 -3
- package/core/dimensions/alignedDimension.js +5 -4
- package/core/dimensions/angularDimension.js +6 -5
- package/core/dimensions/baseCircularDimension.js +3 -2
- package/core/dimensions/baseDimension.js +59 -93
- package/core/dimensions/baseLinearDimension.js +6 -5
- package/core/dimensions/diametricDimension.js +4 -3
- package/core/dimensions/dimension.js +21 -14
- package/core/dimensions/radialDimension.js +4 -3
- package/core/dimensions/rotatedDimension.js +12 -11
- package/core/entities/arc.js +112 -145
- package/core/entities/arctext.js +212 -174
- package/core/entities/basePolyline.js +33 -284
- package/core/entities/circle.js +77 -99
- package/core/entities/entity.js +114 -93
- package/core/entities/hatch.js +322 -249
- package/core/entities/insert.js +66 -81
- package/core/entities/line.js +21 -142
- package/core/entities/lwpolyline.js +16 -11
- package/core/entities/polyline.js +4 -4
- package/core/entities/rectangle.js +3 -1
- package/core/entities/solid.js +6 -15
- package/core/entities/text.js +188 -199
- package/core/lib/auxiliary/rubberBand.js +32 -0
- package/core/lib/auxiliary/selectionWindow.js +63 -0
- package/core/lib/auxiliary/snapPoint.js +113 -0
- package/core/lib/auxiliary/trackingLine.js +76 -0
- package/core/lib/canvas.js +228 -166
- package/core/lib/clipboard.js +7 -1
- package/core/lib/colour.js +16 -0
- package/core/lib/commandLine.js +1 -6
- package/core/lib/commandManager.js +18 -8
- package/core/lib/constants.js +28 -0
- package/core/lib/dxf/dxf.js +4 -3
- package/core/lib/entityManager.js +18 -11
- package/core/lib/inputManager.js +36 -13
- package/core/lib/intersect.js +25 -0
- package/core/lib/patterns.js +8 -1
- package/core/lib/plotOptions.js +67 -0
- package/core/lib/polylineUtils.js +75 -0
- package/core/lib/renderers/cairoRenderer.js +371 -0
- package/core/lib/renderers/canvasRenderer.js +315 -0
- package/core/lib/renderers/pdfRenderer.js +366 -0
- package/core/lib/renderers/rendererBase.js +284 -0
- package/core/lib/renderers/svgRenderer.js +343 -0
- package/core/lib/scene.js +27 -5
- package/core/lib/selectionManager.js +2 -2
- package/core/lib/settings.js +4 -2
- package/core/lib/snapping.js +4 -191
- package/core/lib/stateManager.js +30 -1
- package/core/lib/utils.js +21 -2
- package/core/properties/entityProperties.js +104 -0
- package/core/properties/property.js +106 -2
- package/core/properties/propertyManager.js +29 -13
- package/core/tables/block.js +4 -37
- package/core/tables/endblk.js +1 -1
- package/core/tables/layer.js +8 -0
- package/core/tables/styleManagerBase.js +3 -2
- package/core/tables/tableManagerBase.js +8 -3
- package/core/tools/chamfer.js +111 -137
- package/core/tools/chamferFilletBase.js +135 -34
- package/core/tools/copy.js +3 -3
- package/core/tools/explode.js +2 -2
- package/core/tools/extend.js +132 -19
- package/core/tools/fillet.js +86 -183
- package/core/tools/matchProp.js +2 -11
- package/core/tools/mirror.js +7 -6
- package/core/tools/move.js +3 -3
- package/core/tools/offset.js +3 -5
- package/core/tools/pasteclip.js +1 -1
- package/core/tools/rotate.js +6 -3
- package/core/tools/scale.js +1 -1
- package/core/tools/trim.js +265 -23
- package/core/tools/zoom.js +1 -1
- package/jest.config.js +6 -0
- package/package.json +5 -3
- package/test/dimensions/alignedDimension.test.js +14 -7
- package/test/dimensions/angularDimension.test.js +6 -6
- package/test/dimensions/baseDimension.test.js +69 -8
- package/test/dimensions/baseLinearDimension.test.js +62 -0
- package/test/dimensions/diametricDimension.test.js +6 -6
- package/test/dimensions/radialDimension.test.js +6 -6
- package/test/dimensions/rotatedDimension.test.js +14 -7
- package/test/entities/arc.test.js +80 -83
- package/test/entities/arctext.test.js +180 -53
- package/test/entities/basePolyline.test.js +129 -2
- package/test/entities/circle.test.js +57 -85
- package/test/entities/entity.test.js +42 -8
- package/test/entities/hatch.test.js +543 -70
- package/test/entities/insert.test.js +96 -1
- package/test/entities/line.test.js +15 -41
- package/test/entities/lwpolyline.test.js +104 -0
- package/test/entities/polyline.test.js +11 -0
- package/test/entities/rectangle.test.js +11 -0
- package/test/entities/solid.test.js +1 -1
- package/test/entities/text.test.js +294 -69
- package/test/integration/exportIntegration.reference.dxf +9 -9
- package/test/integration/exportIntegration.test.js +2 -2
- package/test/integration/intersectionIntegration.test.js +4 -5
- package/test/integration/pdfRendererIntegration.reference.pdf +17709 -0
- package/test/integration/pdfRendererIntegration.test.js +61 -0
- package/test/integration/svgRendererIntegration.reference.svg +3343 -0
- package/test/integration/svgRendererIntegration.test.js +61 -0
- package/test/integration/userInputIntegration.reference.dxf +1165 -105
- package/test/integration/userInputIntegration.test.js +239 -132
- package/test/lib/canvas.test.js +742 -123
- package/test/lib/constants.test.js +27 -0
- package/test/lib/entityManager.test.js +4 -4
- package/test/lib/inputManager.test.js +80 -19
- package/test/lib/intersect.test.js +83 -0
- package/test/lib/plotOptions.test.js +179 -0
- package/test/lib/rubberBand.test.js +84 -0
- package/test/lib/settings.test.js +5 -6
- package/test/lib/snapping.test.js +71 -129
- package/test/lib/stateManager.test.js +7 -7
- package/test/lib/utils.test.js +36 -2
- package/test/properties/entityProperties.test.js +132 -0
- package/test/properties/property.test.js +53 -0
- package/test/properties/propertyManager.test.js +3 -3
- package/test/renderers/canvasRenderer.test.js +317 -0
- package/test/renderers/pdfRenderer.test.js +271 -0
- package/test/renderers/rendererBase.test.js +213 -0
- package/test/renderers/svgRenderer.test.js +326 -0
- package/test/tables/block.test.js +31 -1
- package/test/tables/endblk.test.js +2 -2
- package/test/tables/layer.test.js +30 -0
- package/test/test-helpers/hatchGridRenderer.js +180 -0
- package/test/test-helpers/test-helpers.js +152 -0
- package/test/tools/chamfer.test.js +227 -5
- package/test/tools/chamferFilletBase.test.js +98 -9
- package/test/tools/copy.test.js +2 -2
- package/test/tools/explode.test.js +3 -3
- package/test/tools/extend.test.js +331 -0
- package/test/tools/fillet.test.js +296 -0
- package/test/tools/matchProp.test.js +5 -5
- package/test/tools/mirror.test.js +13 -13
- package/test/tools/offset.test.js +170 -3
- package/test/tools/pasteclip.test.js +5 -5
- package/test/tools/rotate.test.js +32 -2
- package/test/tools/scale.test.js +5 -5
- package/test/tools/trim.test.js +526 -0
- package/test/tools/zoom.test.js +7 -7
- package/core/lib/selectionWindow.js +0 -83
package/core/entities/arctext.js
CHANGED
|
@@ -11,7 +11,7 @@ import { Property } from '../properties/property.js';
|
|
|
11
11
|
import { Text } from './text.js';
|
|
12
12
|
|
|
13
13
|
import { DesignCore } from '../designCore.js';
|
|
14
|
-
import { SnapPoint } from '../lib/
|
|
14
|
+
import { SnapPoint } from '../lib/auxiliary/snapPoint.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Arc Aligned Character Class
|
|
@@ -21,18 +21,21 @@ export class ArcAlignedCharacter {
|
|
|
21
21
|
#position;
|
|
22
22
|
#angle;
|
|
23
23
|
#height;
|
|
24
|
+
#width;
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* @param {string} character - text character
|
|
27
28
|
* @param {Point} position - center mid point of character
|
|
28
29
|
* @param {number} angle - in radians
|
|
29
30
|
* @param {number} height - character height
|
|
31
|
+
* @param {number} width - character width
|
|
30
32
|
*/
|
|
31
|
-
constructor(character, position, angle, height = 1) {
|
|
33
|
+
constructor(character, position, angle, height = 1, width = 1) {
|
|
32
34
|
this.#character = character;
|
|
33
35
|
this.#position = position;
|
|
34
36
|
this.#angle = angle;
|
|
35
37
|
this.#height = height;
|
|
38
|
+
this.#width = width;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
/**
|
|
@@ -67,6 +70,14 @@ export class ArcAlignedCharacter {
|
|
|
67
70
|
return this.#height;
|
|
68
71
|
}
|
|
69
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Get width
|
|
75
|
+
* @return {number}
|
|
76
|
+
*/
|
|
77
|
+
get width() {
|
|
78
|
+
return this.#width;
|
|
79
|
+
}
|
|
80
|
+
|
|
70
81
|
/**
|
|
71
82
|
* Get baseline point
|
|
72
83
|
* @return {Point}
|
|
@@ -83,7 +94,7 @@ export class ArcAlignedCharacter {
|
|
|
83
94
|
*/
|
|
84
95
|
get boundingBox() {
|
|
85
96
|
const halfHeight = this.#height / 2;
|
|
86
|
-
const halfWidth =
|
|
97
|
+
const halfWidth = this.#width / 2;
|
|
87
98
|
const pt1 = new Point(this.position.x - halfWidth, this.position.y - halfHeight);
|
|
88
99
|
const pt2 = new Point(this.position.x + halfWidth, this.position.y + halfHeight);
|
|
89
100
|
return new BoundingBox(pt1, pt2);
|
|
@@ -105,53 +116,81 @@ export class ArcAlignedText extends Entity {
|
|
|
105
116
|
constructor(data) {
|
|
106
117
|
super(data);
|
|
107
118
|
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
enumerable: false,
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
Object.defineProperty(this, 'lineWidth', {
|
|
115
|
-
enumerable: false,
|
|
116
|
-
});
|
|
119
|
+
// lineType and lineWidth not applicable to arc-aligned text
|
|
120
|
+
this.properties.remove(Property.Names.LINETYPE);
|
|
121
|
+
this.properties.remove(Property.Names.LINEWIDTH);
|
|
117
122
|
|
|
118
123
|
// DXF Groupcode 1 - Text String
|
|
119
|
-
this.
|
|
124
|
+
this.properties.add(Property.Names.STRING, {
|
|
125
|
+
type: Property.Type.STRING,
|
|
126
|
+
value: Property.loadValue([data?.string, data?.[1]], ''),
|
|
127
|
+
dxfCode: 1,
|
|
128
|
+
});
|
|
120
129
|
|
|
121
|
-
// DXF Groupcode 2 - Font name
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Object.defineProperty(this, 'fontName', {
|
|
130
|
+
// DXF Groupcode 2 - Font name (derived from style, not user-editable)
|
|
131
|
+
this.properties.add(Property.Names.FONTNAME, {
|
|
132
|
+
type: Property.Type.STRING,
|
|
125
133
|
value: Property.loadValue([data?.fontName, data?.[2]], 'Arial'),
|
|
126
|
-
|
|
134
|
+
dxfCode: 2,
|
|
135
|
+
visible: false,
|
|
127
136
|
});
|
|
128
137
|
|
|
129
138
|
// DXF Groupcode 3
|
|
130
139
|
// not implemented - always empty in acad output
|
|
131
140
|
|
|
132
141
|
// DXF Groupcode 7 - Text style name
|
|
133
|
-
this.
|
|
142
|
+
this.properties.add(Property.Names.STYLENAME, {
|
|
143
|
+
type: Property.Type.LIST,
|
|
144
|
+
value: Property.loadValue([data?.styleName, data?.[7]], 'STANDARD'),
|
|
145
|
+
dxfCode: 7,
|
|
146
|
+
options: () => DesignCore.StyleManager.getItems().map((s) => ({ display: s.name, value: s.name })),
|
|
147
|
+
});
|
|
134
148
|
|
|
135
149
|
// DXF Groupcode 40 - Radius
|
|
136
|
-
this.
|
|
150
|
+
this.properties.add(Property.Names.RADIUS, {
|
|
151
|
+
type: Property.Type.NUMBER,
|
|
152
|
+
value: Property.loadValue([data?.radius, data?.[40]], 10),
|
|
153
|
+
dxfCode: 40,
|
|
154
|
+
});
|
|
137
155
|
|
|
138
156
|
// DXF Groupcode 41 - Width Factor
|
|
139
|
-
|
|
140
|
-
|
|
157
|
+
this.properties.add(Property.Names.WIDTHFACTOR, {
|
|
158
|
+
type: Property.Type.NUMBER,
|
|
141
159
|
value: Property.loadValue([data?.widthFactor, data?.[41]], 1),
|
|
142
|
-
|
|
160
|
+
dxfCode: 41,
|
|
161
|
+
visible: false,
|
|
143
162
|
});
|
|
144
163
|
|
|
145
164
|
// DXF Groupcode 42 - Text Height
|
|
146
|
-
this.
|
|
165
|
+
this.properties.add(Property.Names.HEIGHT, {
|
|
166
|
+
type: Property.Type.NUMBER,
|
|
167
|
+
value: Property.loadValue([data?.height, data?.[42]], 2.5),
|
|
168
|
+
dxfCode: 42,
|
|
169
|
+
});
|
|
147
170
|
// DXF Groupcode 43 - Character Spacing
|
|
148
|
-
this.
|
|
171
|
+
this.properties.add(Property.Names.CHARACTERSPACING, {
|
|
172
|
+
type: Property.Type.NUMBER,
|
|
173
|
+
value: Property.loadValue([data?.characterSpacing, data?.[43]], 0.095),
|
|
174
|
+
dxfCode: 43,
|
|
175
|
+
});
|
|
149
176
|
// DXF Groupcode 44 - Offset from Arc
|
|
150
|
-
this.
|
|
177
|
+
this.properties.add(Property.Names.OFFSETFROMARC, {
|
|
178
|
+
type: Property.Type.NUMBER,
|
|
179
|
+
value: Property.loadValue([data?.offsetFromArc, data?.[44]], 0),
|
|
180
|
+
dxfCode: 44,
|
|
181
|
+
});
|
|
151
182
|
// DXF Groupcode 45 - Offset from right
|
|
152
|
-
this.
|
|
183
|
+
this.properties.add(Property.Names.OFFSETFROMRIGHT, {
|
|
184
|
+
type: Property.Type.NUMBER,
|
|
185
|
+
value: Property.loadValue([data?.offsetFromRight, data?.[45]], 0),
|
|
186
|
+
dxfCode: 45,
|
|
187
|
+
});
|
|
153
188
|
// DXF Groupcode 46 - Offset from left
|
|
154
|
-
this.
|
|
189
|
+
this.properties.add(Property.Names.OFFSETFROMLEFT, {
|
|
190
|
+
type: Property.Type.NUMBER,
|
|
191
|
+
value: Property.loadValue([data?.offsetFromLeft, data?.[46]], 0),
|
|
192
|
+
dxfCode: 46,
|
|
193
|
+
});
|
|
155
194
|
|
|
156
195
|
// ensure points array has at least one point - the arc center
|
|
157
196
|
if (!this.points.length) {
|
|
@@ -162,48 +201,67 @@ export class ArcAlignedText extends Entity {
|
|
|
162
201
|
// DXF Groupcode 50 - Start Angle in degrees
|
|
163
202
|
const startAngle = Utils.round(Property.loadValue([data?.startAngle, data?.[50]], 0));
|
|
164
203
|
if (this.points[1] === undefined) {
|
|
165
|
-
this.points[1] = this.points[0].project(Utils.degrees2radians(startAngle), this.
|
|
204
|
+
this.points[1] = this.points[0].project(Utils.degrees2radians(startAngle), this.getProperty(Property.Names.RADIUS));
|
|
166
205
|
}
|
|
167
206
|
|
|
168
207
|
// DXF Groupcode 51 - End Angle in degrees
|
|
169
208
|
const endAngle = Utils.round(Property.loadValue([data?.endAngle, data?.[51]], 180));
|
|
170
209
|
if (this.points[2] === undefined) {
|
|
171
|
-
this.points[2] = this.points[0].project(Utils.degrees2radians(endAngle), this.
|
|
210
|
+
this.points[2] = this.points[0].project(Utils.degrees2radians(endAngle), this.getProperty(Property.Names.RADIUS));
|
|
172
211
|
}
|
|
173
212
|
|
|
174
213
|
// DXF Groupcode 70 - Text Direction 0 = forward, 1 = reversed
|
|
175
|
-
|
|
176
|
-
|
|
214
|
+
this.properties.add(Property.Names.TEXTREVERSED, {
|
|
215
|
+
type: Property.Type.BOOLEAN,
|
|
177
216
|
value: Property.loadValue([data?.textReversed, Boolean(parseInt(data?.[70]))], false),
|
|
178
|
-
|
|
217
|
+
dxfCode: 70,
|
|
218
|
+
visible: false,
|
|
179
219
|
});
|
|
180
220
|
|
|
181
221
|
// DXF Groupcode 71 - 1 = outward, 2 = inward
|
|
182
|
-
this.
|
|
222
|
+
this.properties.add(Property.Names.TEXTORIENTATION, {
|
|
223
|
+
type: Property.Type.LIST,
|
|
224
|
+
value: Property.loadValue([data?.textOrientation, data?.[71]], 1),
|
|
225
|
+
dxfCode: 71,
|
|
226
|
+
options: () => [{ display: 'Outward', value: 1 }, { display: 'Inward', value: 2 }],
|
|
227
|
+
});
|
|
183
228
|
// DXF Groupcode 72 - 1 = fit to arc, 2 = left align, 3 = right align, 4 = center
|
|
184
|
-
this.
|
|
229
|
+
this.properties.add(Property.Names.TEXTALIGNMENT, {
|
|
230
|
+
type: Property.Type.LIST,
|
|
231
|
+
value: Property.loadValue([data?.textAlignment, data?.[72]], 4),
|
|
232
|
+
dxfCode: 72,
|
|
233
|
+
options: () => [{ display: 'Fit', value: 1 }, { display: 'Left', value: 2 }, { display: 'Right', value: 3 }, { display: 'Center', value: 4 }],
|
|
234
|
+
});
|
|
185
235
|
// DXF Groupcode 73 - Arc Side: convex = 1, concave = 2
|
|
186
|
-
this.
|
|
236
|
+
this.properties.add(Property.Names.ARCSIDE, {
|
|
237
|
+
type: Property.Type.LIST,
|
|
238
|
+
value: Property.loadValue([data?.arcSide, data?.[73]], 1),
|
|
239
|
+
dxfCode: 73,
|
|
240
|
+
options: () => [{ display: 'Convex', value: 1 }, { display: 'Concave', value: 2 }],
|
|
241
|
+
});
|
|
187
242
|
|
|
188
243
|
// DXF Groupcode 74 - Bold 0 = off, 1 = on
|
|
189
|
-
|
|
190
|
-
|
|
244
|
+
this.properties.add(Property.Names.BOLD, {
|
|
245
|
+
type: Property.Type.BOOLEAN,
|
|
191
246
|
value: Property.loadValue([data?.bold, Boolean(parseInt(data?.[74]))], false),
|
|
192
|
-
|
|
247
|
+
dxfCode: 74,
|
|
248
|
+
visible: false,
|
|
193
249
|
});
|
|
194
250
|
|
|
195
251
|
// DXF Groupcode 75 - Italic 0 = off, 1 = on
|
|
196
|
-
|
|
197
|
-
|
|
252
|
+
this.properties.add(Property.Names.ITALIC, {
|
|
253
|
+
type: Property.Type.BOOLEAN,
|
|
198
254
|
value: Property.loadValue([data?.italic, Boolean(parseInt(data?.[75]))], false),
|
|
199
|
-
|
|
255
|
+
dxfCode: 75,
|
|
256
|
+
visible: false,
|
|
200
257
|
});
|
|
201
258
|
|
|
202
259
|
// DXF Groupcode 76 - Underline 0 = off, 1 = on
|
|
203
|
-
|
|
204
|
-
|
|
260
|
+
this.properties.add(Property.Names.UNDERLINE, {
|
|
261
|
+
type: Property.Type.BOOLEAN,
|
|
205
262
|
value: Property.loadValue([data?.underline, Boolean(parseInt(data?.[76]))], false),
|
|
206
|
-
|
|
263
|
+
dxfCode: 76,
|
|
264
|
+
visible: false,
|
|
207
265
|
});
|
|
208
266
|
|
|
209
267
|
// Not Implemented:
|
|
@@ -254,9 +312,9 @@ export class ArcAlignedText extends Entity {
|
|
|
254
312
|
|
|
255
313
|
// Get the arc properties
|
|
256
314
|
// direction: - ccw > 0, cw <= 0
|
|
257
|
-
this.
|
|
258
|
-
const startPoint = selectedArc.
|
|
259
|
-
const endPoint = selectedArc.
|
|
315
|
+
this.setProperty(Property.Names.RADIUS, selectedArc.getProperty(Property.Names.RADIUS));
|
|
316
|
+
const startPoint = selectedArc.getProperty(Property.Names.DIRECTION) > 0 ? selectedArc.points[1] : selectedArc.points[2];
|
|
317
|
+
const endPoint = selectedArc.getProperty(Property.Names.DIRECTION) > 0 ? selectedArc.points[2] : selectedArc.points[1];
|
|
260
318
|
|
|
261
319
|
// set the points
|
|
262
320
|
this.points[0] = new Point(selectedArc.points[0].x, selectedArc.points[0].y);
|
|
@@ -265,26 +323,26 @@ export class ArcAlignedText extends Entity {
|
|
|
265
323
|
|
|
266
324
|
// set the text style to the current style
|
|
267
325
|
const currentStyle = DesignCore.StyleManager.getCstyle();
|
|
268
|
-
this.
|
|
326
|
+
this.setProperty(Property.Names.STYLENAME, currentStyle);
|
|
269
327
|
|
|
270
328
|
// get properties from style
|
|
271
|
-
const style = DesignCore.StyleManager.getItemByName(this.
|
|
329
|
+
const style = DesignCore.StyleManager.getItemByName(this.getProperty(Property.Names.STYLENAME));
|
|
272
330
|
if (style?.textHeight) {
|
|
273
|
-
this.
|
|
331
|
+
this.setProperty(Property.Names.HEIGHT, style.textHeight);
|
|
274
332
|
}
|
|
275
333
|
|
|
276
334
|
// Get the font size when standard style is used
|
|
277
|
-
if (this.
|
|
278
|
-
const op2 = new PromptOptions(Strings.Input.HEIGHT, [Input.Type.NUMBER], [], this.
|
|
335
|
+
if (this.getProperty(Property.Names.STYLENAME).toUpperCase() === 'STANDARD') {
|
|
336
|
+
const op2 = new PromptOptions(Strings.Input.HEIGHT, [Input.Type.NUMBER], [], this.getProperty(Property.Names.HEIGHT));
|
|
279
337
|
const height = await DesignCore.Scene.inputManager.requestInput(op2);
|
|
280
338
|
if (height === undefined) return;
|
|
281
|
-
this.
|
|
339
|
+
this.setProperty(Property.Names.HEIGHT, height);
|
|
282
340
|
}
|
|
283
341
|
|
|
284
342
|
const op4 = new PromptOptions(Strings.Input.STRING, [Input.Type.STRING, Input.Type.NUMBER]);
|
|
285
343
|
const string = await DesignCore.Scene.inputManager.requestInput(op4);
|
|
286
344
|
if (string === undefined) return;
|
|
287
|
-
this.
|
|
345
|
+
this.setProperty(Property.Names.STRING, String(string));
|
|
288
346
|
|
|
289
347
|
DesignCore.Scene.inputManager.executeCommand(this);
|
|
290
348
|
} catch (err) {
|
|
@@ -300,15 +358,15 @@ export class ArcAlignedText extends Entity {
|
|
|
300
358
|
if (DesignCore.Scene.inputManager.promptOption.types.includes(Input.Type.STRING)) {
|
|
301
359
|
const data = {
|
|
302
360
|
points: this.points,
|
|
303
|
-
height: this.
|
|
361
|
+
height: this.getProperty(Property.Names.HEIGHT),
|
|
304
362
|
rotation: this.rotation,
|
|
305
363
|
startAngle: Utils.radians2degrees(this.startAngle()),
|
|
306
364
|
endAngle: Utils.radians2degrees(this.endAngle()),
|
|
307
|
-
radius: this.
|
|
365
|
+
radius: this.getProperty(Property.Names.RADIUS),
|
|
308
366
|
string: DesignCore.CommandLine.command,
|
|
309
367
|
};
|
|
310
368
|
|
|
311
|
-
DesignCore.Scene.
|
|
369
|
+
DesignCore.Scene.previewEntities.create(this.type, data);
|
|
312
370
|
}
|
|
313
371
|
}
|
|
314
372
|
}
|
|
@@ -375,79 +433,96 @@ export class ArcAlignedText extends Entity {
|
|
|
375
433
|
// character positions on arc
|
|
376
434
|
const arcAlignedCharacters = [];
|
|
377
435
|
|
|
378
|
-
|
|
436
|
+
const str = this.getProperty(Property.Names.STRING) ?? '';
|
|
437
|
+
const arcSide = this.getProperty(Property.Names.ARCSIDE);
|
|
438
|
+
const radius = this.getProperty(Property.Names.RADIUS);
|
|
439
|
+
const offsetFromArc = this.getProperty(Property.Names.OFFSETFROMARC);
|
|
440
|
+
const height = this.getProperty(Property.Names.HEIGHT);
|
|
441
|
+
const offsetFromRight = this.getProperty(Property.Names.OFFSETFROMRIGHT);
|
|
442
|
+
const offsetFromLeft = this.getProperty(Property.Names.OFFSETFROMLEFT);
|
|
443
|
+
const textAlignment = this.getProperty(Property.Names.TEXTALIGNMENT);
|
|
444
|
+
const textOrientation = this.getProperty(Property.Names.TEXTORIENTATION);
|
|
445
|
+
const characterSpacing = this.getProperty(Property.Names.CHARACTERSPACING);
|
|
446
|
+
|
|
447
|
+
if (str.length === 0) {
|
|
379
448
|
return arcAlignedCharacters;
|
|
380
449
|
}
|
|
381
450
|
|
|
382
451
|
// calculate the radial distance - Arc Side: convex = 1, concave = 2
|
|
383
|
-
const radialDistance =
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
const
|
|
388
|
-
|
|
389
|
-
const
|
|
390
|
-
// get total charwidth as angle
|
|
391
|
-
let totalCharWidthAsAngle = this.linearToAngular(totalCharWidth*0.5, radialDistance);
|
|
392
|
-
|
|
393
|
-
// calculate start and end offsets
|
|
394
|
-
const startOffsetAngle = this.linearToAngular(this.offsetFromRight, radialDistance) + charWidthAsAngle * 0.5;
|
|
395
|
-
const endOffsetAngle = this.linearToAngular(this.offsetFromLeft, radialDistance) + charWidthAsAngle * 0.5;
|
|
396
|
-
|
|
397
|
-
// total arc angle
|
|
398
|
-
const totalArcAngle = Math.abs(this.endAngle() - this.startAngle()) - startOffsetAngle - endOffsetAngle;
|
|
399
|
-
|
|
400
|
-
// defined positions - Start and end angles +/- half char width
|
|
401
|
-
const startPosition = this.points[0].project(this.startAngle() + startOffsetAngle, radialDistance);
|
|
402
|
-
const endPosition = this.points[0].project(this.endAngle() - endOffsetAngle, radialDistance);
|
|
452
|
+
const radialDistance = arcSide === 2 ? radius - offsetFromArc - height * 0.5 : radius + offsetFromArc + height * 0.5;
|
|
453
|
+
|
|
454
|
+
// calculate start and end offsets using the first and last character widths of the original string
|
|
455
|
+
const firstCharWidth = Text.getApproximateWidth(str[0], height);
|
|
456
|
+
const lastCharWidth = Text.getApproximateWidth(str.at(-1), height);
|
|
457
|
+
const startOffsetAngle = this.linearToAngular(offsetFromRight, radialDistance) + this.linearToAngular(firstCharWidth * 0.5, radialDistance);
|
|
458
|
+
const endOffsetAngle = this.linearToAngular(offsetFromLeft, radialDistance) + this.linearToAngular(lastCharWidth * 0.5, radialDistance);
|
|
403
459
|
|
|
404
460
|
// default to the arc end position as the string start
|
|
405
|
-
let stringStartPoint =
|
|
461
|
+
let stringStartPoint = this.points[0].project(this.endAngle() - endOffsetAngle, radialDistance);
|
|
406
462
|
// direction: - ccw > 0, cw <= 0
|
|
407
463
|
let direction = 1; // default to ccw
|
|
408
464
|
|
|
409
|
-
let string =
|
|
465
|
+
let string = str.slice(); // make a copy of the string
|
|
410
466
|
|
|
411
467
|
// 1 = fit to arc, 2 = left align, 3 = right align, 4 = center
|
|
412
|
-
if (
|
|
413
|
-
totalCharWidthAsAngle = totalArcAngle / (this.string.length - 1);
|
|
414
|
-
}
|
|
415
|
-
if (this.textAlignment === 2) { // left align
|
|
416
|
-
// default
|
|
417
|
-
}
|
|
418
|
-
if (this.textAlignment === 3) { // right align
|
|
468
|
+
if (textAlignment === 3) { // right align
|
|
419
469
|
// start at the arc start position and create the text cw around the arc
|
|
420
|
-
stringStartPoint =
|
|
470
|
+
stringStartPoint = this.points[0].project(this.startAngle() + startOffsetAngle, radialDistance);
|
|
421
471
|
direction = -1;
|
|
422
|
-
string = string.
|
|
423
|
-
}
|
|
424
|
-
if (this.textAlignment === 4) { // center
|
|
425
|
-
const arcMidPoint = this.points[0].project(this.arcMidAngle(this.startAngle(), this.endAngle()), radialDistance);
|
|
426
|
-
stringStartPoint = arcMidPoint.rotate(this.points[0], 0.5 * totalCharWidthAsAngle * (string.length - 1));
|
|
472
|
+
string = [...string].reverse().join('');
|
|
427
473
|
}
|
|
428
474
|
|
|
429
475
|
// calculate the text rotation angle: 1 = outward, 2 = inward
|
|
430
|
-
const textRotationAngle =
|
|
476
|
+
const textRotationAngle = textOrientation === 2 ? -Math.PI*0.5 : Math.PI*0.5;
|
|
431
477
|
|
|
432
|
-
if (
|
|
478
|
+
if (textOrientation === 2) {
|
|
433
479
|
// direction = -direction;
|
|
434
|
-
string = string.
|
|
480
|
+
string = [...string].reverse().join('');
|
|
435
481
|
}
|
|
436
482
|
|
|
437
483
|
/*
|
|
438
484
|
if (this.textReversed === 1) {
|
|
439
485
|
// reverse the string
|
|
440
|
-
string = string.
|
|
486
|
+
string = [...string].reverse().join('');
|
|
441
487
|
// reverse the direction
|
|
442
488
|
direction = -direction;
|
|
443
489
|
}
|
|
444
490
|
*/
|
|
445
491
|
|
|
492
|
+
// build per-character widths for the final (possibly reversed) string
|
|
493
|
+
const charWidths = [...string].map((ch) => Text.getApproximateWidth(ch, height));
|
|
494
|
+
|
|
495
|
+
// build cumulative arc angle offsets from the string start position to each character center
|
|
496
|
+
// step between adjacent centers is the average of their two half-widths plus spacing
|
|
497
|
+
const charOffsetAngles = [0];
|
|
498
|
+
if (textAlignment === 1) { // fit to arc
|
|
499
|
+
if (string.length === 1) {
|
|
500
|
+
// single character: place at arc midpoint — division by zero otherwise
|
|
501
|
+
stringStartPoint = this.points[0].project(this.arcMidAngle(this.startAngle(), this.endAngle()), radialDistance);
|
|
502
|
+
} else {
|
|
503
|
+
const totalArcAngle = Math.abs(this.endAngle() - this.startAngle()) - startOffsetAngle - endOffsetAngle;
|
|
504
|
+
const fitStep = totalArcAngle / (string.length - 1);
|
|
505
|
+
for (let i = 1; i < string.length; i++) {
|
|
506
|
+
charOffsetAngles.push(fitStep * i);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
} else {
|
|
510
|
+
for (let i = 0; i < string.length - 1; i++) {
|
|
511
|
+
const step = (charWidths[i] + charWidths[i + 1]) / 2 + characterSpacing;
|
|
512
|
+
charOffsetAngles.push(charOffsetAngles[i] + this.linearToAngular(step * 0.5, radialDistance));
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (textAlignment === 4) { // center
|
|
516
|
+
const arcMidPoint = this.points[0].project(this.arcMidAngle(this.startAngle(), this.endAngle()), radialDistance);
|
|
517
|
+
stringStartPoint = arcMidPoint.rotate(this.points[0], charOffsetAngles.at(-1) * 0.5);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
446
521
|
// loop through string and calculate position and angle of each character
|
|
447
522
|
for (let index = 0; index < string.length; index++) {
|
|
448
|
-
const charPosition = stringStartPoint.rotate(this.points[0], -
|
|
523
|
+
const charPosition = stringStartPoint.rotate(this.points[0], -charOffsetAngles[index] * direction);
|
|
449
524
|
const charAngle = this.points[0].angle(charPosition) - textRotationAngle;
|
|
450
|
-
const arcChar = new ArcAlignedCharacter(string[index], charPosition, charAngle,
|
|
525
|
+
const arcChar = new ArcAlignedCharacter(string[index], charPosition, charAngle, height, charWidths[index]);
|
|
451
526
|
arcAlignedCharacters.push(arcChar);
|
|
452
527
|
}
|
|
453
528
|
|
|
@@ -455,63 +530,26 @@ export class ArcAlignedText extends Entity {
|
|
|
455
530
|
}
|
|
456
531
|
|
|
457
532
|
/**
|
|
458
|
-
*
|
|
459
|
-
*
|
|
460
|
-
* @
|
|
533
|
+
* Return a character descriptor array for use with renderer.drawText().
|
|
534
|
+
* Coordinates are in scene space (Y-up). The renderer handles the Y-flip.
|
|
535
|
+
* @return {Array}
|
|
461
536
|
*/
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
ctx.selectFontFace(style?.font, null, null); // (FontName, cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL);
|
|
471
|
-
|
|
472
|
-
const ArcAlignedCharacters = this.getArcAlignedCharacters();
|
|
473
|
-
|
|
474
|
-
for (const arcAlignedChar of ArcAlignedCharacters) {
|
|
475
|
-
ctx.save(); // save current context
|
|
476
|
-
ctx.translate(arcAlignedChar.baseline.x, -arcAlignedChar.baseline.y);
|
|
477
|
-
ctx.rotate(-arcAlignedChar.angle);
|
|
478
|
-
ctx.showText(String(arcAlignedChar.character));
|
|
479
|
-
|
|
480
|
-
ctx.stroke();
|
|
481
|
-
ctx.restore(); // restore context
|
|
482
|
-
|
|
483
|
-
/*
|
|
484
|
-
// debug draw character bounding box
|
|
485
|
-
const bb = arcAlignedChar.boundingBox;
|
|
486
|
-
const center = arcAlignedChar.position;
|
|
487
|
-
|
|
488
|
-
const posOne = new Point(center.x - bb.xLength*0.5, center.y - bb.yLength*0.5).rotate(arcAlignedChar.position, arcAlignedChar.angle);
|
|
489
|
-
const posTwo = new Point(center.x + bb.xLength*0.5, center.y - bb.yLength*0.5).rotate(arcAlignedChar.position, arcAlignedChar.angle);
|
|
490
|
-
const posThree = new Point(center.x + bb.xLength*0.5, center.y + bb.yLength*0.5).rotate(arcAlignedChar.position, arcAlignedChar.angle);
|
|
491
|
-
const posFour = new Point(center.x - bb.xLength*0.5, center.y + bb.yLength*0.5).rotate(arcAlignedChar.position, arcAlignedChar.angle);
|
|
492
|
-
|
|
493
|
-
ctx.moveTo(posOne.x, -posOne.y);
|
|
494
|
-
ctx.lineTo(posTwo.x, -posTwo.y);
|
|
495
|
-
ctx.lineTo(posThree.x, -posThree.y);
|
|
496
|
-
ctx.lineTo(posFour.x, -posFour.y);
|
|
497
|
-
ctx.lineTo(posOne.x, -posOne.y);
|
|
498
|
-
ctx.stroke();
|
|
499
|
-
*/
|
|
500
|
-
|
|
501
|
-
/*
|
|
502
|
-
// debug draw the arcText bounding box
|
|
503
|
-
const bb = this.boundingBox();
|
|
504
|
-
ctx.moveTo(bb.xMin, -bb.yMin);
|
|
505
|
-
ctx.lineTo(bb.xMax, -bb.yMin);
|
|
506
|
-
ctx.lineTo(bb.xMax, -bb.yMax);
|
|
507
|
-
ctx.lineTo(bb.xMin, -bb.yMax);
|
|
508
|
-
ctx.lineTo(bb.xMin, -bb.yMin);
|
|
509
|
-
ctx.stroke();
|
|
510
|
-
*/
|
|
511
|
-
}
|
|
537
|
+
toCharacters() {
|
|
538
|
+
return this.getArcAlignedCharacters().map((ch) => ({
|
|
539
|
+
x: ch.baseline.x,
|
|
540
|
+
y: ch.baseline.y,
|
|
541
|
+
rotation: ch.angle,
|
|
542
|
+
char: ch.character,
|
|
543
|
+
}));
|
|
544
|
+
}
|
|
512
545
|
|
|
513
|
-
|
|
514
|
-
|
|
546
|
+
/**
|
|
547
|
+
* Draw the entity
|
|
548
|
+
* @param {Object} renderer
|
|
549
|
+
*/
|
|
550
|
+
draw(renderer) {
|
|
551
|
+
const style = DesignCore.StyleManager.getItemByName(this.getProperty(Property.Names.STYLENAME));
|
|
552
|
+
renderer.drawText(this.toCharacters(), style?.font, this.getProperty(Property.Names.HEIGHT));
|
|
515
553
|
}
|
|
516
554
|
|
|
517
555
|
/**
|
|
@@ -519,36 +557,36 @@ export class ArcAlignedText extends Entity {
|
|
|
519
557
|
* @param {DXFFile} file
|
|
520
558
|
*/
|
|
521
559
|
dxf(file) {
|
|
522
|
-
const style = DesignCore.StyleManager.getItemByName(this.
|
|
560
|
+
const style = DesignCore.StyleManager.getItemByName(this.getProperty(Property.Names.STYLENAME));
|
|
523
561
|
|
|
524
562
|
file.writeGroupCode('0', 'ARCALIGNEDTEXT');
|
|
525
|
-
file.writeGroupCode('5', this.
|
|
563
|
+
file.writeGroupCode('5', this.getProperty(Property.Names.HANDLE), DXFFile.Version.R2000); // Handle
|
|
526
564
|
file.writeGroupCode('100', 'AcDbEntity', DXFFile.Version.R2000);
|
|
527
|
-
file.writeGroupCode('8', this.
|
|
565
|
+
file.writeGroupCode('8', this.getProperty(Property.Names.LAYER));
|
|
528
566
|
file.writeGroupCode('100', 'AcDbArcAlignedText', DXFFile.Version.R2000);
|
|
529
|
-
file.writeGroupCode('1', this.
|
|
567
|
+
file.writeGroupCode('1', this.getProperty(Property.Names.STRING));
|
|
530
568
|
file.writeGroupCode('2', style?.font);
|
|
531
569
|
file.writeGroupCode('3', '');
|
|
532
|
-
file.writeGroupCode('7', this.
|
|
570
|
+
file.writeGroupCode('7', this.getProperty(Property.Names.STYLENAME)); // Test style name
|
|
533
571
|
file.writeGroupCode('10', this.points[0].x); // x of arc center
|
|
534
572
|
file.writeGroupCode('20', this.points[0].y); // y of arc center
|
|
535
573
|
file.writeGroupCode('30', '0.0'); // z of arc center
|
|
536
|
-
file.writeGroupCode('40', this.
|
|
537
|
-
file.writeGroupCode('41', this.
|
|
538
|
-
file.writeGroupCode('42', this.
|
|
539
|
-
file.writeGroupCode('43', this.
|
|
540
|
-
file.writeGroupCode('44', this.
|
|
541
|
-
file.writeGroupCode('45', this.
|
|
542
|
-
file.writeGroupCode('46', this.
|
|
574
|
+
file.writeGroupCode('40', this.getProperty(Property.Names.RADIUS));
|
|
575
|
+
file.writeGroupCode('41', this.getProperty(Property.Names.WIDTHFACTOR));
|
|
576
|
+
file.writeGroupCode('42', this.getProperty(Property.Names.HEIGHT));
|
|
577
|
+
file.writeGroupCode('43', this.getProperty(Property.Names.CHARACTERSPACING));
|
|
578
|
+
file.writeGroupCode('44', this.getProperty(Property.Names.OFFSETFROMARC));
|
|
579
|
+
file.writeGroupCode('45', this.getProperty(Property.Names.OFFSETFROMRIGHT));
|
|
580
|
+
file.writeGroupCode('46', this.getProperty(Property.Names.OFFSETFROMLEFT));
|
|
543
581
|
file.writeGroupCode('50', Utils.radians2degrees(this.startAngle()));
|
|
544
582
|
file.writeGroupCode('51', Utils.radians2degrees(this.endAngle()));
|
|
545
|
-
file.writeGroupCode('70', this.
|
|
546
|
-
file.writeGroupCode('71', this.
|
|
547
|
-
file.writeGroupCode('72', this.
|
|
548
|
-
file.writeGroupCode('73', this.
|
|
549
|
-
file.writeGroupCode('74', this.
|
|
550
|
-
file.writeGroupCode('75', this.
|
|
551
|
-
file.writeGroupCode('76', this.
|
|
583
|
+
file.writeGroupCode('70', this.getProperty(Property.Names.TEXTREVERSED) ? 1 : 0); // Text direction
|
|
584
|
+
file.writeGroupCode('71', this.getProperty(Property.Names.TEXTORIENTATION)); // Text orientation
|
|
585
|
+
file.writeGroupCode('72', this.getProperty(Property.Names.TEXTALIGNMENT)); // Text alignment
|
|
586
|
+
file.writeGroupCode('73', this.getProperty(Property.Names.ARCSIDE)); // Arc side
|
|
587
|
+
file.writeGroupCode('74', this.getProperty(Property.Names.BOLD) ? 1 : 0);
|
|
588
|
+
file.writeGroupCode('75', this.getProperty(Property.Names.ITALIC) ? 1 : 0);
|
|
589
|
+
file.writeGroupCode('76', this.getProperty(Property.Names.UNDERLINE) ? 1 : 0);
|
|
552
590
|
file.writeGroupCode('77', 0);
|
|
553
591
|
file.writeGroupCode('78', 34);
|
|
554
592
|
file.writeGroupCode('79', 0);
|