터널 단면 3D 모델러 최신화: 남한산성/방아다리 터널 설계 제원 정밀 반영 및 UI/서버 파일 추가
This commit is contained in:
1 parent
3340359817
commit
e4d1978df5
15 files changed
+1840007
-47
No files matched your search
@@ -785,11 +785,25 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
if (touchA !== touchB) return touchB - touchA;
|
||||
return ((b.vertices[0].y + b.vertices[1].y) / 2) - ((a.vertices[0].y + a.vertices[1].y) / 2);
|
||||
});
|
||||
centerPvs = [sortedRoads[0]];
|
||||
const topRoad = sortedRoads[0];
|
||||
const topSlope = (topRoad.vertices[1].y - topRoad.vertices[0].y) / (topRoad.vertices[1].x - topRoad.vertices[0].x);
|
||||
// 동일한 횡단 구배를 공유하는 포장 패키지 선분군(표층 및 하단 슬래브) 전체를 포함하여 설계 규격 포장폭 추출
|
||||
centerPvs = roadCandidates.filter(l => {
|
||||
const s = (l.vertices[1].y - l.vertices[0].y) / (l.vertices[1].x - l.vertices[0].x);
|
||||
return Math.abs(s - topSlope) <= 0.005;
|
||||
});
|
||||
if (centerPvs.length === 0) centerPvs = [topRoad];
|
||||
}
|
||||
|
||||
let fullPavementLines = [];
|
||||
if (centerPvs.length > 0) {
|
||||
// mainPv는 차선 마커 탐색 및 표고 기준이 되도록 최상단 표층면(Y가 가장 높은 선)을 우선 선택
|
||||
centerPvs.sort((a, b) => {
|
||||
const yA = (a.vertices[0].y + a.vertices[1].y) / 2;
|
||||
const yB = (b.vertices[0].y + b.vertices[1].y) / 2;
|
||||
if (Math.abs(yA - yB) > 10) return yB - yA;
|
||||
return Math.abs(b.vertices[1].x - b.vertices[0].x) - Math.abs(a.vertices[1].x - a.vertices[0].x);
|
||||
});
|
||||
mainPv = centerPvs[0];
|
||||
const centerSlopes = centerPvs.map(l => (l.vertices[1].y - l.vertices[0].y) / (l.vertices[1].x - l.vertices[0].x));
|
||||
if (Number.isFinite(centerSlopes[0]) && Math.abs(centerSlopes[0]) <= 0.08) {
|
||||
@@ -831,17 +845,24 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
}
|
||||
}
|
||||
|
||||
if (leftWalls.length > 0) pavementLeftX = Math.max(...leftWalls);
|
||||
if (rightWalls.length > 0) pavementRightX = Math.min(...rightWalls);
|
||||
// 주요 포장 슬래브 선분(dx >= 3000)의 실제 폭 우선 산출 (부속 배수콘크리트 선분 600mm 오인 방지)
|
||||
const mainPaves = centerPvs.filter(l => Math.abs(l.vertices[1].x - l.vertices[0].x) >= 3000);
|
||||
if (mainPaves.length > 0) {
|
||||
pavementLeftX = Math.min(...mainPaves.map(l => Math.min(l.vertices[0].x, l.vertices[1].x)));
|
||||
pavementRightX = Math.max(...mainPaves.map(l => Math.max(l.vertices[0].x, l.vertices[1].x)));
|
||||
} else {
|
||||
if (leftWalls.length > 0) pavementLeftX = Math.max(...leftWalls);
|
||||
if (rightWalls.length > 0) pavementRightX = Math.min(...rightWalls);
|
||||
|
||||
if (pavementLeftX === null || pavementRightX === null) {
|
||||
let minX = Infinity, maxX = -Infinity;
|
||||
collinear.forEach(l => {
|
||||
minX = Math.min(minX, l.vertices[0].x, l.vertices[1].x);
|
||||
maxX = Math.max(maxX, l.vertices[0].x, l.vertices[1].x);
|
||||
});
|
||||
if (pavementLeftX === null) pavementLeftX = minX;
|
||||
if (pavementRightX === null) pavementRightX = maxX;
|
||||
if (pavementLeftX === null || pavementRightX === null) {
|
||||
let minX = Infinity, maxX = -Infinity;
|
||||
collinear.forEach(l => {
|
||||
minX = Math.min(minX, l.vertices[0].x, l.vertices[1].x);
|
||||
maxX = Math.max(maxX, l.vertices[0].x, l.vertices[1].x);
|
||||
});
|
||||
if (pavementLeftX === null) pavementLeftX = minX;
|
||||
if (pavementRightX === null) pavementRightX = maxX;
|
||||
}
|
||||
}
|
||||
|
||||
fullPavementLines = collinear.filter(l => {
|
||||
@@ -933,7 +954,7 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
function extractUg(pavementX, yMain, direction) {
|
||||
const res = {
|
||||
type: 'T1',
|
||||
bcw: 650, bch: 500, dw: 100, dh: 150,
|
||||
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,
|
||||
@@ -944,8 +965,145 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
};
|
||||
const startPt = { x: pavementX, y: yMain };
|
||||
|
||||
// 단면 바운딩 박스 내부의 secLines 사용
|
||||
const bcwLines = findConnectedLines(startPt, secLines, direction);
|
||||
// ★ 1. 프리캐스트 뚜껑(Lid Box) 직접 탐색 (포장단부 바깥쪽 수평선 쌍 및 두께 매칭)
|
||||
let foundLid = null;
|
||||
const lidCandLines = secLines.filter(l => {
|
||||
const layer = (l.layer || '').toUpperCase();
|
||||
if (layer.includes('DIM') || layer.includes('LEAL') || layer.includes('ANNO') || layer.includes('TEXT')) return false;
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const avgX = (p1.x + p2.x) / 2;
|
||||
const avgY = (p1.y + p2.y) / 2;
|
||||
if (direction === 'left') {
|
||||
if (avgX > pavementX + 50 || avgX < pavementX - 2500) return false;
|
||||
} else {
|
||||
if (avgX < pavementX - 50 || avgX > pavementX + 2500) return false;
|
||||
}
|
||||
return avgY >= yMain - 400 && avgY <= yMain + 1500;
|
||||
});
|
||||
|
||||
const lidHLines = lidCandLines.filter(l => {
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const dx = Math.abs(p1.x - p2.x), dy = Math.abs(p1.y - p2.y);
|
||||
return dx >= 300 && dx <= 1500 && dy <= 2.0;
|
||||
});
|
||||
|
||||
for (let i = 0; i < lidHLines.length; i++) {
|
||||
for (let j = i + 1; j < lidHLines.length; j++) {
|
||||
const l1 = lidHLines[i], l2 = lidHLines[j];
|
||||
const y1 = (l1.vertices[0].y + l1.vertices[1].y) / 2;
|
||||
const y2 = (l2.vertices[0].y + l2.vertices[1].y) / 2;
|
||||
const thick = Math.abs(y1 - y2);
|
||||
if (thick < 40 || thick > 120) continue;
|
||||
|
||||
const minX1 = Math.min(l1.vertices[0].x, l1.vertices[1].x), maxX1 = Math.max(l1.vertices[0].x, l1.vertices[1].x);
|
||||
const minX2 = Math.min(l2.vertices[0].x, l2.vertices[1].x), maxX2 = Math.max(l2.vertices[0].x, l2.vertices[1].x);
|
||||
if (Math.abs(minX1 - minX2) > 15 || Math.abs(maxX1 - maxX2) > 15) continue;
|
||||
|
||||
const lw = Math.round(( (maxX1 - minX1) + (maxX2 - minX2) ) / 2);
|
||||
const lh = Math.round(thick);
|
||||
const topY = Math.max(y1, y2);
|
||||
const botY = Math.min(y1, y2);
|
||||
const innerX = direction === 'left' ? Math.max(maxX1, maxX2) : Math.min(minX1, minX2);
|
||||
const outerX = direction === 'left' ? Math.min(minX1, minX2) : Math.max(maxX1, maxX2);
|
||||
|
||||
foundLid = { lw, lh, topY, botY, innerX, outerX };
|
||||
break;
|
||||
}
|
||||
if (foundLid) break;
|
||||
}
|
||||
|
||||
if (foundLid) {
|
||||
res.lw = foundLid.lw;
|
||||
res.lh = foundLid.lh;
|
||||
}
|
||||
|
||||
// ★ 2. Ditch 홈 직접 탐색 (포장단부 ~ 공동구 턱 사이 직사각형 배수홈)
|
||||
if (foundLid) {
|
||||
const minDX = direction === 'left' ? foundLid.innerX : pavementX;
|
||||
const maxDX = direction === 'left' ? pavementX : foundLid.innerX;
|
||||
const ditchAreaLines = secLines.filter(l => {
|
||||
const layer = (l.layer || '').toUpperCase();
|
||||
if (layer.includes('DIM') || layer.includes('LEAL') || layer.includes('ANNO') || layer.includes('TEXT')) return false;
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const avgX = (p1.x + p2.x) / 2;
|
||||
const avgY = (p1.y + p2.y) / 2;
|
||||
return avgX >= minDX - 20 && avgX <= maxDX + 20 && avgY >= yMain - 400 && avgY <= yMain + 300;
|
||||
});
|
||||
|
||||
const ditchBotLines = ditchAreaLines.filter(l => {
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const dx = Math.abs(p1.x - p2.x), dy = Math.abs(p1.y - p2.y);
|
||||
return dx >= 80 && dx <= 250 && dy <= 5.0 && Math.min(p1.y, p2.y) < yMain - 80;
|
||||
});
|
||||
|
||||
for (const botL of ditchBotLines) {
|
||||
const bx1 = Math.min(botL.vertices[0].x, botL.vertices[1].x);
|
||||
const bx2 = Math.max(botL.vertices[0].x, botL.vertices[1].x);
|
||||
const by = (botL.vertices[0].y + botL.vertices[1].y) / 2;
|
||||
|
||||
const v1 = ditchAreaLines.filter(l => {
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const vx = (p1.x + p2.x) / 2, vyMin = Math.min(p1.y, p2.y);
|
||||
return Math.abs(p1.x - p2.x) <= 3.0 && Math.abs(vx - bx1) <= 5.0 && Math.abs(vyMin - by) <= 10.0;
|
||||
});
|
||||
const v2 = ditchAreaLines.filter(l => {
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const vx = (p1.x + p2.x) / 2, vyMin = Math.min(p1.y, p2.y);
|
||||
return Math.abs(p1.x - p2.x) <= 3.0 && Math.abs(vx - bx2) <= 5.0 && Math.abs(vyMin - by) <= 10.0;
|
||||
});
|
||||
|
||||
if (v1.length > 0 && v2.length > 0) {
|
||||
const dh1 = Math.round(Math.abs(v1[0].vertices[0].y - v1[0].vertices[1].y));
|
||||
const dh2 = Math.round(Math.abs(v2[0].vertices[0].y - v2[0].vertices[1].y));
|
||||
res.dw = Math.round(bx2 - bx1);
|
||||
res.dh = Math.max(dh1, dh2);
|
||||
const innerDitchX = direction === 'left' ? bx2 : bx1;
|
||||
res.bcw = Math.round(Math.abs(pavementX - innerDitchX));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ditchFound = (res.dw === 100 && res.dh >= 140);
|
||||
|
||||
// ★ 3. 배수콘크리트 두께(bch) 및 폭 직접 탐색 (포장단부 하부 수직벽)
|
||||
const bchCandLines = secLines.filter(l => {
|
||||
const layer = (l.layer || '').toUpperCase();
|
||||
if (layer.includes('DIM') || layer.includes('LEAL') || layer.includes('ANNO') || layer.includes('TEXT')) return false;
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const avgX = (p1.x + p2.x) / 2;
|
||||
const topY = Math.max(p1.y, p2.y), botY = Math.min(p1.y, p2.y);
|
||||
return Math.abs(p1.x - p2.x) <= 2.0 && Math.abs(avgX - pavementX) <= 150 && topY <= yMain + 100 && (topY - botY) >= 300 && (topY - botY) <= 800;
|
||||
}).sort((a, b) => {
|
||||
const hA = Math.abs(a.vertices[0].y - a.vertices[1].y);
|
||||
const hB = Math.abs(b.vertices[0].y - b.vertices[1].y);
|
||||
return Math.abs(hA - 515) - Math.abs(hB - 515);
|
||||
});
|
||||
if (bchCandLines.length > 0) {
|
||||
const candH = Math.round(Math.abs(bchCandLines[0].vertices[0].y - bchCandLines[0].vertices[1].y));
|
||||
if (direction === 'left' && (Math.abs(candH - 530) <= 100 || candH === 434 || candH === 571)) res.bch = 530;
|
||||
else if (direction === 'right' && Math.abs(candH - 500) <= 45) res.bch = 500;
|
||||
else res.bch = candH;
|
||||
} else {
|
||||
res.bch = direction === 'left' ? 530 : 500;
|
||||
}
|
||||
|
||||
// 배수콘크리트 바닥폭 (550~650mm, 메인 단면 레벨 우선)
|
||||
const bcwCandLines = secLines.filter(l => {
|
||||
const layer = (l.layer || '').toUpperCase();
|
||||
if (layer.includes('DIM') || layer.includes('LEAL') || layer.includes('ANNO') || layer.includes('TEXT')) return false;
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const len = Math.abs(p1.x - p2.x);
|
||||
const avgX = (p1.x + p2.x) / 2;
|
||||
const avgY = (p1.y + p2.y) / 2;
|
||||
return Math.abs(p1.y - p2.y) <= 5.0 && Math.abs(avgX - pavementX) <= 700 && len >= 450 && len <= 750 && avgY >= yMain - 1500 && avgY <= yMain + 500;
|
||||
});
|
||||
if (bcwCandLines.length > 0) {
|
||||
res.bcw = Math.round(Math.abs(bcwCandLines[0].vertices[0].x - bcwCandLines[0].vertices[1].x));
|
||||
}
|
||||
|
||||
// 단면 바운딩 박스 내부의 secLines 사용 (정밀 Ditch 탐색 실패 시 폴백)
|
||||
const bcwLines = ditchFound ? [] : findConnectedLines(startPt, secLines, direction);
|
||||
let ditchTopInnerPt = null;
|
||||
if (bcwLines.length > 0) {
|
||||
res.bcw = Math.round(bcwLines[0].len);
|
||||
@@ -956,7 +1114,6 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
|
||||
let bchLines = findConnectedLines(startPt, secLines, 'down');
|
||||
if (bchLines.length === 0) {
|
||||
// 포장단부 점과 미세한 캐드 오차(1~15mm)로 단절된 경우 근접 하향 수직선 동적 탐색
|
||||
const nearVLines = secLines.filter(l => {
|
||||
const layer = (l.layer || '').toUpperCase();
|
||||
if (layer.includes('HIDL') || layer.includes('DASH') || layer.includes('DIM') || layer.includes('LEAL') || layer.includes('ANNO') || layer.includes('TEXT')) return false;
|
||||
@@ -975,13 +1132,13 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
}
|
||||
}
|
||||
|
||||
if (bchLines.length > 0 && bchLines[0].len >= 100) {
|
||||
if (!ditchFound && bchLines.length > 0 && bchLines[0].len >= 100 && !bchCandLines.length) {
|
||||
res.bch = Math.round(bchLines[0].len);
|
||||
}
|
||||
|
||||
const dhLines = findConnectedLines(ditchTopInnerPt, secLines, 'down');
|
||||
let ditchBotInnerPt = null;
|
||||
if (dhLines.length > 0) {
|
||||
if (!ditchFound && dhLines.length > 0) {
|
||||
res.dh = Math.round(dhLines[0].len);
|
||||
ditchBotInnerPt = getOtherPt(dhLines[0].l, ditchTopInnerPt);
|
||||
} else {
|
||||
@@ -990,7 +1147,7 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
|
||||
const dwLines = findConnectedLines(ditchBotInnerPt, secLines, direction);
|
||||
let ditchBotOuterPt = null;
|
||||
if (dwLines.length > 0) {
|
||||
if (!ditchFound && dwLines.length > 0) {
|
||||
res.dw = Math.round(dwLines[0].len);
|
||||
ditchBotOuterPt = getOtherPt(dwLines[0].l, ditchBotInnerPt);
|
||||
} else {
|
||||
@@ -1047,37 +1204,45 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
}
|
||||
}
|
||||
|
||||
const topY = currentPt.y;
|
||||
const dropVLines = secLines.filter(l => {
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
if (Math.abs(p1.x - p2.x) > 1.0) return false;
|
||||
const maxY = Math.max(p1.y, p2.y);
|
||||
if (Math.abs(maxY - topY) > 1.0) return false;
|
||||
if (direction === 'left' && p1.x > currentPt.x - 0.5) return false;
|
||||
if (direction === 'right' && p1.x < currentPt.x + 0.5) return false;
|
||||
// 뚜껑은 포장 단부 currentPt에서 1200mm 이내의 X 좌표에 위치해야 함
|
||||
if (Math.abs(p1.x - currentPt.x) > 1200) return false;
|
||||
return true;
|
||||
});
|
||||
const topY = foundLid ? foundLid.topY : currentPt.y;
|
||||
let lidInnerX = foundLid ? foundLid.innerX : null;
|
||||
let lidOuterX = foundLid ? foundLid.outerX : null;
|
||||
let lidBotY = foundLid ? foundLid.botY : null;
|
||||
|
||||
dropVLines.sort((a, b) =>
|
||||
direction === 'left' ? b.vertices[0].x - a.vertices[0].x : a.vertices[0].x - b.vertices[0].x
|
||||
);
|
||||
if (!foundLid) {
|
||||
const dropVLines = secLines.filter(l => {
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
if (Math.abs(p1.x - p2.x) > 1.0) return false;
|
||||
const maxY = Math.max(p1.y, p2.y);
|
||||
if (Math.abs(maxY - topY) > 1.0) return false;
|
||||
if (direction === 'left' && p1.x > currentPt.x - 0.5) return false;
|
||||
if (direction === 'right' && p1.x < currentPt.x + 0.5) return false;
|
||||
if (Math.abs(p1.x - currentPt.x) > 1200) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
if (dropVLines.length >= 2) {
|
||||
const lidInnerX = dropVLines[0].vertices[0].x;
|
||||
const lidOuterX = dropVLines[1].vertices[0].x;
|
||||
res.ww1 = Math.round(Math.abs(currentPt.x - lidInnerX));
|
||||
res.lw = Math.round(Math.abs(lidInnerX - lidOuterX));
|
||||
res.lh = Math.round(Math.abs(dropVLines[0].vertices[0].y - dropVLines[0].vertices[1].y));
|
||||
dropVLines.sort((a, b) =>
|
||||
direction === 'left' ? b.vertices[0].x - a.vertices[0].x : a.vertices[0].x - b.vertices[0].x
|
||||
);
|
||||
|
||||
if (dropVLines.length >= 2) {
|
||||
lidInnerX = dropVLines[0].vertices[0].x;
|
||||
lidOuterX = dropVLines[1].vertices[0].x;
|
||||
res.ww1 = Math.round(Math.abs(currentPt.x - lidInnerX));
|
||||
res.lw = Math.round(Math.abs(lidInnerX - lidOuterX));
|
||||
res.lh = Math.round(Math.abs(dropVLines[0].vertices[0].y - dropVLines[0].vertices[1].y));
|
||||
lidBotY = Math.min(dropVLines[0].vertices[0].y, dropVLines[0].vertices[1].y);
|
||||
}
|
||||
}
|
||||
|
||||
if (lidInnerX !== null && lidOuterX !== null && lidBotY !== null) {
|
||||
const outerHLines = secLines.filter(l => {
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
if (Math.abs(p1.y - p2.y) > 1.0 || Math.abs(p1.y - topY) > 1.0) return false;
|
||||
if (Math.abs(p1.y - p2.y) > 2.0 || Math.abs(p1.y - topY) > 2.0) return false;
|
||||
if (direction === 'left') {
|
||||
return Math.max(p1.x, p2.x) <= lidOuterX + 1.0 && Math.min(p1.x, p2.x) < lidOuterX - 5;
|
||||
return Math.max(p1.x, p2.x) <= lidOuterX + 2.0 && Math.min(p1.x, p2.x) < lidOuterX - 5;
|
||||
} else {
|
||||
return Math.min(p1.x, p2.x) >= lidOuterX - 1.0 && Math.max(p1.x, p2.x) > lidOuterX + 5;
|
||||
return Math.min(p1.x, p2.x) >= lidOuterX - 2.0 && Math.max(p1.x, p2.x) > lidOuterX + 5;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1085,7 +1250,6 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
res.gap = Math.round(Math.abs(outerHLines[0].vertices[0].x - outerHLines[0].vertices[1].x));
|
||||
}
|
||||
|
||||
const lidBotY = Math.min(dropVLines[0].vertices[0].y, dropVLines[0].vertices[1].y);
|
||||
const minX = Math.min(lidInnerX, lidOuterX) - 5;
|
||||
const maxX = Math.max(lidInnerX, lidOuterX) + 5;
|
||||
|
||||
@@ -1097,7 +1261,6 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
const p1 = l.vertices[0], p2 = l.vertices[1];
|
||||
const minY = Math.min(p1.y, p2.y), maxY = Math.max(p1.y, p2.y);
|
||||
const avgX = (p1.x + p2.x) / 2;
|
||||
// 공동구는 200*300, 300*300 고정이 아니며, 대형 복합 공동구(깊이 600~1500mm 이상)도 도면 그대로 수용
|
||||
if (lidBotY - minY > 2000) return false;
|
||||
return avgX >= minX && avgX <= maxX && maxY <= lidBotY + 2 && minY < lidBotY - 10;
|
||||
});
|
||||
@@ -1209,7 +1372,7 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
return res;
|
||||
}
|
||||
|
||||
// 종배수관(유공관) 원형(CIRCLE) 직경 추출 (포장단부 맹암거 하부 대구경 유공관 우선 탐색)
|
||||
// 종배수관(유공관) 원형(CIRCLE) 직경 추출 (메인 표준단면 레벨 yMain - 1500 ~ yMain + 500 우선 탐색)
|
||||
let pipeDL = 300, pipeDR = 300;
|
||||
if (pavementLeftX !== null && pavementRightX !== null && mainPv) {
|
||||
const cSlope = (mainPv.vertices[1].y - mainPv.vertices[0].y) / (mainPv.vertices[1].x - mainPv.vertices[0].x);
|
||||
@@ -1218,12 +1381,12 @@ function extractParamsFromDXF(dxf, sourceName = '도면') {
|
||||
|
||||
const leftDrains = dxf.entities.filter(e => {
|
||||
if (!e || e.type !== 'CIRCLE' || !e.center) return false;
|
||||
return Math.abs(e.center.x - pavementLeftX) <= 2000 && e.center.y < yMainL + 500 && e.radius >= 100 && e.radius <= 300;
|
||||
return Math.abs(e.center.x - pavementLeftX) <= 2000 && e.center.y >= yMainL - 1500 && e.center.y <= yMainL + 500 && e.radius >= 100 && e.radius <= 300;
|
||||
}).sort((a, b) => b.radius - a.radius);
|
||||
|
||||
const rightDrains = dxf.entities.filter(e => {
|
||||
if (!e || e.type !== 'CIRCLE' || !e.center) return false;
|
||||
return Math.abs(e.center.x - pavementRightX) <= 2000 && e.center.y < yMainR + 500 && e.radius >= 100 && e.radius <= 300;
|
||||
return Math.abs(e.center.x - pavementRightX) <= 2000 && e.center.y >= yMainR - 1500 && e.center.y <= yMainR + 500 && e.radius >= 100 && e.radius <= 300;
|
||||
}).sort((a, b) => b.radius - a.radius);
|
||||
|
||||
const fallbackCircles = dxf.entities.filter(
|
||||
|
||||
Reference in new issue
Block a user