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