abstract-3d 4.1.0 → 4.1.2

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.
Files changed (184) hide show
  1. package/lib/renderers/svg/svg-encoding.d.ts +0 -2
  2. package/lib/renderers/svg/svg-encoding.d.ts.map +1 -1
  3. package/lib/renderers/svg/svg-encoding.js +0 -12
  4. package/lib/renderers/svg/svg-encoding.js.map +1 -1
  5. package/lib/renderers/svg/svg-geometries/shared.d.ts +2 -19
  6. package/lib/renderers/svg/svg-geometries/shared.d.ts.map +1 -1
  7. package/lib/renderers/svg/svg-geometries/shared.js +1 -16
  8. package/lib/renderers/svg/svg-geometries/shared.js.map +1 -1
  9. package/lib/renderers/svg/svg-geometries/svg-box.d.ts.map +1 -1
  10. package/lib/renderers/svg/svg-geometries/svg-box.js +30 -44
  11. package/lib/renderers/svg/svg-geometries/svg-box.js.map +1 -1
  12. package/lib/renderers/svg/svg-geometries/svg-cone.d.ts.map +1 -1
  13. package/lib/renderers/svg/svg-geometries/svg-cone.js +3 -3
  14. package/lib/renderers/svg/svg-geometries/svg-cone.js.map +1 -1
  15. package/lib/renderers/svg/svg-geometries/svg-cylinder.d.ts.map +1 -1
  16. package/lib/renderers/svg/svg-geometries/svg-cylinder.js +6 -19
  17. package/lib/renderers/svg/svg-geometries/svg-cylinder.js.map +1 -1
  18. package/lib/renderers/svg/svg-geometries/svg-image.d.ts.map +1 -1
  19. package/lib/renderers/svg/svg-geometries/svg-image.js +2 -3
  20. package/lib/renderers/svg/svg-geometries/svg-image.js.map +1 -1
  21. package/lib/renderers/svg/svg-geometries/svg-line.d.ts.map +1 -1
  22. package/lib/renderers/svg/svg-geometries/svg-line.js +1 -3
  23. package/lib/renderers/svg/svg-geometries/svg-line.js.map +1 -1
  24. package/lib/renderers/svg/svg-geometries/svg-plane.d.ts.map +1 -1
  25. package/lib/renderers/svg/svg-geometries/svg-plane.js +2 -6
  26. package/lib/renderers/svg/svg-geometries/svg-plane.js.map +1 -1
  27. package/lib/renderers/svg/svg-geometries/svg-polygon.d.ts.map +1 -1
  28. package/lib/renderers/svg/svg-geometries/svg-polygon.js +2 -10
  29. package/lib/renderers/svg/svg-geometries/svg-polygon.js.map +1 -1
  30. package/lib/renderers/svg/svg-geometries/svg-shape.d.ts.map +1 -1
  31. package/lib/renderers/svg/svg-geometries/svg-shape.js +2 -5
  32. package/lib/renderers/svg/svg-geometries/svg-shape.js.map +1 -1
  33. package/lib/renderers/svg/svg-geometries/svg-text.js +1 -1
  34. package/lib/renderers/svg/svg-geometries/svg-text.js.map +1 -1
  35. package/lib/renderers/svg/svg-order.d.ts +5 -6
  36. package/lib/renderers/svg/svg-order.d.ts.map +1 -1
  37. package/lib/renderers/svg/svg-order.js +124 -233
  38. package/lib/renderers/svg/svg-order.js.map +1 -1
  39. package/lib/renderers/svg/svg.d.ts.map +1 -1
  40. package/lib/renderers/svg/svg.js +12 -11
  41. package/lib/renderers/svg/svg.js.map +1 -1
  42. package/lib/renderers/svg-bsp/class-names.d.ts +11 -0
  43. package/lib/renderers/svg-bsp/class-names.d.ts.map +1 -0
  44. package/lib/renderers/svg-bsp/class-names.js +11 -0
  45. package/lib/renderers/svg-bsp/class-names.js.map +1 -0
  46. package/lib/renderers/svg-bsp/index.d.ts +5 -0
  47. package/lib/renderers/svg-bsp/index.d.ts.map +1 -0
  48. package/lib/renderers/svg-bsp/index.js +4 -0
  49. package/lib/renderers/svg-bsp/index.js.map +1 -0
  50. package/lib/renderers/svg-bsp/svg-encoding.d.ts +19 -0
  51. package/lib/renderers/svg-bsp/svg-encoding.d.ts.map +1 -0
  52. package/lib/renderers/svg-bsp/svg-encoding.js +135 -0
  53. package/lib/renderers/svg-bsp/svg-encoding.js.map +1 -0
  54. package/lib/renderers/svg-bsp/svg-geometries/shared.d.ts +47 -0
  55. package/lib/renderers/svg-bsp/svg-geometries/shared.d.ts.map +1 -0
  56. package/lib/renderers/svg-bsp/svg-geometries/shared.js +45 -0
  57. package/lib/renderers/svg-bsp/svg-geometries/shared.js.map +1 -0
  58. package/lib/renderers/svg-bsp/svg-geometries/svg-box.d.ts +4 -0
  59. package/lib/renderers/svg-bsp/svg-geometries/svg-box.d.ts.map +1 -0
  60. package/lib/renderers/svg-bsp/svg-geometries/svg-box.js +58 -0
  61. package/lib/renderers/svg-bsp/svg-geometries/svg-box.js.map +1 -0
  62. package/lib/renderers/svg-bsp/svg-geometries/svg-cone.d.ts +4 -0
  63. package/lib/renderers/svg-bsp/svg-geometries/svg-cone.d.ts.map +1 -0
  64. package/lib/renderers/svg-bsp/svg-geometries/svg-cone.js +39 -0
  65. package/lib/renderers/svg-bsp/svg-geometries/svg-cone.js.map +1 -0
  66. package/lib/renderers/svg-bsp/svg-geometries/svg-cylinder.d.ts +4 -0
  67. package/lib/renderers/svg-bsp/svg-geometries/svg-cylinder.d.ts.map +1 -0
  68. package/lib/renderers/svg-bsp/svg-geometries/svg-cylinder.js +62 -0
  69. package/lib/renderers/svg-bsp/svg-geometries/svg-cylinder.js.map +1 -0
  70. package/lib/renderers/svg-bsp/svg-geometries/svg-image.d.ts +4 -0
  71. package/lib/renderers/svg-bsp/svg-geometries/svg-image.d.ts.map +1 -0
  72. package/lib/renderers/svg-bsp/svg-geometries/svg-image.js +44 -0
  73. package/lib/renderers/svg-bsp/svg-geometries/svg-image.js.map +1 -0
  74. package/lib/renderers/svg-bsp/svg-geometries/svg-line.d.ts +4 -0
  75. package/lib/renderers/svg-bsp/svg-geometries/svg-line.d.ts.map +1 -0
  76. package/lib/renderers/svg-bsp/svg-geometries/svg-line.js +12 -0
  77. package/lib/renderers/svg-bsp/svg-geometries/svg-line.js.map +1 -0
  78. package/lib/renderers/svg-bsp/svg-geometries/svg-plane.d.ts +4 -0
  79. package/lib/renderers/svg-bsp/svg-geometries/svg-plane.d.ts.map +1 -0
  80. package/lib/renderers/svg-bsp/svg-geometries/svg-plane.js +24 -0
  81. package/lib/renderers/svg-bsp/svg-geometries/svg-plane.js.map +1 -0
  82. package/lib/renderers/svg-bsp/svg-geometries/svg-polygon.d.ts +4 -0
  83. package/lib/renderers/svg-bsp/svg-geometries/svg-polygon.d.ts.map +1 -0
  84. package/lib/renderers/svg-bsp/svg-geometries/svg-polygon.js +24 -0
  85. package/lib/renderers/svg-bsp/svg-geometries/svg-polygon.js.map +1 -0
  86. package/lib/renderers/svg-bsp/svg-geometries/svg-shape.d.ts +4 -0
  87. package/lib/renderers/svg-bsp/svg-geometries/svg-shape.d.ts.map +1 -0
  88. package/lib/renderers/svg-bsp/svg-geometries/svg-shape.js +19 -0
  89. package/lib/renderers/svg-bsp/svg-geometries/svg-shape.js.map +1 -0
  90. package/lib/renderers/svg-bsp/svg-geometries/svg-text.d.ts +4 -0
  91. package/lib/renderers/svg-bsp/svg-geometries/svg-text.d.ts.map +1 -0
  92. package/lib/renderers/svg-bsp/svg-geometries/svg-text.js +26 -0
  93. package/lib/renderers/svg-bsp/svg-geometries/svg-text.js.map +1 -0
  94. package/lib/renderers/svg-bsp/svg-order.d.ts +10 -0
  95. package/lib/renderers/svg-bsp/svg-order.d.ts.map +1 -0
  96. package/lib/renderers/svg-bsp/svg-order.js +257 -0
  97. package/lib/renderers/svg-bsp/svg-order.js.map +1 -0
  98. package/lib/renderers/svg-bsp/svg.d.ts +16 -0
  99. package/lib/renderers/svg-bsp/svg.d.ts.map +1 -0
  100. package/lib/renderers/svg-bsp/svg.js +120 -0
  101. package/lib/renderers/svg-bsp/svg.js.map +1 -0
  102. package/lib/renderers/three/build/parts.d.ts +2 -1
  103. package/lib/renderers/three/build/parts.d.ts.map +1 -1
  104. package/lib/renderers/three/build/parts.js +25 -15
  105. package/lib/renderers/three/build/parts.js.map +1 -1
  106. package/package.json +6 -1
  107. package/src/renderers/svg/svg-encoding.ts +0 -13
  108. package/src/renderers/svg/svg-geometries/shared.ts +3 -31
  109. package/src/renderers/svg/svg-geometries/svg-box.ts +36 -51
  110. package/src/renderers/svg/svg-geometries/svg-cone.ts +3 -18
  111. package/src/renderers/svg/svg-geometries/svg-cylinder.ts +6 -26
  112. package/src/renderers/svg/svg-geometries/svg-image.ts +2 -3
  113. package/src/renderers/svg/svg-geometries/svg-line.ts +1 -3
  114. package/src/renderers/svg/svg-geometries/svg-plane.ts +2 -12
  115. package/src/renderers/svg/svg-geometries/svg-polygon.ts +2 -10
  116. package/src/renderers/svg/svg-geometries/svg-shape.ts +2 -11
  117. package/src/renderers/svg/svg-geometries/svg-text.ts +1 -1
  118. package/src/renderers/svg/svg.ts +12 -14
  119. package/src/renderers/svg-bsp/class-names.ts +10 -0
  120. package/src/renderers/svg-bsp/index.ts +4 -0
  121. package/src/renderers/svg-bsp/svg-encoding.ts +190 -0
  122. package/src/renderers/svg-bsp/svg-geometries/shared.ts +88 -0
  123. package/src/renderers/svg-bsp/svg-geometries/svg-box.ts +76 -0
  124. package/src/renderers/svg-bsp/svg-geometries/svg-cone.ts +68 -0
  125. package/src/renderers/svg-bsp/svg-geometries/svg-cylinder.ts +82 -0
  126. package/src/renderers/svg-bsp/svg-geometries/svg-image.ts +56 -0
  127. package/src/renderers/svg-bsp/svg-geometries/svg-line.ts +21 -0
  128. package/src/renderers/svg-bsp/svg-geometries/svg-plane.ts +43 -0
  129. package/src/renderers/svg-bsp/svg-geometries/svg-polygon.ts +33 -0
  130. package/src/renderers/svg-bsp/svg-geometries/svg-shape.ts +34 -0
  131. package/src/renderers/svg-bsp/svg-geometries/svg-text.ts +40 -0
  132. package/src/renderers/svg-bsp/svg.ts +183 -0
  133. package/src/renderers/three/build/build.test.ts +8 -4
  134. package/src/renderers/three/build/parts.ts +27 -19
  135. package/lib/renderers/dxf/color.d.ts +0 -7
  136. package/lib/renderers/dxf/color.d.ts.map +0 -1
  137. package/lib/renderers/dxf/color.js +0 -311
  138. package/lib/renderers/dxf/color.js.map +0 -1
  139. package/lib/renderers/dxf/dxf-encoding.d.ts +0 -17
  140. package/lib/renderers/dxf/dxf-encoding.d.ts.map +0 -1
  141. package/lib/renderers/dxf/dxf-encoding.js +0 -18379
  142. package/lib/renderers/dxf/dxf-encoding.js.map +0 -1
  143. package/lib/renderers/react/react-camera.d.ts +0 -71
  144. package/lib/renderers/react/react-camera.d.ts.map +0 -1
  145. package/lib/renderers/react/react-camera.js +0 -174
  146. package/lib/renderers/react/react-camera.js.map +0 -1
  147. package/lib/renderers/react/react-dimension.d.ts +0 -17
  148. package/lib/renderers/react/react-dimension.d.ts.map +0 -1
  149. package/lib/renderers/react/react-dimension.js +0 -15
  150. package/lib/renderers/react/react-dimension.js.map +0 -1
  151. package/lib/renderers/react/react-group.d.ts +0 -23
  152. package/lib/renderers/react/react-group.d.ts.map +0 -1
  153. package/lib/renderers/react/react-group.js +0 -69
  154. package/lib/renderers/react/react-group.js.map +0 -1
  155. package/lib/renderers/react/react-hotspot.d.ts +0 -27
  156. package/lib/renderers/react/react-hotspot.d.ts.map +0 -1
  157. package/lib/renderers/react/react-hotspot.js +0 -37
  158. package/lib/renderers/react/react-hotspot.js.map +0 -1
  159. package/lib/renderers/react/react-image-material.d.ts +0 -28
  160. package/lib/renderers/react/react-image-material.d.ts.map +0 -1
  161. package/lib/renderers/react/react-image-material.js +0 -81
  162. package/lib/renderers/react/react-image-material.js.map +0 -1
  163. package/lib/renderers/react/react-material.d.ts +0 -19
  164. package/lib/renderers/react/react-material.d.ts.map +0 -1
  165. package/lib/renderers/react/react-material.js +0 -39
  166. package/lib/renderers/react/react-material.js.map +0 -1
  167. package/lib/renderers/react/react-mesh.d.ts +0 -11
  168. package/lib/renderers/react/react-mesh.d.ts.map +0 -1
  169. package/lib/renderers/react/react-mesh.js +0 -337
  170. package/lib/renderers/react/react-mesh.js.map +0 -1
  171. package/lib/renderers/react/react-scene.d.ts +0 -28
  172. package/lib/renderers/react/react-scene.d.ts.map +0 -1
  173. package/lib/renderers/react/react-scene.js +0 -13
  174. package/lib/renderers/react/react-scene.js.map +0 -1
  175. package/lib/renderers/react/react-types.d.ts +0 -7
  176. package/lib/renderers/react/react-types.d.ts.map +0 -1
  177. package/lib/renderers/react/react-types.js +0 -3
  178. package/lib/renderers/react/react-types.js.map +0 -1
  179. package/lib/renderers/shared.d.ts +0 -27
  180. package/lib/renderers/shared.d.ts.map +0 -1
  181. package/lib/renderers/shared.js +0 -131
  182. package/lib/renderers/shared.js.map +0 -1
  183. /package/src/renderers/{svg → svg-bsp}/svg-order.test.ts +0 -0
  184. /package/src/renderers/{svg → svg-bsp}/svg-order.ts +0 -0
