Devesh36/usb-c-phone-stand-light
A 3D-printed tilted phone stand integrating USB‑C PD power, a Qi wireless charging coil with magnetic alignment ring, indicator LEDs/light pipes, control and protection PCBs, wiring, fasteners, and rubber feet.
- Version
- 0.0.6
- License
- unset
- Stars
- 0
scripts/export-mechanics.tsx
import { writeFile, mkdir } from 'node:fs/promises'
import {fileURLToPath} from 'node:url'
import modeling from '@jscad/modeling'
import { executeJscadOperations } from 'jscad-planner'
import { renderToJscadPlan } from 'jscad-fiber/headless'
import { BaseBody,UsbBezel,BaseLid,Backrest,ChargingCover,ChargerRearHousing,PowerLens,ChargeLens,RearSupport } from '../stand-mechanics'
const dir=fileURLToPath(new URL('../mechanical/',import.meta.url))
await mkdir(dir,{recursive:true})
const parts=[['base',BaseBody],['usb-bezel',UsbBezel],['lid',BaseLid],['backrest',Backrest],['charging-cover',ChargingCover],['rear-housing',ChargerRearHousing],['power-lens',PowerLens],['charge-lens',ChargeLens],['rear-support',RearSupport]] as const
const result=[]
for(const [name,Part] of parts){
let solid=executeJscadOperations(modeling as any,renderToJscadPlan(<Part/>))
const bounds=modeling.measurements.measureBoundingBox(solid)
const volume=modeling.measurements.measureVolume(solid)
if(!(volume>0))throw new Error(name+' has no positive solid volume')
solid=modeling.transforms.translate([0,0,-bounds[0][2]],solid)
solid=modeling.modifiers.generalize({snap:true,triangulate:true},solid)
const triangles=modeling.geometries.geom3.toPolygons(solid).flatMap(p=>p.vertices.slice(2).map((v,i)=>[p.vertices[0],p.vertices[i+1],v]))
const bytes=new Uint8Array(84+triangles.length*50)
bytes.set(new TextEncoder().encode('DeskGlow '+name+' / millimeters'))
const data=new DataView(bytes.buffer);data.setUint32(80,triangles.length,true)
let pos=84
for(const v of triangles){
const a=v[0],b=v[1],c=v[2],u=b.map((q,i)=>q-a[i]),w=c.map((q,i)=>q-a[i])
const n=[u[1]*w[2]-u[2]*w[1],u[2]*w[0]-u[0]*w[2],u[0]*w[1]-u[1]*w[0]]
const len=Math.hypot(...n)||1
for(const q of [...n.map(x=>x/len),...a,...b,...c]){data.setFloat32(pos,q,true);pos+=4}
data.setUint16(pos,0,true);pos+=2
}
await writeFile(dir+name+'.stl',bytes)
const dimensions=bounds[1].map((v,i)=>Number((v-bounds[0][i]).toFixed(3)))
result.push({name,file:name+'.stl',dimensionsMm:dimensions,volumeMm3:Math.round(volume),triangles:triangles.length})
console.log(name,dimensions,triangles.length,'triangles')
}
await writeFile(dir+'parts.json',JSON.stringify(result,null,2))