abstract-3d 0.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 (219) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +7 -0
  4. package/lib/abstract-3d.d.ts +317 -0
  5. package/lib/abstract-3d.d.ts.map +1 -0
  6. package/lib/abstract-3d.js +333 -0
  7. package/lib/abstract-3d.js.map +1 -0
  8. package/lib/index.d.ts +3 -0
  9. package/lib/index.d.ts.map +1 -0
  10. package/lib/index.js +19 -0
  11. package/lib/index.js.map +1 -0
  12. package/lib/renderers/dxf/dxf-encoding.d.ts +7 -0
  13. package/lib/renderers/dxf/dxf-encoding.d.ts.map +1 -0
  14. package/lib/renderers/dxf/dxf-encoding.js +343 -0
  15. package/lib/renderers/dxf/dxf-encoding.js.map +1 -0
  16. package/lib/renderers/dxf/dxf-geometries/dxf-box.d.ts +3 -0
  17. package/lib/renderers/dxf/dxf-geometries/dxf-box.d.ts.map +1 -0
  18. package/lib/renderers/dxf/dxf-geometries/dxf-box.js +52 -0
  19. package/lib/renderers/dxf/dxf-geometries/dxf-box.js.map +1 -0
  20. package/lib/renderers/dxf/dxf-geometries/dxf-cone.d.ts +3 -0
  21. package/lib/renderers/dxf/dxf-geometries/dxf-cone.d.ts.map +1 -0
  22. package/lib/renderers/dxf/dxf-geometries/dxf-cone.js +54 -0
  23. package/lib/renderers/dxf/dxf-geometries/dxf-cone.js.map +1 -0
  24. package/lib/renderers/dxf/dxf-geometries/dxf-cylinder.d.ts +3 -0
  25. package/lib/renderers/dxf/dxf-geometries/dxf-cylinder.d.ts.map +1 -0
  26. package/lib/renderers/dxf/dxf-geometries/dxf-cylinder.js +62 -0
  27. package/lib/renderers/dxf/dxf-geometries/dxf-cylinder.js.map +1 -0
  28. package/lib/renderers/dxf/dxf-geometries/dxf-plane.d.ts +3 -0
  29. package/lib/renderers/dxf/dxf-geometries/dxf-plane.d.ts.map +1 -0
  30. package/lib/renderers/dxf/dxf-geometries/dxf-plane.js +38 -0
  31. package/lib/renderers/dxf/dxf-geometries/dxf-plane.js.map +1 -0
  32. package/lib/renderers/dxf/dxf-geometries/dxf-polygon.d.ts +3 -0
  33. package/lib/renderers/dxf/dxf-geometries/dxf-polygon.d.ts.map +1 -0
  34. package/lib/renderers/dxf/dxf-geometries/dxf-polygon.js +61 -0
  35. package/lib/renderers/dxf/dxf-geometries/dxf-polygon.js.map +1 -0
  36. package/lib/renderers/dxf/dxf-geometries/dxf-shape.d.ts +3 -0
  37. package/lib/renderers/dxf/dxf-geometries/dxf-shape.d.ts.map +1 -0
  38. package/lib/renderers/dxf/dxf-geometries/dxf-shape.js +61 -0
  39. package/lib/renderers/dxf/dxf-geometries/dxf-shape.js.map +1 -0
  40. package/lib/renderers/dxf/dxf.d.ts +3 -0
  41. package/lib/renderers/dxf/dxf.d.ts.map +1 -0
  42. package/lib/renderers/dxf/dxf.js +64 -0
  43. package/lib/renderers/dxf/dxf.js.map +1 -0
  44. package/lib/renderers/dxf/index.d.ts +2 -0
  45. package/lib/renderers/dxf/index.d.ts.map +1 -0
  46. package/lib/renderers/dxf/index.js +18 -0
  47. package/lib/renderers/dxf/index.js.map +1 -0
  48. package/lib/renderers/index.d.ts +5 -0
  49. package/lib/renderers/index.d.ts.map +1 -0
  50. package/lib/renderers/index.js +21 -0
  51. package/lib/renderers/index.js.map +1 -0
  52. package/lib/renderers/react/index.d.ts +6 -0
  53. package/lib/renderers/react/index.d.ts.map +1 -0
  54. package/lib/renderers/react/index.js +21 -0
  55. package/lib/renderers/react/index.js.map +1 -0
  56. package/lib/renderers/react/react-camera.d.ts +60 -0
  57. package/lib/renderers/react/react-camera.d.ts.map +1 -0
  58. package/lib/renderers/react/react-camera.js +132 -0
  59. package/lib/renderers/react/react-camera.js.map +1 -0
  60. package/lib/renderers/react/react-dimension.d.ts +12 -0
  61. package/lib/renderers/react/react-dimension.d.ts.map +1 -0
  62. package/lib/renderers/react/react-dimension.js +39 -0
  63. package/lib/renderers/react/react-dimension.js.map +1 -0
  64. package/lib/renderers/react/react-group.d.ts +18 -0
  65. package/lib/renderers/react/react-group.d.ts.map +1 -0
  66. package/lib/renderers/react/react-group.js +62 -0
  67. package/lib/renderers/react/react-group.js.map +1 -0
  68. package/lib/renderers/react/react-hotspot.d.ts +30 -0
  69. package/lib/renderers/react/react-hotspot.d.ts.map +1 -0
  70. package/lib/renderers/react/react-hotspot.js +71 -0
  71. package/lib/renderers/react/react-hotspot.js.map +1 -0
  72. package/lib/renderers/react/react-material.d.ts +13 -0
  73. package/lib/renderers/react/react-material.d.ts.map +1 -0
  74. package/lib/renderers/react/react-material.js +85 -0
  75. package/lib/renderers/react/react-material.js.map +1 -0
  76. package/lib/renderers/react/react-mesh.d.ts +10 -0
  77. package/lib/renderers/react/react-mesh.d.ts.map +1 -0
  78. package/lib/renderers/react/react-mesh.js +238 -0
  79. package/lib/renderers/react/react-mesh.js.map +1 -0
  80. package/lib/renderers/react/react-scene.d.ts +20 -0
  81. package/lib/renderers/react/react-scene.d.ts.map +1 -0
  82. package/lib/renderers/react/react-scene.js +44 -0
  83. package/lib/renderers/react/react-scene.js.map +1 -0
  84. package/lib/renderers/react/react.d.ts +30 -0
  85. package/lib/renderers/react/react.d.ts.map +1 -0
  86. package/lib/renderers/react/react.js +48 -0
  87. package/lib/renderers/react/react.js.map +1 -0
  88. package/lib/renderers/shared.d.ts +6 -0
  89. package/lib/renderers/shared.d.ts.map +1 -0
  90. package/lib/renderers/shared.js +93 -0
  91. package/lib/renderers/shared.js.map +1 -0
  92. package/lib/renderers/stl/index.d.ts +2 -0
  93. package/lib/renderers/stl/index.d.ts.map +1 -0
  94. package/lib/renderers/stl/index.js +18 -0
  95. package/lib/renderers/stl/index.js.map +1 -0
  96. package/lib/renderers/stl/stl-encoding.d.ts +4 -0
  97. package/lib/renderers/stl/stl-encoding.d.ts.map +1 -0
  98. package/lib/renderers/stl/stl-encoding.js +26 -0
  99. package/lib/renderers/stl/stl-encoding.js.map +1 -0
  100. package/lib/renderers/stl/stl-geometries/stl-box.d.ts +3 -0
  101. package/lib/renderers/stl/stl-geometries/stl-box.d.ts.map +1 -0
  102. package/lib/renderers/stl/stl-geometries/stl-box.js +57 -0
  103. package/lib/renderers/stl/stl-geometries/stl-box.js.map +1 -0
  104. package/lib/renderers/stl/stl-geometries/stl-cone.d.ts +3 -0
  105. package/lib/renderers/stl/stl-geometries/stl-cone.d.ts.map +1 -0
  106. package/lib/renderers/stl/stl-geometries/stl-cone.js +54 -0
  107. package/lib/renderers/stl/stl-geometries/stl-cone.js.map +1 -0
  108. package/lib/renderers/stl/stl-geometries/stl-cylinder.d.ts +3 -0
  109. package/lib/renderers/stl/stl-geometries/stl-cylinder.d.ts.map +1 -0
  110. package/lib/renderers/stl/stl-geometries/stl-cylinder.js +62 -0
  111. package/lib/renderers/stl/stl-geometries/stl-cylinder.js.map +1 -0
  112. package/lib/renderers/stl/stl-geometries/stl-plane.d.ts +3 -0
  113. package/lib/renderers/stl/stl-geometries/stl-plane.d.ts.map +1 -0
  114. package/lib/renderers/stl/stl-geometries/stl-plane.js +44 -0
  115. package/lib/renderers/stl/stl-geometries/stl-plane.js.map +1 -0
  116. package/lib/renderers/stl/stl-geometries/stl-polygon.d.ts +3 -0
  117. package/lib/renderers/stl/stl-geometries/stl-polygon.d.ts.map +1 -0
  118. package/lib/renderers/stl/stl-geometries/stl-polygon.js +59 -0
  119. package/lib/renderers/stl/stl-geometries/stl-polygon.js.map +1 -0
  120. package/lib/renderers/stl/stl-geometries/stl-shape.d.ts +3 -0
  121. package/lib/renderers/stl/stl-geometries/stl-shape.d.ts.map +1 -0
  122. package/lib/renderers/stl/stl-geometries/stl-shape.js +59 -0
  123. package/lib/renderers/stl/stl-geometries/stl-shape.js.map +1 -0
  124. package/lib/renderers/stl/stl.d.ts +3 -0
  125. package/lib/renderers/stl/stl.d.ts.map +1 -0
  126. package/lib/renderers/stl/stl.js +57 -0
  127. package/lib/renderers/stl/stl.js.map +1 -0
  128. package/lib/renderers/svg/index.d.ts +3 -0
  129. package/lib/renderers/svg/index.d.ts.map +1 -0
  130. package/lib/renderers/svg/index.js +18 -0
  131. package/lib/renderers/svg/index.js.map +1 -0
  132. package/lib/renderers/svg/svg-encoding.d.ts +14 -0
  133. package/lib/renderers/svg/svg-encoding.d.ts.map +1 -0
  134. package/lib/renderers/svg/svg-encoding.js +27 -0
  135. package/lib/renderers/svg/svg-encoding.js.map +1 -0
  136. package/lib/renderers/svg/svg-geometries/shared.d.ts +12 -0
  137. package/lib/renderers/svg/svg-geometries/shared.d.ts.map +1 -0
  138. package/lib/renderers/svg/svg-geometries/shared.js +12 -0
  139. package/lib/renderers/svg/svg-geometries/shared.js.map +1 -0
  140. package/lib/renderers/svg/svg-geometries/svg-box.d.ts +4 -0
  141. package/lib/renderers/svg/svg-geometries/svg-box.d.ts.map +1 -0
  142. package/lib/renderers/svg/svg-geometries/svg-box.js +70 -0
  143. package/lib/renderers/svg/svg-geometries/svg-box.js.map +1 -0
  144. package/lib/renderers/svg/svg-geometries/svg-cone.d.ts +4 -0
  145. package/lib/renderers/svg/svg-geometries/svg-cone.d.ts.map +1 -0
  146. package/lib/renderers/svg/svg-geometries/svg-cone.js +64 -0
  147. package/lib/renderers/svg/svg-geometries/svg-cone.js.map +1 -0
  148. package/lib/renderers/svg/svg-geometries/svg-cylinder.d.ts +4 -0
  149. package/lib/renderers/svg/svg-geometries/svg-cylinder.d.ts.map +1 -0
  150. package/lib/renderers/svg/svg-geometries/svg-cylinder.js +69 -0
  151. package/lib/renderers/svg/svg-geometries/svg-cylinder.js.map +1 -0
  152. package/lib/renderers/svg/svg-geometries/svg-line.d.ts +4 -0
  153. package/lib/renderers/svg/svg-geometries/svg-line.d.ts.map +1 -0
  154. package/lib/renderers/svg/svg-geometries/svg-line.js +39 -0
  155. package/lib/renderers/svg/svg-geometries/svg-line.js.map +1 -0
  156. package/lib/renderers/svg/svg-geometries/svg-plane.d.ts +5 -0
  157. package/lib/renderers/svg/svg-geometries/svg-plane.d.ts.map +1 -0
  158. package/lib/renderers/svg/svg-geometries/svg-plane.js +57 -0
  159. package/lib/renderers/svg/svg-geometries/svg-plane.js.map +1 -0
  160. package/lib/renderers/svg/svg-geometries/svg-polygon.d.ts +4 -0
  161. package/lib/renderers/svg/svg-geometries/svg-polygon.d.ts.map +1 -0
  162. package/lib/renderers/svg/svg-geometries/svg-polygon.js +20 -0
  163. package/lib/renderers/svg/svg-geometries/svg-polygon.js.map +1 -0
  164. package/lib/renderers/svg/svg-geometries/svg-shape.d.ts +4 -0
  165. package/lib/renderers/svg/svg-geometries/svg-shape.d.ts.map +1 -0
  166. package/lib/renderers/svg/svg-geometries/svg-shape.js +20 -0
  167. package/lib/renderers/svg/svg-geometries/svg-shape.js.map +1 -0
  168. package/lib/renderers/svg/svg-geometries/svg-text.d.ts +4 -0
  169. package/lib/renderers/svg/svg-geometries/svg-text.d.ts.map +1 -0
  170. package/lib/renderers/svg/svg-geometries/svg-text.js +46 -0
  171. package/lib/renderers/svg/svg-geometries/svg-text.js.map +1 -0
  172. package/lib/renderers/svg/svg.d.ts +10 -0
  173. package/lib/renderers/svg/svg.d.ts.map +1 -0
  174. package/lib/renderers/svg/svg.js +98 -0
  175. package/lib/renderers/svg/svg.js.map +1 -0
  176. package/package.json +31 -0
  177. package/src/abstract-3d.ts +578 -0
  178. package/src/index.ts +2 -0
  179. package/src/renderers/dxf/dxf-encoding.ts +348 -0
  180. package/src/renderers/dxf/dxf-geometries/dxf-box.ts +27 -0
  181. package/src/renderers/dxf/dxf-geometries/dxf-cone.ts +31 -0
  182. package/src/renderers/dxf/dxf-geometries/dxf-cylinder.ts +45 -0
  183. package/src/renderers/dxf/dxf-geometries/dxf-plane.ts +16 -0
  184. package/src/renderers/dxf/dxf-geometries/dxf-polygon.ts +36 -0
  185. package/src/renderers/dxf/dxf-geometries/dxf-shape.ts +36 -0
  186. package/src/renderers/dxf/dxf.ts +38 -0
  187. package/src/renderers/dxf/index.ts +1 -0
  188. package/src/renderers/index.ts +4 -0
  189. package/src/renderers/react/index.ts +5 -0
  190. package/src/renderers/react/react-camera.tsx +208 -0
  191. package/src/renderers/react/react-dimension.tsx +76 -0
  192. package/src/renderers/react/react-group.tsx +133 -0
  193. package/src/renderers/react/react-hotspot.tsx +116 -0
  194. package/src/renderers/react/react-material.tsx +159 -0
  195. package/src/renderers/react/react-mesh.tsx +380 -0
  196. package/src/renderers/react/react-scene.tsx +137 -0
  197. package/src/renderers/react/react.tsx +118 -0
  198. package/src/renderers/shared.ts +111 -0
  199. package/src/renderers/stl/index.ts +1 -0
  200. package/src/renderers/stl/stl-encoding.ts +22 -0
  201. package/src/renderers/stl/stl-geometries/stl-box.ts +33 -0
  202. package/src/renderers/stl/stl-geometries/stl-cone.ts +37 -0
  203. package/src/renderers/stl/stl-geometries/stl-cylinder.ts +45 -0
  204. package/src/renderers/stl/stl-geometries/stl-plane.ts +16 -0
  205. package/src/renderers/stl/stl-geometries/stl-polygon.ts +35 -0
  206. package/src/renderers/stl/stl-geometries/stl-shape.ts +35 -0
  207. package/src/renderers/stl/stl.ts +33 -0
  208. package/src/renderers/svg/index.ts +2 -0
  209. package/src/renderers/svg/svg-encoding.ts +46 -0
  210. package/src/renderers/svg/svg-geometries/shared.ts +10 -0
  211. package/src/renderers/svg/svg-geometries/svg-box.ts +61 -0
  212. package/src/renderers/svg/svg-geometries/svg-cone.ts +52 -0
  213. package/src/renderers/svg/svg-geometries/svg-cylinder.ts +58 -0
  214. package/src/renderers/svg/svg-geometries/svg-line.ts +20 -0
  215. package/src/renderers/svg/svg-geometries/svg-plane.ts +44 -0
  216. package/src/renderers/svg/svg-geometries/svg-polygon.ts +25 -0
  217. package/src/renderers/svg/svg-geometries/svg-shape.ts +25 -0
  218. package/src/renderers/svg/svg-geometries/svg-text.ts +28 -0
  219. package/src/renderers/svg/svg.ts +201 -0
