BLOCK8 기준 보기와 분석·작업 로그 화면 추가

This commit is contained in:
김지영 committed 2026-10-20 12:18:31 +09:00
1 parent 62c7395dc1
commit 1986680183
4 files changed
+251 -15

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
# BLOCK8 도면 분석 기록
## 사용 자료
| 자료 | 파일 | 확인 범위 |
|---|---|---|
| 전체 일반도 DXF | `public/drawings/광터지하차도_BLOCK8.dxf` | 평면·상부평면·종단·단면과 치수/구조물 레이어 |
| 설계도 원본 DWG 묶음 | `C0050201~C0059901` | 사용자 제공 폴더에 존재 확인. 이 환경에서 직접 열람/대조는 미완료 |
DXF 내부 표제 및 주석에서 `평면도`, `상부평면도`, `종단면도`, `(BLOCK8)`, `U-Type 구간`을 확인했다. 입력 도면은 여러 구간/도면을 포함하므로 BLOCK8 경계 표기로 자료를 선별했다.
## 도면 연결 및 기준값
| 항목 | 읽은 값 | 근거/위치 | 상태 |
|---|---:|---|---|
| BLOCK8 시점 측점 | STA. 0K+319.010 | 일반도 DXF, BLOCK8 경계 주석 | 도면 명시값 |
| BLOCK8 종점 측점 | STA. 0K+338.990 | 일반도 DXF, BLOCK8 경계 주석 | 도면 명시값 |
| 측점 차이 | 19.980 m | 위 두 측점 차 계산 | 계산으로 도출한 값 |
| 인접 표기 측점 | STA. 0K+319.000, 0K+339.000 | 평면/구조 배치 주변 주석 | 도면 명시값; 경계 측점과 각각 0.010m 차이 |
| 단면 기준 EL 후보(시점) | 101.777~107.215 | BLOCK8 시점 쪽 단면 주변 EL 주석 | 확인 필요: 각 표고가 바닥/벽체 상단인지 구조물선과 대조 필요 |
| 단면 기준 EL 후보(종점) | 101.292~107.857 | BLOCK8 종점 쪽 단면 주변 EL 주석 | 확인 필요: 각 표고가 바닥/벽체 상단인지 구조물선과 대조 필요 |
| 상부/평면 치수 후보 | 19.5, 20.099, 20.3, 8.75, 1.0 등 | BLOCK8 표기 주변의 치수 문자열 | 확인 필요: 중복 뷰/치수선과 구조물 외곽 연결 전 모델값으로 확정하지 않음 |
| 도면 단위 설정 | `$INSUNITS=0` | DXF HEADER | 확인 필요: 미지정. 치수 표기와 좌표 변환으로 단위 검증 필요 |
## 레이어 및 형상 해석
- DXF 모델 공간에는 `CS-CONC-MAJR` 510개, `CS-CONC-MINR` 57개 엔티티가 있다. `CS-DIMT`/`CS-DIML`은 치수, `CS-TEXT`/`CS-NOTE`는 문자·주석으로 구분했다.
- 구조 윤곽 추출은 `CS-CONC-MAJR`, `CS-CONC-MINR`만 대상으로 해야 한다. 단순히 도면 전체 선을 모델링하면 치수선과 보조선이 섞인다.
- 주요 형상 중 일부가 INSERT 블록으로 저장되어 있어 블록 내부 변환(삽입점·축척·회전)을 풀어 원 좌표로 검증해야 한다. 현재 레이어별 원시 개수는 확인했으나, 모든 블록 내부 윤곽의 완전 추출은 아직 끝나지 않았다.
- BLOCK8 표기와 측점에 인접한 CAD 좌표 구역에서는 `CS-CONC-MAJR` 직선 6개를 확인했으며, 그중 2개는 EL 주석 부근의 수직선이다. 같은 2D 창에서 `CS-CONC-MINR` 구조선은 확인되지 않았다. 따라서 이 구역만으로 단면 윤곽 전체를 구성할 근거가 부족하다.
- 평면 중심선과 종단면, 시점·종점 단면, 측구 상세의 동일 부재 대응은 원본 DWG/블록 도형과의 위치 검토가 더 필요하다.
## 축척
DXF HEADER의 `$INSUNITS=0`으로 파일 단위는 지정되지 않았다. 도면 축척 문구를 모든 뷰에서 확인하고, 표기 치수(예: 19.980m)와 CAD 좌표 차이를 비교해 좌표 단위를 확정해야 한다. 이 확인 전에는 화면상 축척 측정값을 도면 명시 치수로 취급하지 않는다.
## 오류·누락·확인 항목
1. 319.000/339.000 표기와 BLOCK8 경계 319.010/338.990 사이에 각각 0.010m 차이가 있다. 어떤 경계를 모델 끝으로 쓸지 구조 이음/상세에서 확인한다.
2. 종단/단면 EL 후보를 벽체 상단 및 중심 기준 EL로 확정하려면 각 주석의 지시선과 CS-CONC 구조선을 연결해야 한다.
3. 단면 전체 윤곽, 두께, 측구/공동구 상세 치수 및 부재 개수는 INSERT 내부 요소까지 추출해 확인해야 한다.
4. 원본 DWG의 제원·특기사항 및 구조도와 교차 대조가 미완료다.
따라서 현재 확정 가능한 모델 기준은 BLOCK8 경계 측점과 19.980m 길이뿐이다. 미확정 단면 윤곽과 높이는 임의로 만들어 넣지 않는다.
## 모델 생성 진행 상태
현재는 도면 원본 보존과 1차 분석까지 완료했다. 실제 3D 형상 생성은 보류 상태다. 이유는 BLOCK8 단면의 구조물선 전체와 A-A/B-B 대응을 확인하지 못했고, DXF 단위도 미지정이기 때문이다. 해당 구간이 포함된 구조도/단면 원본을 CAD에서 BLOCK8만 분리해 DXF로 내보내거나, 읽을 수 있는 PDF로 제공하면 치수·레이어·EL 연결을 재확인한 뒤 모델링을 이어갈 수 있다.
+24
View File
@@ -0,0 +1,24 @@
광터지하차도 BLOCK8 작업기록
※ 초기화 커밋 이전의 이력은 제외하고, 초기화 이후 작업만 기록합니다.
※ 날짜: 2026-10-20
1. 작업지침 저장
- 도면 기반 3D 모델 분석·기록·검증 지침을 AGENTS.md에 저장
- 커밋: 0adb717 도면 기반 모델 작업지침 추가
2. 도면 등록 및 1차 분석
- BLOCK8 DXF 원본을 프로젝트에 등록
- 시점 STA. 0K+319.010, 종점 STA. 0K+338.990, 계산 길이 19.980m 기록
- DXF 단위 미지정, 단면 윤곽 및 EL 연결 확인 필요 사항 기록
- 커밋: 1783d1f BLOCK8 도면 자료와 1차 분석 기록 추가
3. 구조 윤곽 분석 상태 보완
- BLOCK8 인접 좌표 구역의 구조선 추출 한계와 추가 도면 자료 필요 사항 기록
- 커밋: 62c7395 BLOCK8 윤곽 추출 한계와 추가 자료 기록
4. 모델/자료 보기 화면 추가
- 확인된 측점 구간을 기준선으로 표시
- 단면 형상이 미확정임을 웹 화면에 표시
- 분석 파일과 작업 로그를 웹 화면에서 열 수 있도록 연결
- 초기화 이후 커밋 이력만 이 파일에 정리
+95 -9
View File
@@ -1,14 +1,100 @@
export default function App() {
import { useState } from 'react'
const views = {
전체: { transform: 'rotate(-8 450 180) skewY(-2deg)' },
평면: { transform: 'rotate(0 450 180)' },
정면: { transform: 'rotate(-90 450 180)' },
측면: { transform: 'rotate(90 450 180)' },
}
function StationModel({ view }) {
return (
<main className="welcome">
<section className="welcome-card" aria-labelledby="welcome-title">
<span className="welcome-mark" aria-hidden="true">3D</span>
<p className="welcome-kicker">새 프로젝트</p>
<h1 id="welcome-title">작업을 시작할 준비가 되었습니다</h1>
<p className="welcome-description">
이 공간은 비어 있습니다. 도면과 작업 내용을 추가해 새 모델을 만들어 보세요.
</p>
<svg className="model-svg" viewBox="0 0 900 360" role="img" aria-labelledby="model-title model-desc">
<title id="model-title">BLOCK8 확인된 종단 기준선</title>
<desc id="model-desc">측점 319.010에서 338.990까지 19.980미터의 기준 구간입니다. 단면 형상은 미확정입니다.</desc>
<defs>
<marker id="arrow" markerWidth="8" markerHeight="8" refX="4" refY="4" orient="auto-start-reverse">
<path d="M 0 0 L 8 4 L 0 8 z" fill="#718b78" />
</marker>
</defs>
<g className="model-grid">
<path d="M90 250 L810 250 M130 280 L850 280 M110 220 L830 220" />
<path d="M180 200 L180 290 M360 200 L360 290 M540 200 L540 290 M720 200 L720 290" />
</g>
<g style={views[view]} className="station-line">
<path className="station-shadow" d="M180 185 L720 185" />
<path className="station-main" d="M180 185 L720 185" />
<path className="station-cap" d="M180 164 L180 207 M720 164 L720 207" />
<circle cx="180" cy="185" r="9" />
<circle cx="720" cy="185" r="9" />
<path className="dimension" d="M190 137 L710 137" markerStart="url(#arrow)" markerEnd="url(#arrow)" />
<path className="dimension-tick" d="M180 145 L180 164 M720 145 L720 164" />
<text x="450" y="122" textAnchor="middle" className="length-label">19.980 m · 측점 차이</text>
<text x="180" y="228" textAnchor="middle" className="endpoint-label">STA. 0K+319.010</text>
<text x="720" y="228" textAnchor="middle" className="endpoint-label">STA. 0K+338.990</text>
</g>
<g className="axis-labels">
<path d="M82 303 L150 303" /><path d="M82 303 L82 263" />
<text x="157" y="307">종단 기준</text><text x="76" y="255">EL 기준 미연결</text>
</g>
</svg>
)
}
export default function App() {
const [view, setView] = useState('전체')
return (
<main className="page-shell">
<header className="topbar">
<a className="brand" href="#top"><span className="brand-mark">B8</span><span>도면 모델 작업실</span></a>
<span className="project-chip">광터지하차도 · BLOCK8</span>
<nav className="file-links" aria-label="작업 자료">
<a href="/analysis/도면분석.md" target="_blank" rel="noreferrer">분석 파일 ↗</a>
<a href="/작업기록.txt" target="_blank" rel="noreferrer">작업 로그 ↗</a>
<a href="/drawings/광터지하차도_BLOCK8.dxf" download>원본 DXF ↓</a>
</nav>
</header>
<section className="intro" id="top">
<div>
<span className="kicker">도면 근거가 확인된 범위부터 표시합니다</span>
<h1>BLOCK8 <em>모델 보기</em></h1>
<p>현재 도면에서 확인된 종단 구간 기준선입니다. 구조물 단면은 추가 확인이 필요합니다.</p>
</div>
<span className="status-pill"><i /> 단면 윤곽 확인 필요</span>
</section>
<section className="summary-grid" aria-label="확인된 기준값">
<article><span>시점</span><strong>0K+319.010</strong><small>도면 명시값</small></article>
<article><span>종점</span><strong>0K+338.990</strong><small>도면 명시값</small></article>
<article><span>구간 길이</span><strong>19.980 <i>m</i></strong><small>측점 차이로 계산</small></article>
<article className="unknown"><span>단면 폭 · 높이</span><strong>확인 필요</strong><small>구조선과 EL 연결 전</small></article>
</section>
<section className="model-card" aria-labelledby="model-heading">
<div className="card-heading">
<div><span className="eyebrow">3D 기준 보기 · 형상 검토 중</span><h2 id="model-heading">확인된 종단 구간</h2></div>
<div className="view-controls" aria-label="보기 방향">
{Object.keys(views).map(name => <button key={name} className={view === name ? 'active' : ''} onClick={() => setView(name)}>{name}</button>)}
</div>
</div>
<div className="model-stage"><StationModel view={view} /><span className="stage-note">선은 측점 범위를 나타냅니다 · 구조물 단면/폭/높이를 표현한 형상이 아닙니다</span></div>
<div className="model-caption"><span><i className="legend-line" /> 도면 명시 측점으로 계산한 기준선</span><span>단면 윤곽 · 배치 · EL 연결: 확인 필요</span></div>
</section>
<section className="bottom-grid">
<article className="info-card">
<span className="eyebrow">진행 상태</span><h2>분석은 완료, 구조 형상은 미확정</h2>
<p>도면에서 측점과 구간 길이를 읽었습니다. DXF 단위가 지정되지 않았고 BLOCK8의 전체 구조물 윤곽을 확인하지 못해, 임의의 폭·높이를 넣은 구조물 모델은 표시하지 않습니다.</p>
<a className="text-link" href="/analysis/도면분석.md" target="_blank" rel="noreferrer">도면 분석 내용 보기 <span>↗</span></a>
</article>
<article className="info-card log-card">
<span className="eyebrow">작업 기록</span><h2>분석 자료와 변경 이력</h2>
<p>초기화 이후 도면 등록과 분석 기록을 날짜·커밋 단위로 정리했습니다.</p>
<a className="text-link" href="/작업기록.txt" target="_blank" rel="noreferrer">작업 로그 파일 열기 <span>↗</span></a>
</article>
</section>
<footer>단위 m · 도면 명시값과 계산값을 구분해 표시합니다.</footer>
</main>
)
}
+84 -6
View File
@@ -8,9 +8,87 @@
* { box-sizing: border-box; }
body { min-width: 320px; min-height: 100vh; margin: 0; }
.welcome { display: grid; min-height: 100vh; place-items: center; padding: 24px; }
.welcome-card { width: min(100%, 560px); padding: 48px 32px; text-align: center; background: #fafcf8; border: 1px solid #dbe4d7; border-radius: 16px; }
.welcome-mark { display: grid; width: 52px; height: 52px; margin: 0 auto 24px; place-items: center; border-radius: 15px; background: #446b58; color: white; font-size: 17px; font-weight: 700; }
.welcome-kicker { margin: 0 0 10px; color: #71877a; font-size: 12px; font-weight: 700; letter-spacing: .08em; }
h1 { margin: 0; font-size: clamp(22px, 5vw, 30px); letter-spacing: -.05em; }
.welcome-description { margin: 16px 0 0; color: #77857b; font-size: 14px; line-height: 1.8; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }
.page-shell { width: min(100% - 64px, 1380px); margin: 0 auto; padding-bottom: 25px; }
.topbar { min-height: 72px; display: flex; align-items: center; gap: 20px; border-bottom: 1px solid #d8e0d6; }
.brand { display: inline-flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 700; white-space: nowrap; }
.brand-mark { display: grid; width: 34px; height: 34px; place-items: center; border-radius: 10px; background: #446b58; color: #fff; font-size: 12px; }
.project-chip { color: #819087; font-size: 11px; }
.file-links { display: flex; gap: 8px; margin-left: auto; }
.file-links a { padding: 9px 11px; border: 1px solid #d7dfd4; border-radius: 7px; background: #fafcf8; color: #536d5b; font-size: 11px; white-space: nowrap; }
.file-links a:hover,.text-link:hover { border-color: #89a28d; color: #2d6045; }
.intro { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 36px 0 25px; }
.kicker,.eyebrow { display: block; color: #788a7d; font-size: 10px; font-weight: 700; letter-spacing: .08em; }
h1 { margin: 8px 0; font-size: clamp(27px, 4vw, 34px); letter-spacing: -.06em; }
h1 em { margin-left: 7px; color: #778b7d; font-size: .8em; font-style: normal; font-weight: 400; }
.intro p,.info-card p { margin: 0; color: #79877c; font-size: 12px; line-height: 1.8; }
.status-pill { display: inline-flex; align-items: center; gap: 8px; padding: 10px 14px; border: 1px solid #e5dbc2; border-radius: 30px; background: #faf5e9; color: #967641; font-size: 11px; white-space: nowrap; }
.status-pill i { width: 7px; height: 7px; border-radius: 50%; background: #b98f48; }
.summary-grid { display: grid; grid-template-columns: repeat(4, 1fr); margin-bottom: 18px; overflow: hidden; border: 1px solid #dce4d9; border-radius: 11px; background: #fafcf8; }
.summary-grid article { min-height: 112px; padding: 18px 22px; border-right: 1px solid #e3e9e1; }
.summary-grid article:last-child { border: 0; }
.summary-grid span,.summary-grid small { display: block; color: #839084; font-size: 10px; }
.summary-grid strong { display: block; margin: 10px 0 6px; font-family: Georgia,serif; font-size: clamp(19px, 2.5vw, 26px); font-weight: 400; white-space: nowrap; }
.summary-grid strong i { color: #78877c; font-family: sans-serif; font-size: 12px; font-style: normal; }
.summary-grid .unknown strong { color: #a38048; font-family: inherit; font-size: 18px; }
.model-card,.info-card { overflow: hidden; border: 1px solid #dbe4d7; border-radius: 12px; background: #fafcf8; }
.card-heading { display: flex; align-items: center; justify-content: space-between; gap: 15px; padding: 19px 22px 12px; }
h2 { margin: 5px 0 0; font-size: 17px; letter-spacing: -.04em; }
.view-controls { display: flex; gap: 4px; padding: 3px; border-radius: 7px; background: #edf1ea; }
.view-controls button { padding: 7px 11px; border: 0; border-radius: 5px; background: transparent; color: #768579; font-size: 10px; }
.view-controls button.active { background: white; color: #426a50; box-shadow: 0 1px 4px #233c2912; }
.model-stage { position: relative; display: grid; min-height: 330px; place-items: center; overflow: hidden; border-top: 1px solid #e0e7dd; border-bottom: 1px solid #e0e7dd; background: linear-gradient(180deg,#f6f9f5,#edf2ec); }
.model-svg { width: min(100%, 940px); height: auto; min-height: 270px; overflow: visible; }
.model-grid path { fill: none; stroke: #dbe4dc; stroke-width: 1; }
.station-line { transform-box: view-box; transform-origin: center; transition: transform .35s ease; }
.station-shadow { fill: none; stroke: #d2ddd2; stroke-width: 15; stroke-linecap: round; }
.station-main { fill: none; stroke: #547d62; stroke-width: 5; stroke-linecap: round; }
.station-cap { fill: none; stroke: #819782; stroke-width: 2; }
.station-line circle { fill: #fafcf8; stroke: #52785d; stroke-width: 4; }
.dimension { fill: none; stroke: #718b78; stroke-width: 1.5; }
.dimension-tick { fill: none; stroke: #a5b5a5; stroke-width: 1; }
.length-label { fill: #49694f; font-size: 16px; font-weight: 700; }
.endpoint-label { fill: #566e5c; font-size: 12px; }
.axis-labels path { stroke: #758e79; stroke-width: 2; }
.axis-labels text { fill: #809083; font-size: 10px; }
.stage-note { position: absolute; right: 15px; bottom: 12px; color: #9a835b; font-size: 9px; text-align: right; }
.model-caption { display: flex; justify-content: space-between; gap: 14px; padding: 13px 20px; color: #839084; font-size: 10px; }
.model-caption>span:first-child { display: inline-flex; align-items: center; gap: 8px; }
.legend-line { width: 19px; height: 3px; border-radius: 2px; background: #547d62; }
.bottom-grid { display: grid; grid-template-columns: 1.25fr 1fr; gap: 16px; margin-top: 17px; }
.info-card { min-height: 172px; padding: 19px 21px; }
.info-card h2 { margin-bottom: 10px; }
.info-card p { max-width: 720px; }
.text-link { display: inline-flex; align-items: center; gap: 9px; margin-top: 14px; padding: 8px 10px; border: 1px solid #d8e1d6; border-radius: 6px; color: #4b6b52; font-size: 10px; }
.text-link span { font-size: 13px; }
footer { padding-top: 18px; color: #89958a; font-size: 9px; }
@media (max-width: 760px) {
.page-shell { width: min(100% - 32px, 620px); }
.topbar { flex-wrap: wrap; gap: 10px; padding: 13px 0; }
.project-chip { margin-left: auto; }
.file-links { width: 100%; margin: 0; }
.file-links a { flex: 1; text-align: center; }
.intro { align-items: flex-start; flex-direction: column; padding: 27px 0 19px; }
.summary-grid { grid-template-columns: 1fr 1fr; }
.summary-grid article { min-height: 98px; padding: 15px; border-bottom: 1px solid #e3e9e1; }
.summary-grid article:nth-child(2) { border-right: 0; }
.summary-grid article:nth-child(n+3) { border-bottom: 0; }
.card-heading { align-items: flex-start; flex-direction: column; padding: 17px 15px 12px; }
.model-stage { min-height: 260px; }
.model-svg { min-height: 220px; }
.endpoint-label { font-size: 11px; }
.stage-note { max-width: 260px; line-height: 1.5; }
.model-caption { flex-direction: column; padding: 12px 15px; }
.bottom-grid { grid-template-columns: 1fr; gap: 11px; }
.info-card { min-height: 0; padding: 17px; }
}
@media (max-width: 400px) {
.file-links { gap: 5px; }
.file-links a { padding: 8px 5px; font-size: 10px; }
.view-controls button { padding: 7px 9px; }
.model-stage { min-height: 220px; }
.length-label { font-size: 13px; }
}