abstract-3d 4.1.1 → 4.1.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/lib/renderers/svg/svg-encoding.d.ts +0 -2
- package/lib/renderers/svg/svg-encoding.d.ts.map +1 -1
- package/lib/renderers/svg/svg-encoding.js +0 -12
- package/lib/renderers/svg/svg-encoding.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/shared.d.ts +2 -19
- package/lib/renderers/svg/svg-geometries/shared.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/shared.js +1 -16
- package/lib/renderers/svg/svg-geometries/shared.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-box.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-box.js +30 -44
- package/lib/renderers/svg/svg-geometries/svg-box.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-cone.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-cone.js +3 -3
- package/lib/renderers/svg/svg-geometries/svg-cone.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-cylinder.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-cylinder.js +6 -19
- package/lib/renderers/svg/svg-geometries/svg-cylinder.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-image.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-image.js +2 -3
- package/lib/renderers/svg/svg-geometries/svg-image.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-line.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-line.js +1 -3
- package/lib/renderers/svg/svg-geometries/svg-line.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-plane.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-plane.js +2 -6
- package/lib/renderers/svg/svg-geometries/svg-plane.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-polygon.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-polygon.js +2 -10
- package/lib/renderers/svg/svg-geometries/svg-polygon.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-shape.d.ts.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-shape.js +2 -5
- package/lib/renderers/svg/svg-geometries/svg-shape.js.map +1 -1
- package/lib/renderers/svg/svg-geometries/svg-text.js +1 -1
- package/lib/renderers/svg/svg-geometries/svg-text.js.map +1 -1
- package/lib/renderers/svg/svg-order.d.ts +5 -6
- package/lib/renderers/svg/svg-order.d.ts.map +1 -1
- package/lib/renderers/svg/svg-order.js +124 -233
- package/lib/renderers/svg/svg-order.js.map +1 -1
- package/lib/renderers/svg/svg.d.ts.map +1 -1
- package/lib/renderers/svg/svg.js +12 -11
- package/lib/renderers/svg/svg.js.map +1 -1
- package/lib/renderers/svg-bsp/class-names.d.ts +11 -0
- package/lib/renderers/svg-bsp/class-names.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/class-names.js +11 -0
- package/lib/renderers/svg-bsp/class-names.js.map +1 -0
- package/lib/renderers/svg-bsp/index.d.ts +5 -0
- package/lib/renderers/svg-bsp/index.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/index.js +4 -0
- package/lib/renderers/svg-bsp/index.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-encoding.d.ts +19 -0
- package/lib/renderers/svg-bsp/svg-encoding.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-encoding.js +135 -0
- package/lib/renderers/svg-bsp/svg-encoding.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/shared.d.ts +47 -0
- package/lib/renderers/svg-bsp/svg-geometries/shared.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/shared.js +45 -0
- package/lib/renderers/svg-bsp/svg-geometries/shared.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-box.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-box.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-box.js +58 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-box.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-cone.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-cone.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-cone.js +39 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-cone.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-cylinder.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-cylinder.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-cylinder.js +62 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-cylinder.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-image.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-image.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-image.js +44 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-image.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-line.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-line.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-line.js +12 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-line.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-plane.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-plane.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-plane.js +24 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-plane.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-polygon.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-polygon.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-polygon.js +24 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-polygon.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-shape.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-shape.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-shape.js +19 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-shape.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-text.d.ts +4 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-text.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-text.js +26 -0
- package/lib/renderers/svg-bsp/svg-geometries/svg-text.js.map +1 -0
- package/lib/renderers/svg-bsp/svg-order.d.ts +10 -0
- package/lib/renderers/svg-bsp/svg-order.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg-order.js +257 -0
- package/lib/renderers/svg-bsp/svg-order.js.map +1 -0
- package/lib/renderers/svg-bsp/svg.d.ts +16 -0
- package/lib/renderers/svg-bsp/svg.d.ts.map +1 -0
- package/lib/renderers/svg-bsp/svg.js +120 -0
- package/lib/renderers/svg-bsp/svg.js.map +1 -0
- package/package.json +6 -1
- package/src/renderers/svg/svg-encoding.ts +0 -13
- package/src/renderers/svg/svg-geometries/shared.ts +3 -31
- package/src/renderers/svg/svg-geometries/svg-box.ts +36 -51
- package/src/renderers/svg/svg-geometries/svg-cone.ts +3 -18
- package/src/renderers/svg/svg-geometries/svg-cylinder.ts +6 -26
- package/src/renderers/svg/svg-geometries/svg-image.ts +2 -3
- package/src/renderers/svg/svg-geometries/svg-line.ts +1 -3
- package/src/renderers/svg/svg-geometries/svg-plane.ts +2 -12
- package/src/renderers/svg/svg-geometries/svg-polygon.ts +2 -10
- package/src/renderers/svg/svg-geometries/svg-shape.ts +2 -11
- package/src/renderers/svg/svg-geometries/svg-text.ts +1 -1
- package/src/renderers/svg/svg.ts +12 -14
- package/src/renderers/svg-bsp/class-names.ts +10 -0
- package/src/renderers/svg-bsp/index.ts +4 -0
- package/src/renderers/svg-bsp/svg-encoding.ts +190 -0
- package/src/renderers/svg-bsp/svg-geometries/shared.ts +88 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-box.ts +76 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-cone.ts +68 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-cylinder.ts +82 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-image.ts +56 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-line.ts +21 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-plane.ts +43 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-polygon.ts +33 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-shape.ts +34 -0
- package/src/renderers/svg-bsp/svg-geometries/svg-text.ts +40 -0
- package/src/renderers/svg-bsp/svg.ts +183 -0
- /package/src/renderers/{svg → svg-bsp}/svg-order.test.ts +0 -0
- /package/src/renderers/{svg → svg-bsp}/svg-order.ts +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { exhaustiveCheck } from "ts-exhaustive-check";
|
|
2
|
+
import { vec2, vec3Rot, vec3Zero, vec3RotCombine, vec3, vec3TransRot, rotationForCameraPos, sizeBoundsForCameraPos, bounds2FromPosAndSize, bounds2ToSize, bounds2Merge, vec2Zero, vec3Flip, dimensionConvertToTypeMesh, } from "../../abstract-3d.js";
|
|
3
|
+
import { calculateVisibleViews, isViewVisible } from "../../utils.js";
|
|
4
|
+
import { svg } from "./svg-encoding.js";
|
|
5
|
+
import { box } from "./svg-geometries/svg-box.js";
|
|
6
|
+
import { cone } from "./svg-geometries/svg-cone.js";
|
|
7
|
+
import { cylinder } from "./svg-geometries/svg-cylinder.js";
|
|
8
|
+
import { image } from "./svg-geometries/svg-image.js";
|
|
9
|
+
import { line } from "./svg-geometries/svg-line.js";
|
|
10
|
+
import { plane } from "./svg-geometries/svg-plane.js";
|
|
11
|
+
import { polygon } from "./svg-geometries/svg-polygon.js";
|
|
12
|
+
import { shape } from "./svg-geometries/svg-shape.js";
|
|
13
|
+
import { text } from "./svg-geometries/svg-text.js";
|
|
14
|
+
import { orderElements } from "./svg-order.js";
|
|
15
|
+
export function renderScenes(scenes, baseOptions) {
|
|
16
|
+
const allElements = Array();
|
|
17
|
+
const bounds = Array();
|
|
18
|
+
for (const view of scenes) {
|
|
19
|
+
const { elements, size, center } = renderInternal(view.scene, { ...baseOptions, ...view.options }, view.pos);
|
|
20
|
+
allElements.push(...elements);
|
|
21
|
+
const newBounds = bounds2FromPosAndSize(center, size);
|
|
22
|
+
bounds.push(newBounds);
|
|
23
|
+
}
|
|
24
|
+
const mergedBounds = bounds2Merge(...bounds);
|
|
25
|
+
const size = bounds2ToSize(mergedBounds);
|
|
26
|
+
const image = svg(mergedBounds.min, size, allElements.reduce((a, { element }) => `${a} ${element}`, ""), baseOptions?.className ?? "");
|
|
27
|
+
return { image, width: size.x, height: size.y };
|
|
28
|
+
}
|
|
29
|
+
export function render(scene, options) {
|
|
30
|
+
const { elements, size, center } = renderInternal(scene, options, vec2Zero);
|
|
31
|
+
const image = svg(vec2(center.x - size.x / 2, center.y - size.y / 2), size, elements.reduce((a, { element }) => `${a} ${element}`, ""), options?.className ?? "");
|
|
32
|
+
return { image, width: size.x, height: size.y };
|
|
33
|
+
}
|
|
34
|
+
function renderInternal(scene, options, offset) {
|
|
35
|
+
const opts = {
|
|
36
|
+
view: options?.view ?? "front",
|
|
37
|
+
stroke_thickness: options?.stroke_thickness ?? 2,
|
|
38
|
+
only_stroke: options?.only_stroke ?? false,
|
|
39
|
+
gray_scale: options?.gray_scale ?? false,
|
|
40
|
+
background: options?.background ?? "rgba(255,255,255,0)",
|
|
41
|
+
font: options?.font ?? "",
|
|
42
|
+
imageDataByUrl: options?.imageDataByUrl ?? {},
|
|
43
|
+
rotation: options?.rotation ?? 0,
|
|
44
|
+
imageBg: options?.imageBg ?? false,
|
|
45
|
+
className: options?.className ?? "",
|
|
46
|
+
};
|
|
47
|
+
// A three-quarter view: the front turned 30° to show the side, and tilted 20° to show the top, the front foremost
|
|
48
|
+
const angled = opts.view === "TopLeft" || opts.view === "TopRight";
|
|
49
|
+
const view = angled ? "front" : opts.view;
|
|
50
|
+
const angledRot = angled
|
|
51
|
+
? vec3RotCombine(vec3((20 * Math.PI) / 180, 0, 0), vec3(0, ((opts.view === "TopRight" ? -1 : 1) * 30 * Math.PI) / 180, 0))
|
|
52
|
+
: vec3Zero;
|
|
53
|
+
const cameraRot = vec3RotCombine(angledRot, rotationForCameraPos(view));
|
|
54
|
+
const viewRot = opts.rotation ? vec3RotCombine(vec3(0, 0, (opts.rotation * Math.PI) / 180), cameraRot) : cameraRot;
|
|
55
|
+
const unitRot = vec3RotCombine(viewRot, scene.rotation_deprecated ?? vec3Zero);
|
|
56
|
+
const unitCenter = vec3Rot(scene.center_deprecated ?? vec3Zero, vec3Zero, cameraRot);
|
|
57
|
+
const [unitSize] = sizeBoundsForCameraPos(scene.size_deprecated, unitCenter, unitRot);
|
|
58
|
+
const svgSize = vec2(unitSize.x + 1.5 * opts.stroke_thickness, unitSize.y + 1.5 * opts.stroke_thickness);
|
|
59
|
+
const svgCenter = vec2(offset.x + opts.stroke_thickness * 0.75, offset.y + opts.stroke_thickness * 0.75);
|
|
60
|
+
const point = (x, y) => vec2(svgCenter.x + x, svgCenter.y - y);
|
|
61
|
+
const unitCenterFlipped = vec3Flip(unitCenter);
|
|
62
|
+
const elements = [
|
|
63
|
+
...orderElements(scene.groups.flatMap((g) => svgGroup(g, unitCenterFlipped, unitRot, point, opts)), point),
|
|
64
|
+
];
|
|
65
|
+
const dimOpts = { ...opts, only_stroke: false, gray_scale: false };
|
|
66
|
+
const visibleViews = calculateVisibleViews(view, scene.rotation_deprecated);
|
|
67
|
+
// Dimensions are drawn for the flat views
|
|
68
|
+
for (const dim of angled ? [] : (scene.dimensions_deprecated?.dimensions ?? [])) {
|
|
69
|
+
const d = dimensionConvertToTypeMesh(dim, scene.rotation_deprecated ?? vec3Zero, scene.dimensions_deprecated?.material);
|
|
70
|
+
if (isViewVisible(d.views[0], visibleViews)) {
|
|
71
|
+
const pos = vec3TransRot(d.pos, unitCenterFlipped, unitRot);
|
|
72
|
+
const rot = vec3RotCombine(unitRot, d.rot);
|
|
73
|
+
for (const m of d.meshes) {
|
|
74
|
+
elements.push(...svgMesh(m, pos, rot, point, scene.dimensions_deprecated?.material ?? { normal: "" }, dimOpts));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { elements, size: svgSize, center: svgCenter };
|
|
79
|
+
}
|
|
80
|
+
function svgGroup(g, parentPos, parentRot, point, opts) {
|
|
81
|
+
const pos = vec3TransRot(g.pos, parentPos, parentRot);
|
|
82
|
+
const rot = vec3RotCombine(parentRot, g.rot ?? vec3Zero);
|
|
83
|
+
const elements = Array();
|
|
84
|
+
for (const m of g.meshes ?? []) {
|
|
85
|
+
elements.push(...svgMesh(m, pos, rot, point, m.material, opts));
|
|
86
|
+
}
|
|
87
|
+
for (const sg of g.groups ?? []) {
|
|
88
|
+
elements.push(...svgGroup(sg, pos, rot, point, opts));
|
|
89
|
+
}
|
|
90
|
+
return elements;
|
|
91
|
+
}
|
|
92
|
+
function svgMesh(mesh, parentPos, parentRot, point, material, opts) {
|
|
93
|
+
switch (mesh.geometry.type) {
|
|
94
|
+
case "Box":
|
|
95
|
+
return box(mesh.geometry, point, material, opts, parentPos, parentRot);
|
|
96
|
+
case "Plane":
|
|
97
|
+
return plane(mesh.geometry, point, material, opts, parentPos, parentRot);
|
|
98
|
+
case "Cylinder":
|
|
99
|
+
return cylinder(mesh.geometry, point, material, opts, parentPos, parentRot);
|
|
100
|
+
case "Cone":
|
|
101
|
+
return cone(mesh.geometry, point, material, opts, parentPos, parentRot);
|
|
102
|
+
case "CulledLine":
|
|
103
|
+
case "Line":
|
|
104
|
+
return line(mesh.geometry, point, material.normal, opts, parentPos, parentRot);
|
|
105
|
+
case "Polygon":
|
|
106
|
+
return polygon(mesh.geometry, point, material, opts, parentPos, parentRot);
|
|
107
|
+
case "Shape":
|
|
108
|
+
return shape(mesh.geometry, point, material, opts, parentPos, parentRot);
|
|
109
|
+
case "Text":
|
|
110
|
+
return text(mesh.geometry, point, material.normal, opts, parentPos, parentRot);
|
|
111
|
+
case "Image":
|
|
112
|
+
return image(mesh.geometry, point, opts, parentPos, parentRot);
|
|
113
|
+
case "Tube":
|
|
114
|
+
case "Sphere":
|
|
115
|
+
return [];
|
|
116
|
+
default:
|
|
117
|
+
return exhaustiveCheck(mesh.geometry);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=svg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg.js","sourceRoot":"","sources":["../../../src/renderers/svg-bsp/svg.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abstract-3d",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.3",
|
|
4
4
|
"gitHead": "17921b59da5eee6cc446fd37a2134165af4d1901",
|
|
5
5
|
"description": "Abstract 3D",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,6 +59,11 @@
|
|
|
59
59
|
"ts": "./src/renderers/svg/index.ts",
|
|
60
60
|
"types": "./lib/renderers/svg/index.d.ts",
|
|
61
61
|
"import": "./lib/renderers/svg/index.js"
|
|
62
|
+
},
|
|
63
|
+
"./svg-bsp": {
|
|
64
|
+
"ts": "./src/renderers/svg-bsp/index.ts",
|
|
65
|
+
"types": "./lib/renderers/svg-bsp/index.d.ts",
|
|
66
|
+
"import": "./lib/renderers/svg-bsp/index.js"
|
|
62
67
|
}
|
|
63
68
|
},
|
|
64
69
|
"dependencies": {
|
|
@@ -100,19 +100,6 @@ function svgStrokedHoles(pos: Vec2, rot: Vec3, holes: ReadonlyArray<Hole>, strok
|
|
|
100
100
|
return svgHoles;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
/** A polygon's edges that are flagged, the edge from each point to the next, as one path, without a fill */
|
|
104
|
-
export function svgEdges(points: ReadonlyArray<Vec2>, edges: ReadonlyArray<boolean>, stroke: string, strokeWidth: number): string {
|
|
105
|
-
// From after an unflagged edge, so a run of edges isn't broken where the points wrap around
|
|
106
|
-
const start = edges.indexOf(false) + 1;
|
|
107
|
-
const d = points.reduce((path, _, k) => {
|
|
108
|
-
const i = (start + k) % points.length;
|
|
109
|
-
const [p, q] = [points[i]!, points[(i + 1) % points.length]!];
|
|
110
|
-
const move = k > 0 && edges[(i + points.length - 1) % points.length] ? "" : `M${p.x.toFixed(0)},${p.y.toFixed(0)}`;
|
|
111
|
-
return edges[i] ? `${path}${move}L${q.x.toFixed(0)},${q.y.toFixed(0)}` : path;
|
|
112
|
-
}, "");
|
|
113
|
-
return `<path class="${classNames.stroke}" d="${d}" fill="none" stroke="${stroke}" stroke-width="${strokeWidth}" />`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
103
|
export const svgCircle2 = (radius: number, pos: Vec2, fill: string, stroke: string, strokeWidth: number, _holes?: ReadonlyArray<Hole>): string =>
|
|
117
104
|
`<circle class="${classNames.stroke}" r="${radius.toFixed(0)}" cx="${pos.x.toFixed(0)}" cy="${pos.y.toFixed(
|
|
118
105
|
0
|
|
@@ -1,36 +1,8 @@
|
|
|
1
1
|
import type { Vec2, Vec3, View } from "../../../abstract-3d.js";
|
|
2
2
|
import { vec3TransRot, vec3Zero } from "../../../abstract-3d.js";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* whether it hides what's behind it, and the style of a plain polygon, without holes, by which its pieces are drawn when it's split
|
|
7
|
-
*/
|
|
8
|
-
export type zOrderElement = {
|
|
9
|
-
readonly element: string;
|
|
10
|
-
readonly zOrder: number;
|
|
11
|
-
readonly polygon?: ReadonlyArray<Vec3>;
|
|
12
|
-
readonly opaque?: boolean;
|
|
13
|
-
readonly style?: PolygonStyle;
|
|
14
|
-
};
|
|
15
|
-
export type PolygonStyle = { readonly fill: string; readonly opacity: number; readonly stroke: string; readonly strokeWidth: number };
|
|
16
|
-
export const zElem = (element: string, zOrder: number, polygon?: ReadonlyArray<Vec3>, opaque?: boolean, style?: PolygonStyle): zOrderElement => ({
|
|
17
|
-
element,
|
|
18
|
-
zOrder,
|
|
19
|
-
...(polygon && { polygon }),
|
|
20
|
-
...(opaque && { opaque }),
|
|
21
|
-
...(style && { style }),
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
/** Whether a fill hides what's behind it: fully opaque, and not transparent, e.g. a sketch's default background */
|
|
25
|
-
export const isOpaque = (fill: string, opacity: number): boolean => opacity >= 1 && !/^(transparent|none|rgba\(.*,\s*0(\.0*)?\s*\))$/.test(fill);
|
|
26
|
-
|
|
27
|
-
/** Twice the signed area of a polygon on screen */
|
|
28
|
-
export function getArea(points: ReadonlyArray<Vec2>): number {
|
|
29
|
-
return points.reduce((sum, p, i) => {
|
|
30
|
-
const q = points[(i + 1) % points.length]!;
|
|
31
|
-
return sum + p.x * q.y - q.x * p.y;
|
|
32
|
-
}, 0);
|
|
33
|
-
}
|
|
4
|
+
export type zOrderElement = { readonly element: string; readonly zOrder: number };
|
|
5
|
+
export const zElem = (element: string, zOrder: number): zOrderElement => ({ element, zOrder });
|
|
34
6
|
|
|
35
7
|
export const stBW = 0.7;
|
|
36
8
|
export const stN = 0.1;
|
|
@@ -42,7 +14,7 @@ export const black = "rgb(15, 15, 15)";
|
|
|
42
14
|
|
|
43
15
|
export type ImageDataUri = `data:image/png;base64,${string}` | `data:image/jpeg;base64,${string}` | `data:image/svg+xml,${string}`;
|
|
44
16
|
|
|
45
|
-
/** A view, or
|
|
17
|
+
/** A view, or an isometric one from the front's top left or top right, which shows the front, the top and that side, foreshortened alike */
|
|
46
18
|
export type SvgView = View | "TopLeft" | "TopRight";
|
|
47
19
|
|
|
48
20
|
export type SvgOptions = {
|
|
@@ -3,7 +3,7 @@ import { vec3Scale, vec3TransRot, vec3RotCombine, vec3Zero, vec3, vec3ZMean } fr
|
|
|
3
3
|
import { rgbGrayScale } from "../../../utils.js";
|
|
4
4
|
import { svgPolygon } from "../svg-encoding.js";
|
|
5
5
|
import type { zOrderElement, SvgOptions } from "./shared.js";
|
|
6
|
-
import { gray, black, zElem
|
|
6
|
+
import { gray, black, zElem } from "./shared.js";
|
|
7
7
|
|
|
8
8
|
export function box(
|
|
9
9
|
b: Box,
|
|
@@ -16,61 +16,46 @@ export function box(
|
|
|
16
16
|
const half = vec3Scale(b.size, 0.5);
|
|
17
17
|
const pos = vec3TransRot(b.pos, parentPos, parentRot);
|
|
18
18
|
const rot = vec3RotCombine(parentRot, b.rot ?? vec3Zero);
|
|
19
|
-
const
|
|
19
|
+
const vec3tr = (p: Vec3): Vec3 => vec3TransRot(p, pos, rot);
|
|
20
|
+
|
|
21
|
+
const v1 = vec3tr(vec3(-half.x, -half.y, half.z));
|
|
22
|
+
const v2 = vec3tr(vec3(half.x, -half.y, half.z));
|
|
23
|
+
const v3 = vec3tr(vec3(half.x, half.y, half.z));
|
|
24
|
+
const v4 = vec3tr(vec3(-half.x, half.y, half.z));
|
|
25
|
+
const v5 = vec3tr(vec3(-half.x, -half.y, -half.z));
|
|
26
|
+
const v6 = vec3tr(vec3(half.x, -half.y, -half.z));
|
|
27
|
+
const v7 = vec3tr(vec3(half.x, half.y, -half.z));
|
|
28
|
+
const v8 = vec3tr(vec3(-half.x, half.y, -half.z));
|
|
29
|
+
|
|
30
|
+
const frontMean = vec3ZMean(v1, v2, v3, v4);
|
|
31
|
+
const backMean = vec3ZMean(v5, v6, v7, v8);
|
|
32
|
+
const [frontBackPoints, frontBackMean] =
|
|
33
|
+
frontMean > backMean
|
|
34
|
+
? [[point(v1.x, v1.y), point(v2.x, v2.y), point(v3.x, v3.y), point(v4.x, v4.y)], frontMean]
|
|
35
|
+
: [[point(v5.x, v5.y), point(v6.x, v6.y), point(v7.x, v7.y), point(v8.x, v8.y)], backMean];
|
|
36
|
+
const topMean = vec3ZMean(v8, v7, v3, v4);
|
|
37
|
+
const botMean = vec3ZMean(v5, v6, v2, v1);
|
|
38
|
+
const [topBotPoints, topBotMean] =
|
|
39
|
+
topMean > botMean
|
|
40
|
+
? [[point(v8.x, v8.y), point(v7.x, v7.y), point(v3.x, v3.y), point(v4.x, v4.y)], topMean]
|
|
41
|
+
: [[point(v5.x, v5.y), point(v6.x, v6.y), point(v2.x, v2.y), point(v1.x, v1.y)], botMean];
|
|
42
|
+
|
|
43
|
+
const rightMean = vec3ZMean(v6, v2, v3, v7);
|
|
44
|
+
const leftMean = vec3ZMean(v5, v1, v4, v8);
|
|
45
|
+
const [rightLeftPoints, rightLeftMean] =
|
|
46
|
+
rightMean > leftMean
|
|
47
|
+
? [[point(v6.x, v6.y), point(v2.x, v2.y), point(v3.x, v3.y), point(v7.x, v7.y)], rightMean]
|
|
48
|
+
: [[point(v5.x, v5.y), point(v1.x, v1.y), point(v4.x, v4.y), point(v8.x, v8.y)], leftMean];
|
|
20
49
|
|
|
21
50
|
const color = material.normal;
|
|
22
51
|
const opacity = material.opacity ?? 1.0;
|
|
23
52
|
const [strokeColor, fill, strokeUse] = opts.only_stroke
|
|
24
53
|
? [opts.gray_scale ? gray : color, opts.background, opts.stroke_thickness]
|
|
25
54
|
: [black, opts.gray_scale ? rgbGrayScale(color) : color, 0];
|
|
26
|
-
const opaque = isOpaque(fill, opacity);
|
|
27
55
|
|
|
28
|
-
return
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return [];
|
|
34
|
-
}
|
|
35
|
-
// Only the front and back have holes, which show what's behind them
|
|
36
|
-
const holes = i === 0 ? b.holes : undefined;
|
|
37
|
-
const plain = !holes?.length;
|
|
38
|
-
return [
|
|
39
|
-
zElem(
|
|
40
|
-
svgPolygon(rot, points, fill, opacity, strokeColor, strokeUse, holes),
|
|
41
|
-
vec3ZMean(...polygon),
|
|
42
|
-
polygon,
|
|
43
|
-
opaque && plain,
|
|
44
|
-
plain ? { fill, opacity, stroke: strokeColor, strokeWidth: strokeUse } : undefined
|
|
45
|
-
),
|
|
46
|
-
];
|
|
47
|
-
});
|
|
56
|
+
return [
|
|
57
|
+
zElem(svgPolygon(rot, frontBackPoints, fill, opacity, strokeColor, strokeUse, b.holes, parentPos), frontBackMean),
|
|
58
|
+
zElem(svgPolygon(rot, topBotPoints, fill, opacity, strokeColor, strokeUse), topBotMean),
|
|
59
|
+
zElem(svgPolygon(rot, rightLeftPoints, fill, opacity, strokeColor, strokeUse), rightLeftMean),
|
|
60
|
+
];
|
|
48
61
|
}
|
|
49
|
-
|
|
50
|
-
const unitCorners = [
|
|
51
|
-
vec3(-1, -1, 1),
|
|
52
|
-
vec3(1, -1, 1),
|
|
53
|
-
vec3(1, 1, 1),
|
|
54
|
-
vec3(-1, 1, 1),
|
|
55
|
-
vec3(-1, -1, -1),
|
|
56
|
-
vec3(1, -1, -1),
|
|
57
|
-
vec3(1, 1, -1),
|
|
58
|
-
vec3(-1, 1, -1),
|
|
59
|
-
];
|
|
60
|
-
/** Pairs of opposite faces by their corners, front and back, top and bottom, right and left, of which the one toward the viewer is drawn */
|
|
61
|
-
const faces: ReadonlyArray<readonly [ReadonlyArray<number>, ReadonlyArray<number>]> = [
|
|
62
|
-
[
|
|
63
|
-
[0, 1, 2, 3],
|
|
64
|
-
[4, 5, 6, 7],
|
|
65
|
-
],
|
|
66
|
-
[
|
|
67
|
-
[7, 6, 2, 3],
|
|
68
|
-
[4, 5, 1, 0],
|
|
69
|
-
],
|
|
70
|
-
[
|
|
71
|
-
[5, 1, 2, 6],
|
|
72
|
-
[4, 0, 3, 7],
|
|
73
|
-
],
|
|
74
|
-
];
|
|
75
|
-
/** Of a face on screen, in the scene's units squared, below which it's seen edge on */
|
|
76
|
-
const minArea = 1e-6;
|
|
@@ -3,7 +3,7 @@ import { vec3, vec3TransRot, vec3RotCombine, vec3Zero, vec3ZMean, equals } from
|
|
|
3
3
|
import { rgbGrayScale } from "../../../utils.js";
|
|
4
4
|
import { svgCircle, svgPolygon } from "../svg-encoding.js";
|
|
5
5
|
import type { zOrderElement, SvgOptions } from "./shared.js";
|
|
6
|
-
import { gray,
|
|
6
|
+
import { gray, stBW, zElem, transparent } from "./shared.js";
|
|
7
7
|
|
|
8
8
|
export function cone(
|
|
9
9
|
c: Cone,
|
|
@@ -37,15 +37,7 @@ export function cone(
|
|
|
37
37
|
if (i !== 0) {
|
|
38
38
|
const prevBot = botVec3Array[i - 1]!;
|
|
39
39
|
const points = [point(currBot.x, currBot.y), point(prevBot.x, prevBot.y), point(topPos.x, topPos.y), point(topPos.x, topPos.y)];
|
|
40
|
-
zOrderComponents.push(
|
|
41
|
-
zElem(
|
|
42
|
-
svgPolygon(rot, points, fill, opacity, stroke, stBW),
|
|
43
|
-
vec3ZMean(currBot, prevBot, topPos),
|
|
44
|
-
[currBot, prevBot, topPos],
|
|
45
|
-
isOpaque(fill, opacity),
|
|
46
|
-
{ fill, opacity, stroke, strokeWidth: stBW }
|
|
47
|
-
)
|
|
48
|
-
);
|
|
40
|
+
zOrderComponents.push(zElem(svgPolygon(rot, points, fill, opacity, stroke, stBW), vec3ZMean(currBot, prevBot, topPos)));
|
|
49
41
|
}
|
|
50
42
|
currentAngle += angleStep;
|
|
51
43
|
}
|
|
@@ -54,14 +46,7 @@ export function cone(
|
|
|
54
46
|
const cylTop = vec3tr(vec3(0, half.y, 0));
|
|
55
47
|
const cylBottom = vec3tr(vec3(0, -half.y, 0));
|
|
56
48
|
if (equals(cylTop.x, cylBottom.x, 0.1) && equals(cylTop.y, cylBottom.y, 0.1)) {
|
|
57
|
-
zOrderComponents.push(
|
|
58
|
-
zElem(
|
|
59
|
-
svgCircle(c.radius, rot, point(cylBottom.x, cylBottom.y), fill, opacity, stroke, stBW),
|
|
60
|
-
cylBottom.z,
|
|
61
|
-
botVec3Array,
|
|
62
|
-
isOpaque(fill, opacity)
|
|
63
|
-
)
|
|
64
|
-
);
|
|
49
|
+
zOrderComponents.push(zElem(svgCircle(c.radius, rot, point(cylBottom.x, cylBottom.y), fill, opacity, stroke, stBW), cylBottom.z));
|
|
65
50
|
}
|
|
66
51
|
|
|
67
52
|
return zOrderComponents;
|
|
@@ -3,7 +3,7 @@ import { vec3, vec3TransRot, vec3RotCombine, vec3Zero, vec3ZMean, equals } from
|
|
|
3
3
|
import { rgbGrayScale } from "../../../utils.js";
|
|
4
4
|
import { svgCircle, svgPolygon } from "../svg-encoding.js";
|
|
5
5
|
import type { SvgOptions, zOrderElement } from "./shared.js";
|
|
6
|
-
import {
|
|
6
|
+
import { gray, stBW, transparent, zElem } from "./shared.js";
|
|
7
7
|
|
|
8
8
|
export function cylinder(
|
|
9
9
|
c: Cylinder,
|
|
@@ -24,10 +24,6 @@ export function cylinder(
|
|
|
24
24
|
const [stroke, fill] = opts.only_stroke
|
|
25
25
|
? [opts.gray_scale ? gray : color, opts.background]
|
|
26
26
|
: [transparent, opts.gray_scale ? rgbGrayScale(color) : color];
|
|
27
|
-
const opaque = isOpaque(fill, opacity);
|
|
28
|
-
const style = { fill, opacity, stroke, strokeWidth: stBW };
|
|
29
|
-
// A closed opaque cylinder's facets turned away are hidden by those toward the viewer and its near end
|
|
30
|
-
const cullBack = opaque && !c.open;
|
|
31
27
|
const zOrderComponents = Array<zOrderElement>();
|
|
32
28
|
|
|
33
29
|
const sides = 8;
|
|
@@ -43,39 +39,23 @@ export function cylinder(
|
|
|
43
39
|
const currTop = vec3tr(vec3(sin * radiusEnd, half, cos * radiusEnd));
|
|
44
40
|
botVec3Array.push(currBot);
|
|
45
41
|
topVec3Array.push(currTop);
|
|
46
|
-
|
|
47
|
-
if (i !== 0 && !(cullBack && vec3TransRot(vec3(Math.sin(mid), 0, Math.cos(mid)), vec3Zero, rot).z < -1e-6)) {
|
|
42
|
+
if (i !== 0) {
|
|
48
43
|
const prevBot = botVec3Array[i - 1]!;
|
|
49
44
|
const prevTop = topVec3Array[i - 1]!;
|
|
50
45
|
|
|
51
46
|
const points = [point(currBot.x, currBot.y), point(prevBot.x, prevBot.y), point(prevTop.x, prevTop.y), point(currTop.x, currTop.y)];
|
|
52
|
-
|
|
53
|
-
zOrderComponents.push(zElem(svgPolygon(rot, points, fill, opacity, stroke, stBW), vec3ZMean(...polygon), polygon, opaque, style));
|
|
47
|
+
zOrderComponents.push(zElem(svgPolygon(rot, points, fill, opacity, stroke, stBW), vec3ZMean(currBot, prevBot, currTop, prevTop)));
|
|
54
48
|
}
|
|
55
49
|
currentAngle += angleStep;
|
|
56
50
|
}
|
|
57
51
|
if (!c.open) {
|
|
58
|
-
//
|
|
52
|
+
// Add circle if direcly facing camera
|
|
59
53
|
const circleTop = vec3tr(vec3(0, half, 0));
|
|
60
54
|
const circleBottom = vec3tr(vec3(0, -half, 0));
|
|
61
|
-
const [circlePos, circleRadius, ring] =
|
|
62
|
-
circleTop.z > circleBottom.z ? [circleTop, radiusEnd, topVec3Array] : [circleBottom, c.radius, botVec3Array];
|
|
63
55
|
if (equals(circleTop.x, circleBottom.x, 0.1) && equals(circleTop.y, circleBottom.y, 0.1)) {
|
|
56
|
+
const [circlePos, circleRadius] = circleTop.z > circleBottom.z ? [circleTop, radiusEnd] : [circleBottom, c.radius];
|
|
64
57
|
const holes = radiusEnd === c.radius ? c.holes : undefined;
|
|
65
|
-
zOrderComponents.push(
|
|
66
|
-
zElem(
|
|
67
|
-
svgCircle(circleRadius, rot, point(circlePos.x, circlePos.y), fill, opacity, stroke, stBW, holes),
|
|
68
|
-
circlePos.z,
|
|
69
|
-
ring,
|
|
70
|
-
opaque && !holes?.length
|
|
71
|
-
)
|
|
72
|
-
);
|
|
73
|
-
} else {
|
|
74
|
-
const points = ring.map((p) => point(p.x, p.y));
|
|
75
|
-
// Not seen edge on, when it's only a line along the facets' edges
|
|
76
|
-
if (Math.abs(getArea(points)) >= 1e-6) {
|
|
77
|
-
zOrderComponents.push(zElem(svgPolygon(rot, points, fill, opacity, stroke, stBW), circlePos.z, ring, opaque && !c.holes?.length, style));
|
|
78
|
-
}
|
|
58
|
+
zOrderComponents.push(zElem(svgCircle(circleRadius, rot, point(circlePos.x, circlePos.y), fill, opacity, stroke, stBW, holes), circlePos.z));
|
|
79
59
|
}
|
|
80
60
|
}
|
|
81
61
|
return zOrderComponents;
|
|
@@ -21,7 +21,6 @@ export function image(
|
|
|
21
21
|
|
|
22
22
|
const v2 = vec3tr(half.x, -half.y);
|
|
23
23
|
const v4 = vec3tr(-half.x, half.y);
|
|
24
|
-
const corners = [vec3tr(-half.x, -half.y), v2, vec3tr(half.x, half.y), v4];
|
|
25
24
|
|
|
26
25
|
switch (i.image.type) {
|
|
27
26
|
case "AbstractImage": {
|
|
@@ -31,7 +30,7 @@ export function image(
|
|
|
31
30
|
};
|
|
32
31
|
const svg = createSVG(i.image.image, opts);
|
|
33
32
|
const img = svgImage(point(v4.x, v4.y), i.size, rot, { type: "svg", svg }, opts.imageBg ? opts.background : undefined, scale);
|
|
34
|
-
return [zElem(img, (v2.z + v4.z) / 2
|
|
33
|
+
return [zElem(img, (v2.z + v4.z) / 2)];
|
|
35
34
|
}
|
|
36
35
|
case "Url": {
|
|
37
36
|
const imageData = opts.imageDataByUrl[i.image.url];
|
|
@@ -46,7 +45,7 @@ export function image(
|
|
|
46
45
|
|
|
47
46
|
if (image) {
|
|
48
47
|
const img = svgImage(point(v4.x, v4.y), i.size, rot, image, opts.imageBg ? opts.background : undefined);
|
|
49
|
-
return [zElem(img, (v2.z + v4.z) / 2
|
|
48
|
+
return [zElem(img, (v2.z + v4.z) / 2)];
|
|
50
49
|
}
|
|
51
50
|
return [];
|
|
52
51
|
}
|
|
@@ -15,7 +15,5 @@ export function line(
|
|
|
15
15
|
): ReadonlyArray<zOrderElement> {
|
|
16
16
|
const v1 = vec3TransRot(l.start, parentPos, parentRot);
|
|
17
17
|
const v2 = vec3TransRot(l.end, parentPos, parentRot);
|
|
18
|
-
return [
|
|
19
|
-
zElem(svgLine(point(v1.x, v1.y), point(v2.x, v2.y), opts.gray_scale ? rgbGrayScale(fill) : fill, l.thickness), vec3ZMean(v1, v2), [v1, v2]),
|
|
20
|
-
];
|
|
18
|
+
return [zElem(svgLine(point(v1.x, v1.y), point(v2.x, v2.y), opts.gray_scale ? rgbGrayScale(fill) : fill, l.thickness), vec3ZMean(v1, v2))];
|
|
21
19
|
}
|
|
@@ -3,7 +3,7 @@ import { vec2Scale, vec3TransRot, vec3RotCombine, vec3Zero, vec3, vec3ZMean } fr
|
|
|
3
3
|
import { rgbGrayScale } from "../../../utils.js";
|
|
4
4
|
import { svgPolygon } from "../svg-encoding.js";
|
|
5
5
|
import type { zOrderElement, SvgOptions } from "./shared.js";
|
|
6
|
-
import { gray, black,
|
|
6
|
+
import { gray, black, zElem } from "./shared.js";
|
|
7
7
|
|
|
8
8
|
export function plane(
|
|
9
9
|
p: Plane,
|
|
@@ -29,15 +29,5 @@ export function plane(
|
|
|
29
29
|
const [strokeColor, fill, strokeThickness] = opts.only_stroke
|
|
30
30
|
? [opts.gray_scale ? gray : material.normal, opts.background, opts.stroke_thickness]
|
|
31
31
|
: [black, opts.gray_scale ? rgbGrayScale(material.normal) : material.normal, 0];
|
|
32
|
-
|
|
33
|
-
const plain = !holes?.length;
|
|
34
|
-
return [
|
|
35
|
-
zElem(
|
|
36
|
-
svgPolygon(rot, points, fill, opacity, strokeColor, strokeThickness, holes),
|
|
37
|
-
vec3ZMean(v1, v2, v3, v4),
|
|
38
|
-
[v1, v2, v3, v4],
|
|
39
|
-
isOpaque(fill, opacity) && plain,
|
|
40
|
-
plain ? { fill, opacity, stroke: strokeColor, strokeWidth: strokeThickness } : undefined
|
|
41
|
-
),
|
|
42
|
-
];
|
|
32
|
+
return [zElem(svgPolygon(rot, points, fill, material.opacity ?? 1.0, strokeColor, strokeThickness, holes), vec3ZMean(v1, v2, v3, v4))];
|
|
43
33
|
}
|
|
@@ -3,7 +3,7 @@ import { vec3ZMean, vec3TransRot, vec3RotCombine, vec3Zero } from "../../../abst
|
|
|
3
3
|
import { rgbGrayScale } from "../../../utils.js";
|
|
4
4
|
import { svgPolygon } from "../svg-encoding.js";
|
|
5
5
|
import type { zOrderElement, SvgOptions } from "./shared.js";
|
|
6
|
-
import { gray,
|
|
6
|
+
import { gray, zElem, transparent } from "./shared.js";
|
|
7
7
|
|
|
8
8
|
export function polygon(
|
|
9
9
|
p: Polygon,
|
|
@@ -21,13 +21,5 @@ export function polygon(
|
|
|
21
21
|
const [strokeColor, fill, strokeThickness] = opts.only_stroke
|
|
22
22
|
? [opts.gray_scale ? gray : color, opts.background, opts.stroke_thickness]
|
|
23
23
|
: [transparent, opts.gray_scale ? rgbGrayScale(color) : color, 0];
|
|
24
|
-
|
|
25
|
-
return [
|
|
26
|
-
zElem(svgPolygon(rot, points, fill, opacity, strokeColor, strokeThickness), vec3ZMean(...rotatedPoints), rotatedPoints, isOpaque(fill, opacity), {
|
|
27
|
-
fill,
|
|
28
|
-
opacity,
|
|
29
|
-
stroke: strokeColor,
|
|
30
|
-
strokeWidth: strokeThickness,
|
|
31
|
-
}),
|
|
32
|
-
];
|
|
24
|
+
return [zElem(svgPolygon(rot, points, fill, material.opacity ?? 1.0, strokeColor, strokeThickness), vec3ZMean(...rotatedPoints))];
|
|
33
25
|
}
|
|
@@ -3,7 +3,7 @@ import { vec3ZMean, vec3TransRot, vec3RotCombine, vec3, vec3Zero } from "../../.
|
|
|
3
3
|
import { rgbGrayScale } from "../../../utils.js";
|
|
4
4
|
import { svgPolygon } from "../svg-encoding.js";
|
|
5
5
|
import type { zOrderElement, SvgOptions } from "./shared.js";
|
|
6
|
-
import { gray,
|
|
6
|
+
import { gray, zElem, transparent } from "./shared.js";
|
|
7
7
|
|
|
8
8
|
export function shape(
|
|
9
9
|
s: Shape,
|
|
@@ -21,14 +21,5 @@ export function shape(
|
|
|
21
21
|
const [strokeColor, fill] = opts.only_stroke
|
|
22
22
|
? [opts.gray_scale ? gray : color, opts.background]
|
|
23
23
|
: [transparent, opts.gray_scale ? rgbGrayScale(color) : color];
|
|
24
|
-
|
|
25
|
-
return [
|
|
26
|
-
zElem(
|
|
27
|
-
svgPolygon(rot, points, fill, opacity, strokeColor, 0),
|
|
28
|
-
vec3ZMean(...rotatedPoints),
|
|
29
|
-
rotatedPoints,
|
|
30
|
-
isOpaque(fill, opacity) && !s.holes?.length,
|
|
31
|
-
{ fill, opacity, stroke: strokeColor, strokeWidth: 0 }
|
|
32
|
-
),
|
|
33
|
-
];
|
|
24
|
+
return [zElem(svgPolygon(rot, points, fill, material.opacity ?? 1.0, strokeColor, 0), vec3ZMean(...rotatedPoints))];
|
|
34
25
|
}
|
|
@@ -32,7 +32,7 @@ export function text(
|
|
|
32
32
|
let posY = strings.length === 1 ? 0 : (fontSize * strings.length - fontSize) / 2;
|
|
33
33
|
for (const s of strings) {
|
|
34
34
|
const matrix = svgTrsMatrix(point(pos.x, pos.y + posY), rot);
|
|
35
|
-
texts.push(zElem(svgText(s, matrix, fill, opts.font, fontSize), pos.z
|
|
35
|
+
texts.push(zElem(svgText(s, matrix, fill, opts.font, fontSize), pos.z));
|
|
36
36
|
posY -= fontSize * 1.2;
|
|
37
37
|
}
|
|
38
38
|
|
package/src/renderers/svg/svg.ts
CHANGED
|
@@ -29,7 +29,6 @@ import { plane } from "./svg-geometries/svg-plane.js";
|
|
|
29
29
|
import { polygon } from "./svg-geometries/svg-polygon.js";
|
|
30
30
|
import { shape } from "./svg-geometries/svg-shape.js";
|
|
31
31
|
import { text } from "./svg-geometries/svg-text.js";
|
|
32
|
-
import { orderElements } from "./svg-order.js";
|
|
33
32
|
|
|
34
33
|
export type SvgScene = {
|
|
35
34
|
readonly scene: Scene;
|
|
@@ -93,13 +92,13 @@ function renderInternal(
|
|
|
93
92
|
imageBg: options?.imageBg ?? false,
|
|
94
93
|
className: options?.className ?? "",
|
|
95
94
|
};
|
|
96
|
-
//
|
|
97
|
-
const
|
|
98
|
-
const view =
|
|
99
|
-
const
|
|
100
|
-
? vec3RotCombine(vec3((
|
|
95
|
+
// Isometric: the front turned 45° to show the side, and tilted by arctan(1/√2) to show the top, so the three axes are foreshortened alike
|
|
96
|
+
const isometric = opts.view === "TopLeft" || opts.view === "TopRight";
|
|
97
|
+
const view = isometric ? "front" : opts.view;
|
|
98
|
+
const isometricRot = isometric
|
|
99
|
+
? vec3RotCombine(vec3(Math.atan(1 / Math.SQRT2), 0, 0), vec3(0, ((opts.view === "TopRight" ? -1 : 1) * Math.PI) / 4, 0))
|
|
101
100
|
: vec3Zero;
|
|
102
|
-
const cameraRot = vec3RotCombine(
|
|
101
|
+
const cameraRot = vec3RotCombine(isometricRot, rotationForCameraPos(view));
|
|
103
102
|
const viewRot = opts.rotation ? vec3RotCombine(vec3(0, 0, (opts.rotation * Math.PI) / 180), cameraRot) : cameraRot;
|
|
104
103
|
const unitRot = vec3RotCombine(viewRot, scene.rotation_deprecated ?? vec3Zero);
|
|
105
104
|
|
|
@@ -110,17 +109,16 @@ function renderInternal(
|
|
|
110
109
|
const point = (x: number, y: number): Vec2 => vec2(svgCenter.x + x, svgCenter.y - y);
|
|
111
110
|
const unitCenterFlipped = vec3Flip(unitCenter);
|
|
112
111
|
|
|
113
|
-
const elements =
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
),
|
|
118
|
-
];
|
|
112
|
+
const elements = Array<zOrderElement>();
|
|
113
|
+
for (const g of scene.groups) {
|
|
114
|
+
elements.push(...svgGroup(g, unitCenterFlipped, unitRot, point, opts));
|
|
115
|
+
}
|
|
119
116
|
const dimOpts: SvgOptions = { ...opts, only_stroke: false, gray_scale: false };
|
|
117
|
+
elements.sort((a, b) => a.zOrder - b.zOrder);
|
|
120
118
|
const visibleViews = calculateVisibleViews(view, scene.rotation_deprecated);
|
|
121
119
|
|
|
122
120
|
// Dimensions are drawn for the flat views
|
|
123
|
-
for (const dim of
|
|
121
|
+
for (const dim of isometric ? [] : (scene.dimensions_deprecated?.dimensions ?? [])) {
|
|
124
122
|
const d = dimensionConvertToTypeMesh(dim, scene.rotation_deprecated ?? vec3Zero, scene.dimensions_deprecated?.material);
|
|
125
123
|
if (isViewVisible(d.views[0], visibleViews)) {
|
|
126
124
|
const pos = vec3TransRot(d.pos, unitCenterFlipped, unitRot);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The classes the svg renderer puts on what it draws, for the page's CSS: `root` on the svg, e.g. sized to fill its box, `stroke` on each stroked
|
|
3
|
+
* element, e.g. as thick at any size by `vector-effect: non-scaling-stroke`, `image` on an embedded picture or svg. Colors and strokes are
|
|
4
|
+
* attributes, which a class overrides
|
|
5
|
+
*/
|
|
6
|
+
export const classNames = {
|
|
7
|
+
root: "a3d-root",
|
|
8
|
+
stroke: "a3d-stroke",
|
|
9
|
+
image: "a3d-image",
|
|
10
|
+
} as const;
|