@@ -0,0 +1,380 @@
1
+ /* eslint-disable functional/no-class */
2
+ /* eslint-disable functional/no-this-expression */
3
+ /* eslint-disable functional/prefer-readonly-type */
4
+ import React from "react";
5
+ // import { Text } from "@react-three/drei/core/Text";
6
+ // import { Line } from "@react-three/drei/core/Line";
7
+ import { Text, Line } from "@react-three/drei";
8
+ import {
9
+ BoxGeometry,
10
+ CylinderGeometry,
11
+ ConeGeometry,
12
+ PlaneGeometry,
13
+ Shape,
14
+ Path,
15
+ ExtrudeGeometry,
16
+ Vector3,
17
+ Euler,
18
+ Quaternion,
19
+ TubeGeometry,
20
+ CatmullRomCurve3,
21
+ Curve,
22
+ BufferAttribute,
23
+ SphereGeometry,
24
+ } from "three";
25
+ import { exhaustiveCheck } from "ts-exhaustive-check";
26
+ import * as A3d from "../../abstract-3d";
27
+ import { Hole } from "../../abstract-3d";
28
+
29
+ const boxGeometry = new BoxGeometry();
30
+ const cylinderGeometry = new CylinderGeometry(1, 1, 1, 40, 1);
31
+ const coneGeometry = new ConeGeometry(1, 1, 16, 1);
32
+ const planeGeometry = new PlaneGeometry();
33
+ const sphereGeometry = new SphereGeometry(1, 12, 12);
34
+ export const euler = new Euler();
35
+ export const vector3 = new Vector3();
36
+ export const quaternion = new Quaternion();
37
+
38
+ export function ReactMesh({
39
+ mesh,
40
+ children,
41
+ }: {
42
+ readonly mesh: A3d.Mesh;
43
+ readonly children?: JSX.Element;
44
+ }): JSX.Element {
45
+ switch (mesh.geometry.type) {
46
+ case "Box": {
47
+ const { pos, size, rot, holes } = mesh.geometry;
48
+ return !holes || holes.length === 0 ? (
49
+ <mesh
50
+ geometry={boxGeometry}
51
+ scale={[size.x, size.y, size.z]}
52
+ position={[pos.x, pos.y, pos.z]}
53
+ rotation={[rot?.x ?? 0, rot?.y ?? 0, rot?.z ?? 0]}
54
+ >
55
+ {children}
56
+ </mesh>
57
+ ) : (
58
+ <ExcrudeBoxPlane geo={mesh.geometry} sizeZ={size.z}>
59
+ {children}
60
+ </ExcrudeBoxPlane>
61
+ );
62
+ }
63
+ case "Cone": {
64
+ const { pos, radius, rot, length } = mesh.geometry;
65
+ return (
66
+ <mesh
67
+ geometry={coneGeometry}
68
+ scale={[radius, length, radius]}
69
+ position={[pos.x, pos.y, pos.z]}
70
+ rotation={[rot?.x ?? 0, rot?.y ?? 0, rot?.z ?? 0]}
71
+ >
72
+ {children}
73
+ </mesh>
74
+ );
75
+ }
76
+ case "Cylinder": {
77
+ const { pos, radius, rot, length, holes } = mesh.geometry;
78
+ return !holes || holes.length === 0 ? (
79
+ <mesh
80
+ geometry={cylinderGeometry}
81
+ scale={[radius, length, radius]}
82
+ position={[pos.x, pos.y, pos.z]}
83
+ rotation={[rot?.x ?? 0, rot?.y ?? 0, rot?.z ?? 0]}
84
+ >
85
+ {children}
86
+ </mesh>
87
+ ) : (
88
+ <ExcrudeCylinder cyl={mesh.geometry}>{children}</ExcrudeCylinder>
89
+ );
90
+ }
91
+ case "Plane": {
92
+ const { pos, size, rot, holes } = mesh.geometry;
93
+ return !holes || holes.length === 0 ? (
94
+ <mesh
95
+ geometry={planeGeometry}
96
+ scale={[size.x, size.y, 1]}
97
+ position={[pos.x, pos.y, pos.z]}
98
+ rotation={[rot?.x ?? 0, rot?.y ?? 0, rot?.z ?? 0]}
99
+ >
100
+ {children}
101
+ </mesh>
102
+ ) : (
103
+ <ExcrudeBoxPlane geo={mesh.geometry} sizeZ={0}>
104
+ {children}
105
+ </ExcrudeBoxPlane>
106
+ );
107
+ }
108
+ case "Sphere": {
109
+ const { pos, radius } = mesh.geometry;
110
+ return (
111
+ <mesh geometry={sphereGeometry} scale={radius} position={[pos.x, pos.y, pos.z]}>
112
+ {children}
113
+ </mesh>
114
+ );
115
+ }
116
+ case "Shape":
117
+ return <ExcrudeShape s={mesh.geometry}>{children}</ExcrudeShape>;
118
+ case "Text": {
119
+ const { pos, rot, text, fontSize } = mesh.geometry;
120
+ return (
121
+ <Text
122
+ position={[pos.x, pos.y, pos.z]}
123
+ rotation={[rot?.x ?? 0, rot?.y ?? 0, rot?.z ?? 0]}
124
+ fontSize={fontSize}
125
+ textAlign="center"
126
+ letterSpacing={0.001}
127
+ lineHeight={1.5}
128
+ // outlineColor="rgb(255,255,255)"
129
+ // depthOffset={10}
130
+ // outlineWidth={3}
131
+ // outlineOpacity={1}
132
+ >
133
+ {children}
134
+ {text}
135
+ </Text>
136
+ );
137
+ }
138
+ case "Line": {
139
+ const { start, end, thickness } = mesh.geometry;
140
+ return (
141
+ <Line
142
+ points={[
143
+ [start.x, start.y, start.z],
144
+ [end.x, end.y, end.z],
145
+ ]}
146
+ lineWidth={thickness}
147
+ color={mesh.material.normal}
148
+ >
149
+ {children}
150
+ </Line>
151
+ );
152
+ }
153
+ case "Polygon":
154
+ return <Polygon polygon={mesh.geometry}>{children}</Polygon>;
155
+ case "Tube":
156
+ return <Tube tube={mesh.geometry}>{children}</Tube>;
157
+ default:
158
+ return <group />;
159
+ }
160
+ }
161
+
162
+ function ExcrudeBoxPlane({
163
+ geo,
164
+ sizeZ,
165
+ children,
166
+ }: {
167
+ readonly geo: A3d.Box | A3d.Plane;
168
+ readonly sizeZ: number;
169
+ readonly children?: JSX.Element;
170
+ }): JSX.Element {
171
+ const half = A3d.vec2Scale(geo.size, 0.5);
172
+
173
+ const excrudeGeometry = React.useMemo(() => {
174
+ const shape = new Shape();
175
+ shape.moveTo(-half.x, -half.y).lineTo(-half.x, half.y).lineTo(half.x, half.y).lineTo(half.x, -half.y).closePath();
176
+ holes(geo.holes, shape);
177
+ return new ExtrudeGeometry(shape, { depth: sizeZ, bevelEnabled: false });
178
+ }, [geo]);
179
+
180
+ return (
181
+ // Doesn't seem to adjust for excrude z size directly???
182
+ <mesh rotation={[geo.rot?.x ?? 0, geo.rot?.y ?? 0, geo.rot?.z ?? 0]} position={[geo.pos.x, geo.pos.y, geo.pos.z]}>
183
+ <mesh geometry={excrudeGeometry} position-z={-sizeZ / 2}>
184
+ {children}
185
+ </mesh>
186
+ </mesh>
187
+ );
188
+ }
189
+
190
+ function ExcrudeShape({ s, children }: { readonly s: A3d.Shape; readonly children?: JSX.Element }): JSX.Element {
191
+ const excrudeGeometry = React.useMemo(() => {
192
+ const shape = new Shape();
193
+ if (s.points.length > 0) {
194
+ const p = s.points[0]!;
195
+ shape.moveTo(p.x, p.y);
196
+ }
197
+ for (let i = 1; i < s.points.length; i++) {
198
+ const p = s.points[i]!;
199
+ shape.lineTo(p.x, p.y);
200
+ }
201
+ shape.closePath();
202
+ holes(s.holes, shape);
203
+ return new ExtrudeGeometry(shape, { depth: s.thickness, bevelEnabled: false });
204
+ }, [s]);
205
+
206
+ return (
207
+ // Doesn't seem to adjust for excrude z size directly???
208
+ <mesh rotation={[s.rot?.x ?? 0, s.rot?.y ?? 0, s.rot?.z ?? 0]} position={[s.pos.x, s.pos.y, s.pos.z]}>
209
+ <mesh geometry={excrudeGeometry} position-z={-s.thickness / 2}>
210
+ {children}
211
+ </mesh>
212
+ </mesh>
213
+ );
214
+ }
215
+
216
+ function ExcrudeCylinder({
217
+ cyl,
218
+ children,
219
+ }: {
220
+ readonly cyl: A3d.Cylinder;
221
+ readonly children?: JSX.Element;
222
+ }): JSX.Element {
223
+ const excrudeGeometry = React.useMemo(() => {
224
+ const shape = new Shape();
225
+ shape.moveTo(0, cyl.radius).absellipse(0, 0, cyl.radius, cyl.radius, 0, Math.PI * 2, true);
226
+ holes(cyl.holes, shape);
227
+ return new ExtrudeGeometry(shape, { depth: cyl.length, bevelEnabled: false });
228
+ }, [cyl]);
229
+
230
+ return (
231
+ // Doesn't seem to adjust for excrude z size directly???
232
+ <mesh rotation={[cyl.rot?.x ?? 0, cyl.rot?.y ?? 0, cyl.rot?.z ?? 0]} position={[cyl.pos.x, cyl.pos.y, cyl.pos.z]}>
233
+ <mesh geometry={excrudeGeometry} rotation-x={Math.PI / 2} position-y={+cyl.length / 2}>
234
+ {children}
235
+ </mesh>
236
+ </mesh>
237
+ );
238
+ }
239
+
240
+ function holes(holes: ReadonlyArray<Hole> | undefined, shape: Shape): void {
241
+ holes?.forEach((h) => {
242
+ switch (h.type) {
243
+ case "RoundHole":
244
+ shape.holes.push(new Path().absarc(h.pos.x, h.pos.y, h.radius, 0, Math.PI * 2, true));
245
+ break;
246
+ case "SquareHole": {
247
+ const path = new Path();
248
+ const halfHole = A3d.vec2Scale(h.size, 0.5);
249
+ const min = A3d.vec2Sub(h.pos, halfHole);
250
+ const max = A3d.vec2Add(h.pos, halfHole);
251
+ path.moveTo(min.x, min.y).lineTo(min.x, max.y).lineTo(max.x, max.y).lineTo(max.x, min.y).closePath();
252
+ shape.holes.push(path);
253
+ break;
254
+ }
255
+ default:
256
+ exhaustiveCheck(h);
257
+ }
258
+ });
259
+ }
260
+
261
+ function Polygon({
262
+ polygon,
263
+ children,
264
+ }: {
265
+ readonly polygon: A3d.Polygon;
266
+ readonly children?: JSX.Element;
267
+ }): JSX.Element {
268
+ const ref = React.useRef<BufferAttribute>(undefined!);
269
+ const vertices = React.useMemo(() => {
270
+ let newVertices: Float32Array = undefined!;
271
+ switch (polygon.points.length) {
272
+ default:
273
+ case 3: {
274
+ newVertices = new Float32Array(polygon.points.length * 3);
275
+ let i = 0;
276
+ polygon.points.forEach((p) => {
277
+ newVertices[i++] = p.x;
278
+ newVertices[i++] = p.y;
279
+ newVertices[i++] = p.z;
280
+ });
281
+ break;
282
+ }
283
+ case 4: {
284
+ const v0 = polygon.points[0]!;
285
+ const v1 = polygon.points[1]!;
286
+ const v2 = polygon.points[2]!;
287
+ const v3 = polygon.points[3]!;
288
+ newVertices = new Float32Array([
289
+ v0.x,
290
+ v0.y,
291
+ v0.z,
292
+ v1.x,
293
+ v1.y,
294
+ v1.z,
295
+ v2.x,
296
+ v2.y,
297
+ v2.z,
298
+ v2.x,
299
+ v2.y,
300
+ v2.z,
301
+ v3.x,
302
+ v3.y,
303
+ v3.z,
304
+ v0.x,
305
+ v0.y,
306
+ v0.z,
307
+ ]);
308
+ break;
309
+ }
310
+ }
311
+ if (ref.current) {
312
+ ref.current.needsUpdate = true;
313
+ }
314
+ return newVertices;
315
+ }, [polygon]);
316
+
317
+ return (
318
+ <mesh
319
+ rotation={[polygon.rot?.x ?? 0, polygon.rot?.y ?? 0, polygon.rot?.z ?? 0]}
320
+ position={[polygon.pos.x, polygon.pos.y, polygon.pos.z]}
321
+ >
322
+ <bufferGeometry attach="geometry" onUpdate={(self) => self.computeVertexNormals()}>
323
+ <bufferAttribute
324
+ attach="attributes-position"
325
+ needsUpdate={true}
326
+ ref={ref}
327
+ array={vertices}
328
+ count={vertices.length / 3}
329
+ itemSize={3}
330
+ />
331
+ </bufferGeometry>
332
+ {children}
333
+ </mesh>
334
+ );
335
+ }
336
+
337
+ function Tube({ tube, children }: { readonly tube: A3d.Tube; readonly children?: JSX.Element }): JSX.Element {
338
+ const tubeGeometry = React.useMemo(() => {
339
+ return new TubeGeometry(
340
+ tube.curve.type === "SplineCurve"
341
+ ? new CatmullRomCurve3(tube.curve.points.map((p) => new Vector3(p.x, p.y, p.z)))
342
+ : new CircleCurve(tube.curve),
343
+ 9,
344
+ tube.radius,
345
+ 9,
346
+ false
347
+ );
348
+ }, [tube]);
349
+
350
+ return (
351
+ <mesh
352
+ rotation={[tube.rot?.x ?? 0, tube.rot?.y ?? 0, tube.rot?.z ?? 0]}
353
+ position={[tube.pos.x, tube.pos.y, tube.pos.z]}
354
+ geometry={tubeGeometry}
355
+ >
356
+ {children}
357
+ </mesh>
358
+ );
359
+ }
360
+
361
+ class CircleCurve extends Curve<Vector3> {
362
+ radius: number;
363
+ angleLength: number;
364
+ startAngle: number;
365
+
366
+ constructor(circleCurve: A3d.CircleCurve) {
367
+ super();
368
+ this.radius = circleCurve.radius;
369
+ this.startAngle = circleCurve.angleStart;
370
+ this.angleLength = circleCurve.angleLength;
371
+ }
372
+
373
+ getPoint(t: number, optionalTarget = new Vector3()): Vector3 {
374
+ return optionalTarget.set(
375
+ -this.radius * Math.sin(this.startAngle + this.angleLength * t),
376
+ -this.radius * Math.cos(this.startAngle + this.angleLength * t),
377
+ 0
378
+ );
379
+ }
380
+ }
@@ -0,0 +1,137 @@
1
+ import React from "react";
2
+ import { extend } from "@react-three/fiber";
3
+ import {
4
+ Mesh,
5
+ Group,
6
+ MeshLambertMaterial,
7
+ MeshPhongMaterial,
8
+ MeshBasicMaterial,
9
+ BoxGeometry,
10
+ PlaneGeometry,
11
+ CylinderGeometry,
12
+ ConeGeometry,
13
+ Texture,
14
+ DoubleSide,
15
+ BufferAttribute,
16
+ Shape,
17
+ Path,
18
+ ExtrudeGeometry,
19
+ } from "three";
20
+ import * as A3d from "../../abstract-3d";
21
+ import { HotSpotInfo, ReactHotSpots } from "./react-hotspot";
22
+ import { ReactDimensions } from "./react-dimension";
23
+ import { ReactGroup } from "./react-group";
24
+ import { MaterialState } from "./react-material";
25
+
26
+ extend({
27
+ Mesh,
28
+ Group,
29
+ MeshLambertMaterial,
30
+ MeshPhongMaterial,
31
+ MeshBasicMaterial,
32
+ BufferAttribute,
33
+ Shape,
34
+ ExtrudeGeometry,
35
+ Path,
36
+ Texture,
37
+ CylinderGeometry,
38
+ BoxGeometry,
39
+ PlaneGeometry,
40
+ ConeGeometry,
41
+ DoubleSide,
42
+ });
43
+
44
+ export function ReactScene({
45
+ scene,
46
+ selectedId,
47
+ hoveredIdExternal,
48
+ activeHotSpots,
49
+ activeComponents,
50
+ hotSpotTexts,
51
+ showHotSpotTexts,
52
+ showDimensions,
53
+ materialStateImages,
54
+ onClickGroup,
55
+ onContextMenuGroup,
56
+ onClickHotSpot,
57
+ createGroupKey,
58
+ createGroupId,
59
+ }: {
60
+ readonly scene: A3d.Scene;
61
+ readonly selectedId: string | undefined;
62
+ readonly hoveredIdExternal: string | undefined;
63
+ readonly activeHotSpots: Record<string, HotSpotInfo> | undefined;
64
+ readonly activeComponents: Record<string, MaterialState> | undefined;
65
+ readonly showHotSpotTexts: boolean;
66
+ readonly showDimensions: boolean;
67
+ readonly hotSpotTexts?: Record<string, string>;
68
+ readonly materialStateImages?: Record<string, string>;
69
+ readonly onClickGroup?: (
70
+ id: string | undefined,
71
+ rootData: Record<string, string> | undefined,
72
+ data: Record<string, string> | undefined
73
+ ) => void;
74
+ readonly onContextMenuGroup?: (
75
+ id: string,
76
+ rootData: Record<string, string> | undefined,
77
+ data: Record<string, string> | undefined,
78
+ left: number,
79
+ top: number
80
+ ) => void;
81
+ readonly onClickHotSpot?: (hotSpot: HotSpotInfo) => void;
82
+ readonly createGroupKey?: (
83
+ g: A3d.Group,
84
+ idx: number,
85
+ rootData: Record<string, string> | undefined,
86
+ id: string
87
+ ) => string;
88
+ readonly createGroupId?: (g: A3d.Group) => string;
89
+ }): JSX.Element {
90
+ const [hoveredId, setHoveredId] = React.useState<string | undefined>(undefined);
91
+ return (
92
+ <group
93
+ rotation={[scene.rotation?.x ?? 0, scene.rotation?.y ?? 0, scene.rotation?.z ?? 0]}
94
+ position={[-scene.center.x, -scene.center.y, -scene.center.z]}
95
+ >
96
+ {scene.groups.map((g, i) => {
97
+ const id = createGroupId ? createGroupId(g) : "";
98
+ return (
99
+ <ReactGroup
100
+ key={createGroupKey ? createGroupKey(g, 0, g.data, id) : i}
101
+ g={g}
102
+ selectedId={selectedId}
103
+ hotSpotsActive={activeHotSpots !== undefined}
104
+ activeComponents={activeComponents}
105
+ materialStateImages={materialStateImages}
106
+ hoveredId={hoveredId}
107
+ hoveredIdExternal={hoveredIdExternal}
108
+ onClickGroup={onClickGroup}
109
+ onContextMenuGroup={onContextMenuGroup}
110
+ setHoveredId={setHoveredId}
111
+ createGroupKey={createGroupKey}
112
+ id={id}
113
+ rootData={g.data}
114
+ />
115
+ );
116
+ })}
117
+ <group
118
+ rotation={[-(scene.rotation?.x ?? 0), -(scene.rotation?.y ?? 0), -(scene.rotation?.z ?? 0)]}
119
+ position={[-scene.center.x, -scene.center.y, -scene.center.z]}
120
+ >
121
+ <group position={[scene.center.x, scene.center.y, scene.center.z]}>
122
+ <ReactDimensions dimensions={scene.dimensions} showDimensions={showDimensions} />
123
+ </group>
124
+ </group>
125
+ <ReactHotSpots
126
+ hotSpots={scene.hotSpots}
127
+ hotSpotZAdjPos={scene.size.z / 2}
128
+ activeHotSpots={activeHotSpots}
129
+ hotSpotTexts={hotSpotTexts}
130
+ hoveredId={hoveredId}
131
+ onClickHotSpot={onClickHotSpot}
132
+ setHoveredId={setHoveredId}
133
+ showHotSpotTexts={showHotSpotTexts}
134
+ />
135
+ </group>
136
+ );
137
+ }
@@ -0,0 +1,118 @@
1
+ import React, { memo } from "react";
2
+ import { Canvas, Props } from "@react-three/fiber";
3
+ import { OrbitControlsProps } from "@react-three/drei";
4
+ import { ReactScene } from "./react-scene";
5
+ import * as A3d from "../../abstract-3d";
6
+ import { ReactCamera, ControlsHelper, Camera } from "./react-camera";
7
+ import { HotSpotInfo } from "./react-hotspot";
8
+ import { MaterialState } from "./react-material";
9
+
10
+ export const toReact = memo(
11
+ ({
12
+ scene,
13
+ selectedId,
14
+ activeHotSpots,
15
+ activeComponents,
16
+ hoveredIdExternal,
17
+ hotSpotTexts,
18
+ showHotSpotTexts = false,
19
+ showDimensions = true,
20
+ useAnimations = false,
21
+ camera = { type: "Perspective" },
22
+ view = "front",
23
+ controlsHelper,
24
+ canvasProps,
25
+ orbitContolsProps,
26
+ materialStateImages,
27
+ onClickGroup,
28
+ onContextMenuGroup,
29
+ onClickHotSpot,
30
+ createGroupKey,
31
+ createGroupId,
32
+ }: {
33
+ readonly scene: A3d.Scene;
34
+ readonly selectedId?: string | undefined;
35
+ readonly activeHotSpots?: Record<string, HotSpotInfo> | undefined;
36
+ readonly activeComponents?: Record<string, MaterialState> | undefined;
37
+ readonly hoveredIdExternal?: string | undefined;
38
+ readonly showHotSpotTexts?: boolean;
39
+ readonly showDimensions?: boolean;
40
+ readonly hotSpotTexts?: Record<string, string>;
41
+ readonly useAnimations?: boolean;
42
+ readonly camera?: Camera;
43
+ readonly view?: A3d.View;
44
+ readonly controlsHelper?: ControlsHelper;
45
+ readonly canvasProps?: Omit<Props & React.RefAttributes<HTMLCanvasElement>, "children">;
46
+ readonly orbitContolsProps?: OrbitControlsProps & React.RefAttributes<unknown>;
47
+ readonly materialStateImages?: Record<string, string>;
48
+ readonly onClickGroup?: (
49
+ id: string | undefined,
50
+ rootData: Record<string, string> | undefined,
51
+ data: Record<string, string> | undefined
52
+ ) => void;
53
+ readonly onContextMenuGroup?: (
54
+ id: string,
55
+ rootData: Record<string, string> | undefined,
56
+ data: Record<string, string> | undefined,
57
+ left: number,
58
+ top: number
59
+ ) => void;
60
+ readonly onClickHotSpot?: (hotSpot: HotSpotInfo) => void;
61
+ readonly createGroupKey?: (
62
+ g: A3d.Group,
63
+ idx: number,
64
+ rootData: Record<string, string> | undefined,
65
+ id: string
66
+ ) => string;
67
+ readonly createGroupId?: (g: A3d.Group) => string;
68
+ }): JSX.Element => {
69
+ return (
70
+ <Canvas dpr={[1, window.devicePixelRatio]} frameloop="demand" {...canvasProps}>
71
+ {/* <Stats showPanel={0} className="stats" /> */}
72
+ <ReactCamera
73
+ scene={scene}
74
+ useAnimations={useAnimations}
75
+ camera={camera}
76
+ view={view}
77
+ controlsHelper={controlsHelper}
78
+ orbitContolsProps={orbitContolsProps}
79
+ />
80
+ <ambientLight intensity={0.7} />
81
+ <directionalLight
82
+ position={[
83
+ -scene.center.x + 0.7 * scene.size.x,
84
+ -scene.center.y + 1.4 * scene.size.y,
85
+ -scene.center.z + 3 * scene.size.z,
86
+ ]}
87
+ intensity={3.3}
88
+ />
89
+ <directionalLight
90
+ position={[
91
+ -scene.center.x - 0.7 * scene.size.x,
92
+ -scene.center.y - 1.1 * scene.size.y,
93
+ -scene.center.z - 3 * scene.size.z,
94
+ ]}
95
+ intensity={3.3}
96
+ />
97
+ <React.Suspense fallback={<></>}>
98
+ <ReactScene
99
+ scene={scene}
100
+ selectedId={selectedId}
101
+ activeHotSpots={activeHotSpots}
102
+ activeComponents={activeComponents}
103
+ showDimensions={showDimensions}
104
+ showHotSpotTexts={showHotSpotTexts}
105
+ hoveredIdExternal={hoveredIdExternal}
106
+ hotSpotTexts={hotSpotTexts}
107
+ materialStateImages={materialStateImages}
108
+ onClickGroup={onClickGroup}
109
+ onContextMenuGroup={onContextMenuGroup}
110
+ onClickHotSpot={onClickHotSpot}
111
+ createGroupKey={createGroupKey}
112
+ createGroupId={createGroupId}
113
+ />
114
+ </React.Suspense>
115
+ </Canvas>
116
+ );
117
+ }
118
+ );