- scripts/verify_solids_step3.py: deterministic checks M1-M6, S1-S2, G1 (9/9 PASS) - scripts/verify_geom/: independent DXF-vs-STEP section deviation scripts (agent run) - data/verify_geom_hd2_results.json: Hausdorff results at 4+745, 5+100, 5+470 Judgement: DOC/05_검증/검증_본선3D솔리드모델_2026-10-22_v0.1.00.md (FAIL 3 items to Step 4) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A5Cun3RHQKna9qxE6ybZ4A
78 lines
3.4 KiB
Python
78 lines
3.4 KiB
Python
import sys, json, pickle, math
|
|
sys.path += ['/root/.local/lib/python3.13/site-packages','/usr/local/lib/python3.13/dist-packages','/usr/lib/python3/dist-packages']
|
|
from build123d import import_step, Edge, Shape
|
|
from OCP.BRepAlgoAPI import BRepAlgoAPI_Section
|
|
from OCP.gp import gp_Pln, gp_Pnt, gp_Dir
|
|
from OCP.BRepBuilderAPI import BRepBuilderAPI_MakeFace
|
|
from OCP.TopExp import TopExp_Explorer
|
|
from OCP.TopAbs import TopAbs_EDGE
|
|
from OCP.TopoDS import TopoDS
|
|
import numpy as np
|
|
solids = import_step("/mnt/user-data/uploads/97.과제/Code/3d-drawing/model/tunnel_solids.step").solids()
|
|
mp = pickle.load(open('/tmp/verify_daesan2_run/mapping.pkl','rb'))['mapping']
|
|
caps = json.load(open('/tmp/verify_daesan2_run/caps.json'))
|
|
ch = json.load(open('/tmp/verify_daesan2_run/chain.json'))
|
|
lin = ch['lin']
|
|
starts = {k: np.array(v) for k,v in ch['starts'].items()}
|
|
ends = {k: np.array(v) for k,v in ch['ends'].items()}
|
|
# station knots
|
|
S = [caps[k]['from_sta'] for k in lin] + [caps[lin[-1]]['to_sta']]
|
|
P = [starts[k] for k in lin] + [ends[lin[-1]]]
|
|
def plane_at(s):
|
|
for i in range(len(lin)):
|
|
if S[i] <= s <= S[i+1]:
|
|
f=(s-S[i])/(S[i+1]-S[i])
|
|
Q=(1-f)*P[i]+f*P[i+1]
|
|
T=(P[i+1]-P[i])[:2]; T=T/np.linalg.norm(T)
|
|
return Q, T, lin[i]
|
|
raise ValueError(s)
|
|
def slice_solid(idx, Q, T):
|
|
nrm=np.array([T[0],T[1],0.0])
|
|
pl=gp_Pln(gp_Pnt(*Q), gp_Dir(*nrm))
|
|
face=BRepBuilderAPI_MakeFace(pl,-80,80,-80,80).Face()
|
|
sec=BRepAlgoAPI_Section(solids[idx].wrapped, face); sec.Build()
|
|
sh=sec.Shape()
|
|
polys=[]
|
|
exp=TopExp_Explorer(sh, TopAbs_EDGE)
|
|
while exp.More():
|
|
e=Shape.cast(exp.Current())
|
|
L=e.length; N=max(2,int(L/0.02))
|
|
pts=[e.position_at(i/N) for i in range(N+1)]
|
|
polys.append([[p.X,p.Y,p.Z] for p in pts])
|
|
exp.Next()
|
|
return polys
|
|
out={}
|
|
stations=[4745.0005, 5100.0, 5469.9995]
|
|
for s in stations:
|
|
Q,T,lk=plane_at(s)
|
|
eh=np.array([-T[1],T[0]])
|
|
print(f"== station {s}: comp {lk}, Q=({Q[0]:.4f},{Q[1]:.4f},{Q[2]:.4f}) T=({T[0]:.5f},{T[1]:.5f}) ")
|
|
out[str(s)]={'Q':Q.tolist(),'T':T.tolist(),'eh':eh.tolist(),'comps':{}}
|
|
for cid,info in caps.items():
|
|
if not (info['from_sta'] <= s <= info['to_sta']): continue
|
|
polys=slice_solid(mp[cid], Q, T)
|
|
uv=[]
|
|
for pl_ in polys:
|
|
arr=np.array(pl_)
|
|
dx=arr[:,:2]-Q[:2]
|
|
u=dx@eh; v=arr[:,2]
|
|
uv.append(np.stack([u,v],1).tolist())
|
|
out[str(s)]['comps'][cid]={'group':info['group'],'polys':uv}
|
|
allp=np.vstack([np.array(x) for x in uv]) if uv else np.zeros((0,2))
|
|
if info['group'] in ('라이닝','굴착면','노면(계획고)','기층·인버트(가정)','공동구(가정)') or cid.startswith('DRN') or 'DRN' in cid or 'HI' in cid:
|
|
pass
|
|
# summary per group
|
|
import collections
|
|
summ=collections.defaultdict(list)
|
|
for cid,v in out[str(s)]['comps'].items():
|
|
summ[v['group']].append(cid)
|
|
for g,cids in summ.items():
|
|
allp=[p for cid in cids for poly in out[str(s)]['comps'][cid]['polys'] for p in poly]
|
|
A=np.array(allp) if allp else np.zeros((0,2))
|
|
if len(A):
|
|
print(f" {g}: n_comp={len(cids)} n_pts={len(A)} u[{A[:,0].min():.3f},{A[:,0].max():.3f}] v[{A[:,1].min():.3f},{A[:,1].max():.3f}] ids={cids[:4]}")
|
|
else:
|
|
print(f" {g}: n_comp={len(cids)} EMPTY ids={cids[:4]}")
|
|
json.dump(out, open('/tmp/verify_daesan2_run/sections_raw.json','w'))
|
|
print("saved sections_raw.json")
|