import sys, json, re, io, collections, math sys.path.insert(0,'pylib') import rhino3dm tab=json.load(open('ok2_table.json',encoding='utf-8')) det=[e for e in json.load(open('ok2_shapes.json',encoding='utf-8')) if 'L' in e] Mo=json.load(open('ok_model_dims.json',encoding='utf-8')) UW={'H35':7.51,'H32':6.23,'H29':5.04,'H25':3.98,'H22':3.04,'H19':2.25,'H16':1.56,'H13':0.995} # 모델 곡선 실제 길이 m3=rhino3dm.File3dm.Read(r"D:\★Pier 자료\심수석님 검토 파일\검토_옥성교P1\옥성교P1_G5.3dm") geo=collections.defaultdict(list) for o in m3.Objects: g=o.Geometry; nm=o.Attributes.Name or '' if nm.startswith('P1-RC-') and hasattr(g,'GetLength'): us=dict(o.Attributes.GetUserStrings()); mk=us.get('mark') or nm.split('-')[2] geo[mk].append(g.GetLength()) def mm(s): out=[] for p in s.split('~'): p=re.sub(r'[^\d.]','',p) if not p: continue v=float(p); out.append(v*1000 if '.' in p and v<100 else v) return out D=collections.defaultdict(list) for e in det: D[e['mark']].append(e) o=io.open('ok_rerun2.txt','w',encoding='utf-8') res={} for t in tab: mk=t['mark']; r={'mark':mk,'issues':[]} # 표 산술 if abs(t['L']*t['n']/1000.0-t['tot'])>0.0015*max(1,t['n']): r['issues'].append(u'표 산술 L×N≠총길이 (%.3f×%d=%.3f ↔ %.3f)'%(t['L']/1000,t['n'],t['L']*t['n']/1e6,t['tot'])) m=Mo.get(mk) if not m: r['issues'].append(u'모델에 없음'); res[mk]=r; o.write(u'%s 표 n=%d L=%.0f → 모델 없음\n'%(mk,t['n'],t['L'])); continue half=2 if mk in('P3','P4') else 1 n=m['n']//half if n!=t['n']: r['issues'].append(u'본수 표%d/모델%d'%(t['n'],n)) dl=[v*half for v in m['dl']]; mean=sum(dl)/len(dl); tot=sum(dl)/1000.0/half*half tot_m=sum(m['dl'])/1000.0 r['L']=(t['L'],mean,min(dl),max(dl)); r['tot']=(t['tot'],tot_m) # 길이 판정 dev=mean-t['L'] if abs(dev)>3 or max(dl)-min(dl)>3: r['issues'].append(u'길이 표%.0f 모델평균%.0f (%.0f~%.0f) %+.0f'%(t['L'],mean,min(dl),max(dl),dev)) # 실제 곡선 길이 vs 설계길이 gl=geo.get(mk,[]) if gl: gm=sum(gl)/len(gl)*(half) r['geo']=gm if gm