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))