abstract-3d 4.1.6 → 4.2.1
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/lib/abstract-3d.d.ts +63 -6
- package/lib/abstract-3d.d.ts.map +1 -1
- package/lib/abstract-3d.js +277 -74
- package/lib/abstract-3d.js.map +1 -1
- package/lib/renderers/dxf/dxf-encoding/dxf-dimension.d.ts +2 -2
- package/lib/renderers/dxf/dxf-encoding/dxf-dimension.d.ts.map +1 -1
- package/lib/renderers/dxf/dxf-encoding/dxf-dimension.js +6 -6
- package/lib/renderers/dxf/dxf-encoding/dxf-dimension.js.map +1 -1
- package/lib/renderers/dxf/dxf-geometries/dxf-dimension.d.ts +2 -2
- package/lib/renderers/dxf/dxf-geometries/dxf-dimension.d.ts.map +1 -1
- package/lib/renderers/dxf/dxf-geometries/dxf-dimension.js +3 -3
- package/lib/renderers/dxf/dxf-geometries/dxf-dimension.js.map +1 -1
- package/lib/renderers/dxf/dxf.d.ts.map +1 -1
- package/lib/renderers/dxf/dxf.js +12 -8
- package/lib/renderers/dxf/dxf.js.map +1 -1
- package/lib/renderers/ifc/ifc.d.ts.map +1 -1
- package/lib/renderers/ifc/ifc.js +5 -3
- package/lib/renderers/ifc/ifc.js.map +1 -1
- package/lib/renderers/step/step.d.ts.map +1 -1
- package/lib/renderers/step/step.js +3 -2
- package/lib/renderers/step/step.js.map +1 -1
- package/lib/renderers/stl/stl.d.ts.map +1 -1
- package/lib/renderers/stl/stl.js +7 -3
- package/lib/renderers/stl/stl.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-text.d.ts +1 -1
- package/lib/renderers/svg/svg-geometries/svg-text.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-text.js +2 -2
- package/lib/renderers/svg/svg-geometries/svg-text.js.map +1 -1
- package/lib/renderers/svg/svg.d.ts.map +1 -1
- package/lib/renderers/svg/svg.js +13 -10
- package/lib/renderers/svg/svg.js.map +1 -1
- package/lib/renderers/svg-bsp/svg-geometries/svg-text.d.ts +1 -1
- package/lib/renderers/svg-bsp/svg-geometries/svg-text.d.ts.map +1 -1
- package/lib/renderers/svg-bsp/svg-geometries/svg-text.js +2 -2
- package/lib/renderers/svg-bsp/svg-geometries/svg-text.js.map +1 -1
- package/lib/renderers/svg-bsp/svg.d.ts.map +1 -1
- package/lib/renderers/svg-bsp/svg.js +13 -10
- package/lib/renderers/svg-bsp/svg.js.map +1 -1
- package/lib/renderers/three/build/build.js +1 -1
- package/lib/renderers/three/build/build.js.map +1 -1
- package/lib/renderers/three/compile/compile.d.ts +2 -0
- package/lib/renderers/three/compile/compile.d.ts.map +1 -1
- package/lib/renderers/three/compile/compile.js +6 -4
- package/lib/renderers/three/compile/compile.js.map +1 -1
- package/package.json +1 -1
- package/src/abstract-3d.test.ts +254 -0
- package/src/abstract-3d.ts +427 -85
- package/src/renderers/dxf/dxf-encoding/dxf-dimension.ts +22 -2
- package/src/renderers/dxf/dxf-geometries/dxf-dimension.ts +12 -2
- package/src/renderers/dxf/dxf.ts +21 -4
- package/src/renderers/ifc/ifc.ts +16 -3
- package/src/renderers/step/step.ts +3 -2
- package/src/renderers/stl/stl.ts +12 -4
- package/src/renderers/svg/svg-geometries/svg-text.ts +3 -2
- package/src/renderers/svg/svg.ts +29 -9
- package/src/renderers/svg-bsp/svg-geometries/svg-text.ts +3 -2
- package/src/renderers/svg-bsp/svg.ts +29 -9
- package/src/renderers/three/build/build.test.ts +2 -2
- package/src/renderers/three/build/build.ts +1 -1
- package/src/renderers/three/compile/compile.ts +22 -4
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type Dimension,
|
|
3
|
+
type DimensionPlacement,
|
|
4
|
+
dimensionIsOfTypeMesh,
|
|
5
|
+
type Vec3,
|
|
6
|
+
vec3Length,
|
|
7
|
+
vec3Sub,
|
|
8
|
+
vec3TransRot,
|
|
9
|
+
} from "../../../abstract-3d.js";
|
|
2
10
|
import type { Handle } from "../dxf-encoding/dxf-common.js";
|
|
3
11
|
import { type DxfDimensionDefinition, dxfEncDimension } from "../dxf-encoding/dxf-dimension.js";
|
|
4
12
|
|
|
@@ -8,6 +16,8 @@ export function dxfDimension(
|
|
|
8
16
|
parentRot: Vec3,
|
|
9
17
|
sceneRotation: Vec3,
|
|
10
18
|
viewRotation: Vec3,
|
|
19
|
+
textHeight: number | undefined,
|
|
20
|
+
placement: DimensionPlacement | undefined,
|
|
11
21
|
handleRef: Handle
|
|
12
22
|
): DxfDimensionDefinition {
|
|
13
23
|
if (dimensionIsOfTypeMesh(dimension)) {
|
|
@@ -21,5 +31,5 @@ export function dxfDimension(
|
|
|
21
31
|
const me = vec3TransRot(dimension.measurementEnd, parentPos, parentRot);
|
|
22
32
|
const lp = vec3TransRot(dimension.linePosition, parentPos, parentRot);
|
|
23
33
|
const text = dimension.text ?? `${vec3Length(vec3Sub(me, ms))}`;
|
|
24
|
-
return dxfEncDimension(ms, me, lp, text, 7, sceneRotation, viewRotation, dimension.views ?? ["front"], handleRef);
|
|
34
|
+
return dxfEncDimension(ms, me, lp, text, 7, sceneRotation, viewRotation, dimension.views ?? ["front"], textHeight, placement, handleRef);
|
|
25
35
|
}
|
package/src/renderers/dxf/dxf.ts
CHANGED
|
@@ -10,8 +10,11 @@ import {
|
|
|
10
10
|
bounds3Merge,
|
|
11
11
|
bounds3ToSize,
|
|
12
12
|
boundsScene,
|
|
13
|
+
dimensionPlacements,
|
|
13
14
|
group,
|
|
15
|
+
groupTextBackgrounds,
|
|
14
16
|
rotationForCameraPos,
|
|
17
|
+
sceneTextHeight,
|
|
15
18
|
sizeBoundsForCameraPos,
|
|
16
19
|
vec3,
|
|
17
20
|
vec3Add,
|
|
@@ -103,8 +106,9 @@ const renderInternal = (
|
|
|
103
106
|
const dxfOriginOffset = originOffsetFromBounds(bounds, options.origin);
|
|
104
107
|
const pos = options.origin === "SameAsScene" ? vec3Zero : vec3NegateY(vec3Add(unitCenter, vec3Add(offset, dxfOriginOffset)));
|
|
105
108
|
const visibleViews = calculateVisibleViews(options.view, scene.rotation_deprecated);
|
|
109
|
+
const textHeight = sceneTextHeight(scene.groups);
|
|
106
110
|
return {
|
|
107
|
-
groups: scene.groups.reduce((a, c) => a + dxfGroup(c, pos, unitRot, options, handleRef), ""),
|
|
111
|
+
groups: scene.groups.reduce((a, c) => a + dxfGroup(groupTextBackgrounds(c, textHeight), pos, unitRot, options, handleRef), ""),
|
|
108
112
|
dimensions: dxfDimensions(
|
|
109
113
|
scene.dimensions_deprecated,
|
|
110
114
|
pos,
|
|
@@ -113,6 +117,7 @@ const renderInternal = (
|
|
|
113
117
|
viewRotation,
|
|
114
118
|
visibleViews,
|
|
115
119
|
options,
|
|
120
|
+
textHeight,
|
|
116
121
|
handleRef
|
|
117
122
|
),
|
|
118
123
|
size,
|
|
@@ -200,6 +205,7 @@ function dxfDimensions(
|
|
|
200
205
|
viewRotation: Vec3,
|
|
201
206
|
visibleViews: Record<string, boolean>,
|
|
202
207
|
options: DxfOptions,
|
|
208
|
+
textHeight: number,
|
|
203
209
|
handleRef: Handle
|
|
204
210
|
): DxfDimensionDefinition {
|
|
205
211
|
if (!d || !options.showDimensions) {
|
|
@@ -209,9 +215,13 @@ function dxfDimensions(
|
|
|
209
215
|
blockRecord: "",
|
|
210
216
|
};
|
|
211
217
|
}
|
|
218
|
+
const placements = dimensionPlacements(d.dimensions, textHeight);
|
|
212
219
|
return d.dimensions
|
|
213
|
-
.
|
|
214
|
-
|
|
220
|
+
.flatMap((dim, i) =>
|
|
221
|
+
dim.views?.[0] && visibleViews[dim.views[0]] === true
|
|
222
|
+
? [dxfDimension(dim, parentPos, parentRot, sceneRotation, viewRotation, textHeight, placements[i], handleRef)]
|
|
223
|
+
: []
|
|
224
|
+
)
|
|
215
225
|
.reduce<DxfDimensionDefinition>(
|
|
216
226
|
(prev, curr) => ({
|
|
217
227
|
block: prev.block + curr.block,
|
|
@@ -243,7 +253,13 @@ export const renderOld = (scene: Scene, options?: Optional<DxfOptions>): string
|
|
|
243
253
|
const visibleViews = calculateVisibleViews(opts.view, scene.rotation_deprecated);
|
|
244
254
|
|
|
245
255
|
const bounds2 = bounds3FromPosAndSize(offset, scene.size_deprecated);
|
|
246
|
-
const
|
|
256
|
+
const textHeight = sceneTextHeight(scene.groups);
|
|
257
|
+
const groupRoot = group(
|
|
258
|
+
[],
|
|
259
|
+
offset,
|
|
260
|
+
vec3Zero,
|
|
261
|
+
scene.groups.map((g) => groupTextBackgrounds(g, textHeight))
|
|
262
|
+
);
|
|
247
263
|
const handleRef = dxfHandleInit();
|
|
248
264
|
const dimensions = dxfDimensions(
|
|
249
265
|
scene.dimensions_deprecated,
|
|
@@ -253,6 +269,7 @@ export const renderOld = (scene: Scene, options?: Optional<DxfOptions>): string
|
|
|
253
269
|
viewRotation,
|
|
254
270
|
visibleViews,
|
|
255
271
|
opts,
|
|
272
|
+
textHeight,
|
|
256
273
|
handleRef
|
|
257
274
|
);
|
|
258
275
|
return dxfBuild(dxfGroup(groupRoot, center, unitRot, opts, handleRef), dimensions, bounds2, scene.size_deprecated, center);
|
package/src/renderers/ifc/ifc.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { Color, SRGBColorSpace } from "three";
|
|
2
2
|
import type { Scene, Group, Material, Relation, Vec3, GroupType, AirType } from "../../abstract-3d.js";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
vec3Zero,
|
|
5
|
+
vec3PosX,
|
|
6
|
+
vec3PosY,
|
|
7
|
+
vec3Rot,
|
|
8
|
+
vec3Sub,
|
|
9
|
+
vec3TransRot,
|
|
10
|
+
vec3RotCombine,
|
|
11
|
+
vec3RotInverse,
|
|
12
|
+
groupTextBackgrounds,
|
|
13
|
+
sceneTextHeight,
|
|
14
|
+
} from "../../abstract-3d.js";
|
|
4
15
|
import type { MutableIfc } from "./ifc-encoding.js";
|
|
5
16
|
import { add, guid, ifcFile, point, real, ref, refs, serialize, str } from "./ifc-encoding.js";
|
|
6
17
|
import type { Polyline, Triangulation } from "./ifc-geometry.js";
|
|
@@ -259,11 +270,13 @@ export function render(scene: Scene, options: IfcOptions = {}): string {
|
|
|
259
270
|
|
|
260
271
|
const center = scene.center_deprecated ?? vec3Zero;
|
|
261
272
|
const sceneRot = scene.rotation_deprecated ?? vec3Zero;
|
|
273
|
+
const textHeight = sceneTextHeight(scene.groups);
|
|
274
|
+
const groups = scene.groups.map((g) => groupTextBackgrounds(g, textHeight));
|
|
262
275
|
// A scene that is something as a whole is one element, with its groups as the parts of it
|
|
263
276
|
const roots =
|
|
264
277
|
scene.id !== undefined || scene.name !== undefined || scene.type !== undefined
|
|
265
|
-
? [{ pos: vec3Zero, id: scene.id, name: scene.name, type: scene.type, groups
|
|
266
|
-
:
|
|
278
|
+
? [{ pos: vec3Zero, id: scene.id, name: scene.name, type: scene.type, groups }]
|
|
279
|
+
: groups;
|
|
267
280
|
const elements = mergeSameId(roots)
|
|
268
281
|
.flatMap((g) => elementNode(g, vec3TransRot(g.pos, center, sceneRot), vec3RotCombine(sceneRot, g.rot ?? vec3Zero), g.layer) ?? [])
|
|
269
282
|
.map((node, i) => element(m, node, `${i + 1}`, { element: storey, placement: storeyPlacement, pos: vec3Zero, rot: vec3Zero }, c));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Scene, Group, Vec3 } from "../../abstract-3d.js";
|
|
2
|
-
import { vec3Zero, vec3TransRot, vec3RotCombine } from "../../abstract-3d.js";
|
|
2
|
+
import { vec3Zero, vec3TransRot, vec3RotCombine, groupTextBackgrounds, sceneTextHeight } from "../../abstract-3d.js";
|
|
3
3
|
import type { MutableStep } from "./step-encoding.js";
|
|
4
4
|
import {
|
|
5
5
|
GEOMETRIC_REPRESENTATION_CONTEXT_3D,
|
|
@@ -39,8 +39,9 @@ export const render = (scene: Scene): string => {
|
|
|
39
39
|
throw Error("Context 3d is not correct");
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
const textHeight = sceneTextHeight(scene.groups);
|
|
42
43
|
for (const g of scene.groups) {
|
|
43
|
-
stepGroup(g, scene.center_deprecated ?? vec3Zero, scene.rotation_deprecated ?? vec3Zero, m);
|
|
44
|
+
stepGroup(groupTextBackgrounds(g, textHeight), scene.center_deprecated ?? vec3Zero, scene.rotation_deprecated ?? vec3Zero, m);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
return `${HEADER(date ?? DEFAULT_DATE_UNIX)}${m.step}${ENDSEC()}`;
|
package/src/renderers/stl/stl.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import type { Scene, Group, Vec3 } from "../../abstract-3d.js";
|
|
2
|
-
import { vec3Zero, vec3TransRot, vec3RotCombine } from "../../abstract-3d.js";
|
|
2
|
+
import { vec3Zero, vec3TransRot, vec3RotCombine, groupTextBackgrounds, sceneTextHeight } from "../../abstract-3d.js";
|
|
3
3
|
import { stlBox } from "./stl-geometries/stl-box.js";
|
|
4
4
|
import { stlCone } from "./stl-geometries/stl-cone.js";
|
|
5
5
|
import { stlCylinder } from "./stl-geometries/stl-cylinder.js";
|
|
6
6
|
import { stlPlane } from "./stl-geometries/stl-plane.js";
|
|
7
7
|
import { stlPolygon } from "./stl-geometries/stl-polygon.js";
|
|
8
8
|
|
|
9
|
-
export const render = (scene: Scene): string =>
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export const render = (scene: Scene): string => {
|
|
10
|
+
const textHeight = sceneTextHeight(scene.groups);
|
|
11
|
+
return (
|
|
12
|
+
`solid
|
|
13
|
+
` +
|
|
14
|
+
scene.groups.reduce(
|
|
15
|
+
(a, c) => a + stlGroup(groupTextBackgrounds(c, textHeight), scene.center_deprecated ?? vec3Zero, scene.rotation_deprecated ?? vec3Zero),
|
|
16
|
+
""
|
|
17
|
+
)
|
|
18
|
+
);
|
|
19
|
+
};
|
|
12
20
|
|
|
13
21
|
function stlGroup(g: Group, parentPos: Vec3, parentRot: Vec3): string {
|
|
14
22
|
const pos = vec3TransRot(g.pos, parentPos, parentRot);
|
|
@@ -14,7 +14,8 @@ export function text(
|
|
|
14
14
|
fill: string,
|
|
15
15
|
opts: SvgOptions,
|
|
16
16
|
parentPos: Vec3,
|
|
17
|
-
parentRot: Vec3
|
|
17
|
+
parentRot: Vec3,
|
|
18
|
+
textHeight: number
|
|
18
19
|
): ReadonlyArray<zOrderElement> {
|
|
19
20
|
const pos = vec3TransRot(t.pos, parentPos, parentRot);
|
|
20
21
|
const rot = vec3RotCombine(parentRot, t.rot ?? vec3Zero);
|
|
@@ -27,7 +28,7 @@ export function text(
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const texts = Array<zOrderElement>();
|
|
30
|
-
const fontSize = t.fontSize;
|
|
31
|
+
const fontSize = t.fontSize ?? textHeight;
|
|
31
32
|
const strings = t.text.split("\n");
|
|
32
33
|
let posY = strings.length === 1 ? 0 : (fontSize * strings.length - fontSize) / 2;
|
|
33
34
|
for (const s of strings) {
|
package/src/renderers/svg/svg.ts
CHANGED
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
vec2Zero,
|
|
16
16
|
vec3Flip,
|
|
17
17
|
dimensionConvertToTypeMesh,
|
|
18
|
+
dimensionPlacements,
|
|
19
|
+
groupTextBackgrounds,
|
|
20
|
+
sceneTextHeight,
|
|
18
21
|
} from "../../abstract-3d.js";
|
|
19
22
|
import type { Optional } from "../../utils.js";
|
|
20
23
|
import { calculateVisibleViews, isViewVisible } from "../../utils.js";
|
|
@@ -109,37 +112,53 @@ function renderInternal(
|
|
|
109
112
|
const point = (x: number, y: number): Vec2 => vec2(svgCenter.x + x, svgCenter.y - y);
|
|
110
113
|
const unitCenterFlipped = vec3Flip(unitCenter);
|
|
111
114
|
|
|
115
|
+
const textHeight = sceneTextHeight(scene.groups);
|
|
112
116
|
const elements = Array<zOrderElement>();
|
|
113
117
|
for (const g of scene.groups) {
|
|
114
|
-
elements.push(...svgGroup(g, unitCenterFlipped, unitRot, point, opts));
|
|
118
|
+
elements.push(...svgGroup(groupTextBackgrounds(g, textHeight), unitCenterFlipped, unitRot, point, opts, textHeight));
|
|
115
119
|
}
|
|
116
120
|
const dimOpts: SvgOptions = { ...opts, only_stroke: false, gray_scale: false };
|
|
117
121
|
elements.sort((a, b) => a.zOrder - b.zOrder);
|
|
118
122
|
const visibleViews = calculateVisibleViews(view, scene.rotation_deprecated);
|
|
119
123
|
|
|
120
124
|
// Dimensions are drawn for the flat views
|
|
121
|
-
|
|
122
|
-
|
|
125
|
+
const dimensions = isometric ? [] : (scene.dimensions_deprecated?.dimensions ?? []);
|
|
126
|
+
const placements = dimensionPlacements(dimensions, textHeight);
|
|
127
|
+
for (const [i, dim] of dimensions.entries()) {
|
|
128
|
+
const d = dimensionConvertToTypeMesh(
|
|
129
|
+
dim,
|
|
130
|
+
scene.rotation_deprecated ?? vec3Zero,
|
|
131
|
+
scene.dimensions_deprecated?.material,
|
|
132
|
+
textHeight,
|
|
133
|
+
placements[i]
|
|
134
|
+
);
|
|
123
135
|
if (isViewVisible(d.views[0], visibleViews)) {
|
|
124
136
|
const pos = vec3TransRot(d.pos, unitCenterFlipped, unitRot);
|
|
125
137
|
const rot = vec3RotCombine(unitRot, d.rot);
|
|
126
138
|
for (const m of d.meshes) {
|
|
127
|
-
elements.push(...svgMesh(m, pos, rot, point, scene.dimensions_deprecated?.material ?? { normal: "" }, dimOpts));
|
|
139
|
+
elements.push(...svgMesh(m, pos, rot, point, scene.dimensions_deprecated?.material ?? { normal: "" }, dimOpts, textHeight));
|
|
128
140
|
}
|
|
129
141
|
}
|
|
130
142
|
}
|
|
131
143
|
return { elements, size: svgSize, center: svgCenter };
|
|
132
144
|
}
|
|
133
145
|
|
|
134
|
-
function svgGroup(
|
|
146
|
+
function svgGroup(
|
|
147
|
+
g: Group,
|
|
148
|
+
parentPos: Vec3,
|
|
149
|
+
parentRot: Vec3,
|
|
150
|
+
point: (x: number, y: number) => Vec2,
|
|
151
|
+
opts: SvgOptions,
|
|
152
|
+
textHeight: number
|
|
153
|
+
): ReadonlyArray<zOrderElement> {
|
|
135
154
|
const pos = vec3TransRot(g.pos, parentPos, parentRot);
|
|
136
155
|
const rot = vec3RotCombine(parentRot, g.rot ?? vec3Zero);
|
|
137
156
|
const elements = Array<zOrderElement>();
|
|
138
157
|
for (const m of g.meshes ?? []) {
|
|
139
|
-
elements.push(...svgMesh(m, pos, rot, point, m.material, opts));
|
|
158
|
+
elements.push(...svgMesh(m, pos, rot, point, m.material, opts, textHeight));
|
|
140
159
|
}
|
|
141
160
|
for (const sg of g.groups ?? []) {
|
|
142
|
-
elements.push(...svgGroup(sg, pos, rot, point, opts));
|
|
161
|
+
elements.push(...svgGroup(sg, pos, rot, point, opts, textHeight));
|
|
143
162
|
}
|
|
144
163
|
return elements;
|
|
145
164
|
}
|
|
@@ -150,7 +169,8 @@ function svgMesh(
|
|
|
150
169
|
parentRot: Vec3,
|
|
151
170
|
point: (x: number, y: number) => Vec2,
|
|
152
171
|
material: Material,
|
|
153
|
-
opts: SvgOptions
|
|
172
|
+
opts: SvgOptions,
|
|
173
|
+
textHeight: number
|
|
154
174
|
): ReadonlyArray<zOrderElement> {
|
|
155
175
|
switch (mesh.geometry.type) {
|
|
156
176
|
case "Box":
|
|
@@ -169,7 +189,7 @@ function svgMesh(
|
|
|
169
189
|
case "Shape":
|
|
170
190
|
return shape(mesh.geometry, point, material, opts, parentPos, parentRot);
|
|
171
191
|
case "Text":
|
|
172
|
-
return text(mesh.geometry, point, material.normal, opts, parentPos, parentRot);
|
|
192
|
+
return text(mesh.geometry, point, material.normal, opts, parentPos, parentRot, textHeight);
|
|
173
193
|
case "Image":
|
|
174
194
|
return image(mesh.geometry, point, opts, parentPos, parentRot);
|
|
175
195
|
case "Tube":
|
|
@@ -14,7 +14,8 @@ export function text(
|
|
|
14
14
|
fill: string,
|
|
15
15
|
opts: SvgOptions,
|
|
16
16
|
parentPos: Vec3,
|
|
17
|
-
parentRot: Vec3
|
|
17
|
+
parentRot: Vec3,
|
|
18
|
+
textHeight: number
|
|
18
19
|
): ReadonlyArray<zOrderElement> {
|
|
19
20
|
const pos = vec3TransRot(t.pos, parentPos, parentRot);
|
|
20
21
|
const rot = vec3RotCombine(parentRot, t.rot ?? vec3Zero);
|
|
@@ -27,7 +28,7 @@ export function text(
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
const texts = Array<zOrderElement>();
|
|
30
|
-
const fontSize = t.fontSize;
|
|
31
|
+
const fontSize = t.fontSize ?? textHeight;
|
|
31
32
|
const strings = t.text.split("\n");
|
|
32
33
|
let posY = strings.length === 1 ? 0 : (fontSize * strings.length - fontSize) / 2;
|
|
33
34
|
for (const s of strings) {
|
|
@@ -15,6 +15,9 @@ import {
|
|
|
15
15
|
vec2Zero,
|
|
16
16
|
vec3Flip,
|
|
17
17
|
dimensionConvertToTypeMesh,
|
|
18
|
+
dimensionPlacements,
|
|
19
|
+
groupTextBackgrounds,
|
|
20
|
+
sceneTextHeight,
|
|
18
21
|
} from "../../abstract-3d.js";
|
|
19
22
|
import type { Optional } from "../../utils.js";
|
|
20
23
|
import { calculateVisibleViews, isViewVisible } from "../../utils.js";
|
|
@@ -110,9 +113,10 @@ function renderInternal(
|
|
|
110
113
|
const point = (x: number, y: number): Vec2 => vec2(svgCenter.x + x, svgCenter.y - y);
|
|
111
114
|
const unitCenterFlipped = vec3Flip(unitCenter);
|
|
112
115
|
|
|
116
|
+
const textHeight = sceneTextHeight(scene.groups);
|
|
113
117
|
const elements = [
|
|
114
118
|
...orderElements(
|
|
115
|
-
scene.groups.flatMap((g) => svgGroup(g, unitCenterFlipped, unitRot, point, opts)),
|
|
119
|
+
scene.groups.flatMap((g) => svgGroup(groupTextBackgrounds(g, textHeight), unitCenterFlipped, unitRot, point, opts, textHeight)),
|
|
116
120
|
point
|
|
117
121
|
),
|
|
118
122
|
];
|
|
@@ -120,28 +124,43 @@ function renderInternal(
|
|
|
120
124
|
const visibleViews = calculateVisibleViews(view, scene.rotation_deprecated);
|
|
121
125
|
|
|
122
126
|
// Dimensions are drawn for the flat views
|
|
123
|
-
|
|
124
|
-
|
|
127
|
+
const dimensions = angled ? [] : (scene.dimensions_deprecated?.dimensions ?? []);
|
|
128
|
+
const placements = dimensionPlacements(dimensions, textHeight);
|
|
129
|
+
for (const [i, dim] of dimensions.entries()) {
|
|
130
|
+
const d = dimensionConvertToTypeMesh(
|
|
131
|
+
dim,
|
|
132
|
+
scene.rotation_deprecated ?? vec3Zero,
|
|
133
|
+
scene.dimensions_deprecated?.material,
|
|
134
|
+
textHeight,
|
|
135
|
+
placements[i]
|
|
136
|
+
);
|
|
125
137
|
if (isViewVisible(d.views[0], visibleViews)) {
|
|
126
138
|
const pos = vec3TransRot(d.pos, unitCenterFlipped, unitRot);
|
|
127
139
|
const rot = vec3RotCombine(unitRot, d.rot);
|
|
128
140
|
for (const m of d.meshes) {
|
|
129
|
-
elements.push(...svgMesh(m, pos, rot, point, scene.dimensions_deprecated?.material ?? { normal: "" }, dimOpts));
|
|
141
|
+
elements.push(...svgMesh(m, pos, rot, point, scene.dimensions_deprecated?.material ?? { normal: "" }, dimOpts, textHeight));
|
|
130
142
|
}
|
|
131
143
|
}
|
|
132
144
|
}
|
|
133
145
|
return { elements, size: svgSize, center: svgCenter };
|
|
134
146
|
}
|
|
135
147
|
|
|
136
|
-
function svgGroup(
|
|
148
|
+
function svgGroup(
|
|
149
|
+
g: Group,
|
|
150
|
+
parentPos: Vec3,
|
|
151
|
+
parentRot: Vec3,
|
|
152
|
+
point: (x: number, y: number) => Vec2,
|
|
153
|
+
opts: SvgOptions,
|
|
154
|
+
textHeight: number
|
|
155
|
+
): ReadonlyArray<zOrderElement> {
|
|
137
156
|
const pos = vec3TransRot(g.pos, parentPos, parentRot);
|
|
138
157
|
const rot = vec3RotCombine(parentRot, g.rot ?? vec3Zero);
|
|
139
158
|
const elements = Array<zOrderElement>();
|
|
140
159
|
for (const m of g.meshes ?? []) {
|
|
141
|
-
elements.push(...svgMesh(m, pos, rot, point, m.material, opts));
|
|
160
|
+
elements.push(...svgMesh(m, pos, rot, point, m.material, opts, textHeight));
|
|
142
161
|
}
|
|
143
162
|
for (const sg of g.groups ?? []) {
|
|
144
|
-
elements.push(...svgGroup(sg, pos, rot, point, opts));
|
|
163
|
+
elements.push(...svgGroup(sg, pos, rot, point, opts, textHeight));
|
|
145
164
|
}
|
|
146
165
|
return elements;
|
|
147
166
|
}
|
|
@@ -152,7 +171,8 @@ function svgMesh(
|
|
|
152
171
|
parentRot: Vec3,
|
|
153
172
|
point: (x: number, y: number) => Vec2,
|
|
154
173
|
material: Material,
|
|
155
|
-
opts: SvgOptions
|
|
174
|
+
opts: SvgOptions,
|
|
175
|
+
textHeight: number
|
|
156
176
|
): ReadonlyArray<zOrderElement> {
|
|
157
177
|
switch (mesh.geometry.type) {
|
|
158
178
|
case "Box":
|
|
@@ -171,7 +191,7 @@ function svgMesh(
|
|
|
171
191
|
case "Shape":
|
|
172
192
|
return shape(mesh.geometry, point, material, opts, parentPos, parentRot);
|
|
173
193
|
case "Text":
|
|
174
|
-
return text(mesh.geometry, point, material.normal, opts, parentPos, parentRot);
|
|
194
|
+
return text(mesh.geometry, point, material.normal, opts, parentPos, parentRot, textHeight);
|
|
175
195
|
case "Image":
|
|
176
196
|
return image(mesh.geometry, point, opts, parentPos, parentRot);
|
|
177
197
|
case "Tube":
|
|
@@ -96,8 +96,8 @@ describe("buildScene", () => {
|
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
it("keeps dimensions in their own group, and doesn't pick hidden ones", () => {
|
|
99
|
-
// Its text is centered half
|
|
100
|
-
const dimension = alignedDimension(vec3(-500,
|
|
99
|
+
// Its text, the empty scene's 32 high, is centered a gap and half its height out from the line, over the origin
|
|
100
|
+
const dimension = alignedDimension(vec3(-500, 100, 0), vec3(500, 100, 0), vec3(0, 30, 0), "1000", ["front"], undefined, "dim");
|
|
101
101
|
const built = build(scene([], { dimensions_deprecated: { dimensions: [dimension], material: red } }));
|
|
102
102
|
expect(built.dimensions.children.length).toBeGreaterThan(0);
|
|
103
103
|
expect(pickId(built, 0)).toBe("dim");
|
|
@@ -216,7 +216,7 @@ function createPart(
|
|
|
216
216
|
case "text":
|
|
217
217
|
return createTextPart(
|
|
218
218
|
items.flatMap(({ mesh: { geometry: g } }) =>
|
|
219
|
-
g.type === "Text" ? [{ text: g.text, fontSize: g.fontSize, local: transform(g.pos, g.rot) }] : []
|
|
219
|
+
g.type === "Text" ? [{ text: g.text, fontSize: g.fontSize ?? compiled.textHeight, local: transform(g.pos, g.rot) }] : []
|
|
220
220
|
),
|
|
221
221
|
options.atlas
|
|
222
222
|
);
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { Euler, Matrix4, Quaternion, Vector3 } from "three";
|
|
2
2
|
import type { Group, Mesh, Relation, Scene, Vec3 } from "../../../abstract-3d.js";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
dimensionConvertToTypeMesh,
|
|
5
|
+
dimensionPlacements,
|
|
6
|
+
groupTextBackgrounds,
|
|
7
|
+
sceneTextHeight,
|
|
8
|
+
vec3,
|
|
9
|
+
vec3Scale,
|
|
10
|
+
vec3Zero,
|
|
11
|
+
} from "../../../abstract-3d.js";
|
|
4
12
|
|
|
5
13
|
/**
|
|
6
14
|
* Scene → flat items with world matrices, with no GPU objects, so everything here is testable in Node; groups transform as the r3f renderer's
|
|
@@ -48,6 +56,8 @@ export type CompiledScene = {
|
|
|
48
56
|
readonly matrix: Matrix4;
|
|
49
57
|
/** World matrix of each top-level group */
|
|
50
58
|
readonly roots: ReadonlyArray<Matrix4>;
|
|
59
|
+
/** The height of the scene's texts without a font size, see `sceneTextHeight` */
|
|
60
|
+
readonly textHeight: number;
|
|
51
61
|
};
|
|
52
62
|
|
|
53
63
|
type Output = { readonly items: Array<Item>; readonly animations: Array<Animation> };
|
|
@@ -67,16 +77,24 @@ export function compileScene(scene: Scene, createGroupId?: (g: Group) => string)
|
|
|
67
77
|
...dimensions.map((d): Target => ({ kind: "dimension", id: d.id })),
|
|
68
78
|
...relations.map((relation): Target => ({ kind: "relation", relation })),
|
|
69
79
|
];
|
|
70
|
-
|
|
80
|
+
const textHeight = sceneTextHeight(scene.groups);
|
|
81
|
+
scene.groups.forEach((g, i) => addGroup(out, groupTextBackgrounds(g, textHeight), matrix, undefined, "group", i));
|
|
82
|
+
const placements = dimensionPlacements(dimensions, textHeight);
|
|
71
83
|
dimensions.forEach((dimension, i) => {
|
|
72
|
-
const mesh = dimensionConvertToTypeMesh(
|
|
84
|
+
const mesh = dimensionConvertToTypeMesh(
|
|
85
|
+
dimension,
|
|
86
|
+
scene.rotation_deprecated ?? vec3Zero,
|
|
87
|
+
scene.dimensions_deprecated?.material,
|
|
88
|
+
textHeight,
|
|
89
|
+
placements[i]
|
|
90
|
+
);
|
|
73
91
|
const base = { style: "dimension", target: scene.groups.length + i, data: undefined, animation: undefined } as const;
|
|
74
92
|
addMeshes(out, mesh.meshes, matrix.clone().multiply(transform(mesh.pos, mesh.rot)), base);
|
|
75
93
|
});
|
|
76
94
|
relations.forEach((relation, i) =>
|
|
77
95
|
relation.groups?.forEach((g) => addGroup(out, g, matrix, undefined, "relation", scene.groups.length + dimensions.length + i))
|
|
78
96
|
);
|
|
79
|
-
return { ...out, targets, matrix, roots: scene.groups.map((g) => matrix.clone().multiply(transform(g.pos, g.rot))) };
|
|
97
|
+
return { ...out, targets, matrix, roots: scene.groups.map((g) => matrix.clone().multiply(transform(g.pos, g.rot))), textHeight };
|
|
80
98
|
}
|
|
81
99
|
|
|
82
100
|
function addGroup(out: Output, g: Group, parent: Matrix4, parentAnimation: number | undefined, style: "group" | "relation", target: number): void {
|