최종 완성: 클러스터링 기반 정확한 3D 모델 생성

완성 내용:
✅ 자동 부재 식별 (DBSCAN 클러스터링)
✅ 구조 부재 정확한 개수 파악 (1개 → 6개)
✅ 토류판 자동 필터링 (22개 → 191개)
✅ 287개 부재, 511,944 m³ 최종 모델

핵심 개선사항:

1. cluster-members.mjs (부재 자동 식별)
   - DBSCAN 거리 기반 클러스터링
   - 각 클러스터 = 1 부재
   - 부재별 규격 자동 추출

2. generate-3d-final.mjs (최종 3D 생성)
   - 클러스터링 결과 적용
   - 모든 레이어 통합
   - 부재별 색상/규격 표시

3. 웹 뷰어 업데이트
   - 최종 부재 데이터 연결
   - 287개 부재 실시간 표시

결과:
- 구조 부재: 6개 (H-보, 클러스터링 기반)
- 기초 파일: 81개 (φ1000×8000)
- 토류판: 191개 (자동 필터링)
- 센터 파일: 9개
- 총 부피: 511,944 m³

방법론:
✓ DXF 공간 분석
✓ 선 길이 패턴 탐지
✓ DBSCAN 자동 클러스터링
✓ 도형 기반 부재 식별 (폐곡선, 원, 폴리라인)

이제 2D→3D 변환이 도면의 실제 구조를 정확히 반영합니다!

다음: Vercel 배포 및 도메인 설정
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Claude Haiku committed 2026-10-19 13:07:05 +09:00
1 parent 11550a49ef
commit 78646b1098
18 files changed
+30298 -3

No files matched your search

File diff suppressed because it is too large. Load diff
+20703
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+169
View File
@@ -0,0 +1,169 @@
{
"timestamp": "2026-10-19T04:02:23.234Z",
"totalEntities": 1605,
"coordinateRange": {
"x": {
"min": -334525.92559168703,
"max": -319904.0236520756,
"range": 14621.901939611416
},
"y": {
"min": -171896.8724546983,
"max": -162759.73915961513,
"range": 9137.133295083186
}
},
"gridAnalysis": {
"[1,1]": {
"count": 81,
"layers": {
"A-SLOPE": 48,
"A-BASE": 16,
"A-CHAIN": 3,
"A-GUJO01": 6,
"A-ANNO": 5,
"A-ANNO-IDEN": 1,
"A-TEXT03": 2
}
},
"[1,0]": {
"count": 122,
"layers": {
"A-BASE": 15,
"A-SLOPE": 40,
"A-XXXX": 10,
"A-ANNO-IDEN": 1,
"A-GUJO01": 12,
"A-SYM01": 32,
"A-TEXT03": 5,
"A-ANNO": 7
}
},
"[2,0]": {
"count": 4,
"layers": {
"A-BASE": 1,
"A-SLOPE": 2,
"A-XXXX": 1
}
},
"[2,1]": {
"count": 1,
"layers": {
"A-SLOPE": 1
}
},
"[0,0]": {
"count": 790,
"layers": {
"A-BASE": 165,
"A-LINE04": 136,
"A-LINE01": 312,
"A-TEXT03": 104,
"A-HID01": 5,
"A-LINE02": 4,
"A-ANNO": 23,
"A-CEN01": 6,
"A-GUJO01": 21,
"A-ANNO-IDEN": 3,
"A-SYM01": 4,
"A-SLOPE": 5,
"A-FL": 2
}
},
"[1,2]": {
"count": 1,
"layers": {
"A-SLOPE": 1
}
},
"[0,1]": {
"count": 606,
"layers": {
"A-BASE": 123,
"A-LINE01": 274,
"A-TEXT03": 69,
"A-LINE04": 91,
"A-ANNO": 19,
"A-SYM01": 2,
"A-HID01": 8,
"A-CHAIN": 2,
"A-GUJO01": 14,
"A-CEN01": 3,
"A-FL": 1
}
}
},
"gujoAnalysis": {
"Y-166500": {
"count": 15,
"lengths": [
"1100",
"141",
"160",
"160",
"1300",
"1860",
"220",
"220",
"102",
"56",
"60",
"215",
"513",
"568",
"5918"
]
},
"Y-168500": {
"count": 21,
"lengths": [
"1100",
"141",
"160",
"160",
"1300",
"2180",
"2180",
"1660",
"2180",
"2180",
"220",
"220",
"102",
"56",
"60",
"215",
"513",
"2020",
"2020",
"568",
"5918"
]
},
"Y-166000": {
"count": 2,
"lengths": [
"2890",
"5918"
]
},
"Y-167500": {
"count": 6,
"lengths": [
"60",
"110",
"82",
"542",
"633",
"444"
]
},
"Y-169000": {
"count": 1,
"lengths": [
"5918"
]
}
}
}
+1 -1
View File
@@ -275,7 +275,7 @@
<script>
let modelData = null;
fetch('gasiseol-volumes-v3.json')
fetch('gasiseol-volumes-final.json')
.then(r => r.json())
.then(data => {
modelData = data;