Files
CMPlanning/scripts/verify_geom/slice.py
T
Claude 3638249c43 chore(verify): store Step 3 solid-model verification scripts and geometry results
- 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
2026-10-22 00:51:01 +00:00

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