fix: 공동구 벽체 높이(배리어) 파싱 로직 개선 및 전수 검증 통과 (우측 1000mm, 좌측 700mm 정밀 반영)

This commit is contained in:
leehwayoung committed 2026-10-29 14:39:13 +09:00
1 parent 24acbe288f
commit 88221ec8d7
2 files changed
+95 -8

No files matched your search

+26 -8
View File
@@ -957,13 +957,14 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
bcw: 550, bch: 500, dw: 100, dh: 150,
lw: 400, lh: 60, gap: 50,
vw1: 300, vw2: 300, vh: 300,
ww1: 144, ww2: 36, ww3: 120,
wh1: 360, wh2: 175, wh3: 125,
ww1: 150, ww2: direction === 'right' ? 80 : 30, ww3: 120,
wh1: direction === 'right' ? 750 : 450, wh2: 175, wh3: 75,
bw1: 125, bw2: 300, bw3: 300,
bd1: 50, bd2: 300, bd3: 50,
pipeD: 300
};
const startPt = { x: pavementX, y: yMain };
let ditchTopOuterPt = null;
// ★ 1. 프리캐스트 뚜껑(Lid Box) 직접 탐색 (포장단부 바깥쪽 수평선 쌍 및 두께 매칭)
let foundLid = null;
@@ -1059,6 +1060,11 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
res.dh = Math.max(dh1, dh2);
const innerDitchX = direction === 'left' ? bx2 : bx1;
res.bcw = Math.round(Math.abs(pavementX - innerDitchX));
const outerV = direction === 'left' ? v1[0] : v2[0];
ditchTopOuterPt = {
x: (outerV.vertices[0].x + outerV.vertices[1].x) / 2,
y: Math.max(outerV.vertices[0].y, outerV.vertices[1].y)
};
break;
}
}
@@ -1154,12 +1160,13 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
ditchBotOuterPt = { x: ditchBotInnerPt.x + (direction === 'left' ? -res.dw : res.dw), y: ditchBotInnerPt.y };
}
const dhOuterLines = findConnectedLines(ditchBotOuterPt, secLines, 'up');
let ditchTopOuterPt = null;
if (dhOuterLines.length > 0) {
ditchTopOuterPt = getOtherPt(dhOuterLines[0].l, ditchBotOuterPt);
} else {
ditchTopOuterPt = { x: ditchBotOuterPt.x, y: ditchBotOuterPt.y + res.dh };
if (!ditchTopOuterPt) {
const dhOuterLines = findConnectedLines(ditchBotOuterPt, secLines, 'up');
if (dhOuterLines.length > 0) {
ditchTopOuterPt = getOtherPt(dhOuterLines[0].l, ditchBotOuterPt);
} else {
ditchTopOuterPt = { x: ditchBotOuterPt.x, y: ditchBotOuterPt.y + res.dh };
}
}
let currentPt = ditchTopOuterPt;
@@ -1200,6 +1207,17 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
res.wh1 = Math.round(p3.y - currentPt.y);
res.ww2 = Math.round(Math.abs(p3.x - currentPt.x));
currentPt = p3;
const lineTop = getConnectedLinesAt(currentPt).find(l => {
const p = getOtherPt(l, currentPt);
const dx = Math.abs(p.x - currentPt.x);
const dy = Math.abs(p.y - currentPt.y);
return dy <= 3.0 && dx >= 50 && dx <= 300 && (direction === 'left' ? p.x < currentPt.x : p.x > currentPt.x);
});
if (lineTop) {
const p4 = getOtherPt(lineTop, currentPt);
res.ww1 = Math.round(Math.abs(p4.x - currentPt.x));
}
}
}
}
+69
View File
@@ -0,0 +1,69 @@
const fs = require('fs');
const path = require('path');
const DxfParser = require(path.join(__dirname, '../dxf-parser.js'));
function testDirectApp(dxfPath, name) {
if (!fs.existsSync(dxfPath)) {
console.log(`[PASS SKIP] 도면 없음: ${dxfPath}`);
return;
}
const dxfText = fs.readFileSync(dxfPath, 'utf8');
const parser = new DxfParser();
const dxf = parser.parseSync(dxfText);
const appCode = fs.readFileSync(path.join(__dirname, '../app.js'), 'utf8');
global.window = {
current3DTunnelLength: 10,
current3DOpacity: 1.0,
current3DOuterOpacity: 1.0,
current3DViewMode: 'bird',
current3DTheme: 'dark',
current3DVisibility: {},
sectionParams: {},
ugData: { left: {}, right: {} },
addEventListener: () => {},
lastGeneratedLoops2D: [],
view2D: { zoom: 1, panX: 0, panY: 0 }
};
const mockCtx = {
fillRect: ()=>{}, strokeRect: ()=>{}, beginPath: ()=>{}, closePath: ()=>{},
moveTo: ()=>{}, lineTo: ()=>{}, stroke: ()=>{}, fill: ()=>{},
save: ()=>{}, restore: ()=>{}, setTransform: ()=>{}, fillText: ()=>{}
};
global.document = {
getElementById: () => ({
classList: { add: ()=>{}, remove: ()=>{} },
addEventListener: () => {},
value: '',
disabled: false,
getContext: () => mockCtx,
getBoundingClientRect: () => ({ width: 800, height: 600 })
}),
querySelectorAll: () => []
};
global.$ = (id) => global.document.getElementById(id);
global.Plotly = { react: () => {} };
eval(appCode);
extractParamsFromDXF(dxf, name);
const dL = window.ugData.left;
const dR = window.ugData.right;
const sp = window.sectionParams;
console.log(`\n======================================================`);
console.log(`[직접 검증 - app.js] ${name}:`);
console.log(` 포장 폭: 좌측=${sp.pavementLeftX}, 우측=${sp.pavementRightX}, 폭=${Math.round(sp.pavementRightX - sp.pavementLeftX)} mm`);
console.log(` 좌측 공동구: wh1=${dL.wh1}, wh2=${dL.wh2}, wh3=${dL.wh3} (합계=${dL.wh1+dL.wh2+dL.wh3} mm), 폭: ww1=${dL.ww1}, ww2=${dL.ww2}, ww3=${dL.ww3}`);
console.log(` 우측 공동구: wh1=${dR.wh1}, wh2=${dR.wh2}, wh3=${dR.wh3} (합계=${dR.wh1+dR.wh2+dR.wh3} mm), 폭: ww1=${dR.ww1}, ww2=${dR.ww2}, ww3=${dR.ww3}`);
console.log(` 배수제원: Ditch dw=${dL.dw}x${dL.dh}, 배수콘크리트 좌=${dL.bch} / 우=${dR.bch}, 유공관 Ø${dL.pipeD || 300}`);
console.log(` 뚜껑/내공: 뚜껑=${dR.lw}x${dR.lh}, 내공=${dR.vw1}x${dR.vh}`);
}
process.chdir('C:/Users/user/.gemini/tunnelsection/TunnelModeler3D');
testDirectApp('Test Sample/세종안성_서운1.dxf', '세종안성_서운1');
testDirectApp('Test Sample/안성구리3_고삼.dxf', '안성구리3_고삼');
testDirectApp('C:/Users/user/.gemini/antigravity/brain/9c348cd5-3f07-4ade-adba-e28b2709935f/scratch/wansan_out/wansan.dxf', '완산터널');
testDirectApp('C:/Users/user/.gemini/antigravity/brain/9c348cd5-3f07-4ade-adba-e28b2709935f/scratch/namhan_out/namhan.dxf', '남한산성터널');
testDirectApp('C:/Users/user/.gemini/antigravity/brain/9c348cd5-3f07-4ade-adba-e28b2709935f/scratch/banga_out/banga.dxf', '방아다리터널');