@tscircuit/3d-viewer 0.0.2 → 0.0.4
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/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/dist/index.cjs +0 -657
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -10
package/dist/index.js
CHANGED
|
@@ -413,7 +413,9 @@ var import_fiber2 = require("@react-three/fiber");
|
|
|
413
413
|
var import_drei = require("@react-three/drei");
|
|
414
414
|
var THREE = __toESM(require("three"));
|
|
415
415
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
416
|
-
|
|
416
|
+
if (typeof window !== "undefined") {
|
|
417
|
+
window.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0);
|
|
418
|
+
}
|
|
417
419
|
function computePointInFront(rotationVector, distance) {
|
|
418
420
|
const quaternion = new THREE.Quaternion().setFromEuler(
|
|
419
421
|
new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z)
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/@tscircuit/soup-util/index.ts","../src/index.tsx","../src/hooks/use-convert-children-to-soup.ts","../src/CadViewer.tsx","../src/soup-to-3d/index.ts","../src/geoms/plated-hole.ts","../src/geoms/constants.ts","../src/hooks/use-stls-from-geom.ts","../src/three-components/STLModel.tsx","../src/CadViewerContainer.tsx","../src/three-components/cube-with-labeled-sides.tsx","../src/three-components/MixedStlModel.tsx"],"sourcesContent":["import type {\n AnySoupElement,\n AnySoupElementInput,\n SourceComponentBase,\n SourcePort,\n} from \"@tscircuit/soup\"\n\ntype SoupOps<\n K extends AnySoupElement[\"type\"],\n T extends AnySoupElement | AnySoupElementInput\n> = {\n get: (id: string) => Extract<T, { type: K }> | null\n select: (selector: string) => Extract<T, { type: K }> | null\n getWhere: (where: any) => Extract<T, { type: K }> | null\n getUsing: (using: {\n [key: `${string}_id`]: string\n }) => Extract<T, { type: K }> | null\n list: (where?: any) => Extract<T, { type: K }>[]\n}\n\nexport type SoupUtilObject = {\n [K in AnySoupElement[\"type\"]]: SoupOps<K, AnySoupElement>\n}\nexport type SoupInputUtilObject = {\n [K in AnySoupElementInput[\"type\"]]: SoupOps<K, AnySoupElementInput>\n}\n\nexport type GetSoupUtilObject = ((soup: AnySoupElement[]) => SoupUtilObject) & {\n unparsed: (soup: AnySoupElementInput[]) => SoupInputUtilObject\n}\n\nexport const su: GetSoupUtilObject = ((soup: AnySoupElement[]) => {\n const su = new Proxy(\n {},\n {\n get: (proxy_target: any, component_type: string) => {\n return {\n get: (id: string) =>\n soup.find(\n (e: any) =>\n e.type === component_type && e[`${component_type}_id`] === id\n ),\n getUsing: (using: any) => {\n const keys = Object.keys(using)\n if (keys.length !== 1) {\n throw new Error(\n \"getUsing requires exactly one key, e.g. { pcb_component_id }\"\n )\n }\n const join_key = keys[0] as string\n const join_type = join_key.replace(\"_id\", \"\")\n const joiner: any = soup.find(\n (e: any) =>\n e.type === join_type && e[join_key] === using[join_key]\n )\n if (!joiner) return null\n return soup.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joiner[`${component_type}_id`]\n )\n },\n getWhere: (where: any) => {\n const keys = Object.keys(where)\n return soup.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key])\n )\n },\n list: (where?: any) => {\n const keys = !where ? [] : Object.keys(where)\n return soup.filter(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key])\n )\n },\n select: (selector: string) => {\n // TODO when applySelector is isolated we can use it, until then we\n // do a poor man's selector implementation for two common cases\n if (component_type === \"source_component\") {\n return soup.find(\n (e) =>\n e.type === \"source_component\" &&\n e.name === selector.replace(/\\./g, \"\")\n )\n } else if (\n component_type === \"pcb_port\" ||\n component_type === \"source_port\" ||\n component_type === \"schematic_port\"\n ) {\n const [component_name, port_selector] = selector\n .replace(/\\./g, \"\")\n .split(/[\\s\\>]+/)\n const source_component = soup.find(\n (e) =>\n e.type === \"source_component\" && e.name === component_name\n ) as SourceComponentBase\n if (!source_component) return null\n const source_port = soup.find(\n (e) =>\n e.type === \"source_port\" &&\n e.source_component_id ===\n source_component.source_component_id &&\n (e.name === port_selector ||\n (e.port_hints ?? []).includes(port_selector!))\n ) as SourcePort\n if (!source_port) return null\n if (component_type === \"source_port\") return source_port\n\n if (component_type === \"pcb_port\") {\n return soup.find(\n (e) =>\n e.type === \"pcb_port\" &&\n e.source_port_id === source_port.source_port_id\n )\n } else if (component_type === \"schematic_port\") {\n return soup.find(\n (e) =>\n e.type === \"schematic_port\" &&\n e.source_port_id === source_port.source_port_id\n )\n }\n }\n },\n }\n },\n }\n )\n\n return su\n}) as any\nsu.unparsed = su as any\n\nexport default su\n","export { CadViewer } from \"./CadViewer\"\n","import type { AnySoupElement } from \"@tscircuit/soup\"\n\nexport const useConvertChildrenToSoup = (\n children?: any,\n defaultSoup?: AnySoupElement[]\n) => {\n // TODO convert children if defined\n\n return defaultSoup!\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { useConvertChildrenToSoup } from \"./hooks/use-convert-children-to-soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { useMemo } from \"react\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport { useStlsFromGeom } from \"./hooks/use-stls-from-geom\"\nimport { STLModel } from \"./three-components/STLModel\"\nimport { CadViewerContainer } from \"./CadViewerContainer\"\nimport { MixedStlModel } from \"./three-components/MixedStlModel\"\n\ninterface Props {\n soup?: AnySoupElement[]\n children?: any\n}\n\nexport const CadViewer = ({ soup, children }: Props) => {\n soup ??= useConvertChildrenToSoup(children, soup)\n\n // TODO convert board\n\n const boardGeom = useMemo(() => createBoardGeomFromSoup(soup), [soup])\n\n const { stls, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n // TODO canvas/camera etc.\n return (\n <CadViewerContainer>\n {stls.map(({ stlUrl, color }, index) => (\n <STLModel\n key={stlUrl}\n stlUrl={stlUrl}\n color={color}\n opacity={index === 0 ? 0.95 : 1}\n />\n ))}\n {/* <MixedStlModel url=\"/easyeda-models/84af7f0f6529479fb6b1c809c61d205f\" /> */}\n <MixedStlModel\n url=\"/easyeda-models/dc694c23844346e9981bdbac7bb76421\"\n position={[0, 0, 0.5]}\n rotation={[0, 0, Math.PI / 2]}\n />\n <MixedStlModel\n url=\"/easyeda-models/c7acac53bcbc44d68fbab8f60a747688\"\n position={[-5.65, 0, 0.5]}\n rotation={[0, 0, Math.PI / 2]}\n />\n <MixedStlModel\n url=\"/easyeda-models/c7acac53bcbc44d68fbab8f60a747688\"\n position={[6.75, 0, 0.5]}\n rotation={[0, 0, 0]}\n />\n </CadViewerContainer>\n )\n}\n","import type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { AnySoupElement, PCBPlatedHole } from \"@tscircuit/soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\nimport { cuboid, cylinder, line } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract } from \"@jscad/modeling/src/operations/booleans\"\nimport { platedHole } from \"../geoms/plated-hole\"\nimport { M, colors } from \"../geoms/constants\"\nimport { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { expand } from \"@jscad/modeling/src/operations/expansions\"\n\nexport const createBoardGeomFromSoup = (soup: AnySoupElement[]): Geom3[] => {\n const board = su(soup).pcb_board.list()[0]\n if (!board) {\n throw new Error(\"No pcb_board found\")\n }\n\n const plated_holes = su(soup).pcb_plated_hole.list()\n const pads = su(soup).pcb_smtpad.list()\n const traces = su(soup).pcb_trace.list()\n const pcb_vias = su(soup).pcb_via.list()\n\n // PCB Board\n let boardGeom = cuboid({ size: [board.width, board.height, 1.2] })\n\n const platedHoleGeoms: Geom3[] = []\n const padGeoms: Geom3[] = []\n const traceGeoms: Geom3[] = []\n const ctx = {\n pcbThickness: 1.2,\n }\n\n const addPlatedHole = (plated_hole: PCBPlatedHole) => {\n if (!(plated_hole as any).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n const cyGeom = cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 + M,\n })\n boardGeom = subtract(boardGeom, cyGeom)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n }\n }\n\n for (const plated_hole of plated_holes) {\n addPlatedHole(plated_hole)\n }\n\n for (const pad of pads) {\n if (pad.shape === \"rect\") {\n const padGeom = colorize(\n colors.copper,\n cuboid({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n size: [pad.width, pad.height, M],\n })\n )\n padGeoms.push(padGeom)\n } else if (pad.shape === \"circle\") {\n const padGeom = colorize(\n colors.copper,\n cylinder({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n radius: pad.radius,\n height: M,\n })\n )\n padGeoms.push(padGeom)\n }\n }\n\n for (const { route: mixedRoute } of traces) {\n const subRoutes = mixedRoute.reduce(\n (c, p) => {\n // @ts-ignore\n const lastLayer = c.current?.[c.current.length - 1]?.layer\n if (\n p.route_type === \"via\" ||\n (p.route_type === \"wire\" && p.layer !== lastLayer)\n ) {\n if (c.current.length > 2) {\n c.allPrev.push(c.current)\n }\n c.current = p.route_type === \"wire\" ? [p] : []\n return c\n }\n c.current.push(p)\n return c\n },\n {\n current: [] as typeof mixedRoute,\n allPrev: [] as Array<typeof mixedRoute>,\n }\n )\n for (const route of subRoutes.allPrev.concat([subRoutes.current])) {\n // TODO break into segments based on layers\n const linePath = line(route.map((p) => [p.x, p.y]))\n\n const layer = route[0]!.route_type === \"wire\" ? route[0]!.layer : \"top\"\n const layerSign = layer === \"top\" ? 1 : -1\n // traceGeoms.push(traceGeom)\n let traceGeom = translate(\n [0, 0, (layerSign * 1.2) / 2],\n extrudeLinear(\n { height: M * layerSign },\n expand({ delta: 0.1, corners: \"edge\" }, linePath)\n )\n )\n\n // HACK: Subtract all vias from every trace- this mostly is because the\n // vias aren't inside the route- we should probably pre-filter to make sure\n // that vias are only near the route\n for (const via of pcb_vias) {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n })\n )\n }\n\n traceGeom = colorize(colors.fr4GreenSolderWithMask, traceGeom)\n\n traceGeoms.push(traceGeom)\n }\n for (const via of mixedRoute.filter((p) => p.route_type === \"via\")) {\n if (via.route_type !== \"via\") continue // TODO remove when ts is smart\n\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: 0.8,\n outer_diameter: 1.6,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n }\n\n for (const via of pcb_vias) {\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: via.hole_diameter,\n outer_diameter: via.outer_diameter,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n\n // Colorize to a PCB green color: #05A32E\n boardGeom = colorize(colors.fr4Green, boardGeom)\n\n return [boardGeom, ...platedHoleGeoms, ...padGeoms, ...traceGeoms]\n}\n","import type { PCBPlatedHole } from \"@tscircuit/soup\"\nimport type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport { cylinder } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { M, colors } from \"./constants\"\nimport { GeomContext } from \"../GeomContext\"\n\nexport const platedHole = (\n plated_hole: PCBPlatedHole,\n ctx: GeomContext\n): Geom3 => {\n if (!(plated_hole as any).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n return colorize(\n colors.copper,\n subtract(\n union(\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2,\n height: 1.2,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, -1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n })\n ),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 - M,\n height: 1.5,\n })\n )\n )\n } else {\n throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`)\n }\n}\n","import type { RGB } from \"@jscad/modeling/src/colors\"\n\nexport const M = 0.01\n\nexport const colors = {\n copper: [0.9, 0.6, 0.2],\n fr4Green: [0x05 / 255, 0xa3 / 255, 0x2e / 255],\n fr4GreenSolderWithMask: [0x00 / 255, 0x98 / 255, 0x13 / 255],\n} satisfies Record<string, RGB>\n","import { useState, useEffect } from \"react\"\nimport stlSerializer from \"@jscad/stl-serializer\"\nimport { Geom3 } from \"@jscad/modeling/src/geometries/types\"\n\nfunction blobToBase64Url(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n resolve(reader.result as string)\n }\n reader.onerror = reject\n reader.readAsDataURL(blob)\n })\n}\n\ntype StlObj = { stlUrl: string; color: number[] }\n\nexport const useStlsFromGeom = (\n geom: Geom3[] | Geom3\n): {\n stls: StlObj[]\n loading: boolean\n} => {\n const [stls, setStls] = useState<StlObj[]>([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n const generateStls = async () => {\n setLoading(true)\n const geometries = Array.isArray(geom) ? geom : [geom]\n\n const stlPromises = geometries.map(async (g) => {\n const rawData = stlSerializer.serialize({ binary: true }, [g])\n const blobData = new Blob(rawData)\n const stlUrl = await blobToBase64Url(blobData)\n return { stlUrl, color: g.color! }\n })\n\n try {\n const generatedStls = await Promise.all(stlPromises)\n setStls(generatedStls)\n } catch (error) {\n console.error(\"Error generating STLs:\", error)\n setStls([])\n } finally {\n setLoading(false)\n }\n }\n\n generateStls()\n }, [geom])\n\n return { stls, loading }\n}\n","import { useLoader } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport function STLModel({\n stlUrl,\n mtlUrl,\n color,\n opacity = 1,\n}: {\n stlUrl: string\n color?: any\n mtlUrl?: string\n opacity?: number\n}) {\n const geom = useLoader(STLLoader, stlUrl)\n const mesh = useRef<THREE.Mesh>()\n\n // TODO handle mtl url\n\n return (\n <mesh ref={mesh as any}>\n <primitive object={geom} attach=\"geometry\" />\n <meshStandardMaterial\n color={color}\n transparent={opacity !== 1}\n opacity={opacity}\n />\n {/* <Outlines thickness={0.05} color=\"black\" opacity={0.25} /> */}\n </mesh>\n )\n}\n","import {\n Canvas,\n useFrame,\n extend,\n useThree,\n useLoader,\n} from \"@react-three/fiber\"\nimport { Suspense, useEffect, useMemo, useRef, useState } from \"react\"\nimport { OrbitControls, Grid, Outlines } from \"@react-three/drei\"\nimport * as THREE from \"three\"\nimport { CubeWithLabeledSides } from \"./three-components/cube-with-labeled-sides\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport soup from \"./bug-pads-and-traces.json\"\n// import soup from \"./plated-hole-board.json\"\nimport stlSerializer from \"@jscad/stl-serializer\"\n// import { STLLoader } from \"three/examples/jsm/loaders/STLLoader\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport const RotationTracker = () => {\n useFrame(({ camera }) => {\n window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation\n })\n\n return <></>\n}\n\nexport const CadViewerContainer = ({ children }: { children: any }) => {\n return (\n <div style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}>\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 120,\n height: 120,\n }}\n >\n <Canvas\n camera={{\n up: [0, 0, 1],\n // rotation: [-Math.PI / 2, 0, 0],\n // lookAt: new THREE.Vector3(0, 0, 0),\n position: [1, 1, 1],\n }}\n >\n <ambientLight intensity={Math.PI / 2} />\n <CubeWithLabeledSides />\n </Canvas>\n </div>\n <Canvas\n scene={{ up: [0, 0, 1] }}\n camera={{ up: [0, 0, 1], position: [5, 5, 5] }}\n >\n <RotationTracker />\n <OrbitControls autoRotate autoRotateSpeed={1} />\n <ambientLight intensity={Math.PI / 2} />\n <pointLight\n position={[-10, -10, 10]}\n decay={0}\n intensity={Math.PI / 4}\n />\n <Grid\n rotation={[Math.PI / 2, 0, 0]}\n infiniteGrid={true}\n cellSize={1}\n sectionSize={10}\n />\n {children}\n </Canvas>\n </div>\n )\n}\n","import React, { useRef } from \"react\"\nimport { Canvas, useFrame } from \"@react-three/fiber\"\nimport { OrbitControls, Text } from \"@react-three/drei\"\nimport * as THREE from \"three\"\n\ndeclare global {\n interface Window {\n TSCI_MAIN_CAMERA_ROTATION: THREE.Euler\n }\n}\nwindow.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0)\n\nfunction computePointInFront(rotationVector, distance) {\n // Create a quaternion from the rotation vector\n const quaternion = new THREE.Quaternion().setFromEuler(\n new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z)\n )\n\n // Create a vector pointing forward (along the negative z-axis)\n const forwardVector = new THREE.Vector3(0, 0, 1)\n\n // Apply the rotation to the forward vector\n forwardVector.applyQuaternion(quaternion)\n\n // Scale the rotated vector by the distance\n const result = forwardVector.multiplyScalar(distance)\n\n return result\n}\n\nexport const CubeWithLabeledSides = ({}: any) => {\n const ref = useRef<THREE.Mesh>()\n const rotationTrackingRef = useRef({ lastRotation: new THREE.Euler() })\n useFrame((state, delta) => {\n if (!ref.current) return\n\n const mainRot = window.TSCI_MAIN_CAMERA_ROTATION\n\n // Use window.TSCI_CAMERA_ROTATION to compute the position of the camera\n const cameraPosition = computePointInFront(mainRot, 2)\n\n state.camera.position.copy(cameraPosition)\n state.camera.lookAt(0, 0, 0)\n })\n return (\n <mesh ref={ref as any} rotation={[Math.PI / 2, 0, 0]}>\n <boxGeometry args={[1, 1, 1]} />\n <meshStandardMaterial color=\"white\" />\n <Text position={[0, 0, 0.51]} fontSize={0.25} color=\"black\">\n Front\n </Text>\n <Text\n position={[0, 0, -0.51]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI, 0]}\n >\n Back\n </Text>\n <Text\n position={[0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI / 2, 0]}\n >\n Right\n </Text>\n <Text\n position={[-0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, -Math.PI / 2, 0]}\n >\n Left\n </Text>\n <Text\n position={[0, 0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[-Math.PI / 2, 0, 0]}\n >\n Top\n </Text>\n <Text\n position={[0, -0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[Math.PI / 2, 0, 0]}\n >\n Bottom\n </Text>\n <lineSegments\n args={[new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1))]}\n material={\n new THREE.LineBasicMaterial({\n color: 0x000000,\n linewidth: 2,\n })\n }\n />\n </mesh>\n )\n}\n\n// const LabeledCubeScene = () => {\n// return (\n// <Canvas camera={{ position: [1.5, 1.5, 1.5] }}>\n// <ambientLight intensity={0.5} />\n// <pointLight position={[10, 10, 10]} />\n// <LabeledCube />\n// <OrbitControls />\n// </Canvas>\n// )\n// }\n\n// export default LabeledCubeScene\n","import { useEffect, useState } from \"react\"\nimport { Euler, Vector3 } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\nexport function MixedStlModel({\n url,\n position,\n rotation,\n}: {\n url: string\n position?: Vector3 | [number, number, number]\n rotation?: Euler | [number, number, number]\n}) {\n // const group = useLoader(OBJLoader, url)\n // const materials = useLoader(MTLLoader, url)\n // const obj = useLoader(OBJLoader, url)\n\n const [obj, setObj] = useState<any | null>(null)\n useEffect(() => {\n async function loadUrlContent() {\n const response = await fetch(url)\n const text = await response.text()\n\n // Extract all the sections of the file that have newmtl...endmtl to\n // separate into mtlContent and objContent\n\n const mtlContent = text\n .match(/newmtl[\\s\\S]*?endmtl/g)\n ?.join(\"\\n\")!\n .replace(/d 0\\./g, \"d 1.\")!\n const objContent = text.replace(/newmtl[\\s\\S]*?endmtl/g, \"\")\n\n const mtlLoader = new MTLLoader()\n mtlLoader.setMaterialOptions({\n invertTrProperty: true,\n })\n const materials = mtlLoader.parse(\n // Grayscale the colors, for some reason everything from JLCPCB is\n // a bit red, it doesn't look right. The grayscale version looks OK,\n // it's a HACK because we only take the second color rather than\n // averaging the colors\n mtlContent.replace(\n /Kd\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)/g,\n \"Kd $2 $2 $2\"\n ),\n \"test.mtl\"\n )\n\n const objLoader = new OBJLoader()\n objLoader.setMaterials(materials)\n setObj(objLoader.parse(objContent))\n }\n loadUrlContent()\n }, [url])\n\n return (\n <group rotation={rotation} position={position}>\n {obj && <primitive object={obj} />}\n </group>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,QAAA,oBAAA,CAAA;AAAA,IAAAA,UAAA,mBAAA;MAAA,SAAA,MAAA;MAAA,IAAA,MAAAC;IAAA,CAAA;AAAA,IAAAC,QAAA,UAAAC,cAAA,iBAAA;AA+BO,QAAMF,MAAyB,CAAC,SAA2B;AAChE,YAAMA,OAAK,IAAI;QACb,CAAC;QACD;UACE,KAAK,CAAC,cAAmB,mBAA2B;AAClD,mBAAO;cACL,KAAK,CAAC,OACJ,KAAK;gBACH,CAAC,MACC,EAAE,SAAS,kBAAkB,EAAE,GAAG,cAAc,KAAK,MAAM;cAC/D;cACF,UAAU,CAAC,UAAe;AACxB,sBAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,oBAAI,KAAK,WAAW,GAAG;AACrB,wBAAM,IAAI;oBACR;kBACF;gBACF;AACA,sBAAM,WAAW,KAAK,CAAC;AACvB,sBAAM,YAAY,SAAS,QAAQ,OAAO,EAAE;AAC5C,sBAAM,SAAc,KAAK;kBACvB,CAAC,MACC,EAAE,SAAS,aAAa,EAAE,QAAQ,MAAM,MAAM,QAAQ;gBAC1D;AACA,oBAAI,CAAC;AAAQ,yBAAO;AACpB,uBAAO,KAAK;kBACV,CAAC,MACC,EAAE,SAAS,kBACX,EAAE,GAAG,cAAc,KAAK,MAAM,OAAO,GAAG,cAAc,KAAK;gBAC/D;cACF;cACA,UAAU,CAAC,UAAe;AACxB,sBAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,uBAAO,KAAK;kBACV,CAAC,MACC,EAAE,SAAS,kBACX,KAAK,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,MAAM,GAAG,CAAC;gBAC7C;cACF;cACA,MAAM,CAAC,UAAgB;AACrB,sBAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,KAAK,KAAK;AAC5C,uBAAO,KAAK;kBACV,CAAC,MACC,EAAE,SAAS,kBACX,KAAK,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,MAAM,GAAG,CAAC;gBAC7C;cACF;cACA,QAAQ,CAAC,aAAqB;AAG5B,oBAAI,mBAAmB,oBAAoB;AACzC,yBAAO,KAAK;oBACV,CAAC,MACC,EAAE,SAAS,sBACX,EAAE,SAAS,SAAS,QAAQ,OAAO,EAAE;kBACzC;gBACF,WACE,mBAAmB,cACnB,mBAAmB,iBACnB,mBAAmB,kBACnB;AACA,wBAAM,CAAC,gBAAgB,aAAa,IAAI,SACrC,QAAQ,OAAO,EAAE,EACjB,MAAM,SAAS;AAClB,wBAAM,mBAAmB,KAAK;oBAC5B,CAAC,MACC,EAAE,SAAS,sBAAsB,EAAE,SAAS;kBAChD;AACA,sBAAI,CAAC;AAAkB,2BAAO;AAC9B,wBAAM,cAAc,KAAK;oBACvB,CAAC,MACC,EAAE,SAAS,iBACX,EAAE,wBACA,iBAAiB,wBAClB,EAAE,SAAS,kBACT,EAAE,cAAc,CAAC,GAAG,SAAS,aAAc;kBAClD;AACA,sBAAI,CAAC;AAAa,2BAAO;AACzB,sBAAI,mBAAmB;AAAe,2BAAO;AAE7C,sBAAI,mBAAmB,YAAY;AACjC,2BAAO,KAAK;sBACV,CAAC,MACC,EAAE,SAAS,cACX,EAAE,mBAAmB,YAAY;oBACrC;kBACF,WAAW,mBAAmB,kBAAkB;AAC9C,2BAAO,KAAK;sBACV,CAAC,MACC,EAAE,SAAS,oBACX,EAAE,mBAAmB,YAAY;oBACrC;kBACF;gBACF;cACF;YACF;UACF;QACF;MACF;AAEA,aAAOA;IACT;AACA,IAAAA,IAAG,WAAWA;AAEd,QAAO,oBAAQA;;;;;ACvIf;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,2BAA2B,CACtC,UACA,gBACG;AAGH,SAAO;AACT;;;ACPA,IAAAG,oBAAmB;AACnB,IAAAC,gBAAwB;;;ACDxB,uBAAmB;AACnB,wBAA0B;AAC1B,IAAAC,qBAAuC;AACvC,IAAAC,iBAAyB;AACzB,IAAAC,mBAAyB;;;ACJzB,wBAAyB;AACzB,oBAAyB;AACzB,sBAAgC;;;ACFzB,IAAM,IAAI;AAEV,IAAM,SAAS;AAAA,EACpB,QAAQ,CAAC,KAAK,KAAK,GAAG;AAAA,EACtB,UAAU,CAAC,IAAO,KAAK,MAAO,KAAK,KAAO,GAAG;AAAA,EAC7C,wBAAwB,CAAC,IAAO,KAAK,MAAO,KAAK,KAAO,GAAG;AAC7D;;;ADAO,IAAM,aAAa,CACxB,aACA,QACU;AACV,MAAI,CAAE,YAAoB,MAAO,aAAY,QAAQ;AACrD,MAAI,YAAY,UAAU,UAAU;AAClC,eAAO;AAAA,MACL,OAAO;AAAA,UACP;AAAA,YACE;AAAA,cACE,4BAAS;AAAA,YACP,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,CAAC;AAAA,YACxC,QAAQ,YAAY,gBAAgB;AAAA,YACpC,QAAQ;AAAA,UACV,CAAC;AAAA,cACD,4BAAS;AAAA,YACP,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,MAAM,CAAC;AAAA,YAC9C,QAAQ,YAAY,iBAAiB;AAAA,YACrC,QAAQ;AAAA,UACV,CAAC;AAAA,cACD,4BAAS;AAAA,YACP,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,OAAO,CAAC;AAAA,YAC/C,QAAQ,YAAY,iBAAiB;AAAA,YACrC,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,YACA,4BAAS;AAAA,UACP,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,CAAC;AAAA,UACxC,QAAQ,YAAY,gBAAgB,IAAI;AAAA,UACxC,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM,IAAI,MAAM,kCAAkC,YAAY,KAAK,EAAE;AAAA,EACvE;AACF;;;ADnCA,wBAA8B;AAC9B,wBAAuB;AAEhB,IAAM,0BAA0B,CAAC,SAAoC;AAC1E,QAAM,YAAQ,qBAAG,IAAI,EAAE,UAAU,KAAK,EAAE,CAAC;AACzC,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AAEA,QAAM,mBAAe,qBAAG,IAAI,EAAE,gBAAgB,KAAK;AACnD,QAAM,WAAO,qBAAG,IAAI,EAAE,WAAW,KAAK;AACtC,QAAM,aAAS,qBAAG,IAAI,EAAE,UAAU,KAAK;AACvC,QAAM,eAAW,qBAAG,IAAI,EAAE,QAAQ,KAAK;AAGvC,MAAI,gBAAY,2BAAO,EAAE,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,GAAG,EAAE,CAAC;AAEjE,QAAM,kBAA2B,CAAC;AAClC,QAAM,WAAoB,CAAC;AAC3B,QAAM,aAAsB,CAAC;AAC7B,QAAM,MAAM;AAAA,IACV,cAAc;AAAA,EAChB;AAEA,QAAM,gBAAgB,CAAC,gBAA+B;AACpD,QAAI,CAAE,YAAoB,MAAO,aAAY,QAAQ;AACrD,QAAI,YAAY,UAAU,UAAU;AAClC,YAAM,aAAS,6BAAS;AAAA,QACtB,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,CAAC;AAAA,QACxC,QAAQ,YAAY,gBAAgB,IAAI;AAAA,MAC1C,CAAC;AACD,sBAAY,2BAAS,WAAW,MAAM;AAEtC,YAAM,iBAAiB,WAAW,aAAa,GAAG;AAClD,sBAAgB,KAAK,cAAc;AAAA,IACrC;AAAA,EACF;AAEA,aAAW,eAAe,cAAc;AACtC,kBAAc,WAAW;AAAA,EAC3B;AAEA,aAAW,OAAO,MAAM;AACtB,QAAI,IAAI,UAAU,QAAQ;AACxB,YAAM,cAAU;AAAA,QACd,OAAO;AAAA,YACP,2BAAO;AAAA,UACL,QAAQ,CAAC,IAAI,GAAG,IAAI,GAAG,MAAM,IAAI,CAAC;AAAA,UAClC,MAAM,CAAC,IAAI,OAAO,IAAI,QAAQ,CAAC;AAAA,QACjC,CAAC;AAAA,MACH;AACA,eAAS,KAAK,OAAO;AAAA,IACvB,WAAW,IAAI,UAAU,UAAU;AACjC,YAAM,cAAU;AAAA,QACd,OAAO;AAAA,YACP,6BAAS;AAAA,UACP,QAAQ,CAAC,IAAI,GAAG,IAAI,GAAG,MAAM,IAAI,CAAC;AAAA,UAClC,QAAQ,IAAI;AAAA,UACZ,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AACA,eAAS,KAAK,OAAO;AAAA,IACvB;AAAA,EACF;AAEA,aAAW,EAAE,OAAO,WAAW,KAAK,QAAQ;AAC1C,UAAM,YAAY,WAAW;AAAA,MAC3B,CAAC,GAAG,MAAM;AAER,cAAM,YAAY,EAAE,UAAU,EAAE,QAAQ,SAAS,CAAC,GAAG;AACrD,YACE,EAAE,eAAe,SAChB,EAAE,eAAe,UAAU,EAAE,UAAU,WACxC;AACA,cAAI,EAAE,QAAQ,SAAS,GAAG;AACxB,cAAE,QAAQ,KAAK,EAAE,OAAO;AAAA,UAC1B;AACA,YAAE,UAAU,EAAE,eAAe,SAAS,CAAC,CAAC,IAAI,CAAC;AAC7C,iBAAO;AAAA,QACT;AACA,UAAE,QAAQ,KAAK,CAAC;AAChB,eAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,SAAS,CAAC;AAAA,QACV,SAAS,CAAC;AAAA,MACZ;AAAA,IACF;AACA,eAAW,SAAS,UAAU,QAAQ,OAAO,CAAC,UAAU,OAAO,CAAC,GAAG;AAEjE,YAAM,eAAW,yBAAK,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAElD,YAAM,QAAQ,MAAM,CAAC,EAAG,eAAe,SAAS,MAAM,CAAC,EAAG,QAAQ;AAClE,YAAM,YAAY,UAAU,QAAQ,IAAI;AAExC,UAAI,gBAAY;AAAA,QACd,CAAC,GAAG,GAAI,YAAY,MAAO,CAAC;AAAA,YAC5B;AAAA,UACE,EAAE,QAAQ,IAAI,UAAU;AAAA,cACxB,0BAAO,EAAE,OAAO,KAAK,SAAS,OAAO,GAAG,QAAQ;AAAA,QAClD;AAAA,MACF;AAKA,iBAAW,OAAO,UAAU;AAC1B,wBAAY;AAAA,UACV;AAAA,cACA,6BAAS;AAAA,YACP,QAAQ,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC;AAAA,YACxB,QAAQ,IAAI,iBAAiB;AAAA,YAC7B,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAEA,sBAAY,yBAAS,OAAO,wBAAwB,SAAS;AAE7D,iBAAW,KAAK,SAAS;AAAA,IAC3B;AACA,eAAW,OAAO,WAAW,OAAO,CAAC,MAAM,EAAE,eAAe,KAAK,GAAG;AAClE,UAAI,IAAI,eAAe,MAAO;AAE9B,oBAAc;AAAA,QACZ,GAAG,IAAI;AAAA,QACP,GAAG,IAAI;AAAA,QACP,eAAe;AAAA,QACf,gBAAgB;AAAA,QAChB,OAAO;AAAA,QACP,QAAQ,CAAC,OAAO,QAAQ;AAAA,QACxB,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AAEA,aAAW,OAAO,UAAU;AAC1B,kBAAc;AAAA,MACZ,GAAG,IAAI;AAAA,MACP,GAAG,IAAI;AAAA,MACP,eAAe,IAAI;AAAA,MACnB,gBAAgB,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,QAAQ,CAAC,OAAO,QAAQ;AAAA,MACxB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,kBAAY,yBAAS,OAAO,UAAU,SAAS;AAE/C,SAAO,CAAC,WAAW,GAAG,iBAAiB,GAAG,UAAU,GAAG,UAAU;AACnE;;;AGjKA,mBAAoC;AACpC,4BAA0B;AAG1B,SAAS,gBAAgB,MAA6B;AACpD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,IAAI,WAAW;AAC9B,WAAO,SAAS,MAAM;AACpB,cAAQ,OAAO,MAAgB;AAAA,IACjC;AACA,WAAO,UAAU;AACjB,WAAO,cAAc,IAAI;AAAA,EAC3B,CAAC;AACH;AAIO,IAAM,kBAAkB,CAC7B,SAIG;AACH,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAmB,CAAC,CAAC;AAC7C,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,IAAI;AAE3C,8BAAU,MAAM;AACd,UAAM,eAAe,YAAY;AAC/B,iBAAW,IAAI;AACf,YAAM,aAAa,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AAErD,YAAM,cAAc,WAAW,IAAI,OAAO,MAAM;AAC9C,cAAM,UAAU,sBAAAC,QAAc,UAAU,EAAE,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC;AAC7D,cAAM,WAAW,IAAI,KAAK,OAAO;AACjC,cAAM,SAAS,MAAM,gBAAgB,QAAQ;AAC7C,eAAO,EAAE,QAAQ,OAAO,EAAE,MAAO;AAAA,MACnC,CAAC;AAED,UAAI;AACF,cAAM,gBAAgB,MAAM,QAAQ,IAAI,WAAW;AACnD,gBAAQ,aAAa;AAAA,MACvB,SAAS,OAAO;AACd,gBAAQ,MAAM,0BAA0B,KAAK;AAC7C,gBAAQ,CAAC,CAAC;AAAA,MACZ,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAEA,iBAAa;AAAA,EACf,GAAG,CAAC,IAAI,CAAC;AAET,SAAO,EAAE,MAAM,QAAQ;AACzB;;;ACrDA,mBAA0B;AAC1B,IAAAC,gBAAuB;AAEvB,0BAAgD;AAmB5C;AAjBG,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AACZ,GAKG;AACD,QAAM,WAAO,wBAAU,+BAAW,MAAM;AACxC,QAAM,WAAO,sBAAmB;AAIhC,SACE,6CAAC,UAAK,KAAK,MACT;AAAA,gDAAC,eAAU,QAAQ,MAAM,QAAO,YAAW;AAAA,IAC3C;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,aAAa,YAAY;AAAA,QACzB;AAAA;AAAA,IACF;AAAA,KAEF;AAEJ;;;AChCA,IAAAC,gBAMO;AAEP,IAAAC,eAA8C;;;ACR9C,IAAAC,gBAA8B;AAC9B,IAAAC,gBAAiC;AACjC,kBAAoC;AACpC,YAAuB;AA0CnB,IAAAC,sBAAA;AAnCJ,OAAO,4BAA4B,IAAU,YAAM,GAAG,GAAG,CAAC;AAE1D,SAAS,oBAAoB,gBAAgB,UAAU;AAErD,QAAM,aAAa,IAAU,iBAAW,EAAE;AAAA,IACxC,IAAU,YAAM,eAAe,GAAG,eAAe,GAAG,eAAe,CAAC;AAAA,EACtE;AAGA,QAAM,gBAAgB,IAAU,cAAQ,GAAG,GAAG,CAAC;AAG/C,gBAAc,gBAAgB,UAAU;AAGxC,QAAM,SAAS,cAAc,eAAe,QAAQ;AAEpD,SAAO;AACT;AAEO,IAAM,uBAAuB,CAAC,CAAC,MAAW;AAC/C,QAAM,UAAM,sBAAmB;AAC/B,QAAM,0BAAsB,sBAAO,EAAE,cAAc,IAAU,YAAM,EAAE,CAAC;AACtE,8BAAS,CAAC,OAAO,UAAU;AACzB,QAAI,CAAC,IAAI,QAAS;AAElB,UAAM,UAAU,OAAO;AAGvB,UAAM,iBAAiB,oBAAoB,SAAS,CAAC;AAErD,UAAM,OAAO,SAAS,KAAK,cAAc;AACzC,UAAM,OAAO,OAAO,GAAG,GAAG,CAAC;AAAA,EAC7B,CAAC;AACD,SACE,8CAAC,UAAK,KAAiB,UAAU,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC,GACjD;AAAA,iDAAC,iBAAY,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG;AAAA,IAC9B,6CAAC,0BAAqB,OAAM,SAAQ;AAAA,IACpC,6CAAC,oBAAK,UAAU,CAAC,GAAG,GAAG,IAAI,GAAG,UAAU,MAAM,OAAM,SAAQ,mBAE5D;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,GAAG,GAAG,KAAK;AAAA,QACtB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,GAAG,KAAK,IAAI,CAAC;AAAA,QACzB;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,MAAM,GAAG,CAAC;AAAA,QACrB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,GAAG,KAAK,KAAK,GAAG,CAAC;AAAA,QAC7B;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,OAAO,GAAG,CAAC;AAAA,QACtB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC;AAAA,QAC9B;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,GAAG,MAAM,CAAC;AAAA,QACrB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC;AAAA,QAC9B;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,GAAG,OAAO,CAAC;AAAA,QACtB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC;AAAA,QAC7B;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,CAAC,IAAU,oBAAc,IAAU,kBAAY,GAAG,GAAG,CAAC,CAAC,CAAC;AAAA,QAC9D,UACE,IAAU,wBAAkB;AAAA,UAC1B,OAAO;AAAA,UACP,WAAW;AAAA,QACb,CAAC;AAAA;AAAA,IAEL;AAAA,KACF;AAEJ;;;AD/ES,IAAAC,sBAAA;AALF,IAAM,kBAAkB,MAAM;AACnC,8BAAS,CAAC,EAAE,OAAO,MAAM;AACvB,WAAO,4BAA4B,OAAO;AAAA,EAC5C,CAAC;AAED,SAAO,6EAAE;AACX;AAEO,IAAM,qBAAqB,CAAC,EAAE,SAAS,MAAyB;AACrE,SACE,8CAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,OAAO,GAChE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,KAAK;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ;AAAA,cACN,IAAI,CAAC,GAAG,GAAG,CAAC;AAAA;AAAA;AAAA,cAGZ,UAAU,CAAC,GAAG,GAAG,CAAC;AAAA,YACpB;AAAA,YAEA;AAAA,2DAAC,kBAAa,WAAW,KAAK,KAAK,GAAG;AAAA,cACtC,6CAAC,wBAAqB;AAAA;AAAA;AAAA,QACxB;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE;AAAA,QACvB,QAAQ,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,EAAE;AAAA,QAE7C;AAAA,uDAAC,mBAAgB;AAAA,UACjB,6CAAC,8BAAc,YAAU,MAAC,iBAAiB,GAAG;AAAA,UAC9C,6CAAC,kBAAa,WAAW,KAAK,KAAK,GAAG;AAAA,UACtC;AAAA,YAAC;AAAA;AAAA,cACC,UAAU,CAAC,KAAK,KAAK,EAAE;AAAA,cACvB,OAAO;AAAA,cACP,WAAW,KAAK,KAAK;AAAA;AAAA,UACvB;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,UAAU,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC;AAAA,cAC5B,cAAc;AAAA,cACd,UAAU;AAAA,cACV,aAAa;AAAA;AAAA,UACf;AAAA,UACC;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;;;AExEA,IAAAC,gBAAoC;AAEpC,IAAAC,uBAAqC;AAuDvB,IAAAC,sBAAA;AArDP,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AAKD,QAAM,CAAC,KAAK,MAAM,QAAI,wBAAqB,IAAI;AAC/C,+BAAU,MAAM;AACd,mBAAe,iBAAiB;AAC9B,YAAM,WAAW,MAAM,MAAM,GAAG;AAChC,YAAM,OAAO,MAAM,SAAS,KAAK;AAKjC,YAAM,aAAa,KAChB,MAAM,uBAAuB,GAC5B,KAAK,IAAI,EACV,QAAQ,UAAU,MAAM;AAC3B,YAAM,aAAa,KAAK,QAAQ,yBAAyB,EAAE;AAE3D,YAAM,YAAY,IAAI,+BAAU;AAChC,gBAAU,mBAAmB;AAAA,QAC3B,kBAAkB;AAAA,MACpB,CAAC;AACD,YAAM,YAAY,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,QAK1B,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAEA,YAAM,YAAY,IAAI,+BAAU;AAChC,gBAAU,aAAa,SAAS;AAChC,aAAO,UAAU,MAAM,UAAU,CAAC;AAAA,IACpC;AACA,mBAAe;AAAA,EACjB,GAAG,CAAC,GAAG,CAAC;AAER,SACE,6CAAC,WAAM,UAAoB,UACxB,iBAAO,6CAAC,eAAU,QAAQ,KAAK,GAClC;AAEJ;;;ARhCI,IAAAC,sBAAA;AAbG,IAAM,YAAY,CAAC,EAAE,MAAM,SAAS,MAAa;AACtD,WAAS,yBAAyB,UAAU,IAAI;AAIhD,QAAM,gBAAY,uBAAQ,MAAM,wBAAwB,IAAI,GAAG,CAAC,IAAI,CAAC;AAErE,QAAM,EAAE,MAAM,QAAQ,IAAI,gBAAgB,SAAS;AAEnD,QAAM,qBAAiB,sBAAG,IAAI,EAAE,cAAc,KAAK;AAGnD,SACE,8CAAC,sBACE;AAAA,SAAK,IAAI,CAAC,EAAE,QAAQ,MAAM,GAAG,UAC5B;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA;AAAA,QACA,SAAS,UAAU,IAAI,OAAO;AAAA;AAAA,MAHzB;AAAA,IAIP,CACD;AAAA,IAED;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ,UAAU,CAAC,GAAG,GAAG,GAAG;AAAA,QACpB,UAAU,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC;AAAA;AAAA,IAC9B;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ,UAAU,CAAC,OAAO,GAAG,GAAG;AAAA,QACxB,UAAU,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC;AAAA;AAAA,IAC9B;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ,UAAU,CAAC,MAAM,GAAG,GAAG;AAAA,QACvB,UAAU,CAAC,GAAG,GAAG,CAAC;AAAA;AAAA,IACpB;AAAA,KACF;AAEJ;","names":["__export","su","module","__toCommonJS","import_soup_util","import_react","import_primitives","import_colors","import_booleans","stlSerializer","import_react","import_fiber","import_drei","import_react","import_fiber","import_jsx_runtime","import_jsx_runtime","import_react","import_three_stdlib","import_jsx_runtime","import_jsx_runtime"]}
|
|
1
|
+
{"version":3,"sources":["../node_modules/@tscircuit/soup-util/index.ts","../src/index.tsx","../src/hooks/use-convert-children-to-soup.ts","../src/CadViewer.tsx","../src/soup-to-3d/index.ts","../src/geoms/plated-hole.ts","../src/geoms/constants.ts","../src/hooks/use-stls-from-geom.ts","../src/three-components/STLModel.tsx","../src/CadViewerContainer.tsx","../src/three-components/cube-with-labeled-sides.tsx","../src/three-components/MixedStlModel.tsx"],"sourcesContent":["import type {\n AnySoupElement,\n AnySoupElementInput,\n SourceComponentBase,\n SourcePort,\n} from \"@tscircuit/soup\"\n\ntype SoupOps<\n K extends AnySoupElement[\"type\"],\n T extends AnySoupElement | AnySoupElementInput\n> = {\n get: (id: string) => Extract<T, { type: K }> | null\n select: (selector: string) => Extract<T, { type: K }> | null\n getWhere: (where: any) => Extract<T, { type: K }> | null\n getUsing: (using: {\n [key: `${string}_id`]: string\n }) => Extract<T, { type: K }> | null\n list: (where?: any) => Extract<T, { type: K }>[]\n}\n\nexport type SoupUtilObject = {\n [K in AnySoupElement[\"type\"]]: SoupOps<K, AnySoupElement>\n}\nexport type SoupInputUtilObject = {\n [K in AnySoupElementInput[\"type\"]]: SoupOps<K, AnySoupElementInput>\n}\n\nexport type GetSoupUtilObject = ((soup: AnySoupElement[]) => SoupUtilObject) & {\n unparsed: (soup: AnySoupElementInput[]) => SoupInputUtilObject\n}\n\nexport const su: GetSoupUtilObject = ((soup: AnySoupElement[]) => {\n const su = new Proxy(\n {},\n {\n get: (proxy_target: any, component_type: string) => {\n return {\n get: (id: string) =>\n soup.find(\n (e: any) =>\n e.type === component_type && e[`${component_type}_id`] === id\n ),\n getUsing: (using: any) => {\n const keys = Object.keys(using)\n if (keys.length !== 1) {\n throw new Error(\n \"getUsing requires exactly one key, e.g. { pcb_component_id }\"\n )\n }\n const join_key = keys[0] as string\n const join_type = join_key.replace(\"_id\", \"\")\n const joiner: any = soup.find(\n (e: any) =>\n e.type === join_type && e[join_key] === using[join_key]\n )\n if (!joiner) return null\n return soup.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joiner[`${component_type}_id`]\n )\n },\n getWhere: (where: any) => {\n const keys = Object.keys(where)\n return soup.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key])\n )\n },\n list: (where?: any) => {\n const keys = !where ? [] : Object.keys(where)\n return soup.filter(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key])\n )\n },\n select: (selector: string) => {\n // TODO when applySelector is isolated we can use it, until then we\n // do a poor man's selector implementation for two common cases\n if (component_type === \"source_component\") {\n return soup.find(\n (e) =>\n e.type === \"source_component\" &&\n e.name === selector.replace(/\\./g, \"\")\n )\n } else if (\n component_type === \"pcb_port\" ||\n component_type === \"source_port\" ||\n component_type === \"schematic_port\"\n ) {\n const [component_name, port_selector] = selector\n .replace(/\\./g, \"\")\n .split(/[\\s\\>]+/)\n const source_component = soup.find(\n (e) =>\n e.type === \"source_component\" && e.name === component_name\n ) as SourceComponentBase\n if (!source_component) return null\n const source_port = soup.find(\n (e) =>\n e.type === \"source_port\" &&\n e.source_component_id ===\n source_component.source_component_id &&\n (e.name === port_selector ||\n (e.port_hints ?? []).includes(port_selector!))\n ) as SourcePort\n if (!source_port) return null\n if (component_type === \"source_port\") return source_port\n\n if (component_type === \"pcb_port\") {\n return soup.find(\n (e) =>\n e.type === \"pcb_port\" &&\n e.source_port_id === source_port.source_port_id\n )\n } else if (component_type === \"schematic_port\") {\n return soup.find(\n (e) =>\n e.type === \"schematic_port\" &&\n e.source_port_id === source_port.source_port_id\n )\n }\n }\n },\n }\n },\n }\n )\n\n return su\n}) as any\nsu.unparsed = su as any\n\nexport default su\n","export { CadViewer } from \"./CadViewer\"\n","import type { AnySoupElement } from \"@tscircuit/soup\"\n\nexport const useConvertChildrenToSoup = (\n children?: any,\n defaultSoup?: AnySoupElement[]\n) => {\n // TODO convert children if defined\n\n return defaultSoup!\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { useConvertChildrenToSoup } from \"./hooks/use-convert-children-to-soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { useMemo } from \"react\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport { useStlsFromGeom } from \"./hooks/use-stls-from-geom\"\nimport { STLModel } from \"./three-components/STLModel\"\nimport { CadViewerContainer } from \"./CadViewerContainer\"\nimport { MixedStlModel } from \"./three-components/MixedStlModel\"\n\ninterface Props {\n soup?: AnySoupElement[]\n children?: any\n}\n\nexport const CadViewer = ({ soup, children }: Props) => {\n soup ??= useConvertChildrenToSoup(children, soup)\n\n // TODO convert board\n\n const boardGeom = useMemo(() => createBoardGeomFromSoup(soup), [soup])\n\n const { stls, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n // TODO canvas/camera etc.\n return (\n <CadViewerContainer>\n {stls.map(({ stlUrl, color }, index) => (\n <STLModel\n key={stlUrl}\n stlUrl={stlUrl}\n color={color}\n opacity={index === 0 ? 0.95 : 1}\n />\n ))}\n {/* <MixedStlModel url=\"/easyeda-models/84af7f0f6529479fb6b1c809c61d205f\" /> */}\n <MixedStlModel\n url=\"/easyeda-models/dc694c23844346e9981bdbac7bb76421\"\n position={[0, 0, 0.5]}\n rotation={[0, 0, Math.PI / 2]}\n />\n <MixedStlModel\n url=\"/easyeda-models/c7acac53bcbc44d68fbab8f60a747688\"\n position={[-5.65, 0, 0.5]}\n rotation={[0, 0, Math.PI / 2]}\n />\n <MixedStlModel\n url=\"/easyeda-models/c7acac53bcbc44d68fbab8f60a747688\"\n position={[6.75, 0, 0.5]}\n rotation={[0, 0, 0]}\n />\n </CadViewerContainer>\n )\n}\n","import type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { AnySoupElement, PCBPlatedHole } from \"@tscircuit/soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\nimport { cuboid, cylinder, line } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract } from \"@jscad/modeling/src/operations/booleans\"\nimport { platedHole } from \"../geoms/plated-hole\"\nimport { M, colors } from \"../geoms/constants\"\nimport { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { expand } from \"@jscad/modeling/src/operations/expansions\"\n\nexport const createBoardGeomFromSoup = (soup: AnySoupElement[]): Geom3[] => {\n const board = su(soup).pcb_board.list()[0]\n if (!board) {\n throw new Error(\"No pcb_board found\")\n }\n\n const plated_holes = su(soup).pcb_plated_hole.list()\n const pads = su(soup).pcb_smtpad.list()\n const traces = su(soup).pcb_trace.list()\n const pcb_vias = su(soup).pcb_via.list()\n\n // PCB Board\n let boardGeom = cuboid({ size: [board.width, board.height, 1.2] })\n\n const platedHoleGeoms: Geom3[] = []\n const padGeoms: Geom3[] = []\n const traceGeoms: Geom3[] = []\n const ctx = {\n pcbThickness: 1.2,\n }\n\n const addPlatedHole = (plated_hole: PCBPlatedHole) => {\n if (!(plated_hole as any).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n const cyGeom = cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 + M,\n })\n boardGeom = subtract(boardGeom, cyGeom)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n }\n }\n\n for (const plated_hole of plated_holes) {\n addPlatedHole(plated_hole)\n }\n\n for (const pad of pads) {\n if (pad.shape === \"rect\") {\n const padGeom = colorize(\n colors.copper,\n cuboid({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n size: [pad.width, pad.height, M],\n })\n )\n padGeoms.push(padGeom)\n } else if (pad.shape === \"circle\") {\n const padGeom = colorize(\n colors.copper,\n cylinder({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n radius: pad.radius,\n height: M,\n })\n )\n padGeoms.push(padGeom)\n }\n }\n\n for (const { route: mixedRoute } of traces) {\n const subRoutes = mixedRoute.reduce(\n (c, p) => {\n // @ts-ignore\n const lastLayer = c.current?.[c.current.length - 1]?.layer\n if (\n p.route_type === \"via\" ||\n (p.route_type === \"wire\" && p.layer !== lastLayer)\n ) {\n if (c.current.length > 2) {\n c.allPrev.push(c.current)\n }\n c.current = p.route_type === \"wire\" ? [p] : []\n return c\n }\n c.current.push(p)\n return c\n },\n {\n current: [] as typeof mixedRoute,\n allPrev: [] as Array<typeof mixedRoute>,\n }\n )\n for (const route of subRoutes.allPrev.concat([subRoutes.current])) {\n // TODO break into segments based on layers\n const linePath = line(route.map((p) => [p.x, p.y]))\n\n const layer = route[0]!.route_type === \"wire\" ? route[0]!.layer : \"top\"\n const layerSign = layer === \"top\" ? 1 : -1\n // traceGeoms.push(traceGeom)\n let traceGeom = translate(\n [0, 0, (layerSign * 1.2) / 2],\n extrudeLinear(\n { height: M * layerSign },\n expand({ delta: 0.1, corners: \"edge\" }, linePath)\n )\n )\n\n // HACK: Subtract all vias from every trace- this mostly is because the\n // vias aren't inside the route- we should probably pre-filter to make sure\n // that vias are only near the route\n for (const via of pcb_vias) {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n })\n )\n }\n\n traceGeom = colorize(colors.fr4GreenSolderWithMask, traceGeom)\n\n traceGeoms.push(traceGeom)\n }\n for (const via of mixedRoute.filter((p) => p.route_type === \"via\")) {\n if (via.route_type !== \"via\") continue // TODO remove when ts is smart\n\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: 0.8,\n outer_diameter: 1.6,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n }\n\n for (const via of pcb_vias) {\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: via.hole_diameter,\n outer_diameter: via.outer_diameter,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n\n // Colorize to a PCB green color: #05A32E\n boardGeom = colorize(colors.fr4Green, boardGeom)\n\n return [boardGeom, ...platedHoleGeoms, ...padGeoms, ...traceGeoms]\n}\n","import type { PCBPlatedHole } from \"@tscircuit/soup\"\nimport type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport { cylinder } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { M, colors } from \"./constants\"\nimport { GeomContext } from \"../GeomContext\"\n\nexport const platedHole = (\n plated_hole: PCBPlatedHole,\n ctx: GeomContext\n): Geom3 => {\n if (!(plated_hole as any).shape) plated_hole.shape = \"circle\"\n if (plated_hole.shape === \"circle\") {\n return colorize(\n colors.copper,\n subtract(\n union(\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2,\n height: 1.2,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, -1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n })\n ),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 - M,\n height: 1.5,\n })\n )\n )\n } else {\n throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`)\n }\n}\n","import type { RGB } from \"@jscad/modeling/src/colors\"\n\nexport const M = 0.01\n\nexport const colors = {\n copper: [0.9, 0.6, 0.2],\n fr4Green: [0x05 / 255, 0xa3 / 255, 0x2e / 255],\n fr4GreenSolderWithMask: [0x00 / 255, 0x98 / 255, 0x13 / 255],\n} satisfies Record<string, RGB>\n","import { useState, useEffect } from \"react\"\nimport stlSerializer from \"@jscad/stl-serializer\"\nimport { Geom3 } from \"@jscad/modeling/src/geometries/types\"\n\nfunction blobToBase64Url(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n resolve(reader.result as string)\n }\n reader.onerror = reject\n reader.readAsDataURL(blob)\n })\n}\n\ntype StlObj = { stlUrl: string; color: number[] }\n\nexport const useStlsFromGeom = (\n geom: Geom3[] | Geom3\n): {\n stls: StlObj[]\n loading: boolean\n} => {\n const [stls, setStls] = useState<StlObj[]>([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n const generateStls = async () => {\n setLoading(true)\n const geometries = Array.isArray(geom) ? geom : [geom]\n\n const stlPromises = geometries.map(async (g) => {\n const rawData = stlSerializer.serialize({ binary: true }, [g])\n const blobData = new Blob(rawData)\n const stlUrl = await blobToBase64Url(blobData)\n return { stlUrl, color: g.color! }\n })\n\n try {\n const generatedStls = await Promise.all(stlPromises)\n setStls(generatedStls)\n } catch (error) {\n console.error(\"Error generating STLs:\", error)\n setStls([])\n } finally {\n setLoading(false)\n }\n }\n\n generateStls()\n }, [geom])\n\n return { stls, loading }\n}\n","import { useLoader } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport function STLModel({\n stlUrl,\n mtlUrl,\n color,\n opacity = 1,\n}: {\n stlUrl: string\n color?: any\n mtlUrl?: string\n opacity?: number\n}) {\n const geom = useLoader(STLLoader, stlUrl)\n const mesh = useRef<THREE.Mesh>()\n\n // TODO handle mtl url\n\n return (\n <mesh ref={mesh as any}>\n <primitive object={geom} attach=\"geometry\" />\n <meshStandardMaterial\n color={color}\n transparent={opacity !== 1}\n opacity={opacity}\n />\n {/* <Outlines thickness={0.05} color=\"black\" opacity={0.25} /> */}\n </mesh>\n )\n}\n","import {\n Canvas,\n useFrame,\n extend,\n useThree,\n useLoader,\n} from \"@react-three/fiber\"\nimport { Suspense, useEffect, useMemo, useRef, useState } from \"react\"\nimport { OrbitControls, Grid, Outlines } from \"@react-three/drei\"\nimport * as THREE from \"three\"\nimport { CubeWithLabeledSides } from \"./three-components/cube-with-labeled-sides\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport soup from \"./bug-pads-and-traces.json\"\n// import soup from \"./plated-hole-board.json\"\nimport stlSerializer from \"@jscad/stl-serializer\"\n// import { STLLoader } from \"three/examples/jsm/loaders/STLLoader\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport const RotationTracker = () => {\n useFrame(({ camera }) => {\n window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation\n })\n\n return <></>\n}\n\nexport const CadViewerContainer = ({ children }: { children: any }) => {\n return (\n <div style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}>\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 120,\n height: 120,\n }}\n >\n <Canvas\n camera={{\n up: [0, 0, 1],\n // rotation: [-Math.PI / 2, 0, 0],\n // lookAt: new THREE.Vector3(0, 0, 0),\n position: [1, 1, 1],\n }}\n >\n <ambientLight intensity={Math.PI / 2} />\n <CubeWithLabeledSides />\n </Canvas>\n </div>\n <Canvas\n scene={{ up: [0, 0, 1] }}\n camera={{ up: [0, 0, 1], position: [5, 5, 5] }}\n >\n <RotationTracker />\n <OrbitControls autoRotate autoRotateSpeed={1} />\n <ambientLight intensity={Math.PI / 2} />\n <pointLight\n position={[-10, -10, 10]}\n decay={0}\n intensity={Math.PI / 4}\n />\n <Grid\n rotation={[Math.PI / 2, 0, 0]}\n infiniteGrid={true}\n cellSize={1}\n sectionSize={10}\n />\n {children}\n </Canvas>\n </div>\n )\n}\n","import React, { useRef } from \"react\"\nimport { Canvas, useFrame } from \"@react-three/fiber\"\nimport { OrbitControls, Text } from \"@react-three/drei\"\nimport * as THREE from \"three\"\n\ndeclare global {\n interface Window {\n TSCI_MAIN_CAMERA_ROTATION: THREE.Euler\n }\n}\nif (typeof window !== \"undefined\") {\n window.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0)\n}\n\nfunction computePointInFront(rotationVector, distance) {\n // Create a quaternion from the rotation vector\n const quaternion = new THREE.Quaternion().setFromEuler(\n new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z)\n )\n\n // Create a vector pointing forward (along the negative z-axis)\n const forwardVector = new THREE.Vector3(0, 0, 1)\n\n // Apply the rotation to the forward vector\n forwardVector.applyQuaternion(quaternion)\n\n // Scale the rotated vector by the distance\n const result = forwardVector.multiplyScalar(distance)\n\n return result\n}\n\nexport const CubeWithLabeledSides = ({}: any) => {\n const ref = useRef<THREE.Mesh>()\n const rotationTrackingRef = useRef({ lastRotation: new THREE.Euler() })\n useFrame((state, delta) => {\n if (!ref.current) return\n\n const mainRot = window.TSCI_MAIN_CAMERA_ROTATION\n\n // Use window.TSCI_CAMERA_ROTATION to compute the position of the camera\n const cameraPosition = computePointInFront(mainRot, 2)\n\n state.camera.position.copy(cameraPosition)\n state.camera.lookAt(0, 0, 0)\n })\n return (\n <mesh ref={ref as any} rotation={[Math.PI / 2, 0, 0]}>\n <boxGeometry args={[1, 1, 1]} />\n <meshStandardMaterial color=\"white\" />\n <Text position={[0, 0, 0.51]} fontSize={0.25} color=\"black\">\n Front\n </Text>\n <Text\n position={[0, 0, -0.51]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI, 0]}\n >\n Back\n </Text>\n <Text\n position={[0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI / 2, 0]}\n >\n Right\n </Text>\n <Text\n position={[-0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, -Math.PI / 2, 0]}\n >\n Left\n </Text>\n <Text\n position={[0, 0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[-Math.PI / 2, 0, 0]}\n >\n Top\n </Text>\n <Text\n position={[0, -0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[Math.PI / 2, 0, 0]}\n >\n Bottom\n </Text>\n <lineSegments\n args={[new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1))]}\n material={\n new THREE.LineBasicMaterial({\n color: 0x000000,\n linewidth: 2,\n })\n }\n />\n </mesh>\n )\n}\n","import { useEffect, useState } from \"react\"\nimport { Euler, Vector3 } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\nexport function MixedStlModel({\n url,\n position,\n rotation,\n}: {\n url: string\n position?: Vector3 | [number, number, number]\n rotation?: Euler | [number, number, number]\n}) {\n // const group = useLoader(OBJLoader, url)\n // const materials = useLoader(MTLLoader, url)\n // const obj = useLoader(OBJLoader, url)\n\n const [obj, setObj] = useState<any | null>(null)\n useEffect(() => {\n async function loadUrlContent() {\n const response = await fetch(url)\n const text = await response.text()\n\n // Extract all the sections of the file that have newmtl...endmtl to\n // separate into mtlContent and objContent\n\n const mtlContent = text\n .match(/newmtl[\\s\\S]*?endmtl/g)\n ?.join(\"\\n\")!\n .replace(/d 0\\./g, \"d 1.\")!\n const objContent = text.replace(/newmtl[\\s\\S]*?endmtl/g, \"\")\n\n const mtlLoader = new MTLLoader()\n mtlLoader.setMaterialOptions({\n invertTrProperty: true,\n })\n const materials = mtlLoader.parse(\n // Grayscale the colors, for some reason everything from JLCPCB is\n // a bit red, it doesn't look right. The grayscale version looks OK,\n // it's a HACK because we only take the second color rather than\n // averaging the colors\n mtlContent.replace(\n /Kd\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)/g,\n \"Kd $2 $2 $2\"\n ),\n \"test.mtl\"\n )\n\n const objLoader = new OBJLoader()\n objLoader.setMaterials(materials)\n setObj(objLoader.parse(objContent))\n }\n loadUrlContent()\n }, [url])\n\n return (\n <group rotation={rotation} position={position}>\n {obj && <primitive object={obj} />}\n </group>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,QAAA,oBAAA,CAAA;AAAA,IAAAA,UAAA,mBAAA;MAAA,SAAA,MAAA;MAAA,IAAA,MAAAC;IAAA,CAAA;AAAA,IAAAC,QAAA,UAAAC,cAAA,iBAAA;AA+BO,QAAMF,MAAyB,CAAC,SAA2B;AAChE,YAAMA,OAAK,IAAI;QACb,CAAC;QACD;UACE,KAAK,CAAC,cAAmB,mBAA2B;AAClD,mBAAO;cACL,KAAK,CAAC,OACJ,KAAK;gBACH,CAAC,MACC,EAAE,SAAS,kBAAkB,EAAE,GAAG,cAAc,KAAK,MAAM;cAC/D;cACF,UAAU,CAAC,UAAe;AACxB,sBAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,oBAAI,KAAK,WAAW,GAAG;AACrB,wBAAM,IAAI;oBACR;kBACF;gBACF;AACA,sBAAM,WAAW,KAAK,CAAC;AACvB,sBAAM,YAAY,SAAS,QAAQ,OAAO,EAAE;AAC5C,sBAAM,SAAc,KAAK;kBACvB,CAAC,MACC,EAAE,SAAS,aAAa,EAAE,QAAQ,MAAM,MAAM,QAAQ;gBAC1D;AACA,oBAAI,CAAC;AAAQ,yBAAO;AACpB,uBAAO,KAAK;kBACV,CAAC,MACC,EAAE,SAAS,kBACX,EAAE,GAAG,cAAc,KAAK,MAAM,OAAO,GAAG,cAAc,KAAK;gBAC/D;cACF;cACA,UAAU,CAAC,UAAe;AACxB,sBAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,uBAAO,KAAK;kBACV,CAAC,MACC,EAAE,SAAS,kBACX,KAAK,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,MAAM,GAAG,CAAC;gBAC7C;cACF;cACA,MAAM,CAAC,UAAgB;AACrB,sBAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,KAAK,KAAK;AAC5C,uBAAO,KAAK;kBACV,CAAC,MACC,EAAE,SAAS,kBACX,KAAK,MAAM,CAAC,QAAQ,EAAE,GAAG,MAAM,MAAM,GAAG,CAAC;gBAC7C;cACF;cACA,QAAQ,CAAC,aAAqB;AAG5B,oBAAI,mBAAmB,oBAAoB;AACzC,yBAAO,KAAK;oBACV,CAAC,MACC,EAAE,SAAS,sBACX,EAAE,SAAS,SAAS,QAAQ,OAAO,EAAE;kBACzC;gBACF,WACE,mBAAmB,cACnB,mBAAmB,iBACnB,mBAAmB,kBACnB;AACA,wBAAM,CAAC,gBAAgB,aAAa,IAAI,SACrC,QAAQ,OAAO,EAAE,EACjB,MAAM,SAAS;AAClB,wBAAM,mBAAmB,KAAK;oBAC5B,CAAC,MACC,EAAE,SAAS,sBAAsB,EAAE,SAAS;kBAChD;AACA,sBAAI,CAAC;AAAkB,2BAAO;AAC9B,wBAAM,cAAc,KAAK;oBACvB,CAAC,MACC,EAAE,SAAS,iBACX,EAAE,wBACA,iBAAiB,wBAClB,EAAE,SAAS,kBACT,EAAE,cAAc,CAAC,GAAG,SAAS,aAAc;kBAClD;AACA,sBAAI,CAAC;AAAa,2BAAO;AACzB,sBAAI,mBAAmB;AAAe,2BAAO;AAE7C,sBAAI,mBAAmB,YAAY;AACjC,2BAAO,KAAK;sBACV,CAAC,MACC,EAAE,SAAS,cACX,EAAE,mBAAmB,YAAY;oBACrC;kBACF,WAAW,mBAAmB,kBAAkB;AAC9C,2BAAO,KAAK;sBACV,CAAC,MACC,EAAE,SAAS,oBACX,EAAE,mBAAmB,YAAY;oBACrC;kBACF;gBACF;cACF;YACF;UACF;QACF;MACF;AAEA,aAAOA;IACT;AACA,IAAAA,IAAG,WAAWA;AAEd,QAAO,oBAAQA;;;;;ACvIf;AAAA;AAAA;AAAA;AAAA;;;ACEO,IAAM,2BAA2B,CACtC,UACA,gBACG;AAGH,SAAO;AACT;;;ACPA,IAAAG,oBAAmB;AACnB,IAAAC,gBAAwB;;;ACDxB,uBAAmB;AACnB,wBAA0B;AAC1B,IAAAC,qBAAuC;AACvC,IAAAC,iBAAyB;AACzB,IAAAC,mBAAyB;;;ACJzB,wBAAyB;AACzB,oBAAyB;AACzB,sBAAgC;;;ACFzB,IAAM,IAAI;AAEV,IAAM,SAAS;AAAA,EACpB,QAAQ,CAAC,KAAK,KAAK,GAAG;AAAA,EACtB,UAAU,CAAC,IAAO,KAAK,MAAO,KAAK,KAAO,GAAG;AAAA,EAC7C,wBAAwB,CAAC,IAAO,KAAK,MAAO,KAAK,KAAO,GAAG;AAC7D;;;ADAO,IAAM,aAAa,CACxB,aACA,QACU;AACV,MAAI,CAAE,YAAoB,MAAO,aAAY,QAAQ;AACrD,MAAI,YAAY,UAAU,UAAU;AAClC,eAAO;AAAA,MACL,OAAO;AAAA,UACP;AAAA,YACE;AAAA,cACE,4BAAS;AAAA,YACP,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,CAAC;AAAA,YACxC,QAAQ,YAAY,gBAAgB;AAAA,YACpC,QAAQ;AAAA,UACV,CAAC;AAAA,cACD,4BAAS;AAAA,YACP,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,MAAM,CAAC;AAAA,YAC9C,QAAQ,YAAY,iBAAiB;AAAA,YACrC,QAAQ;AAAA,UACV,CAAC;AAAA,cACD,4BAAS;AAAA,YACP,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,OAAO,CAAC;AAAA,YAC/C,QAAQ,YAAY,iBAAiB;AAAA,YACrC,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,YACA,4BAAS;AAAA,UACP,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,CAAC;AAAA,UACxC,QAAQ,YAAY,gBAAgB,IAAI;AAAA,UACxC,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,OAAO;AACL,UAAM,IAAI,MAAM,kCAAkC,YAAY,KAAK,EAAE;AAAA,EACvE;AACF;;;ADnCA,wBAA8B;AAC9B,wBAAuB;AAEhB,IAAM,0BAA0B,CAAC,SAAoC;AAC1E,QAAM,YAAQ,qBAAG,IAAI,EAAE,UAAU,KAAK,EAAE,CAAC;AACzC,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,oBAAoB;AAAA,EACtC;AAEA,QAAM,mBAAe,qBAAG,IAAI,EAAE,gBAAgB,KAAK;AACnD,QAAM,WAAO,qBAAG,IAAI,EAAE,WAAW,KAAK;AACtC,QAAM,aAAS,qBAAG,IAAI,EAAE,UAAU,KAAK;AACvC,QAAM,eAAW,qBAAG,IAAI,EAAE,QAAQ,KAAK;AAGvC,MAAI,gBAAY,2BAAO,EAAE,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,GAAG,EAAE,CAAC;AAEjE,QAAM,kBAA2B,CAAC;AAClC,QAAM,WAAoB,CAAC;AAC3B,QAAM,aAAsB,CAAC;AAC7B,QAAM,MAAM;AAAA,IACV,cAAc;AAAA,EAChB;AAEA,QAAM,gBAAgB,CAAC,gBAA+B;AACpD,QAAI,CAAE,YAAoB,MAAO,aAAY,QAAQ;AACrD,QAAI,YAAY,UAAU,UAAU;AAClC,YAAM,aAAS,6BAAS;AAAA,QACtB,QAAQ,CAAC,YAAY,GAAG,YAAY,GAAG,CAAC;AAAA,QACxC,QAAQ,YAAY,gBAAgB,IAAI;AAAA,MAC1C,CAAC;AACD,sBAAY,2BAAS,WAAW,MAAM;AAEtC,YAAM,iBAAiB,WAAW,aAAa,GAAG;AAClD,sBAAgB,KAAK,cAAc;AAAA,IACrC;AAAA,EACF;AAEA,aAAW,eAAe,cAAc;AACtC,kBAAc,WAAW;AAAA,EAC3B;AAEA,aAAW,OAAO,MAAM;AACtB,QAAI,IAAI,UAAU,QAAQ;AACxB,YAAM,cAAU;AAAA,QACd,OAAO;AAAA,YACP,2BAAO;AAAA,UACL,QAAQ,CAAC,IAAI,GAAG,IAAI,GAAG,MAAM,IAAI,CAAC;AAAA,UAClC,MAAM,CAAC,IAAI,OAAO,IAAI,QAAQ,CAAC;AAAA,QACjC,CAAC;AAAA,MACH;AACA,eAAS,KAAK,OAAO;AAAA,IACvB,WAAW,IAAI,UAAU,UAAU;AACjC,YAAM,cAAU;AAAA,QACd,OAAO;AAAA,YACP,6BAAS;AAAA,UACP,QAAQ,CAAC,IAAI,GAAG,IAAI,GAAG,MAAM,IAAI,CAAC;AAAA,UAClC,QAAQ,IAAI;AAAA,UACZ,QAAQ;AAAA,QACV,CAAC;AAAA,MACH;AACA,eAAS,KAAK,OAAO;AAAA,IACvB;AAAA,EACF;AAEA,aAAW,EAAE,OAAO,WAAW,KAAK,QAAQ;AAC1C,UAAM,YAAY,WAAW;AAAA,MAC3B,CAAC,GAAG,MAAM;AAER,cAAM,YAAY,EAAE,UAAU,EAAE,QAAQ,SAAS,CAAC,GAAG;AACrD,YACE,EAAE,eAAe,SAChB,EAAE,eAAe,UAAU,EAAE,UAAU,WACxC;AACA,cAAI,EAAE,QAAQ,SAAS,GAAG;AACxB,cAAE,QAAQ,KAAK,EAAE,OAAO;AAAA,UAC1B;AACA,YAAE,UAAU,EAAE,eAAe,SAAS,CAAC,CAAC,IAAI,CAAC;AAC7C,iBAAO;AAAA,QACT;AACA,UAAE,QAAQ,KAAK,CAAC;AAChB,eAAO;AAAA,MACT;AAAA,MACA;AAAA,QACE,SAAS,CAAC;AAAA,QACV,SAAS,CAAC;AAAA,MACZ;AAAA,IACF;AACA,eAAW,SAAS,UAAU,QAAQ,OAAO,CAAC,UAAU,OAAO,CAAC,GAAG;AAEjE,YAAM,eAAW,yBAAK,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;AAElD,YAAM,QAAQ,MAAM,CAAC,EAAG,eAAe,SAAS,MAAM,CAAC,EAAG,QAAQ;AAClE,YAAM,YAAY,UAAU,QAAQ,IAAI;AAExC,UAAI,gBAAY;AAAA,QACd,CAAC,GAAG,GAAI,YAAY,MAAO,CAAC;AAAA,YAC5B;AAAA,UACE,EAAE,QAAQ,IAAI,UAAU;AAAA,cACxB,0BAAO,EAAE,OAAO,KAAK,SAAS,OAAO,GAAG,QAAQ;AAAA,QAClD;AAAA,MACF;AAKA,iBAAW,OAAO,UAAU;AAC1B,wBAAY;AAAA,UACV;AAAA,cACA,6BAAS;AAAA,YACP,QAAQ,CAAC,IAAI,GAAG,IAAI,GAAG,CAAC;AAAA,YACxB,QAAQ,IAAI,iBAAiB;AAAA,YAC7B,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAEA,sBAAY,yBAAS,OAAO,wBAAwB,SAAS;AAE7D,iBAAW,KAAK,SAAS;AAAA,IAC3B;AACA,eAAW,OAAO,WAAW,OAAO,CAAC,MAAM,EAAE,eAAe,KAAK,GAAG;AAClE,UAAI,IAAI,eAAe,MAAO;AAE9B,oBAAc;AAAA,QACZ,GAAG,IAAI;AAAA,QACP,GAAG,IAAI;AAAA,QACP,eAAe;AAAA,QACf,gBAAgB;AAAA,QAChB,OAAO;AAAA,QACP,QAAQ,CAAC,OAAO,QAAQ;AAAA,QACxB,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AAEA,aAAW,OAAO,UAAU;AAC1B,kBAAc;AAAA,MACZ,GAAG,IAAI;AAAA,MACP,GAAG,IAAI;AAAA,MACP,eAAe,IAAI;AAAA,MACnB,gBAAgB,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,QAAQ,CAAC,OAAO,QAAQ;AAAA,MACxB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAGA,kBAAY,yBAAS,OAAO,UAAU,SAAS;AAE/C,SAAO,CAAC,WAAW,GAAG,iBAAiB,GAAG,UAAU,GAAG,UAAU;AACnE;;;AGjKA,mBAAoC;AACpC,4BAA0B;AAG1B,SAAS,gBAAgB,MAA6B;AACpD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAS,IAAI,WAAW;AAC9B,WAAO,SAAS,MAAM;AACpB,cAAQ,OAAO,MAAgB;AAAA,IACjC;AACA,WAAO,UAAU;AACjB,WAAO,cAAc,IAAI;AAAA,EAC3B,CAAC;AACH;AAIO,IAAM,kBAAkB,CAC7B,SAIG;AACH,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAmB,CAAC,CAAC;AAC7C,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,IAAI;AAE3C,8BAAU,MAAM;AACd,UAAM,eAAe,YAAY;AAC/B,iBAAW,IAAI;AACf,YAAM,aAAa,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AAErD,YAAM,cAAc,WAAW,IAAI,OAAO,MAAM;AAC9C,cAAM,UAAU,sBAAAC,QAAc,UAAU,EAAE,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC;AAC7D,cAAM,WAAW,IAAI,KAAK,OAAO;AACjC,cAAM,SAAS,MAAM,gBAAgB,QAAQ;AAC7C,eAAO,EAAE,QAAQ,OAAO,EAAE,MAAO;AAAA,MACnC,CAAC;AAED,UAAI;AACF,cAAM,gBAAgB,MAAM,QAAQ,IAAI,WAAW;AACnD,gBAAQ,aAAa;AAAA,MACvB,SAAS,OAAO;AACd,gBAAQ,MAAM,0BAA0B,KAAK;AAC7C,gBAAQ,CAAC,CAAC;AAAA,MACZ,UAAE;AACA,mBAAW,KAAK;AAAA,MAClB;AAAA,IACF;AAEA,iBAAa;AAAA,EACf,GAAG,CAAC,IAAI,CAAC;AAET,SAAO,EAAE,MAAM,QAAQ;AACzB;;;ACrDA,mBAA0B;AAC1B,IAAAC,gBAAuB;AAEvB,0BAAgD;AAmB5C;AAjBG,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AACZ,GAKG;AACD,QAAM,WAAO,wBAAU,+BAAW,MAAM;AACxC,QAAM,WAAO,sBAAmB;AAIhC,SACE,6CAAC,UAAK,KAAK,MACT;AAAA,gDAAC,eAAU,QAAQ,MAAM,QAAO,YAAW;AAAA,IAC3C;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,aAAa,YAAY;AAAA,QACzB;AAAA;AAAA,IACF;AAAA,KAEF;AAEJ;;;AChCA,IAAAC,gBAMO;AAEP,IAAAC,eAA8C;;;ACR9C,IAAAC,gBAA8B;AAC9B,IAAAC,gBAAiC;AACjC,kBAAoC;AACpC,YAAuB;AA4CnB,IAAAC,sBAAA;AArCJ,IAAI,OAAO,WAAW,aAAa;AACjC,SAAO,4BAA4B,IAAU,YAAM,GAAG,GAAG,CAAC;AAC5D;AAEA,SAAS,oBAAoB,gBAAgB,UAAU;AAErD,QAAM,aAAa,IAAU,iBAAW,EAAE;AAAA,IACxC,IAAU,YAAM,eAAe,GAAG,eAAe,GAAG,eAAe,CAAC;AAAA,EACtE;AAGA,QAAM,gBAAgB,IAAU,cAAQ,GAAG,GAAG,CAAC;AAG/C,gBAAc,gBAAgB,UAAU;AAGxC,QAAM,SAAS,cAAc,eAAe,QAAQ;AAEpD,SAAO;AACT;AAEO,IAAM,uBAAuB,CAAC,CAAC,MAAW;AAC/C,QAAM,UAAM,sBAAmB;AAC/B,QAAM,0BAAsB,sBAAO,EAAE,cAAc,IAAU,YAAM,EAAE,CAAC;AACtE,8BAAS,CAAC,OAAO,UAAU;AACzB,QAAI,CAAC,IAAI,QAAS;AAElB,UAAM,UAAU,OAAO;AAGvB,UAAM,iBAAiB,oBAAoB,SAAS,CAAC;AAErD,UAAM,OAAO,SAAS,KAAK,cAAc;AACzC,UAAM,OAAO,OAAO,GAAG,GAAG,CAAC;AAAA,EAC7B,CAAC;AACD,SACE,8CAAC,UAAK,KAAiB,UAAU,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC,GACjD;AAAA,iDAAC,iBAAY,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG;AAAA,IAC9B,6CAAC,0BAAqB,OAAM,SAAQ;AAAA,IACpC,6CAAC,oBAAK,UAAU,CAAC,GAAG,GAAG,IAAI,GAAG,UAAU,MAAM,OAAM,SAAQ,mBAE5D;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,GAAG,GAAG,KAAK;AAAA,QACtB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,GAAG,KAAK,IAAI,CAAC;AAAA,QACzB;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,MAAM,GAAG,CAAC;AAAA,QACrB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,GAAG,KAAK,KAAK,GAAG,CAAC;AAAA,QAC7B;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,OAAO,GAAG,CAAC;AAAA,QACtB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC;AAAA,QAC9B;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,GAAG,MAAM,CAAC;AAAA,QACrB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC;AAAA,QAC9B;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,UAAU,CAAC,GAAG,OAAO,CAAC;AAAA,QACtB,UAAU;AAAA,QACV,OAAM;AAAA,QACN,UAAU,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC;AAAA,QAC7B;AAAA;AAAA,IAED;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM,CAAC,IAAU,oBAAc,IAAU,kBAAY,GAAG,GAAG,CAAC,CAAC,CAAC;AAAA,QAC9D,UACE,IAAU,wBAAkB;AAAA,UAC1B,OAAO;AAAA,UACP,WAAW;AAAA,QACb,CAAC;AAAA;AAAA,IAEL;AAAA,KACF;AAEJ;;;ADjFS,IAAAC,sBAAA;AALF,IAAM,kBAAkB,MAAM;AACnC,8BAAS,CAAC,EAAE,OAAO,MAAM;AACvB,WAAO,4BAA4B,OAAO;AAAA,EAC5C,CAAC;AAED,SAAO,6EAAE;AACX;AAEO,IAAM,qBAAqB,CAAC,EAAE,SAAS,MAAyB;AACrE,SACE,8CAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,OAAO,GAChE;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,KAAK;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,QAAQ;AAAA,cACN,IAAI,CAAC,GAAG,GAAG,CAAC;AAAA;AAAA;AAAA,cAGZ,UAAU,CAAC,GAAG,GAAG,CAAC;AAAA,YACpB;AAAA,YAEA;AAAA,2DAAC,kBAAa,WAAW,KAAK,KAAK,GAAG;AAAA,cACtC,6CAAC,wBAAqB;AAAA;AAAA;AAAA,QACxB;AAAA;AAAA,IACF;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE;AAAA,QACvB,QAAQ,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,EAAE;AAAA,QAE7C;AAAA,uDAAC,mBAAgB;AAAA,UACjB,6CAAC,8BAAc,YAAU,MAAC,iBAAiB,GAAG;AAAA,UAC9C,6CAAC,kBAAa,WAAW,KAAK,KAAK,GAAG;AAAA,UACtC;AAAA,YAAC;AAAA;AAAA,cACC,UAAU,CAAC,KAAK,KAAK,EAAE;AAAA,cACvB,OAAO;AAAA,cACP,WAAW,KAAK,KAAK;AAAA;AAAA,UACvB;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,UAAU,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC;AAAA,cAC5B,cAAc;AAAA,cACd,UAAU;AAAA,cACV,aAAa;AAAA;AAAA,UACf;AAAA,UACC;AAAA;AAAA;AAAA,IACH;AAAA,KACF;AAEJ;;;AExEA,IAAAC,gBAAoC;AAEpC,IAAAC,uBAAqC;AAuDvB,IAAAC,sBAAA;AArDP,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AAKD,QAAM,CAAC,KAAK,MAAM,QAAI,wBAAqB,IAAI;AAC/C,+BAAU,MAAM;AACd,mBAAe,iBAAiB;AAC9B,YAAM,WAAW,MAAM,MAAM,GAAG;AAChC,YAAM,OAAO,MAAM,SAAS,KAAK;AAKjC,YAAM,aAAa,KAChB,MAAM,uBAAuB,GAC5B,KAAK,IAAI,EACV,QAAQ,UAAU,MAAM;AAC3B,YAAM,aAAa,KAAK,QAAQ,yBAAyB,EAAE;AAE3D,YAAM,YAAY,IAAI,+BAAU;AAChC,gBAAU,mBAAmB;AAAA,QAC3B,kBAAkB;AAAA,MACpB,CAAC;AACD,YAAM,YAAY,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,QAK1B,WAAW;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAEA,YAAM,YAAY,IAAI,+BAAU;AAChC,gBAAU,aAAa,SAAS;AAChC,aAAO,UAAU,MAAM,UAAU,CAAC;AAAA,IACpC;AACA,mBAAe;AAAA,EACjB,GAAG,CAAC,GAAG,CAAC;AAER,SACE,6CAAC,WAAM,UAAoB,UACxB,iBAAO,6CAAC,eAAU,QAAQ,KAAK,GAClC;AAEJ;;;ARhCI,IAAAC,sBAAA;AAbG,IAAM,YAAY,CAAC,EAAE,MAAM,SAAS,MAAa;AACtD,WAAS,yBAAyB,UAAU,IAAI;AAIhD,QAAM,gBAAY,uBAAQ,MAAM,wBAAwB,IAAI,GAAG,CAAC,IAAI,CAAC;AAErE,QAAM,EAAE,MAAM,QAAQ,IAAI,gBAAgB,SAAS;AAEnD,QAAM,qBAAiB,sBAAG,IAAI,EAAE,cAAc,KAAK;AAGnD,SACE,8CAAC,sBACE;AAAA,SAAK,IAAI,CAAC,EAAE,QAAQ,MAAM,GAAG,UAC5B;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA;AAAA,QACA,SAAS,UAAU,IAAI,OAAO;AAAA;AAAA,MAHzB;AAAA,IAIP,CACD;AAAA,IAED;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ,UAAU,CAAC,GAAG,GAAG,GAAG;AAAA,QACpB,UAAU,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC;AAAA;AAAA,IAC9B;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ,UAAU,CAAC,OAAO,GAAG,GAAG;AAAA,QACxB,UAAU,CAAC,GAAG,GAAG,KAAK,KAAK,CAAC;AAAA;AAAA,IAC9B;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,KAAI;AAAA,QACJ,UAAU,CAAC,MAAM,GAAG,GAAG;AAAA,QACvB,UAAU,CAAC,GAAG,GAAG,CAAC;AAAA;AAAA,IACpB;AAAA,KACF;AAEJ;","names":["__export","su","module","__toCommonJS","import_soup_util","import_react","import_primitives","import_colors","import_booleans","stlSerializer","import_react","import_fiber","import_drei","import_react","import_fiber","import_jsx_runtime","import_jsx_runtime","import_react","import_three_stdlib","import_jsx_runtime","import_jsx_runtime"]}
|
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/3d-viewer",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"main": "./dist/index.
|
|
5
|
-
"files": [
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
6
8
|
"scripts": {
|
|
7
9
|
"start": "bun run dev",
|
|
8
10
|
"dev": "bunx --bun vite",
|
package/dist/index.cjs
DELETED
|
@@ -1,657 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __commonJS = (cb, mod) => function __require() {
|
|
8
|
-
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
9
|
-
};
|
|
10
|
-
var __export = (target, all) => {
|
|
11
|
-
for (var name in all)
|
|
12
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
-
};
|
|
14
|
-
var __copyProps = (to, from, except, desc) => {
|
|
15
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
16
|
-
for (let key of __getOwnPropNames(from))
|
|
17
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
18
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
19
|
-
}
|
|
20
|
-
return to;
|
|
21
|
-
};
|
|
22
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
23
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
24
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
25
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
26
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
27
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
28
|
-
mod
|
|
29
|
-
));
|
|
30
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
31
|
-
|
|
32
|
-
// node_modules/@tscircuit/soup-util/dist/index.cjs
|
|
33
|
-
var require_dist = __commonJS({
|
|
34
|
-
"node_modules/@tscircuit/soup-util/dist/index.cjs"(exports2, module2) {
|
|
35
|
-
"use strict";
|
|
36
|
-
var __defProp2 = Object.defineProperty;
|
|
37
|
-
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
38
|
-
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
39
|
-
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
40
|
-
var __export2 = (target, all) => {
|
|
41
|
-
for (var name in all)
|
|
42
|
-
__defProp2(target, name, { get: all[name], enumerable: true });
|
|
43
|
-
};
|
|
44
|
-
var __copyProps2 = (to, from, except, desc) => {
|
|
45
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
46
|
-
for (let key of __getOwnPropNames2(from))
|
|
47
|
-
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
48
|
-
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
|
|
49
|
-
}
|
|
50
|
-
return to;
|
|
51
|
-
};
|
|
52
|
-
var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
53
|
-
var soup_util_exports = {};
|
|
54
|
-
__export2(soup_util_exports, {
|
|
55
|
-
default: () => soup_util_default,
|
|
56
|
-
su: () => su3
|
|
57
|
-
});
|
|
58
|
-
module2.exports = __toCommonJS2(soup_util_exports);
|
|
59
|
-
var su3 = (soup) => {
|
|
60
|
-
const su22 = new Proxy(
|
|
61
|
-
{},
|
|
62
|
-
{
|
|
63
|
-
get: (proxy_target, component_type) => {
|
|
64
|
-
return {
|
|
65
|
-
get: (id) => soup.find(
|
|
66
|
-
(e) => e.type === component_type && e[`${component_type}_id`] === id
|
|
67
|
-
),
|
|
68
|
-
getUsing: (using) => {
|
|
69
|
-
const keys = Object.keys(using);
|
|
70
|
-
if (keys.length !== 1) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
"getUsing requires exactly one key, e.g. { pcb_component_id }"
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
const join_key = keys[0];
|
|
76
|
-
const join_type = join_key.replace("_id", "");
|
|
77
|
-
const joiner = soup.find(
|
|
78
|
-
(e) => e.type === join_type && e[join_key] === using[join_key]
|
|
79
|
-
);
|
|
80
|
-
if (!joiner)
|
|
81
|
-
return null;
|
|
82
|
-
return soup.find(
|
|
83
|
-
(e) => e.type === component_type && e[`${component_type}_id`] === joiner[`${component_type}_id`]
|
|
84
|
-
);
|
|
85
|
-
},
|
|
86
|
-
getWhere: (where) => {
|
|
87
|
-
const keys = Object.keys(where);
|
|
88
|
-
return soup.find(
|
|
89
|
-
(e) => e.type === component_type && keys.every((key) => e[key] === where[key])
|
|
90
|
-
);
|
|
91
|
-
},
|
|
92
|
-
list: (where) => {
|
|
93
|
-
const keys = !where ? [] : Object.keys(where);
|
|
94
|
-
return soup.filter(
|
|
95
|
-
(e) => e.type === component_type && keys.every((key) => e[key] === where[key])
|
|
96
|
-
);
|
|
97
|
-
},
|
|
98
|
-
select: (selector) => {
|
|
99
|
-
if (component_type === "source_component") {
|
|
100
|
-
return soup.find(
|
|
101
|
-
(e) => e.type === "source_component" && e.name === selector.replace(/\./g, "")
|
|
102
|
-
);
|
|
103
|
-
} else if (component_type === "pcb_port" || component_type === "source_port" || component_type === "schematic_port") {
|
|
104
|
-
const [component_name, port_selector] = selector.replace(/\./g, "").split(/[\s\>]+/);
|
|
105
|
-
const source_component = soup.find(
|
|
106
|
-
(e) => e.type === "source_component" && e.name === component_name
|
|
107
|
-
);
|
|
108
|
-
if (!source_component)
|
|
109
|
-
return null;
|
|
110
|
-
const source_port = soup.find(
|
|
111
|
-
(e) => e.type === "source_port" && e.source_component_id === source_component.source_component_id && (e.name === port_selector || (e.port_hints ?? []).includes(port_selector))
|
|
112
|
-
);
|
|
113
|
-
if (!source_port)
|
|
114
|
-
return null;
|
|
115
|
-
if (component_type === "source_port")
|
|
116
|
-
return source_port;
|
|
117
|
-
if (component_type === "pcb_port") {
|
|
118
|
-
return soup.find(
|
|
119
|
-
(e) => e.type === "pcb_port" && e.source_port_id === source_port.source_port_id
|
|
120
|
-
);
|
|
121
|
-
} else if (component_type === "schematic_port") {
|
|
122
|
-
return soup.find(
|
|
123
|
-
(e) => e.type === "schematic_port" && e.source_port_id === source_port.source_port_id
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
);
|
|
132
|
-
return su22;
|
|
133
|
-
};
|
|
134
|
-
su3.unparsed = su3;
|
|
135
|
-
var soup_util_default = su3;
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// src/index.tsx
|
|
140
|
-
var src_exports = {};
|
|
141
|
-
__export(src_exports, {
|
|
142
|
-
CadViewer: () => CadViewer
|
|
143
|
-
});
|
|
144
|
-
module.exports = __toCommonJS(src_exports);
|
|
145
|
-
|
|
146
|
-
// src/hooks/use-convert-children-to-soup.ts
|
|
147
|
-
var useConvertChildrenToSoup = (children, defaultSoup) => {
|
|
148
|
-
return defaultSoup;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
// src/CadViewer.tsx
|
|
152
|
-
var import_soup_util2 = __toESM(require_dist(), 1);
|
|
153
|
-
var import_react5 = require("react");
|
|
154
|
-
|
|
155
|
-
// src/soup-to-3d/index.ts
|
|
156
|
-
var import_soup_util = __toESM(require_dist(), 1);
|
|
157
|
-
var import_transforms = require("@jscad/modeling/src/operations/transforms");
|
|
158
|
-
var import_primitives2 = require("@jscad/modeling/src/primitives");
|
|
159
|
-
var import_colors2 = require("@jscad/modeling/src/colors");
|
|
160
|
-
var import_booleans2 = require("@jscad/modeling/src/operations/booleans");
|
|
161
|
-
|
|
162
|
-
// src/geoms/plated-hole.ts
|
|
163
|
-
var import_primitives = require("@jscad/modeling/src/primitives");
|
|
164
|
-
var import_colors = require("@jscad/modeling/src/colors");
|
|
165
|
-
var import_booleans = require("@jscad/modeling/src/operations/booleans");
|
|
166
|
-
|
|
167
|
-
// src/geoms/constants.ts
|
|
168
|
-
var M = 0.01;
|
|
169
|
-
var colors = {
|
|
170
|
-
copper: [0.9, 0.6, 0.2],
|
|
171
|
-
fr4Green: [5 / 255, 163 / 255, 46 / 255],
|
|
172
|
-
fr4GreenSolderWithMask: [0 / 255, 152 / 255, 19 / 255]
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
// src/geoms/plated-hole.ts
|
|
176
|
-
var platedHole = (plated_hole, ctx) => {
|
|
177
|
-
if (plated_hole.shape === "circle" || !plated_hole.shape) {
|
|
178
|
-
return (0, import_colors.colorize)(
|
|
179
|
-
colors.copper,
|
|
180
|
-
(0, import_booleans.subtract)(
|
|
181
|
-
(0, import_booleans.union)(
|
|
182
|
-
(0, import_primitives.cylinder)({
|
|
183
|
-
center: [plated_hole.x, plated_hole.y, 0],
|
|
184
|
-
radius: plated_hole.hole_diameter / 2,
|
|
185
|
-
height: 1.2
|
|
186
|
-
}),
|
|
187
|
-
(0, import_primitives.cylinder)({
|
|
188
|
-
center: [plated_hole.x, plated_hole.y, 1.2 / 2],
|
|
189
|
-
radius: plated_hole.outer_diameter / 2,
|
|
190
|
-
height: M
|
|
191
|
-
}),
|
|
192
|
-
(0, import_primitives.cylinder)({
|
|
193
|
-
center: [plated_hole.x, plated_hole.y, -1.2 / 2],
|
|
194
|
-
radius: plated_hole.outer_diameter / 2,
|
|
195
|
-
height: M
|
|
196
|
-
})
|
|
197
|
-
),
|
|
198
|
-
(0, import_primitives.cylinder)({
|
|
199
|
-
center: [plated_hole.x, plated_hole.y, 0],
|
|
200
|
-
radius: plated_hole.hole_diameter / 2 - M,
|
|
201
|
-
height: 1.5
|
|
202
|
-
})
|
|
203
|
-
)
|
|
204
|
-
);
|
|
205
|
-
} else {
|
|
206
|
-
throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`);
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
// src/soup-to-3d/index.ts
|
|
211
|
-
var import_extrusions = require("@jscad/modeling/src/operations/extrusions");
|
|
212
|
-
var import_expansions = require("@jscad/modeling/src/operations/expansions");
|
|
213
|
-
var createBoardGeomFromSoup = (soup) => {
|
|
214
|
-
const board = (0, import_soup_util.su)(soup).pcb_board.list()[0];
|
|
215
|
-
if (!board) {
|
|
216
|
-
throw new Error("No pcb_board found");
|
|
217
|
-
}
|
|
218
|
-
const plated_holes = (0, import_soup_util.su)(soup).pcb_plated_hole.list();
|
|
219
|
-
const pads = (0, import_soup_util.su)(soup).pcb_smtpad.list();
|
|
220
|
-
const traces = (0, import_soup_util.su)(soup).pcb_trace.list();
|
|
221
|
-
const pcb_vias = (0, import_soup_util.su)(soup).pcb_via.list();
|
|
222
|
-
let boardGeom = (0, import_primitives2.cuboid)({ size: [board.width, board.height, 1.2] });
|
|
223
|
-
const platedHoleGeoms = [];
|
|
224
|
-
const padGeoms = [];
|
|
225
|
-
const traceGeoms = [];
|
|
226
|
-
const ctx = {
|
|
227
|
-
pcbThickness: 1.2
|
|
228
|
-
};
|
|
229
|
-
const addPlatedHole = (plated_hole) => {
|
|
230
|
-
if (plated_hole.shape === "circle" || !plated_hole.shape) {
|
|
231
|
-
const cyGeom = (0, import_primitives2.cylinder)({
|
|
232
|
-
center: [plated_hole.x, plated_hole.y, 0],
|
|
233
|
-
radius: plated_hole.hole_diameter / 2 + M
|
|
234
|
-
});
|
|
235
|
-
boardGeom = (0, import_booleans2.subtract)(boardGeom, cyGeom);
|
|
236
|
-
const platedHoleGeom = platedHole(plated_hole, ctx);
|
|
237
|
-
platedHoleGeoms.push(platedHoleGeom);
|
|
238
|
-
}
|
|
239
|
-
};
|
|
240
|
-
for (const plated_hole of plated_holes) {
|
|
241
|
-
addPlatedHole(plated_hole);
|
|
242
|
-
}
|
|
243
|
-
for (const pad of pads) {
|
|
244
|
-
if (pad.shape === "rect") {
|
|
245
|
-
const padGeom = (0, import_colors2.colorize)(
|
|
246
|
-
colors.copper,
|
|
247
|
-
(0, import_primitives2.cuboid)({
|
|
248
|
-
center: [pad.x, pad.y, 1.2 / 2 + M],
|
|
249
|
-
size: [pad.width, pad.height, M]
|
|
250
|
-
})
|
|
251
|
-
);
|
|
252
|
-
padGeoms.push(padGeom);
|
|
253
|
-
} else if (pad.shape === "circle") {
|
|
254
|
-
const padGeom = (0, import_colors2.colorize)(
|
|
255
|
-
colors.copper,
|
|
256
|
-
(0, import_primitives2.cylinder)({
|
|
257
|
-
center: [pad.x, pad.y, 1.2 / 2 + M],
|
|
258
|
-
radius: pad.radius,
|
|
259
|
-
height: M
|
|
260
|
-
})
|
|
261
|
-
);
|
|
262
|
-
padGeoms.push(padGeom);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
for (const { route: mixedRoute } of traces) {
|
|
266
|
-
const subRoutes = mixedRoute.reduce(
|
|
267
|
-
(c, p) => {
|
|
268
|
-
const lastLayer = c.current?.[c.current.length - 1]?.layer;
|
|
269
|
-
if (p.route_type === "via" || p.route_type === "wire" && p.layer !== lastLayer) {
|
|
270
|
-
if (c.current.length > 2) {
|
|
271
|
-
c.allPrev.push(c.current);
|
|
272
|
-
}
|
|
273
|
-
c.current = p.route_type === "wire" ? [p] : [];
|
|
274
|
-
return c;
|
|
275
|
-
}
|
|
276
|
-
c.current.push(p);
|
|
277
|
-
return c;
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
current: [],
|
|
281
|
-
allPrev: []
|
|
282
|
-
}
|
|
283
|
-
);
|
|
284
|
-
for (const route of subRoutes.allPrev.concat([subRoutes.current])) {
|
|
285
|
-
const linePath = (0, import_primitives2.line)(route.map((p) => [p.x, p.y]));
|
|
286
|
-
const layer = route[0].route_type === "wire" ? route[0].layer : "top";
|
|
287
|
-
const layerSign = layer === "top" ? 1 : -1;
|
|
288
|
-
let traceGeom = (0, import_transforms.translate)(
|
|
289
|
-
[0, 0, layerSign * 1.2 / 2],
|
|
290
|
-
(0, import_extrusions.extrudeLinear)(
|
|
291
|
-
{ height: M * layerSign },
|
|
292
|
-
(0, import_expansions.expand)({ delta: 0.1, corners: "edge" }, linePath)
|
|
293
|
-
)
|
|
294
|
-
);
|
|
295
|
-
for (const via of pcb_vias) {
|
|
296
|
-
traceGeom = (0, import_booleans2.subtract)(
|
|
297
|
-
traceGeom,
|
|
298
|
-
(0, import_primitives2.cylinder)({
|
|
299
|
-
center: [via.x, via.y, 0],
|
|
300
|
-
radius: via.outer_diameter / 2,
|
|
301
|
-
height: 5
|
|
302
|
-
})
|
|
303
|
-
);
|
|
304
|
-
}
|
|
305
|
-
traceGeom = (0, import_colors2.colorize)(colors.fr4GreenSolderWithMask, traceGeom);
|
|
306
|
-
traceGeoms.push(traceGeom);
|
|
307
|
-
}
|
|
308
|
-
for (const via of mixedRoute.filter((p) => p.route_type === "via")) {
|
|
309
|
-
if (via.route_type !== "via") continue;
|
|
310
|
-
addPlatedHole({
|
|
311
|
-
x: via.x,
|
|
312
|
-
y: via.y,
|
|
313
|
-
hole_diameter: 0.8,
|
|
314
|
-
outer_diameter: 1.6,
|
|
315
|
-
shape: "circle",
|
|
316
|
-
layers: ["top", "bottom"],
|
|
317
|
-
type: "pcb_plated_hole"
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
for (const via of pcb_vias) {
|
|
322
|
-
addPlatedHole({
|
|
323
|
-
x: via.x,
|
|
324
|
-
y: via.y,
|
|
325
|
-
hole_diameter: via.hole_diameter,
|
|
326
|
-
outer_diameter: via.outer_diameter,
|
|
327
|
-
shape: "circle",
|
|
328
|
-
layers: ["top", "bottom"],
|
|
329
|
-
type: "pcb_plated_hole"
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
boardGeom = (0, import_colors2.colorize)(colors.fr4Green, boardGeom);
|
|
333
|
-
return [boardGeom, ...platedHoleGeoms, ...padGeoms, ...traceGeoms];
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
// src/hooks/use-stls-from-geom.ts
|
|
337
|
-
var import_react = require("react");
|
|
338
|
-
var import_stl_serializer = __toESM(require("@jscad/stl-serializer"), 1);
|
|
339
|
-
function blobToBase64Url(blob) {
|
|
340
|
-
return new Promise((resolve, reject) => {
|
|
341
|
-
const reader = new FileReader();
|
|
342
|
-
reader.onload = () => {
|
|
343
|
-
resolve(reader.result);
|
|
344
|
-
};
|
|
345
|
-
reader.onerror = reject;
|
|
346
|
-
reader.readAsDataURL(blob);
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
var useStlsFromGeom = (geom) => {
|
|
350
|
-
const [stls, setStls] = (0, import_react.useState)([]);
|
|
351
|
-
const [loading, setLoading] = (0, import_react.useState)(true);
|
|
352
|
-
(0, import_react.useEffect)(() => {
|
|
353
|
-
const generateStls = async () => {
|
|
354
|
-
setLoading(true);
|
|
355
|
-
const geometries = Array.isArray(geom) ? geom : [geom];
|
|
356
|
-
const stlPromises = geometries.map(async (g) => {
|
|
357
|
-
const rawData = import_stl_serializer.default.serialize({ binary: true }, [g]);
|
|
358
|
-
const blobData = new Blob(rawData);
|
|
359
|
-
const stlUrl = await blobToBase64Url(blobData);
|
|
360
|
-
return { stlUrl, color: g.color };
|
|
361
|
-
});
|
|
362
|
-
try {
|
|
363
|
-
const generatedStls = await Promise.all(stlPromises);
|
|
364
|
-
setStls(generatedStls);
|
|
365
|
-
} catch (error) {
|
|
366
|
-
console.error("Error generating STLs:", error);
|
|
367
|
-
setStls([]);
|
|
368
|
-
} finally {
|
|
369
|
-
setLoading(false);
|
|
370
|
-
}
|
|
371
|
-
};
|
|
372
|
-
generateStls();
|
|
373
|
-
}, [geom]);
|
|
374
|
-
return { stls, loading };
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
// src/three-components/STLModel.tsx
|
|
378
|
-
var import_fiber = require("@react-three/fiber");
|
|
379
|
-
var import_react2 = require("react");
|
|
380
|
-
var import_three_stdlib = require("three-stdlib");
|
|
381
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
382
|
-
function STLModel({
|
|
383
|
-
stlUrl,
|
|
384
|
-
mtlUrl,
|
|
385
|
-
color,
|
|
386
|
-
opacity = 1
|
|
387
|
-
}) {
|
|
388
|
-
const geom = (0, import_fiber.useLoader)(import_three_stdlib.STLLoader, stlUrl);
|
|
389
|
-
const mesh = (0, import_react2.useRef)();
|
|
390
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("mesh", { ref: mesh, children: [
|
|
391
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("primitive", { object: geom, attach: "geometry" }),
|
|
392
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
393
|
-
"meshStandardMaterial",
|
|
394
|
-
{
|
|
395
|
-
color,
|
|
396
|
-
transparent: opacity !== 1,
|
|
397
|
-
opacity
|
|
398
|
-
}
|
|
399
|
-
)
|
|
400
|
-
] });
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// src/CadViewerContainer.tsx
|
|
404
|
-
var import_fiber3 = require("@react-three/fiber");
|
|
405
|
-
var import_drei2 = require("@react-three/drei");
|
|
406
|
-
|
|
407
|
-
// src/three-components/cube-with-labeled-sides.tsx
|
|
408
|
-
var import_react3 = require("react");
|
|
409
|
-
var import_fiber2 = require("@react-three/fiber");
|
|
410
|
-
var import_drei = require("@react-three/drei");
|
|
411
|
-
var THREE = __toESM(require("three"), 1);
|
|
412
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
413
|
-
window.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0);
|
|
414
|
-
function computePointInFront(rotationVector, distance) {
|
|
415
|
-
const quaternion = new THREE.Quaternion().setFromEuler(
|
|
416
|
-
new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z)
|
|
417
|
-
);
|
|
418
|
-
const forwardVector = new THREE.Vector3(0, 0, 1);
|
|
419
|
-
forwardVector.applyQuaternion(quaternion);
|
|
420
|
-
const result = forwardVector.multiplyScalar(distance);
|
|
421
|
-
return result;
|
|
422
|
-
}
|
|
423
|
-
var CubeWithLabeledSides = ({}) => {
|
|
424
|
-
const ref = (0, import_react3.useRef)();
|
|
425
|
-
const rotationTrackingRef = (0, import_react3.useRef)({ lastRotation: new THREE.Euler() });
|
|
426
|
-
(0, import_fiber2.useFrame)((state, delta) => {
|
|
427
|
-
if (!ref.current) return;
|
|
428
|
-
const mainRot = window.TSCI_MAIN_CAMERA_ROTATION;
|
|
429
|
-
const cameraPosition = computePointInFront(mainRot, 2);
|
|
430
|
-
state.camera.position.copy(cameraPosition);
|
|
431
|
-
state.camera.lookAt(0, 0, 0);
|
|
432
|
-
});
|
|
433
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("mesh", { ref, rotation: [Math.PI / 2, 0, 0], children: [
|
|
434
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("boxGeometry", { args: [1, 1, 1] }),
|
|
435
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("meshStandardMaterial", { color: "white" }),
|
|
436
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_drei.Text, { position: [0, 0, 0.51], fontSize: 0.25, color: "black", children: "Front" }),
|
|
437
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
438
|
-
import_drei.Text,
|
|
439
|
-
{
|
|
440
|
-
position: [0, 0, -0.51],
|
|
441
|
-
fontSize: 0.25,
|
|
442
|
-
color: "black",
|
|
443
|
-
rotation: [0, Math.PI, 0],
|
|
444
|
-
children: "Back"
|
|
445
|
-
}
|
|
446
|
-
),
|
|
447
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
448
|
-
import_drei.Text,
|
|
449
|
-
{
|
|
450
|
-
position: [0.51, 0, 0],
|
|
451
|
-
fontSize: 0.25,
|
|
452
|
-
color: "black",
|
|
453
|
-
rotation: [0, Math.PI / 2, 0],
|
|
454
|
-
children: "Right"
|
|
455
|
-
}
|
|
456
|
-
),
|
|
457
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
458
|
-
import_drei.Text,
|
|
459
|
-
{
|
|
460
|
-
position: [-0.51, 0, 0],
|
|
461
|
-
fontSize: 0.25,
|
|
462
|
-
color: "black",
|
|
463
|
-
rotation: [0, -Math.PI / 2, 0],
|
|
464
|
-
children: "Left"
|
|
465
|
-
}
|
|
466
|
-
),
|
|
467
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
468
|
-
import_drei.Text,
|
|
469
|
-
{
|
|
470
|
-
position: [0, 0.51, 0],
|
|
471
|
-
fontSize: 0.25,
|
|
472
|
-
color: "black",
|
|
473
|
-
rotation: [-Math.PI / 2, 0, 0],
|
|
474
|
-
children: "Top"
|
|
475
|
-
}
|
|
476
|
-
),
|
|
477
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
478
|
-
import_drei.Text,
|
|
479
|
-
{
|
|
480
|
-
position: [0, -0.51, 0],
|
|
481
|
-
fontSize: 0.25,
|
|
482
|
-
color: "black",
|
|
483
|
-
rotation: [Math.PI / 2, 0, 0],
|
|
484
|
-
children: "Bottom"
|
|
485
|
-
}
|
|
486
|
-
),
|
|
487
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
488
|
-
"lineSegments",
|
|
489
|
-
{
|
|
490
|
-
args: [new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1))],
|
|
491
|
-
material: new THREE.LineBasicMaterial({
|
|
492
|
-
color: 0,
|
|
493
|
-
linewidth: 2
|
|
494
|
-
})
|
|
495
|
-
}
|
|
496
|
-
)
|
|
497
|
-
] });
|
|
498
|
-
};
|
|
499
|
-
|
|
500
|
-
// src/CadViewerContainer.tsx
|
|
501
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
502
|
-
var RotationTracker = () => {
|
|
503
|
-
(0, import_fiber3.useFrame)(({ camera }) => {
|
|
504
|
-
window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation;
|
|
505
|
-
});
|
|
506
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, {});
|
|
507
|
-
};
|
|
508
|
-
var CadViewerContainer = ({ children }) => {
|
|
509
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
|
|
510
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
511
|
-
"div",
|
|
512
|
-
{
|
|
513
|
-
style: {
|
|
514
|
-
position: "absolute",
|
|
515
|
-
top: 0,
|
|
516
|
-
left: 0,
|
|
517
|
-
width: 120,
|
|
518
|
-
height: 120
|
|
519
|
-
},
|
|
520
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
521
|
-
import_fiber3.Canvas,
|
|
522
|
-
{
|
|
523
|
-
camera: {
|
|
524
|
-
up: [0, 0, 1],
|
|
525
|
-
// rotation: [-Math.PI / 2, 0, 0],
|
|
526
|
-
// lookAt: new THREE.Vector3(0, 0, 0),
|
|
527
|
-
position: [1, 1, 1]
|
|
528
|
-
},
|
|
529
|
-
children: [
|
|
530
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ambientLight", { intensity: Math.PI / 2 }),
|
|
531
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CubeWithLabeledSides, {})
|
|
532
|
-
]
|
|
533
|
-
}
|
|
534
|
-
)
|
|
535
|
-
}
|
|
536
|
-
),
|
|
537
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
538
|
-
import_fiber3.Canvas,
|
|
539
|
-
{
|
|
540
|
-
scene: { up: [0, 0, 1] },
|
|
541
|
-
camera: { up: [0, 0, 1], position: [5, 5, 5] },
|
|
542
|
-
children: [
|
|
543
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RotationTracker, {}),
|
|
544
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_drei2.OrbitControls, { autoRotate: true, autoRotateSpeed: 1 }),
|
|
545
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ambientLight", { intensity: Math.PI / 2 }),
|
|
546
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
547
|
-
"pointLight",
|
|
548
|
-
{
|
|
549
|
-
position: [-10, -10, 10],
|
|
550
|
-
decay: 0,
|
|
551
|
-
intensity: Math.PI / 4
|
|
552
|
-
}
|
|
553
|
-
),
|
|
554
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
555
|
-
import_drei2.Grid,
|
|
556
|
-
{
|
|
557
|
-
rotation: [Math.PI / 2, 0, 0],
|
|
558
|
-
infiniteGrid: true,
|
|
559
|
-
cellSize: 1,
|
|
560
|
-
sectionSize: 10
|
|
561
|
-
}
|
|
562
|
-
),
|
|
563
|
-
children
|
|
564
|
-
]
|
|
565
|
-
}
|
|
566
|
-
)
|
|
567
|
-
] });
|
|
568
|
-
};
|
|
569
|
-
|
|
570
|
-
// src/three-components/MixedStlModel.tsx
|
|
571
|
-
var import_react4 = require("react");
|
|
572
|
-
var import_three_stdlib2 = require("three-stdlib");
|
|
573
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
574
|
-
function MixedStlModel({
|
|
575
|
-
url,
|
|
576
|
-
position,
|
|
577
|
-
rotation
|
|
578
|
-
}) {
|
|
579
|
-
const [obj, setObj] = (0, import_react4.useState)(null);
|
|
580
|
-
(0, import_react4.useEffect)(() => {
|
|
581
|
-
async function loadUrlContent() {
|
|
582
|
-
const response = await fetch(url);
|
|
583
|
-
const text = await response.text();
|
|
584
|
-
const mtlContent = text.match(/newmtl[\s\S]*?endmtl/g)?.join("\n").replace(/d 0\./g, "d 1.");
|
|
585
|
-
const objContent = text.replace(/newmtl[\s\S]*?endmtl/g, "");
|
|
586
|
-
const mtlLoader = new import_three_stdlib2.MTLLoader();
|
|
587
|
-
mtlLoader.setMaterialOptions({
|
|
588
|
-
invertTrProperty: true
|
|
589
|
-
});
|
|
590
|
-
const materials = mtlLoader.parse(
|
|
591
|
-
// Grayscale the colors, for some reason everything from JLCPCB is
|
|
592
|
-
// a bit red, it doesn't look right. The grayscale version looks OK,
|
|
593
|
-
// it's a HACK because we only take the second color rather than
|
|
594
|
-
// averaging the colors
|
|
595
|
-
mtlContent.replace(
|
|
596
|
-
/Kd\s+([\d.]+)\s+([\d.]+)\s+([\d.]+)/g,
|
|
597
|
-
"Kd $2 $2 $2"
|
|
598
|
-
),
|
|
599
|
-
"test.mtl"
|
|
600
|
-
);
|
|
601
|
-
const objLoader = new import_three_stdlib2.OBJLoader();
|
|
602
|
-
objLoader.setMaterials(materials);
|
|
603
|
-
setObj(objLoader.parse(objContent));
|
|
604
|
-
}
|
|
605
|
-
loadUrlContent();
|
|
606
|
-
}, [url]);
|
|
607
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("group", { rotation, position, children: obj && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("primitive", { object: obj }) });
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
// src/CadViewer.tsx
|
|
611
|
-
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
612
|
-
var CadViewer = ({ soup, children }) => {
|
|
613
|
-
soup ??= useConvertChildrenToSoup(children, soup);
|
|
614
|
-
const boardGeom = (0, import_react5.useMemo)(() => createBoardGeomFromSoup(soup), [soup]);
|
|
615
|
-
const { stls, loading } = useStlsFromGeom(boardGeom);
|
|
616
|
-
const cad_components = (0, import_soup_util2.su)(soup).cad_component.list();
|
|
617
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(CadViewerContainer, { children: [
|
|
618
|
-
stls.map(({ stlUrl, color }, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
619
|
-
STLModel,
|
|
620
|
-
{
|
|
621
|
-
stlUrl,
|
|
622
|
-
color,
|
|
623
|
-
opacity: index === 0 ? 0.95 : 1
|
|
624
|
-
},
|
|
625
|
-
stlUrl
|
|
626
|
-
)),
|
|
627
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
628
|
-
MixedStlModel,
|
|
629
|
-
{
|
|
630
|
-
url: "/easyeda-models/dc694c23844346e9981bdbac7bb76421",
|
|
631
|
-
position: [0, 0, 0.5],
|
|
632
|
-
rotation: [0, 0, Math.PI / 2]
|
|
633
|
-
}
|
|
634
|
-
),
|
|
635
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
636
|
-
MixedStlModel,
|
|
637
|
-
{
|
|
638
|
-
url: "/easyeda-models/c7acac53bcbc44d68fbab8f60a747688",
|
|
639
|
-
position: [-5.65, 0, 0.5],
|
|
640
|
-
rotation: [0, 0, Math.PI / 2]
|
|
641
|
-
}
|
|
642
|
-
),
|
|
643
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
644
|
-
MixedStlModel,
|
|
645
|
-
{
|
|
646
|
-
url: "/easyeda-models/c7acac53bcbc44d68fbab8f60a747688",
|
|
647
|
-
position: [6.75, 0, 0.5],
|
|
648
|
-
rotation: [0, 0, 0]
|
|
649
|
-
}
|
|
650
|
-
)
|
|
651
|
-
] });
|
|
652
|
-
};
|
|
653
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
654
|
-
0 && (module.exports = {
|
|
655
|
-
CadViewer
|
|
656
|
-
});
|
|
657
|
-
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/@tscircuit/soup-util/index.ts","../src/index.tsx","../src/hooks/use-convert-children-to-soup.ts","../src/CadViewer.tsx","../src/soup-to-3d/index.ts","../src/geoms/plated-hole.ts","../src/geoms/constants.ts","../src/hooks/use-stls-from-geom.ts","../src/three-components/STLModel.tsx","../src/CadViewerContainer.tsx","../src/three-components/cube-with-labeled-sides.tsx","../src/three-components/MixedStlModel.tsx"],"sourcesContent":["import type {\n AnySoupElement,\n AnySoupElementInput,\n SourceComponentBase,\n SourcePort,\n} from \"@tscircuit/soup\"\n\ntype SoupOps<\n K extends AnySoupElement[\"type\"],\n T extends AnySoupElement | AnySoupElementInput\n> = {\n get: (id: string) => Extract<T, { type: K }> | null\n select: (selector: string) => Extract<T, { type: K }> | null\n getWhere: (where: any) => Extract<T, { type: K }> | null\n getUsing: (using: {\n [key: `${string}_id`]: string\n }) => Extract<T, { type: K }> | null\n list: (where?: any) => Extract<T, { type: K }>[]\n}\n\nexport type SoupUtilObject = {\n [K in AnySoupElement[\"type\"]]: SoupOps<K, AnySoupElement>\n}\nexport type SoupInputUtilObject = {\n [K in AnySoupElementInput[\"type\"]]: SoupOps<K, AnySoupElementInput>\n}\n\nexport type GetSoupUtilObject = ((soup: AnySoupElement[]) => SoupUtilObject) & {\n unparsed: (soup: AnySoupElementInput[]) => SoupInputUtilObject\n}\n\nexport const su: GetSoupUtilObject = ((soup: AnySoupElement[]) => {\n const su = new Proxy(\n {},\n {\n get: (proxy_target: any, component_type: string) => {\n return {\n get: (id: string) =>\n soup.find(\n (e: any) =>\n e.type === component_type && e[`${component_type}_id`] === id\n ),\n getUsing: (using: any) => {\n const keys = Object.keys(using)\n if (keys.length !== 1) {\n throw new Error(\n \"getUsing requires exactly one key, e.g. { pcb_component_id }\"\n )\n }\n const join_key = keys[0] as string\n const join_type = join_key.replace(\"_id\", \"\")\n const joiner: any = soup.find(\n (e: any) =>\n e.type === join_type && e[join_key] === using[join_key]\n )\n if (!joiner) return null\n return soup.find(\n (e: any) =>\n e.type === component_type &&\n e[`${component_type}_id`] === joiner[`${component_type}_id`]\n )\n },\n getWhere: (where: any) => {\n const keys = Object.keys(where)\n return soup.find(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key])\n )\n },\n list: (where?: any) => {\n const keys = !where ? [] : Object.keys(where)\n return soup.filter(\n (e: any) =>\n e.type === component_type &&\n keys.every((key) => e[key] === where[key])\n )\n },\n select: (selector: string) => {\n // TODO when applySelector is isolated we can use it, until then we\n // do a poor man's selector implementation for two common cases\n if (component_type === \"source_component\") {\n return soup.find(\n (e) =>\n e.type === \"source_component\" &&\n e.name === selector.replace(/\\./g, \"\")\n )\n } else if (\n component_type === \"pcb_port\" ||\n component_type === \"source_port\" ||\n component_type === \"schematic_port\"\n ) {\n const [component_name, port_selector] = selector\n .replace(/\\./g, \"\")\n .split(/[\\s\\>]+/)\n const source_component = soup.find(\n (e) =>\n e.type === \"source_component\" && e.name === component_name\n ) as SourceComponentBase\n if (!source_component) return null\n const source_port = soup.find(\n (e) =>\n e.type === \"source_port\" &&\n e.source_component_id ===\n source_component.source_component_id &&\n (e.name === port_selector ||\n (e.port_hints ?? []).includes(port_selector!))\n ) as SourcePort\n if (!source_port) return null\n if (component_type === \"source_port\") return source_port\n\n if (component_type === \"pcb_port\") {\n return soup.find(\n (e) =>\n e.type === \"pcb_port\" &&\n e.source_port_id === source_port.source_port_id\n )\n } else if (component_type === \"schematic_port\") {\n return soup.find(\n (e) =>\n e.type === \"schematic_port\" &&\n e.source_port_id === source_port.source_port_id\n )\n }\n }\n },\n }\n },\n }\n )\n\n return su\n}) as any\nsu.unparsed = su as any\n\nexport default su\n","export { CadViewer } from \"./CadViewer\"\n","import type { AnySoupElement } from \"@tscircuit/soup\"\n\nexport const useConvertChildrenToSoup = (\n children?: any,\n defaultSoup?: AnySoupElement[]\n) => {\n // TODO convert children if defined\n\n return defaultSoup!\n}\n","import type { AnySoupElement } from \"@tscircuit/soup\"\nimport { useConvertChildrenToSoup } from \"./hooks/use-convert-children-to-soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { useMemo } from \"react\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport { useStlsFromGeom } from \"./hooks/use-stls-from-geom\"\nimport { STLModel } from \"./three-components/STLModel\"\nimport { CadViewerContainer } from \"./CadViewerContainer\"\nimport { MixedStlModel } from \"./three-components/MixedStlModel\"\n\ninterface Props {\n soup?: AnySoupElement[]\n children?: any\n}\n\nexport const CadViewer = ({ soup, children }: Props) => {\n soup ??= useConvertChildrenToSoup(children, soup)\n\n // TODO convert board\n\n const boardGeom = useMemo(() => createBoardGeomFromSoup(soup), [soup])\n\n const { stls, loading } = useStlsFromGeom(boardGeom)\n\n const cad_components = su(soup).cad_component.list()\n\n // TODO canvas/camera etc.\n return (\n <CadViewerContainer>\n {stls.map(({ stlUrl, color }, index) => (\n <STLModel\n key={stlUrl}\n stlUrl={stlUrl}\n color={color}\n opacity={index === 0 ? 0.95 : 1}\n />\n ))}\n {/* <MixedStlModel url=\"/easyeda-models/84af7f0f6529479fb6b1c809c61d205f\" /> */}\n <MixedStlModel\n url=\"/easyeda-models/dc694c23844346e9981bdbac7bb76421\"\n position={[0, 0, 0.5]}\n rotation={[0, 0, Math.PI / 2]}\n />\n <MixedStlModel\n url=\"/easyeda-models/c7acac53bcbc44d68fbab8f60a747688\"\n position={[-5.65, 0, 0.5]}\n rotation={[0, 0, Math.PI / 2]}\n />\n <MixedStlModel\n url=\"/easyeda-models/c7acac53bcbc44d68fbab8f60a747688\"\n position={[6.75, 0, 0.5]}\n rotation={[0, 0, 0]}\n />\n </CadViewerContainer>\n )\n}\n","import type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport type { AnySoupElement, PCBPlatedHole } from \"@tscircuit/soup\"\nimport { su } from \"@tscircuit/soup-util\"\nimport { translate } from \"@jscad/modeling/src/operations/transforms\"\nimport { cuboid, cylinder, line } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract } from \"@jscad/modeling/src/operations/booleans\"\nimport { platedHole } from \"../geoms/plated-hole\"\nimport { M, colors } from \"../geoms/constants\"\nimport { extrudeLinear } from \"@jscad/modeling/src/operations/extrusions\"\nimport { expand } from \"@jscad/modeling/src/operations/expansions\"\n\nexport const createBoardGeomFromSoup = (soup: AnySoupElement[]): Geom3[] => {\n const board = su(soup).pcb_board.list()[0]\n if (!board) {\n throw new Error(\"No pcb_board found\")\n }\n\n const plated_holes = su(soup).pcb_plated_hole.list()\n const pads = su(soup).pcb_smtpad.list()\n const traces = su(soup).pcb_trace.list()\n const pcb_vias = su(soup).pcb_via.list()\n\n // PCB Board\n let boardGeom = cuboid({ size: [board.width, board.height, 1.2] })\n\n const platedHoleGeoms: Geom3[] = []\n const padGeoms: Geom3[] = []\n const traceGeoms: Geom3[] = []\n const ctx = {\n pcbThickness: 1.2,\n }\n\n const addPlatedHole = (plated_hole: PCBPlatedHole) => {\n if (plated_hole.shape === \"circle\" || !plated_hole.shape) {\n const cyGeom = cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 + M,\n })\n boardGeom = subtract(boardGeom, cyGeom)\n\n const platedHoleGeom = platedHole(plated_hole, ctx)\n platedHoleGeoms.push(platedHoleGeom)\n }\n }\n\n for (const plated_hole of plated_holes) {\n addPlatedHole(plated_hole)\n }\n\n for (const pad of pads) {\n if (pad.shape === \"rect\") {\n const padGeom = colorize(\n colors.copper,\n cuboid({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n size: [pad.width, pad.height, M],\n })\n )\n padGeoms.push(padGeom)\n } else if (pad.shape === \"circle\") {\n const padGeom = colorize(\n colors.copper,\n cylinder({\n center: [pad.x, pad.y, 1.2 / 2 + M],\n radius: pad.radius,\n height: M,\n })\n )\n padGeoms.push(padGeom)\n }\n }\n\n for (const { route: mixedRoute } of traces) {\n const subRoutes = mixedRoute.reduce(\n (c, p) => {\n // @ts-ignore\n const lastLayer = c.current?.[c.current.length - 1]?.layer\n if (\n p.route_type === \"via\" ||\n (p.route_type === \"wire\" && p.layer !== lastLayer)\n ) {\n if (c.current.length > 2) {\n c.allPrev.push(c.current)\n }\n c.current = p.route_type === \"wire\" ? [p] : []\n return c\n }\n c.current.push(p)\n return c\n },\n {\n current: [] as typeof mixedRoute,\n allPrev: [] as Array<typeof mixedRoute>,\n }\n )\n for (const route of subRoutes.allPrev.concat([subRoutes.current])) {\n // TODO break into segments based on layers\n const linePath = line(route.map((p) => [p.x, p.y]))\n\n const layer = route[0].route_type === \"wire\" ? route[0].layer : \"top\"\n const layerSign = layer === \"top\" ? 1 : -1\n // traceGeoms.push(traceGeom)\n let traceGeom = translate(\n [0, 0, (layerSign * 1.2) / 2],\n extrudeLinear(\n { height: M * layerSign },\n expand({ delta: 0.1, corners: \"edge\" }, linePath)\n )\n )\n\n // HACK: Subtract all vias from every trace- this mostly is because the\n // vias aren't inside the route- we should probably pre-filter to make sure\n // that vias are only near the route\n for (const via of pcb_vias) {\n traceGeom = subtract(\n traceGeom,\n cylinder({\n center: [via.x, via.y, 0],\n radius: via.outer_diameter / 2,\n height: 5,\n })\n )\n }\n\n traceGeom = colorize(colors.fr4GreenSolderWithMask, traceGeom)\n\n traceGeoms.push(traceGeom)\n }\n for (const via of mixedRoute.filter((p) => p.route_type === \"via\")) {\n if (via.route_type !== \"via\") continue // TODO remove when ts is smart\n\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: 0.8,\n outer_diameter: 1.6,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n }\n\n for (const via of pcb_vias) {\n addPlatedHole({\n x: via.x,\n y: via.y,\n hole_diameter: via.hole_diameter,\n outer_diameter: via.outer_diameter,\n shape: \"circle\",\n layers: [\"top\", \"bottom\"],\n type: \"pcb_plated_hole\",\n })\n }\n\n // Colorize to a PCB green color: #05A32E\n boardGeom = colorize(colors.fr4Green, boardGeom)\n\n return [boardGeom, ...platedHoleGeoms, ...padGeoms, ...traceGeoms]\n}\n","import type { PCBPlatedHole } from \"@tscircuit/soup\"\nimport type { Geom3 } from \"@jscad/modeling/src/geometries/types\"\nimport { cylinder } from \"@jscad/modeling/src/primitives\"\nimport { colorize } from \"@jscad/modeling/src/colors\"\nimport { subtract, union } from \"@jscad/modeling/src/operations/booleans\"\nimport { M, colors } from \"./constants\"\nimport { GeomContext } from \"../GeomContext\"\n\nexport const platedHole = (\n plated_hole: PCBPlatedHole,\n ctx: GeomContext\n): Geom3 => {\n if (plated_hole.shape === \"circle\" || !plated_hole.shape) {\n return colorize(\n colors.copper,\n subtract(\n union(\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2,\n height: 1.2,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n }),\n cylinder({\n center: [plated_hole.x, plated_hole.y, -1.2 / 2],\n radius: plated_hole.outer_diameter / 2,\n height: M,\n })\n ),\n cylinder({\n center: [plated_hole.x, plated_hole.y, 0],\n radius: plated_hole.hole_diameter / 2 - M,\n height: 1.5,\n })\n )\n )\n } else {\n throw new Error(`Unsupported plated hole shape: ${plated_hole.shape}`)\n }\n}\n","import type { RGB } from \"@jscad/modeling/src/colors\"\n\nexport const M = 0.01\n\nexport const colors = {\n copper: [0.9, 0.6, 0.2],\n fr4Green: [0x05 / 255, 0xa3 / 255, 0x2e / 255],\n fr4GreenSolderWithMask: [0x00 / 255, 0x98 / 255, 0x13 / 255],\n} satisfies Record<string, RGB>\n","import { useState, useEffect } from \"react\"\nimport stlSerializer from \"@jscad/stl-serializer\"\nimport { Geom3 } from \"@jscad/modeling/src/geometries/types\"\n\nfunction blobToBase64Url(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader()\n reader.onload = () => {\n resolve(reader.result as string)\n }\n reader.onerror = reject\n reader.readAsDataURL(blob)\n })\n}\n\ntype StlObj = { stlUrl: string; color: number[] }\n\nexport const useStlsFromGeom = (\n geom: Geom3[] | Geom3\n): {\n stls: StlObj[]\n loading: boolean\n} => {\n const [stls, setStls] = useState<StlObj[]>([])\n const [loading, setLoading] = useState(true)\n\n useEffect(() => {\n const generateStls = async () => {\n setLoading(true)\n const geometries = Array.isArray(geom) ? geom : [geom]\n\n const stlPromises = geometries.map(async (g) => {\n const rawData = stlSerializer.serialize({ binary: true }, [g])\n const blobData = new Blob(rawData)\n const stlUrl = await blobToBase64Url(blobData)\n return { stlUrl, color: g.color! }\n })\n\n try {\n const generatedStls = await Promise.all(stlPromises)\n setStls(generatedStls)\n } catch (error) {\n console.error(\"Error generating STLs:\", error)\n setStls([])\n } finally {\n setLoading(false)\n }\n }\n\n generateStls()\n }, [geom])\n\n return { stls, loading }\n}\n","import { useLoader } from \"@react-three/fiber\"\nimport { useRef } from \"react\"\nimport * as THREE from \"three\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport function STLModel({\n stlUrl,\n mtlUrl,\n color,\n opacity = 1,\n}: {\n stlUrl: string\n color?: any\n mtlUrl?: string\n opacity?: number\n}) {\n const geom = useLoader(STLLoader, stlUrl)\n const mesh = useRef<THREE.Mesh>()\n\n // TODO handle mtl url\n\n return (\n <mesh ref={mesh as any}>\n <primitive object={geom} attach=\"geometry\" />\n <meshStandardMaterial\n color={color}\n transparent={opacity !== 1}\n opacity={opacity}\n />\n {/* <Outlines thickness={0.05} color=\"black\" opacity={0.25} /> */}\n </mesh>\n )\n}\n","import {\n Canvas,\n useFrame,\n extend,\n useThree,\n useLoader,\n} from \"@react-three/fiber\"\nimport { Suspense, useEffect, useMemo, useRef, useState } from \"react\"\nimport { OrbitControls, Grid, Outlines } from \"@react-three/drei\"\nimport * as THREE from \"three\"\nimport { CubeWithLabeledSides } from \"./three-components/cube-with-labeled-sides\"\nimport { createBoardGeomFromSoup } from \"./soup-to-3d\"\nimport soup from \"./bug-pads-and-traces.json\"\n// import soup from \"./plated-hole-board.json\"\nimport stlSerializer from \"@jscad/stl-serializer\"\n// import { STLLoader } from \"three/examples/jsm/loaders/STLLoader\"\nimport { MTLLoader, OBJLoader, STLLoader } from \"three-stdlib\"\n\nexport const RotationTracker = () => {\n useFrame(({ camera }) => {\n window.TSCI_MAIN_CAMERA_ROTATION = camera.rotation\n })\n\n return <></>\n}\n\nexport const CadViewerContainer = ({ children }: { children: any }) => {\n return (\n <div style={{ position: \"relative\", width: \"100%\", height: \"100%\" }}>\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: 120,\n height: 120,\n }}\n >\n <Canvas\n camera={{\n up: [0, 0, 1],\n // rotation: [-Math.PI / 2, 0, 0],\n // lookAt: new THREE.Vector3(0, 0, 0),\n position: [1, 1, 1],\n }}\n >\n <ambientLight intensity={Math.PI / 2} />\n <CubeWithLabeledSides />\n </Canvas>\n </div>\n <Canvas\n scene={{ up: [0, 0, 1] }}\n camera={{ up: [0, 0, 1], position: [5, 5, 5] }}\n >\n <RotationTracker />\n <OrbitControls autoRotate autoRotateSpeed={1} />\n <ambientLight intensity={Math.PI / 2} />\n <pointLight\n position={[-10, -10, 10]}\n decay={0}\n intensity={Math.PI / 4}\n />\n <Grid\n rotation={[Math.PI / 2, 0, 0]}\n infiniteGrid={true}\n cellSize={1}\n sectionSize={10}\n />\n {children}\n </Canvas>\n </div>\n )\n}\n","import React, { useRef } from \"react\"\nimport { Canvas, useFrame } from \"@react-three/fiber\"\nimport { OrbitControls, Text } from \"@react-three/drei\"\nimport * as THREE from \"three\"\n\ndeclare global {\n interface Window {\n TSCI_MAIN_CAMERA_ROTATION: THREE.Euler\n }\n}\nwindow.TSCI_MAIN_CAMERA_ROTATION = new THREE.Euler(0, 0, 0)\n\nfunction computePointInFront(rotationVector, distance) {\n // Create a quaternion from the rotation vector\n const quaternion = new THREE.Quaternion().setFromEuler(\n new THREE.Euler(rotationVector.x, rotationVector.y, rotationVector.z)\n )\n\n // Create a vector pointing forward (along the negative z-axis)\n const forwardVector = new THREE.Vector3(0, 0, 1)\n\n // Apply the rotation to the forward vector\n forwardVector.applyQuaternion(quaternion)\n\n // Scale the rotated vector by the distance\n const result = forwardVector.multiplyScalar(distance)\n\n return result\n}\n\nexport const CubeWithLabeledSides = ({}: any) => {\n const ref = useRef<THREE.Mesh>()\n const rotationTrackingRef = useRef({ lastRotation: new THREE.Euler() })\n useFrame((state, delta) => {\n if (!ref.current) return\n\n const mainRot = window.TSCI_MAIN_CAMERA_ROTATION\n\n // Use window.TSCI_CAMERA_ROTATION to compute the position of the camera\n const cameraPosition = computePointInFront(mainRot, 2)\n\n state.camera.position.copy(cameraPosition)\n state.camera.lookAt(0, 0, 0)\n })\n return (\n <mesh ref={ref} rotation={[Math.PI / 2, 0, 0]}>\n <boxGeometry args={[1, 1, 1]} />\n <meshStandardMaterial color=\"white\" />\n <Text position={[0, 0, 0.51]} fontSize={0.25} color=\"black\">\n Front\n </Text>\n <Text\n position={[0, 0, -0.51]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI, 0]}\n >\n Back\n </Text>\n <Text\n position={[0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, Math.PI / 2, 0]}\n >\n Right\n </Text>\n <Text\n position={[-0.51, 0, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[0, -Math.PI / 2, 0]}\n >\n Left\n </Text>\n <Text\n position={[0, 0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[-Math.PI / 2, 0, 0]}\n >\n Top\n </Text>\n <Text\n position={[0, -0.51, 0]}\n fontSize={0.25}\n color=\"black\"\n rotation={[Math.PI / 2, 0, 0]}\n >\n Bottom\n </Text>\n <lineSegments\n args={[new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1))]}\n material={\n new THREE.LineBasicMaterial({\n color: 0x000000,\n linewidth: 2,\n })\n }\n />\n </mesh>\n )\n}\n\n// const LabeledCubeScene = () => {\n// return (\n// <Canvas camera={{ position: [1.5, 1.5, 1.5] }}>\n// <ambientLight intensity={0.5} />\n// <pointLight position={[10, 10, 10]} />\n// <LabeledCube />\n// <OrbitControls />\n// </Canvas>\n// )\n// }\n\n// export default LabeledCubeScene\n","import { useEffect, useState } from \"react\"\nimport { Euler, Vector3 } from \"three\"\nimport { MTLLoader, OBJLoader } from \"three-stdlib\"\n\nexport function MixedStlModel({\n url,\n position,\n rotation,\n}: {\n url: string\n position?: Vector3 | [number, number, number]\n rotation?: Euler | [number, number, number]\n}) {\n // const group = useLoader(OBJLoader, url)\n // const materials = useLoader(MTLLoader, url)\n // const obj = useLoader(OBJLoader, url)\n\n const [obj, setObj] = useState<any | null>(null)\n useEffect(() => {\n async function loadUrlContent() {\n const response = await fetch(url)\n const text = await response.text()\n\n // Extract all the sections of the file that have newmtl...endmtl to\n // separate into mtlContent and objContent\n\n const mtlContent = text\n .match(/newmtl[\\s\\S]*?endmtl/g)\n ?.join(\"\\n\")!\n .replace(/d 0\\./g, \"d 1.\")!\n const objContent = text.replace(/newmtl[\\s\\S]*?endmtl/g, \"\")\n\n const mtlLoader = new MTLLoader()\n mtlLoader.setMaterialOptions({\n invertTrProperty: true,\n })\n const materials = mtlLoader.parse(\n // Grayscale the colors, for some reason everything from JLCPCB is\n // a bit red, it doesn't look right. The grayscale version looks OK,\n // it's a HACK because we only take the second color rather than\n // averaging the colors\n mtlContent.replace(\n /Kd\\s+([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)/g,\n \"Kd $2 $2 $2\"\n ),\n \"test.mtl\"\n )\n\n const objLoader = new OBJLoader()\n objLoader.setMaterials(materials)\n setObj(objLoader.parse(objContent))\n }\n loadUrlContent()\n }, [url])\n\n return (\n <group rotation={rotation} position={position}>\n {obj && <primitive object={obj} />}\n </group>\n )\n}\n"],"mappings":"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","names":["__export","su","module","__toCommonJS","import_soup_util","import_react","import_primitives","import_colors","import_booleans","stlSerializer","import_react","import_fiber","import_drei","import_react","import_fiber","import_jsx_runtime","import_jsx_runtime","import_react","import_three_stdlib","import_jsx_runtime","import_jsx_runtime"]}
|
package/dist/index.d.cts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { AnySoupElement } from '@tscircuit/soup';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
soup?: AnySoupElement[];
|
|
6
|
-
children?: any;
|
|
7
|
-
}
|
|
8
|
-
declare const CadViewer: ({ soup, children }: Props) => react_jsx_runtime.JSX.Element;
|
|
9
|
-
|
|
10
|
-
export { CadViewer };
|