"""파라메트릭 토치 v1: 앵커(노즐끝=tcpOffset=525, 와이어끝=540) mm검산 + 클로즈업 캡처."""
import asyncio, json
from playwright.async_api import async_playwright
URL='http://localhost:8090/DOZIKWORKS_OS_v5_locked.dc.html'
OUT=r'E:\도진팩토리\3D스캔및티칭시스템\shots\ceo_feedback'
async def main():
    async with async_playwright() as p:
        br=await p.chromium.launch(channel='msedge',headless=True)
        pg=await br.new_page(viewport={'width':1400,'height':1000})
        errs=[]; logs=[]
        pg.on('pageerror',lambda e: errs.append(str(e)))
        pg.on('console',lambda m: logs.append(m.text) if ('torch' in m.text or m.type=='error') else None)
        await pg.goto(URL)
        await pg.wait_for_function("window.__dzw && window.__dzw._torchParts", timeout=15000)
        res=await pg.evaluate("""()=>{ const d=window.__dzw, T=d._T; const out={};
          out.parts = d._torchParts.map(p=>p.name);
          const noz=d._torchParts.find(p=>p.name==='torch_nozzle');
          const wire=d._torchParts.find(p=>p.name==='torch_wire');
          // 노즐끝 로컬좌표 = 노즐 실린더의 +Y끝? 대신 지오메트리로 노즐 상단(=N)과 tcpOffset 비교
          // 앵커 검산: 와이어 상단 월드 vs weldPoint 월드 (torchNode-local이므로 tcpOffset과 비교)
          const N=new T.Vector3(d.tcpOffset[0],d.tcpOffset[1],d.tcpOffset[2]);
          out.tcp=[+N.x.toFixed(1),+N.y.toFixed(1),+N.z.toFixed(1)]; out.tcpLen=+N.length().toFixed(1);
          out.wireEndLen=+(N.clone().add(new T.Vector3(0,0,15)).length()).toFixed(1);
          // 로봇 등 다른 메시 숨김 → 토치만 보이게 (형상 판정용)
          d.three.scene.traverse(o=>{ if(o.isMesh){ let underTorch=false, n=o; while(n){ if(n===d._torchRoot){underTorch=true;break;} n=n.parent; } if(!underTorch) o.visible=false; } });
          // 카메라: 토치 측면 클로즈업
          d._torchRoot.updateMatrixWorld(true);
          const box=new T.Box3().setFromObject(d._torchRoot); const c=new T.Vector3(); box.getCenter(c);
          const sph=box.getBoundingSphere(new T.Sphere());
          if(d.orbit){ d.orbit.tgt.copy(c); d.orbit.r=sph.radius*2.6; d.orbit.theta=0.0; d.orbit.phi=1.5; d.updateCam&&d.updateCam(); }
          return out;
        }""")
        await pg.wait_for_timeout(400)
        await pg.screenshot(path=OUT+r'\PARAMTORCH_v1.png')
        print(json.dumps(res,ensure_ascii=False,indent=1))
        print("errs:", errs if errs else "없음")
        print("logs:", [l for l in logs if 'torch' in l][:3])
        await br.close()
asyncio.run(main())
