@vitrosoftware/common-ui-ts 1.1.122 → 1.1.124
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/css/std/controls/checkbox/checkbox.css +4 -0
- package/css/std/controls/checkbox/img/checkbox-indeterminate.svg +4 -0
- package/css/std/controls/date-picker/date-picker.css +1 -25
- package/css/std/controls/dxf-viewer/annotation.css +85 -0
- package/css/std/controls/dxf-viewer/common.css +24 -0
- package/css/std/controls/dxf-viewer/dxf-viewer-index.css +14081 -0
- package/css/std/controls/dxf-viewer/dxf-viewer.css +194 -0
- package/css/std/controls/dxf-viewer/img/cancel-dark-grey.svg +5 -0
- package/css/std/controls/dxf-viewer/img/collapse-bottom.svg +5 -0
- package/css/std/controls/dxf-viewer/img/collapse-up-blue.svg +5 -0
- package/css/std/controls/dxf-viewer/img/delete-active.svg +11 -0
- package/css/std/controls/dxf-viewer/img/delete.svg +11 -0
- package/css/std/controls/dxf-viewer/img/draw-annotation.svg +3 -0
- package/css/std/controls/dxf-viewer/img/invisible-eye.svg +4 -0
- package/css/std/controls/dxf-viewer/img/show-annotation.svg +3 -0
- package/css/std/controls/dxf-viewer/img/sidebar-layers-toggle.svg +6 -0
- package/css/std/controls/dxf-viewer/img/sidebar-notes-toggle.svg +5 -0
- package/css/std/controls/dxf-viewer/img/sidebar-resizer.svg +6 -0
- package/css/std/controls/dxf-viewer/img/sidebar-toggle.svg +7 -0
- package/css/std/controls/dxf-viewer/img/visible-eye.svg +4 -0
- package/css/std/controls/dxf-viewer/img/zoom-in.svg +6 -0
- package/css/std/controls/dxf-viewer/img/zoom-out.svg +5 -0
- package/css/std/controls/dxf-viewer/layer-list.css +104 -0
- package/css/std/controls/dxf-viewer/panel.css +34 -0
- package/css/std/controls/dxf-viewer/prop-inspector.css +102 -0
- package/css/std/controls/dxf-viewer/select.css +111 -0
- package/css/std/controls/dxf-viewer/sidebar.css +190 -0
- package/css/std/controls/dxf-viewer/thumbnail-list.css +65 -0
- package/css/std/controls/dxf-viewer/toolbar.css +117 -0
- package/css/std/controls/dxf-viewer/treeview.css +3 -0
- package/css/std/controls/dxf-viewer/treeview.panel.css +108 -0
- package/css/std/controls/error-message/error-message.css +22 -0
- package/css/std/controls/image-picker/image-picker.css +0 -26
- package/css/std/controls/input/input.css +1 -24
- package/css/std/controls/issue-tile/issue-tile-header.css +1 -0
- package/css/std/controls/login/ntlm-authentication-form.css +9 -12
- package/css/std/controls/lookup-picker/lookup-picker-value-list.css +38 -2
- package/css/std/controls/lookup-picker/lookup-picker.css +1 -25
- package/css/std/controls/table-view/treegrid-context-menu.css +44 -18
- package/css/std/controls/table-view/treegrid-message.css +4 -4
- package/css/std/controls/time-picker/time-picker.css +1 -25
- package/dist/index.css +81 -143
- package/dist/index.js +15137 -489
- package/dist/index.js.map +1 -1
- package/dist/src/controls/Checkbox/Checkbox.d.ts +1 -0
- package/dist/src/controls/DxfViewer/DxfViewer.d.ts +6 -0
- package/dist/src/controls/DxfViewer/DxfViewerContext.d.ts +31 -0
- package/dist/src/controls/DxfViewer/Layer.d.ts +9 -0
- package/dist/src/controls/DxfViewer/LayerList.d.ts +11 -0
- package/dist/src/controls/DxfViewer/Thumbnail.d.ts +7 -0
- package/dist/src/controls/DxfViewer/ThumbnailList.d.ts +6 -0
- package/dist/src/controls/DxfViewer/Viewer.d.ts +6 -0
- package/dist/src/controls/ErrorMessage/ErrorMessage.d.ts +6 -0
- package/dist/src/controls/Login/FormRef.d.ts +3 -0
- package/dist/src/controls/Login/LoginConstants.d.ts +2 -1
- package/dist/src/controls/Login/LoginFormRef.d.ts +2 -2
- package/dist/src/controls/Login/NTLMAuthenticationForm.d.ts +5 -2
- package/dist/src/controls/LookupPicker/LookupPicker.d.ts +2 -0
- package/dist/src/controls/LookupPicker/ValueList.d.ts +2 -0
- package/dist/src/controls/TableView/TableViewConstants.d.ts +11 -0
- package/dist/src/controls/TableView/TreeGridTableViewContextImpl.d.ts +1 -0
- package/dist/src/controls/TreeView/TreeView.d.ts +4 -0
- package/dist/src/controls/TreeView/TreeViewConfig.d.ts +3 -0
- package/dist/src/controls/TreeView/TreeViewConstants.d.ts +2 -1
- package/dist/src/index.d.ts +7 -1
- package/lib/dxf-viewer/BatchingKey.js +91 -0
- package/lib/dxf-viewer/DxfFetcher.js +39 -0
- package/lib/dxf-viewer/DxfScene.js +2695 -0
- package/lib/dxf-viewer/DxfViewer.js +1056 -0
- package/lib/dxf-viewer/DxfWorker.js +229 -0
- package/lib/dxf-viewer/DynamicBuffer.js +100 -0
- package/lib/dxf-viewer/HatchCalculator.js +345 -0
- package/lib/dxf-viewer/LinearDimension.js +323 -0
- package/lib/dxf-viewer/MTextFormatParser.js +211 -0
- package/lib/dxf-viewer/MaterialKey.js +37 -0
- package/lib/dxf-viewer/OrbitControls.js +1253 -0
- package/lib/dxf-viewer/Pattern.js +94 -0
- package/lib/dxf-viewer/RBTree.js +471 -0
- package/lib/dxf-viewer/TextRenderer.js +1038 -0
- package/lib/dxf-viewer/index.js +42 -0
- package/lib/dxf-viewer/math/Matrix2.js +77 -0
- package/lib/dxf-viewer/math/utils.js +59 -0
- package/lib/dxf-viewer/parser/AutoCadColorIndex.js +265 -0
- package/lib/dxf-viewer/parser/DimStyleCodes.js +33 -0
- package/lib/dxf-viewer/parser/DxfArrayScanner.js +143 -0
- package/lib/dxf-viewer/parser/DxfParser.js +980 -0
- package/lib/dxf-viewer/parser/ExtendedDataParse-My.js +91 -0
- package/lib/dxf-viewer/parser/ExtendedDataParser.js +123 -0
- package/lib/dxf-viewer/parser/ParseHelpers.js +142 -0
- package/lib/dxf-viewer/parser/entities/3dface.js +83 -0
- package/lib/dxf-viewer/parser/entities/arc.js +38 -0
- package/lib/dxf-viewer/parser/entities/attdef.js +89 -0
- package/lib/dxf-viewer/parser/entities/attrib.js +34 -0
- package/lib/dxf-viewer/parser/entities/attribute.js +109 -0
- package/lib/dxf-viewer/parser/entities/circle.js +43 -0
- package/lib/dxf-viewer/parser/entities/dimension.js +72 -0
- package/lib/dxf-viewer/parser/entities/ellipse.js +46 -0
- package/lib/dxf-viewer/parser/entities/hatch.js +343 -0
- package/lib/dxf-viewer/parser/entities/insert.js +62 -0
- package/lib/dxf-viewer/parser/entities/leader.js +84 -0
- package/lib/dxf-viewer/parser/entities/line.js +34 -0
- package/lib/dxf-viewer/parser/entities/lwpolyline.js +100 -0
- package/lib/dxf-viewer/parser/entities/mtext.js +54 -0
- package/lib/dxf-viewer/parser/entities/point.js +35 -0
- package/lib/dxf-viewer/parser/entities/polyline.js +92 -0
- package/lib/dxf-viewer/parser/entities/solid.js +40 -0
- package/lib/dxf-viewer/parser/entities/spline.js +70 -0
- package/lib/dxf-viewer/parser/entities/text.js +47 -0
- package/lib/dxf-viewer/parser/entities/vertex.js +62 -0
- package/lib/dxf-viewer/parser/entities/viewport.js +56 -0
- package/lib/dxf-viewer/parser/objects/dictionary.js +29 -0
- package/lib/dxf-viewer/parser/objects/layout.js +35 -0
- package/lib/dxf-viewer/parser/objects/xrecord.js +29 -0
- package/lib/opentype/opentype.module.js +14571 -0
- package/lib/three/CSS2DRenderer.js +235 -0
- package/lib/three/three.module.js +49912 -0
- package/package.json +12 -10
- package/src/controls/BimViewer/js/bim-viewer.js +2 -2
- package/src/controls/DxfViewer/js/dxf-viewer.js +3580 -0
- package/src/controls/PdfViewer/js/pdf-viewer.js +1 -1
- package/css/std/controls/input/img/error-message.svg +0 -6
- package/css/std/controls/lookup-picker/img/error-message.svg +0 -6
- package/css/std/controls/time-picker/img/error-message.svg +0 -6
- /package/css/std/controls/{date-picker → error-message}/img/error-message.svg +0 -0
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { Matrix3, Vector2 } from "/resource/dxfViewer/js/three/three.module.js"
|
|
2
|
+
import { ParseSpecialChars } from "./TextRenderer.js"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @property {{color: ?number, start: Vector2, end: Vector2}[]} lines
|
|
6
|
+
* @property {{color: ?number, vertices: Vector2[]}[], indices: number[]} triangles On or more
|
|
7
|
+
* triangles in each item.
|
|
8
|
+
* @property {{text: string, size: number, angle: number, color: number, position: Vector2}[]} texts
|
|
9
|
+
* Each item position is specified as middle point of the rendered text.
|
|
10
|
+
*/
|
|
11
|
+
export class DimensionLayout {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.lines = []
|
|
14
|
+
this.triangles = []
|
|
15
|
+
this.texts = []
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
AddLine(start, end, color = null) {
|
|
19
|
+
this.lines.push({ start, end, color })
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Add one or more triangles. */
|
|
23
|
+
AddTriangles(vertices, indices, color = null) {
|
|
24
|
+
this.triangles.push({ vertices, indices, color })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
AddText(text, size, angle, color, position) {
|
|
28
|
+
this.texts.push({ text, size, angle, color, position })
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const arrowHeadShape = {
|
|
33
|
+
vertices: [
|
|
34
|
+
new Vector2(0, 0),
|
|
35
|
+
new Vector2(1, -0.25),
|
|
36
|
+
new Vector2(1, 0.25)
|
|
37
|
+
],
|
|
38
|
+
indices: [0, 1, 2]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Encapsulates all calculations about linear dimensions layout. */
|
|
42
|
+
export class LinearDimension {
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @typedef LinearDimensionParams
|
|
46
|
+
* @property {Vector2} p1 First definition point.
|
|
47
|
+
* @property {Vector2} p2 Second definition point.
|
|
48
|
+
* @property {Vector2} anchor Anchor point defines dimension line location.
|
|
49
|
+
* @property {?number} angle Rotation angle for rotated dimension, deg.
|
|
50
|
+
* @property {boolean} isAligned Dimension line is parallel to base line for aligned dimension.
|
|
51
|
+
* @property {?string} text Dimension text pattern.
|
|
52
|
+
* @property {?Vector2} textAnchor Text location (middle point) override.
|
|
53
|
+
* @property {?number} textRotation Rotation angle of the dimension text away from its default
|
|
54
|
+
* orientation (the direction of the dimension line)
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @param {LinearDimensionParams} params
|
|
59
|
+
* @param {Function<any(string)>} styleResolver Provides value for a requested style parameter.
|
|
60
|
+
* @param {Function<number(string, number)>} textWidthCalculator Get text width in model space
|
|
61
|
+
* units for a given text and font size (height).
|
|
62
|
+
*/
|
|
63
|
+
constructor(params, styleResolver, textWidthCalculator) {
|
|
64
|
+
this.params = params
|
|
65
|
+
this.styleResolver = styleResolver
|
|
66
|
+
this.textWidthCalculator = textWidthCalculator
|
|
67
|
+
/* Can be set to indicate some invalid geometric solution. */
|
|
68
|
+
this.isValid = true
|
|
69
|
+
this._CalculateGeometry()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
IsValid() {
|
|
73
|
+
return this.isValid
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
GetTexts() {
|
|
77
|
+
return [this._GetText()]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @return {DimensionLayout}
|
|
82
|
+
*/
|
|
83
|
+
GenerateLayout() {
|
|
84
|
+
/* See https://ezdxf.readthedocs.io/en/stable/tables/dimstyle_table_entry.html */
|
|
85
|
+
const result = new DimensionLayout()
|
|
86
|
+
|
|
87
|
+
/* Dimension line(s). */
|
|
88
|
+
const dimSize = this.d1.distanceTo(this.d2)
|
|
89
|
+
const dimColor = this.styleResolver("DIMCLRD")
|
|
90
|
+
let dimScale = this.styleResolver("DIMSCALE") ?? 1
|
|
91
|
+
if (dimScale == 0) {
|
|
92
|
+
/* No any auto calculation implemented, since no support for paper space. */
|
|
93
|
+
dimScale = 1
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const text = this._GetText()
|
|
97
|
+
const fontSize = (this.styleResolver("DIMTXT") ?? 1) * dimScale
|
|
98
|
+
const textWidth = this.textWidthCalculator(text, fontSize)
|
|
99
|
+
const textColor = this.styleResolver("DIMCLRT")
|
|
100
|
+
const arrowSize = (this.styleResolver("DIMASZ") ?? 1) * dimScale
|
|
101
|
+
const tickSize = (this.styleResolver("DIMTSZ") ?? 0) * dimScale
|
|
102
|
+
|
|
103
|
+
let textAnchor = this.params.textAnchor
|
|
104
|
+
let flipArrows = false
|
|
105
|
+
|
|
106
|
+
const start = this.d1.clone()
|
|
107
|
+
const dimExt = (this.styleResolver("DIMDLE") ?? 0) * dimScale
|
|
108
|
+
if (dimExt != 0) {
|
|
109
|
+
start.add(this.vDim.clone().multiplyScalar(-dimExt))
|
|
110
|
+
}
|
|
111
|
+
const end = this.d2.clone()
|
|
112
|
+
if (dimExt != 0) {
|
|
113
|
+
end.add(this.vDim.clone().multiplyScalar(dimExt))
|
|
114
|
+
}
|
|
115
|
+
result.AddLine(start, end, dimColor)
|
|
116
|
+
|
|
117
|
+
if (dimSize < arrowSize * 2) {
|
|
118
|
+
flipArrows = true
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!textAnchor) {
|
|
122
|
+
//XXX for now just always draw the text above dimension line with fixed gap
|
|
123
|
+
textAnchor = this.vDim.clone().multiplyScalar(this.d1.distanceTo(this.d2) / 2)
|
|
124
|
+
.add(this.d1).add(this.vDimNorm.clone().multiplyScalar(fontSize * 0.75))
|
|
125
|
+
}
|
|
126
|
+
const angle = this.vDimNorm.angle() * 180 / Math.PI - 90 +
|
|
127
|
+
(this.params.textRotation ?? 0)
|
|
128
|
+
result.AddText(text, fontSize, angle, textColor, textAnchor)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
/* Extension lines. */
|
|
132
|
+
const extColor = this.styleResolver("DIMCLRE")
|
|
133
|
+
const extOffset = (this.styleResolver("DIMEXO") ?? 0) * dimScale
|
|
134
|
+
const extExt = (this.styleResolver("DIMEXE") ?? 0) * dimScale
|
|
135
|
+
|
|
136
|
+
const DrawExtLine = (basePt, dimPt) => {
|
|
137
|
+
const vExt = dimPt.clone().sub(basePt)
|
|
138
|
+
const dist = vExt.length()
|
|
139
|
+
if (dist == 0) {
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
vExt.normalize()
|
|
143
|
+
const start = basePt.clone()
|
|
144
|
+
if (extOffset != 0) {
|
|
145
|
+
start.add(vExt.clone().multiplyScalar(extOffset))
|
|
146
|
+
}
|
|
147
|
+
const end = dimPt.clone()
|
|
148
|
+
if (extExt != 0) {
|
|
149
|
+
end.add(vExt.clone().multiplyScalar(extExt))
|
|
150
|
+
}
|
|
151
|
+
result.AddLine(start, end, extColor)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (!(this.styleResolver("DIMSE1") ?? 0)) {
|
|
155
|
+
DrawExtLine(this.params.p1, this.d1)
|
|
156
|
+
}
|
|
157
|
+
if (!(this.styleResolver("DIMSE2") ?? 0)) {
|
|
158
|
+
DrawExtLine(this.params.p2, this.d2)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* Draw arrows (or anything defined as dimension shape). Assuming shape is defined
|
|
162
|
+
* horizontally for left side with the origin in the dimension point, scale corresponding to
|
|
163
|
+
* size 1. Calculate appropriate transform for the shape.
|
|
164
|
+
*/
|
|
165
|
+
//XXX check suppression by DIMSOXD, DIMSD1, DIMSD2
|
|
166
|
+
for (let i = 0; i < 2; i++) {
|
|
167
|
+
const dimPt = i == 0 ? this.d1 : this.d2
|
|
168
|
+
let flip = i == 1
|
|
169
|
+
if (flipArrows) {
|
|
170
|
+
flip = !flip
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
let transform = new Matrix3().identity()
|
|
174
|
+
if (tickSize > 0) {
|
|
175
|
+
transform.scale(tickSize, tickSize)
|
|
176
|
+
} else {
|
|
177
|
+
transform.scale(arrowSize, arrowSize)
|
|
178
|
+
/* Tick is not flipped. */
|
|
179
|
+
if (flip) {
|
|
180
|
+
transform.scale(-1, 1)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const angle = -this.vDim.angle()
|
|
185
|
+
transform.rotate(angle)
|
|
186
|
+
|
|
187
|
+
transform.translate(dimPt.x, dimPt.y)
|
|
188
|
+
|
|
189
|
+
if (tickSize > 0) {
|
|
190
|
+
this._CreateTick(result, transform, dimColor)
|
|
191
|
+
} else {
|
|
192
|
+
this._CreateArrowShape(result, transform, dimColor)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return result
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
_CreateArrowShape(layout, transform, color) {
|
|
200
|
+
const vertices = []
|
|
201
|
+
for (const v of arrowHeadShape.vertices) {
|
|
202
|
+
vertices.push(v.clone().applyMatrix3(transform))
|
|
203
|
+
}
|
|
204
|
+
layout.AddTriangles(vertices, arrowHeadShape.indices, color)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
_CreateTick(layout, transform, color) {
|
|
208
|
+
layout.AddLine(new Vector2(0.5, 0.5).applyMatrix3(transform),
|
|
209
|
+
new Vector2(-0.5, -0.5).applyMatrix3(transform),
|
|
210
|
+
color)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Calculate and set basic geometric parameters (some points and vectors which define the
|
|
214
|
+
* dimension layout).
|
|
215
|
+
*/
|
|
216
|
+
_CalculateGeometry() {
|
|
217
|
+
/* Base vector. */
|
|
218
|
+
this.vBase = this.params.p2.clone().sub(this.params.p1).normalize()
|
|
219
|
+
|
|
220
|
+
/* Dimension vector. */
|
|
221
|
+
if (this.params.isAligned) {
|
|
222
|
+
this.vDim = this.vBase
|
|
223
|
+
} else {
|
|
224
|
+
/* Angle is defined as angle between X axis and dimension line (CCW is positive). */
|
|
225
|
+
const angle = (this.params.angle ?? 0) * Math.PI / 180
|
|
226
|
+
this.vDim = new Vector2(Math.cos(angle), Math.sin(angle))
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/* Dimension points. Calculate them by projecting base points to dimension line. */
|
|
230
|
+
this.d1 = this.vDim.clone().multiplyScalar(
|
|
231
|
+
/* Projected signed length. */
|
|
232
|
+
this.params.p1.clone().sub(this.params.anchor).dot(this.vDim))
|
|
233
|
+
.add(this.params.anchor)
|
|
234
|
+
this.d2 = this.vDim.clone().multiplyScalar(
|
|
235
|
+
/* Projected signed length. */
|
|
236
|
+
this.params.p2.clone().sub(this.params.anchor).dot(this.vDim))
|
|
237
|
+
.add(this.params.anchor)
|
|
238
|
+
|
|
239
|
+
if (this.d1.distanceTo(this.d2) == 0) {
|
|
240
|
+
this.isValid = false
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Ensure dimension vector still points from d1 to d2 after rotation. */
|
|
244
|
+
this.vDim.copy(this.d2).sub(this.d1).normalize()
|
|
245
|
+
|
|
246
|
+
/* Dimension normal vector is perpendicular to dimension line and is either above or on its
|
|
247
|
+
* left side.
|
|
248
|
+
* 90deg rotated vector is either [y; -x] or [-y; x]. Select most suitable from them
|
|
249
|
+
* (y > x).
|
|
250
|
+
*/
|
|
251
|
+
if (this.vDim.y < -this.vDim.x) {
|
|
252
|
+
this.vDimNorm = new Vector2(this.vDim.y, -this.vDim.x)
|
|
253
|
+
} else {
|
|
254
|
+
this.vDimNorm = new Vector2(-this.vDim.y, this.vDim.x)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
_GetText() {
|
|
259
|
+
if (this.params.text == " ") {
|
|
260
|
+
/* Space indicates empty text. */
|
|
261
|
+
return ""
|
|
262
|
+
}
|
|
263
|
+
if ((this.params.text ?? "") != "" && this.params.text.indexOf("<>") == -1) {
|
|
264
|
+
/* No value placeholder, just return the text. */
|
|
265
|
+
return ParseSpecialChars(this.params.text)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
let measurement = this.d2.distanceTo(this.d1)
|
|
269
|
+
measurement *= this.styleResolver("DIMLFAC") ?? 1
|
|
270
|
+
|
|
271
|
+
const rnd = this.styleResolver("DIMRND") ?? 0
|
|
272
|
+
if (rnd > 0) {
|
|
273
|
+
const n = Math.round(measurement / rnd)
|
|
274
|
+
measurement = rnd * n
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const zeroSupp = this.styleResolver("DIMZIN") ?? 0
|
|
278
|
+
const leadZeroSupp = (zeroSupp & 4) != 0
|
|
279
|
+
const trailingZeroSupp = (zeroSupp & 8) != 0
|
|
280
|
+
|
|
281
|
+
let measText = measurement.toFixed(this.styleResolver("DIMDEC") ?? 2)
|
|
282
|
+
|
|
283
|
+
if (trailingZeroSupp) {
|
|
284
|
+
measText = measText.replace(/.0+$/, "")
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (leadZeroSupp) {
|
|
288
|
+
measText = measText.replace(/^0+/, "")
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (measText.startsWith(".")) {
|
|
292
|
+
measText = "0" + measText
|
|
293
|
+
} else if (measText == "") {
|
|
294
|
+
measText = "0"
|
|
295
|
+
}
|
|
296
|
+
if (measText.endsWith(".")) {
|
|
297
|
+
measText = measText.substring(0, measText.length - 1)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
let decSep = this.styleResolver("DIMDSEP") ?? "."
|
|
301
|
+
if (!isNaN(decSep)) {
|
|
302
|
+
decSep = String.fromCharCode(decSep)
|
|
303
|
+
}
|
|
304
|
+
if (decSep != ".") {
|
|
305
|
+
measText = measText.replace(".", decSep)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const suffix = this.styleResolver("DIMPOST") ?? ""
|
|
309
|
+
if (suffix != "") {
|
|
310
|
+
if (suffix.indexOf("<>") != -1) {
|
|
311
|
+
measText = suffix.replaceAll("<>", measText)
|
|
312
|
+
} else {
|
|
313
|
+
measText += suffix
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if ((this.params.text ?? "") != "") {
|
|
318
|
+
measText = this.params.text.replaceAll("<>", measText)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
return ParseSpecialChars(measText)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/** Parses MTEXT formatted text into more convenient intermediate representation. The MTEXT
|
|
2
|
+
* formatting is not well documented, the only source I found:
|
|
3
|
+
* https://adndevblog.typepad.com/autocad/2017/09/dissecting-mtext-format-codes.html
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const State = Object.freeze({
|
|
7
|
+
TEXT: 0,
|
|
8
|
+
ESCAPE: 1,
|
|
9
|
+
/* Skip currently unsupported format codes till ';' */
|
|
10
|
+
SKIP_FORMAT: 2,
|
|
11
|
+
/* For \pxq* paragraph formatting. Not found documentation yet, so temporal naming for now. */
|
|
12
|
+
PARAGRAPH1: 3,
|
|
13
|
+
PARAGRAPH2: 4,
|
|
14
|
+
PARAGRAPH3: 5
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
const EntityType = Object.freeze({
|
|
18
|
+
TEXT: 0,
|
|
19
|
+
SCOPE: 1,
|
|
20
|
+
PARAGRAPH: 2,
|
|
21
|
+
NON_BREAKING_SPACE: 3,
|
|
22
|
+
/** "alignment" property is either "r", "c", "l", "j", "d" for right, center, left, justify
|
|
23
|
+
* (seems to be the same as left), distribute (justify) alignment.
|
|
24
|
+
*/
|
|
25
|
+
PARAGRAPH_ALIGNMENT: 4
|
|
26
|
+
|
|
27
|
+
/* Many others are not yet implemented. */
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
/** Single letter format codes which are not terminated by ";". */
|
|
31
|
+
const shortFormats = new Set([
|
|
32
|
+
"L", "l", "O", "o", "K", "k", "P", "X", "~"
|
|
33
|
+
])
|
|
34
|
+
|
|
35
|
+
const longFormats = new Set([
|
|
36
|
+
"f", "F", "p", "Q", "H", "W", "S", "A", "C", "T"
|
|
37
|
+
])
|
|
38
|
+
|
|
39
|
+
const validEscapes = new Set([
|
|
40
|
+
"\\", "{", "}"
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
export class MTextFormatParser {
|
|
44
|
+
|
|
45
|
+
constructor() {
|
|
46
|
+
this.entities = []
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
Parse(text) {
|
|
50
|
+
const n = text.length
|
|
51
|
+
let textStart = 0
|
|
52
|
+
let state = State.TEXT
|
|
53
|
+
let scopeStack = []
|
|
54
|
+
let curEntities = this.entities
|
|
55
|
+
let curPos = 0
|
|
56
|
+
const _this = this
|
|
57
|
+
|
|
58
|
+
function EmitText() {
|
|
59
|
+
if (state !== State.TEXT || textStart === curPos) {
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
curEntities.push({
|
|
63
|
+
type: EntityType.TEXT,
|
|
64
|
+
content: text.slice(textStart, curPos)
|
|
65
|
+
})
|
|
66
|
+
textStart = curPos
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function EmitEntity(type) {
|
|
70
|
+
curEntities.push({type: type})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function PushScope() {
|
|
74
|
+
const scope = {
|
|
75
|
+
type: EntityType.SCOPE,
|
|
76
|
+
content: []
|
|
77
|
+
}
|
|
78
|
+
curEntities.push(scope)
|
|
79
|
+
curEntities = scope.content
|
|
80
|
+
scopeStack.push(scope)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function PopScope() {
|
|
84
|
+
if (scopeStack.length === 0) {
|
|
85
|
+
/* Stack underflow, just ignore now. */
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
scopeStack.pop()
|
|
89
|
+
if (scopeStack.length === 0) {
|
|
90
|
+
curEntities = _this.entities
|
|
91
|
+
} else {
|
|
92
|
+
curEntities = scopeStack[scopeStack.length - 1].content
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
for ( ;curPos < n; curPos++) {
|
|
97
|
+
const c = text.charAt(curPos)
|
|
98
|
+
|
|
99
|
+
switch (state) {
|
|
100
|
+
|
|
101
|
+
case State.TEXT:
|
|
102
|
+
if (c === "{") {
|
|
103
|
+
EmitText()
|
|
104
|
+
PushScope()
|
|
105
|
+
textStart = curPos + 1
|
|
106
|
+
continue
|
|
107
|
+
}
|
|
108
|
+
if (c === "}") {
|
|
109
|
+
EmitText()
|
|
110
|
+
PopScope()
|
|
111
|
+
textStart = curPos + 1
|
|
112
|
+
continue
|
|
113
|
+
}
|
|
114
|
+
if (c === "\\") {
|
|
115
|
+
EmitText()
|
|
116
|
+
state = State.ESCAPE
|
|
117
|
+
continue
|
|
118
|
+
}
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
case State.ESCAPE:
|
|
122
|
+
if (shortFormats.has(c)) {
|
|
123
|
+
switch (c) {
|
|
124
|
+
case "P":
|
|
125
|
+
EmitEntity(EntityType.PARAGRAPH)
|
|
126
|
+
break
|
|
127
|
+
case "~":
|
|
128
|
+
EmitEntity(EntityType.NON_BREAKING_SPACE)
|
|
129
|
+
break
|
|
130
|
+
}
|
|
131
|
+
state = State.TEXT
|
|
132
|
+
textStart = curPos + 1
|
|
133
|
+
continue
|
|
134
|
+
}
|
|
135
|
+
if (longFormats.has(c)) {
|
|
136
|
+
switch (c) {
|
|
137
|
+
case "p":
|
|
138
|
+
state = State.PARAGRAPH1
|
|
139
|
+
continue
|
|
140
|
+
}
|
|
141
|
+
state = State.SKIP_FORMAT
|
|
142
|
+
continue
|
|
143
|
+
}
|
|
144
|
+
/* Include current character into a next text chunk. Backslash is also included if
|
|
145
|
+
* character is not among allowed ones (that is how Autodesk viewer behaves).
|
|
146
|
+
*/
|
|
147
|
+
if (validEscapes.has(c)) {
|
|
148
|
+
textStart = curPos
|
|
149
|
+
} else {
|
|
150
|
+
textStart = curPos - 1
|
|
151
|
+
}
|
|
152
|
+
state = State.TEXT
|
|
153
|
+
continue
|
|
154
|
+
|
|
155
|
+
case State.PARAGRAPH1:
|
|
156
|
+
state = c === "x" ? State.PARAGRAPH2 : State.SKIP_FORMAT
|
|
157
|
+
continue
|
|
158
|
+
|
|
159
|
+
case State.PARAGRAPH2:
|
|
160
|
+
state = c === "q" ? State.PARAGRAPH3 : State.SKIP_FORMAT
|
|
161
|
+
continue
|
|
162
|
+
|
|
163
|
+
case State.PARAGRAPH3:
|
|
164
|
+
curEntities.push({type: EntityType.PARAGRAPH_ALIGNMENT, alignment: c})
|
|
165
|
+
state = State.SKIP_FORMAT
|
|
166
|
+
continue
|
|
167
|
+
|
|
168
|
+
case State.SKIP_FORMAT:
|
|
169
|
+
if (c === ";") {
|
|
170
|
+
textStart = curPos + 1
|
|
171
|
+
state = State.TEXT
|
|
172
|
+
}
|
|
173
|
+
continue
|
|
174
|
+
|
|
175
|
+
default:
|
|
176
|
+
throw new Error("Unhandled state")
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
EmitText()
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** @typedef MTextFormatEntity
|
|
184
|
+
* @property type One of EntityType
|
|
185
|
+
*
|
|
186
|
+
* @return {MTextFormatEntity[]} List of format chunks. Each chunk is either a text chunk with
|
|
187
|
+
* TEXT type or some format entity. Entity with type SCOPE represents format scope which has
|
|
188
|
+
* nested list of entities in "content" property.
|
|
189
|
+
*/
|
|
190
|
+
GetContent() {
|
|
191
|
+
return this.entities
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Return only text chunks in a flattened sequence of strings. */
|
|
195
|
+
*GetText() {
|
|
196
|
+
|
|
197
|
+
function *TraverseItems(items) {
|
|
198
|
+
for (const item of items) {
|
|
199
|
+
if (item.type === EntityType.TEXT) {
|
|
200
|
+
yield item.content
|
|
201
|
+
} else if (item.type === EntityType.SCOPE) {
|
|
202
|
+
yield *TraverseItems(item.content)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
yield *TraverseItems(this.GetContent())
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
MTextFormatParser.EntityType = EntityType
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Key for materials. */
|
|
2
|
+
import {BatchingKey, CompareValues} from "./BatchingKey.js";
|
|
3
|
+
|
|
4
|
+
export class MaterialKey {
|
|
5
|
+
/**
|
|
6
|
+
* @param instanceType {Number} One of InstanceType values.
|
|
7
|
+
* @param geometryType {?number} One of BatchingKey.GeometryType.
|
|
8
|
+
* @param color {number} Color ARGB value.
|
|
9
|
+
* @param lineType {?number} Line type ID, null for non-lines. Zero is default type (solid
|
|
10
|
+
* line).
|
|
11
|
+
*/
|
|
12
|
+
constructor(instanceType, geometryType, color, lineType) {
|
|
13
|
+
this.instanceType = instanceType
|
|
14
|
+
this.geometryType = geometryType ?? null
|
|
15
|
+
this.color = color
|
|
16
|
+
this.lineType = lineType ?? null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Comparator function. Fields lexical order corresponds to the constructor arguments order.
|
|
20
|
+
* Null values are always first.
|
|
21
|
+
*/
|
|
22
|
+
Compare(other) {
|
|
23
|
+
let c = CompareValues(this.instanceType, other.instanceType)
|
|
24
|
+
if (c !== 0) {
|
|
25
|
+
return c
|
|
26
|
+
}
|
|
27
|
+
c = CompareValues(this.geometryType, other.geometryType)
|
|
28
|
+
if (c !== 0) {
|
|
29
|
+
return c
|
|
30
|
+
}
|
|
31
|
+
c = CompareValues(this.color, other.color)
|
|
32
|
+
if (c !== 0) {
|
|
33
|
+
return c
|
|
34
|
+
}
|
|
35
|
+
return CompareValues(this.lineType, other.lineType)
|
|
36
|
+
}
|
|
37
|
+
}
|