@@ -0,0 +1,56 @@
1
+ import { createSVG } from "abstract-image";
2
+ import { exhaustiveCheck } from "ts-exhaustive-check";
3
+ import type { ImageMesh, Vec2, Vec3 } from "../../../abstract-3d.js";
4
+ import { vec2Scale, vec3TransRot, vec3RotCombine, vec3Zero, vec3 } from "../../../abstract-3d.js";
5
+ import type { EmbededImage } from "../svg-encoding.js";
6
+ import { rawSvgPrefix, svgImage } from "../svg-encoding.js";
7
+ import type { zOrderElement, SvgOptions } from "./shared.js";
8
+ import { zElem } from "./shared.js";
9
+
10
+ export function image(
11
+ i: ImageMesh,
12
+ point: (x: number, y: number) => Vec2,
13
+ opts: SvgOptions,
14
+ parentPos: Vec3,
15
+ parentRot: Vec3
16
+ ): ReadonlyArray<zOrderElement> {
17
+ const half = vec2Scale(i.size, 0.5);
18
+ const pos = vec3TransRot(i.pos, parentPos, parentRot);
19
+ const rot = vec3RotCombine(parentRot, i.rot ?? vec3Zero);
20
+ const vec3tr = (x: number, y: number): Vec3 => vec3TransRot(vec3(x, y, 0), pos, rot);
21
+
22
+ const v2 = vec3tr(half.x, -half.y);
23
+ const v4 = vec3tr(-half.x, half.y);
24
+ const corners = [vec3tr(-half.x, -half.y), v2, vec3tr(half.x, half.y), v4];
25
+
26
+ switch (i.image.type) {
27
+ case "AbstractImage": {
28
+ const scale = {
29
+ x: i.size.x / i.image.image.size.width,
30
+ y: i.size.y / i.image.image.size.height,
31
+ };
32
+ const svg = createSVG(i.image.image, opts);
33
+ 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, corners)];
35
+ }
36
+ case "Url": {
37
+ const imageData = opts.imageDataByUrl[i.image.url];
38
+ const image: EmbededImage | undefined = imageData?.startsWith(rawSvgPrefix)
39
+ ? {
40
+ type: "svg",
41
+ svg: decodeURIComponent(imageData.slice(rawSvgPrefix.length)).replace(/^\s*(<\?xml[^>]*\?>\s*)?(<!DOCTYPE[^>]*>\s*)?/i, ""),
42
+ }
43
+ : i.image.url
44
+ ? { type: "url", url: imageData ?? i.image.url }
45
+ : undefined;
46
+
47
+ if (image) {
48
+ 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, corners)];
50
+ }
51
+ return [];
52
+ }
53
+ default:
54
+ return exhaustiveCheck(i.image);
55
+ }
56
+ }
@@ -0,0 +1,21 @@
1
+ import type { CulledLine, Line, Vec2, Vec3 } from "../../../abstract-3d.js";
2
+ import { vec3TransRot, vec3ZMean } from "../../../abstract-3d.js";
3
+ import { rgbGrayScale } from "../../../utils.js";
4
+ import { svgLine } from "../svg-encoding.js";
5
+ import type { SvgOptions, zOrderElement } from "./shared.js";
6
+ import { zElem } from "./shared.js";
7
+
8
+ export function line(
9
+ l: Line | CulledLine,
10
+ point: (x: number, y: number) => Vec2,
11
+ fill: string,
12
+ opts: SvgOptions,
13
+ parentPos: Vec3,
14
+ parentRot: Vec3
15
+ ): ReadonlyArray<zOrderElement> {
16
+ const v1 = vec3TransRot(l.start, parentPos, parentRot);
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
+ ];
21
+ }
@@ -0,0 +1,43 @@
1
+ import type { Plane, Vec2, Vec3, Material, Hole } from "../../../abstract-3d.js";
2
+ import { vec2Scale, vec3TransRot, vec3RotCombine, vec3Zero, vec3, vec3ZMean } from "../../../abstract-3d.js";
3
+ import { rgbGrayScale } from "../../../utils.js";
4
+ import { svgPolygon } from "../svg-encoding.js";
5
+ import type { zOrderElement, SvgOptions } from "./shared.js";
6
+ import { gray, black, isOpaque, zElem } from "./shared.js";
7
+
8
+ export function plane(
9
+ p: Plane,
10
+ point: (x: number, y: number) => Vec2,
11
+ material: Material,
12
+ opts: SvgOptions,
13
+ parentPos: Vec3,
14
+ parentRot: Vec3,
15
+ holes?: ReadonlyArray<Hole>
16
+ ): ReadonlyArray<zOrderElement> {
17
+ const half = vec2Scale(p.size, 0.5);
18
+ const pos = vec3TransRot(p.pos, parentPos, parentRot);
19
+ const rot = vec3RotCombine(parentRot, p.rot ?? vec3Zero);
20
+ const vec3tr = (x: number, y: number): Vec3 => vec3TransRot(vec3(x, y, 0), pos, rot);
21
+
22
+ const v1 = vec3tr(-half.x, -half.y);
23
+ const v2 = vec3tr(half.x, -half.y);
24
+ const v3 = vec3tr(half.x, half.y);
25
+ const v4 = vec3tr(-half.x, half.y);
26
+
27
+ const points = [point(v1.x, v1.y), point(v2.x, v2.y), point(v3.x, v3.y), point(v4.x, v4.y)];
28
+
29
+ const [strokeColor, fill, strokeThickness] = opts.only_stroke
30
+ ? [opts.gray_scale ? gray : material.normal, opts.background, opts.stroke_thickness]
31
+ : [black, opts.gray_scale ? rgbGrayScale(material.normal) : material.normal, 0];
32
+ const opacity = material.opacity ?? 1.0;
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
+ ];
43
+ }
@@ -0,0 +1,33 @@
1
+ import type { Polygon, Vec3, Vec2, Material } from "../../../abstract-3d.js";
2
+ import { vec3ZMean, vec3TransRot, vec3RotCombine, vec3Zero } from "../../../abstract-3d.js";
3
+ import { rgbGrayScale } from "../../../utils.js";
4
+ import { svgPolygon } from "../svg-encoding.js";
5
+ import type { zOrderElement, SvgOptions } from "./shared.js";
6
+ import { gray, isOpaque, zElem, transparent } from "./shared.js";
7
+
8
+ export function polygon(
9
+ p: Polygon,
10
+ point: (x: number, y: number) => Vec2,
11
+ material: Material,
12
+ opts: SvgOptions,
13
+ parentPos: Vec3,
14
+ parentRot: Vec3
15
+ ): ReadonlyArray<zOrderElement> {
16
+ const pos = vec3TransRot(p.pos, parentPos, parentRot);
17
+ const rot = vec3RotCombine(parentRot, p.rot ?? vec3Zero);
18
+ const rotatedPoints = p.points.map((p) => vec3TransRot(p, pos, rot));
19
+ const points = rotatedPoints.map(({ x, y }) => point(x, y));
20
+ const color = material.normal;
21
+ const [strokeColor, fill, strokeThickness] = opts.only_stroke
22
+ ? [opts.gray_scale ? gray : color, opts.background, opts.stroke_thickness]
23
+ : [transparent, opts.gray_scale ? rgbGrayScale(color) : color, 0];
24
+ const opacity = material.opacity ?? 1.0;
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
+ ];
33
+ }
@@ -0,0 +1,34 @@
1
+ import type { Vec3, Vec2, Shape, Material } from "../../../abstract-3d.js";
2
+ import { vec3ZMean, vec3TransRot, vec3RotCombine, vec3, vec3Zero } from "../../../abstract-3d.js";
3
+ import { rgbGrayScale } from "../../../utils.js";
4
+ import { svgPolygon } from "../svg-encoding.js";
5
+ import type { zOrderElement, SvgOptions } from "./shared.js";
6
+ import { gray, isOpaque, zElem, transparent } from "./shared.js";
7
+
8
+ export function shape(
9
+ s: Shape,
10
+ point: (x: number, y: number) => Vec2,
11
+ material: Material,
12
+ opts: SvgOptions,
13
+ parentPos: Vec3,
14
+ parentRot: Vec3
15
+ ): ReadonlyArray<zOrderElement> {
16
+ const pos = vec3TransRot(s.pos, parentPos, parentRot);
17
+ const rot = vec3RotCombine(parentRot, s.rot ?? vec3Zero);
18
+ const rotatedPoints = s.points.map((p) => vec3TransRot(vec3(p.x, p.y, 0), pos, rot));
19
+ const points = rotatedPoints.map(({ x, y }) => point(x, y));
20
+ const color = material.normal;
21
+ const [strokeColor, fill] = opts.only_stroke
22
+ ? [opts.gray_scale ? gray : color, opts.background]
23
+ : [transparent, opts.gray_scale ? rgbGrayScale(color) : color];
24
+ const opacity = material.opacity ?? 1.0;
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
+ ];
34
+ }
@@ -0,0 +1,40 @@
1
+ import type { Text, Vec2, Vec3 } from "../../../abstract-3d.js";
2
+ import { vec3TransRot, vec3RotCombine, vec3Zero, vec3, vec3Dot, vec3Rot } from "../../../abstract-3d.js";
3
+ import { svgText } from "../svg-encoding.js";
4
+ import type { SvgOptions, zOrderElement } from "./shared.js";
5
+ import { svgTrsMatrix, zElem } from "./shared.js";
6
+
7
+ const SVG_FORWARD: Vec3 = vec3(0.0, 0.0, 1.0);
8
+ const SVG_DOT_OPPOSITE_THRESHOLD: number = -0.9;
9
+
10
+ // dummy
11
+ export function text(
12
+ t: Text,
13
+ point: (x: number, y: number) => Vec2,
14
+ fill: string,
15
+ opts: SvgOptions,
16
+ parentPos: Vec3,
17
+ parentRot: Vec3
18
+ ): ReadonlyArray<zOrderElement> {
19
+ const pos = vec3TransRot(t.pos, parentPos, parentRot);
20
+ const rot = vec3RotCombine(parentRot, t.rot ?? vec3Zero);
21
+
22
+ const textForward = vec3Rot({ x: 0, y: 0, z: 1 }, vec3Zero, rot);
23
+
24
+ //discard texts that are pointing away
25
+ if (vec3Dot(textForward, SVG_FORWARD) <= SVG_DOT_OPPOSITE_THRESHOLD) {
26
+ return [];
27
+ }
28
+
29
+ const texts = Array<zOrderElement>();
30
+ const fontSize = t.fontSize;
31
+ const strings = t.text.split("\n");
32
+ let posY = strings.length === 1 ? 0 : (fontSize * strings.length - fontSize) / 2;
33
+ for (const s of strings) {
34
+ const matrix = svgTrsMatrix(point(pos.x, pos.y + posY), rot);
35
+ texts.push(zElem(svgText(s, matrix, fill, opts.font, fontSize), pos.z, [pos]));
36
+ posY -= fontSize * 1.2;
37
+ }
38
+
39
+ return texts;
40
+ }
@@ -0,0 +1,183 @@
1
+ import { exhaustiveCheck } from "ts-exhaustive-check";
2
+ import type { Scene, Vec3, Mesh, Vec2, Group, Material, Bounds2 } from "../../abstract-3d.js";
3
+ import {
4
+ vec2,
5
+ vec3Rot,
6
+ vec3Zero,
7
+ vec3RotCombine,
8
+ vec3,
9
+ vec3TransRot,
10
+ rotationForCameraPos,
11
+ sizeBoundsForCameraPos,
12
+ bounds2FromPosAndSize,
13
+ bounds2ToSize,
14
+ bounds2Merge,
15
+ vec2Zero,
16
+ vec3Flip,
17
+ dimensionConvertToTypeMesh,
18
+ } from "../../abstract-3d.js";
19
+ import type { Optional } from "../../utils.js";
20
+ import { calculateVisibleViews, isViewVisible } from "../../utils.js";
21
+ import { svg } from "./svg-encoding.js";
22
+ import type { SvgOptions, zOrderElement } from "./svg-geometries/shared.js";
23
+ import { box } from "./svg-geometries/svg-box.js";
24
+ import { cone } from "./svg-geometries/svg-cone.js";
25
+ import { cylinder } from "./svg-geometries/svg-cylinder.js";
26
+ import { image } from "./svg-geometries/svg-image.js";
27
+ import { line } from "./svg-geometries/svg-line.js";
28
+ import { plane } from "./svg-geometries/svg-plane.js";
29
+ import { polygon } from "./svg-geometries/svg-polygon.js";
30
+ import { shape } from "./svg-geometries/svg-shape.js";
31
+ import { text } from "./svg-geometries/svg-text.js";
32
+ import { orderElements } from "./svg-order.js";
33
+
34
+ export type SvgScene = {
35
+ readonly scene: Scene;
36
+ readonly options?: Optional<SvgOptions>;
37
+ readonly pos: Vec2;
38
+ };
39
+
40
+ export type SvgWithSize = { readonly image: string; readonly width: number; readonly height: number };
41
+
42
+ export function renderScenes(scenes: ReadonlyArray<SvgScene>, baseOptions?: Optional<SvgOptions>): SvgWithSize {
43
+ const allElements = Array<zOrderElement>();
44
+ const bounds = Array<Bounds2>();
45
+
46
+ for (const view of scenes) {
47
+ const { elements, size, center } = renderInternal(view.scene, { ...baseOptions, ...view.options }, view.pos);
48
+ allElements.push(...elements);
49
+ const newBounds = bounds2FromPosAndSize(center, size);
50
+ bounds.push(newBounds);
51
+ }
52
+ const mergedBounds = bounds2Merge(...bounds);
53
+ const size = bounds2ToSize(mergedBounds);
54
+ const image = svg(
55
+ mergedBounds.min,
56
+ size,
57
+ allElements.reduce((a, { element }) => `${a} ${element}`, ""),
58
+ baseOptions?.className ?? ""
59
+ );
60
+ return { image, width: size.x, height: size.y };
61
+ }
62
+
63
+ export function render(scene: Scene, options?: Optional<SvgOptions>): SvgWithSize {
64
+ const { elements, size, center } = renderInternal(scene, options, vec2Zero);
65
+
66
+ const image = svg(
67
+ vec2(center.x - size.x / 2, center.y - size.y / 2),
68
+ size,
69
+ elements.reduce((a, { element }) => `${a} ${element}`, ""),
70
+ options?.className ?? ""
71
+ );
72
+ return { image, width: size.x, height: size.y };
73
+ }
74
+
75
+ function renderInternal(
76
+ scene: Scene,
77
+ options: Optional<SvgOptions> | undefined,
78
+ offset: Vec2
79
+ ): {
80
+ readonly elements: ReadonlyArray<zOrderElement>;
81
+ readonly size: Vec2;
82
+ readonly center: Vec2;
83
+ } {
84
+ const opts: SvgOptions = {
85
+ view: options?.view ?? "front",
86
+ stroke_thickness: options?.stroke_thickness ?? 2,
87
+ only_stroke: options?.only_stroke ?? false,
88
+ gray_scale: options?.gray_scale ?? false,
89
+ background: options?.background ?? "rgba(255,255,255,0)",
90
+ font: options?.font ?? "",
91
+ imageDataByUrl: options?.imageDataByUrl ?? {},
92
+ rotation: options?.rotation ?? 0,
93
+ imageBg: options?.imageBg ?? false,
94
+ className: options?.className ?? "",
95
+ };
96
+ // A three-quarter view: the front turned 30° to show the side, and tilted 20° to show the top, the front foremost
97
+ const angled = opts.view === "TopLeft" || opts.view === "TopRight";
98
+ const view = angled ? "front" : opts.view;
99
+ const angledRot = angled
100
+ ? vec3RotCombine(vec3((20 * Math.PI) / 180, 0, 0), vec3(0, ((opts.view === "TopRight" ? -1 : 1) * 30 * Math.PI) / 180, 0))
101
+ : vec3Zero;
102
+ const cameraRot = vec3RotCombine(angledRot, rotationForCameraPos(view));
103
+ const viewRot = opts.rotation ? vec3RotCombine(vec3(0, 0, (opts.rotation * Math.PI) / 180), cameraRot) : cameraRot;
104
+ const unitRot = vec3RotCombine(viewRot, scene.rotation_deprecated ?? vec3Zero);
105
+
106
+ const unitCenter = vec3Rot(scene.center_deprecated ?? vec3Zero, vec3Zero, cameraRot);
107
+ const [unitSize] = sizeBoundsForCameraPos(scene.size_deprecated, unitCenter, unitRot);
108
+ const svgSize = vec2(unitSize.x + 1.5 * opts.stroke_thickness, unitSize.y + 1.5 * opts.stroke_thickness);
109
+ const svgCenter = vec2(offset.x + opts.stroke_thickness * 0.75, offset.y + opts.stroke_thickness * 0.75);
110
+ const point = (x: number, y: number): Vec2 => vec2(svgCenter.x + x, svgCenter.y - y);
111
+ const unitCenterFlipped = vec3Flip(unitCenter);
112
+
113
+ const elements = [
114
+ ...orderElements(
115
+ scene.groups.flatMap((g) => svgGroup(g, unitCenterFlipped, unitRot, point, opts)),
116
+ point
117
+ ),
118
+ ];
119
+ const dimOpts: SvgOptions = { ...opts, only_stroke: false, gray_scale: false };
120
+ const visibleViews = calculateVisibleViews(view, scene.rotation_deprecated);
121
+
122
+ // Dimensions are drawn for the flat views
123
+ for (const dim of angled ? [] : (scene.dimensions_deprecated?.dimensions ?? [])) {
124
+ const d = dimensionConvertToTypeMesh(dim, scene.rotation_deprecated ?? vec3Zero, scene.dimensions_deprecated?.material);
125
+ if (isViewVisible(d.views[0], visibleViews)) {
126
+ const pos = vec3TransRot(d.pos, unitCenterFlipped, unitRot);
127
+ const rot = vec3RotCombine(unitRot, d.rot);
128
+ for (const m of d.meshes) {
129
+ elements.push(...svgMesh(m, pos, rot, point, scene.dimensions_deprecated?.material ?? { normal: "" }, dimOpts));
130
+ }
131
+ }
132
+ }
133
+ return { elements, size: svgSize, center: svgCenter };
134
+ }
135
+
136
+ function svgGroup(g: Group, parentPos: Vec3, parentRot: Vec3, point: (x: number, y: number) => Vec2, opts: SvgOptions): ReadonlyArray<zOrderElement> {
137
+ const pos = vec3TransRot(g.pos, parentPos, parentRot);
138
+ const rot = vec3RotCombine(parentRot, g.rot ?? vec3Zero);
139
+ const elements = Array<zOrderElement>();
140
+ for (const m of g.meshes ?? []) {
141
+ elements.push(...svgMesh(m, pos, rot, point, m.material, opts));
142
+ }
143
+ for (const sg of g.groups ?? []) {
144
+ elements.push(...svgGroup(sg, pos, rot, point, opts));
145
+ }
146
+ return elements;
147
+ }
148
+
149
+ function svgMesh(
150
+ mesh: Mesh,
151
+ parentPos: Vec3,
152
+ parentRot: Vec3,
153
+ point: (x: number, y: number) => Vec2,
154
+ material: Material,
155
+ opts: SvgOptions
156
+ ): ReadonlyArray<zOrderElement> {
157
+ switch (mesh.geometry.type) {
158
+ case "Box":
159
+ return box(mesh.geometry, point, material, opts, parentPos, parentRot);
160
+ case "Plane":
161
+ return plane(mesh.geometry, point, material, opts, parentPos, parentRot);
162
+ case "Cylinder":
163
+ return cylinder(mesh.geometry, point, material, opts, parentPos, parentRot);
164
+ case "Cone":
165
+ return cone(mesh.geometry, point, material, opts, parentPos, parentRot);
166
+ case "CulledLine":
167
+ case "Line":
168
+ return line(mesh.geometry, point, material.normal, opts, parentPos, parentRot);
169
+ case "Polygon":
170
+ return polygon(mesh.geometry, point, material, opts, parentPos, parentRot);
171
+ case "Shape":
172
+ return shape(mesh.geometry, point, material, opts, parentPos, parentRot);
173
+ case "Text":
174
+ return text(mesh.geometry, point, material.normal, opts, parentPos, parentRot);
175
+ case "Image":
176
+ return image(mesh.geometry, point, opts, parentPos, parentRot);
177
+ case "Tube":
178
+ case "Sphere":
179
+ return [];
180
+ default:
181
+ return exhaustiveCheck(mesh.geometry);
182
+ }
183
+ }
@@ -129,14 +129,18 @@ describe("buildScene", () => {
129
129
  expect(position.toArray().map((v) => Math.round(v * 1000) / 1000 + 0)).toEqual([5, 1, 0]);
130
130
  });
131
131
 
132
- it("hides culled lines that face away from the camera", () => {
133
- const built = build(scene([group([culledLine(vec3(0, 0, 0), vec3(10, 0, 0), vec3(0, 0, 1), 1, red)])]));
132
+ it("doesn't draw culled lines that face away from the camera", () => {
133
+ const built = build(
134
+ scene([
135
+ group([culledLine(vec3(0, 0, 0), vec3(10, 0, 0), vec3(0, 0, 1), 1, red), culledLine(vec3(0, 0, 0), vec3(20, 0, 0), vec3(0, 0, -1), 1, red)]),
136
+ ])
137
+ );
134
138
  const line = built.parts.find((p) => p.kind === "line")!;
135
139
  const endX = (): number => (line.object.geometry.getAttribute("instanceEnd") as unknown as { readonly getX: (i: number) => number }).getX(0);
136
140
  cullScene(built, new Vector3(0, 0, -100));
137
- expect(endX()).toBe(0);
141
+ expect([line.object.geometry.instanceCount, endX()]).toEqual([1, 20]);
138
142
  cullScene(built, new Vector3(0, 0, 100));
139
- expect(endX()).toBe(10);
143
+ expect([line.object.geometry.instanceCount, endX()]).toEqual([1, 10]);
140
144
  });
141
145
 
142
146
  it("disposes its batches and materials", () => {
@@ -50,8 +50,9 @@ export type Part =
50
50
  readonly kind: "line";
51
51
  readonly object: LineSegments2;
52
52
  readonly segments: ReadonlyArray<Segment>;
53
- /** World start, end and normal of each segment, while the drawn positions collapse hidden ones */
53
+ /** World start, end and normal, and color, of each segment, while the drawn ones are its visible ones packed first */
54
54
  readonly world: Float32Array;
55
+ readonly rgb: Float32Array;
55
56
  readonly visible: Uint8Array;
56
57
  readonly positions: InterleavedBuffer;
57
58
  readonly colors: InterleavedBuffer;
@@ -114,6 +115,7 @@ export function createLinePart(segments: ReadonlyArray<Segment>, thickness: numb
114
115
  object: line,
115
116
  segments,
116
117
  world: new Float32Array(segments.length * 9),
118
+ rgb: new Float32Array(segments.length * 3),
117
119
  visible: new Uint8Array(segments.length).fill(1),
118
120
  positions: (geometry.getAttribute("instanceStart") as InterleavedBufferAttribute).data,
119
121
  colors: (geometry.getAttribute("instanceColorStart") as InterleavedBufferAttribute).data,
@@ -145,7 +147,6 @@ export function placeSlot(part: Part, slot: number, matrix: Matrix4): void {
145
147
  part.world.set(vector.set(start.x, start.y, start.z).applyMatrix4(matrix).toArray(), slot * 9);
146
148
  part.world.set(vector.set(end.x, end.y, end.z).applyMatrix4(matrix).toArray(), slot * 9 + 3);
147
149
  part.world.set(normal ? vector.set(normal.x, normal.y, normal.z).transformDirection(matrix).toArray() : [0, 0, 0], slot * 9 + 6);
148
- writeSegment(part, slot);
149
150
  break;
150
151
  }
151
152
  default:
@@ -165,7 +166,7 @@ export function paintSlot(part: Part, slot: number, rgba: Vector4): void {
165
166
  }
166
167
  break;
167
168
  case "line":
168
- part.colors.array.set([rgba.x, rgba.y, rgba.z, rgba.x, rgba.y, rgba.z], slot * 6);
169
+ part.rgb.set([rgba.x, rgba.y, rgba.z], slot * 3);
169
170
  break;
170
171
  default:
171
172
  part.object.material.color.setRGB(rgba.x, rgba.y, rgba.z);
@@ -188,8 +189,7 @@ export function flushPart(part: Part, moved: boolean): void {
188
189
  part.object.boundingSphere = null;
189
190
  break;
190
191
  case "line":
191
- part.positions.needsUpdate = true;
192
- part.colors.needsUpdate = true;
192
+ writeSegments(part);
193
193
  break;
194
194
  default:
195
195
  }
@@ -214,19 +214,20 @@ export function cullLines(part: Part, cameraPosition: Vector3): void {
214
214
  if (part.kind !== "line") {
215
215
  return;
216
216
  }
217
- part.segments.forEach((segment, slot) => {
217
+ const changed = part.segments.reduce((acc, segment, slot) => {
218
218
  const w = slot * 9;
219
219
  const mid = vector
220
220
  .fromArray(part.world, w)
221
221
  .add(normal.fromArray(part.world, w + 3))
222
222
  .multiplyScalar(0.5);
223
223
  const facing = !segment.normal || normal.fromArray(part.world, w + 6).dot(mid.subVectors(cameraPosition, mid)) > 0 ? 1 : 0;
224
- if (facing !== part.visible[slot]) {
225
- part.visible[slot] = facing;
226
- writeSegment(part, slot);
227
- part.positions.needsUpdate = true;
228
- }
229
- });
224
+ const flipped = facing !== part.visible[slot];
225
+ part.visible[slot] = facing;
226
+ return acc || flipped;
227
+ }, false);
228
+ if (changed) {
229
+ writeSegments(part);
230
+ }
230
231
  }
231
232
 
232
233
  export function disposePart(part: Part): void {
@@ -239,13 +240,20 @@ export function disposePart(part: Part): void {
239
240
  (Array.isArray(materials) ? materials : [materials]).forEach((m: Material) => m.dispose());
240
241
  }
241
242
 
242
- /** A hidden segment collapses to its start */
243
- function writeSegment(part: Extract<Part, { readonly kind: "line" }>, slot: number): void {
244
- const w = slot * 9;
245
- part.positions.array.set(
246
- part.visible[slot] ? part.world.subarray(w, w + 6) : [...part.world.subarray(w, w + 3), ...part.world.subarray(w, w + 3)],
247
- slot * 6
248
- );
243
+ /** Packs the visible segments first and draws only those, as a hidden one collapsed to a point still drew a dot of the line's caps */
244
+ function writeSegments(part: Extract<Part, { readonly kind: "line" }>): void {
245
+ const drawn = part.segments.reduce((d, _, slot) => {
246
+ if (!part.visible[slot]) {
247
+ return d;
248
+ }
249
+ const rgb = part.rgb.subarray(slot * 3, slot * 3 + 3);
250
+ part.positions.array.set(part.world.subarray(slot * 9, slot * 9 + 6), d * 6);
251
+ part.colors.array.set([...rgb, ...rgb], d * 6);
252
+ return d + 1;
253
+ }, 0);
254
+ part.object.geometry.instanceCount = drawn;
255
+ part.positions.needsUpdate = true;
256
+ part.colors.needsUpdate = true;
249
257
  }
250
258
 
251
259
  const textVertexShader = /* glsl */ `
@@ -1,7 +0,0 @@
1
- import { Color } from "abstract-image";
2
- import { Vec3 } from "../../abstract-3d.js";
3
- export declare function colorToInteger(color: string): number;
4
- export declare function colorHexFromAbstractImageColor(color: Color): string;
5
- export declare function color(colorNormal: string | undefined): number;
6
- export declare const ACI_COLOR_TABLE: ReadonlyArray<Vec3>;
7
- //# sourceMappingURL=color.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"color.d.ts","sourceRoot":"","sources":["../../../src/renderers/dxf/color.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,IAAI,EAAyB,MAAM,sBAAsB,CAAC;AAEnE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQpD;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAEnE;AAED,wBAAgB,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAqB7D;AAsBD,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,IAAI,CAiQ/C,CAAC"}