Update Pier_v1 project
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
f25e36c050
commit
ad73ddec2b
2476 files changed
+3423
-4902
No files matched your search
@@ -12,3 +12,5 @@ __pycache__/
|
||||
*.zip
|
||||
pierzainer_ground/data/cache/
|
||||
pierzainer_ground/data/output/**/cache/
|
||||
verify/
|
||||
도면추출/output/
|
||||
@@ -11,19 +11,22 @@ npm run dev -- --host 127.0.0.1 --port 5173
|
||||
|
||||
브라우저에서 http://127.0.0.1:5173/ 을 엽니다. 랜딩페이지의 Excel 가져오기와 실제 교량 샘플 선택을 사용합니다.
|
||||
|
||||
랜딩페이지의 **도면 불러오기**를 누르면 프로그램 내부의 도면추출 팝업이 열립니다. DWG 폴더를 선택하고 자동 추출을 시작하면 진행 로그와 결과가 팝업에 표시됩니다. 결과의 **교각 불러오기**로 바로 Excel 인식·형상 생성 단계에 연결하거나 **Excel 저장**으로 파일을 받을 수 있습니다. 원래 추출 엔진은 화면 없이 실행하며 미확정 값은 검토 대상으로 유지합니다.
|
||||
|
||||
결과는 프로젝트의 `도면추출/output/작업ID/`에 저장합니다. 선택한 원본 도면 폴더는 수정하지 않습니다. 팝업을 닫아도 추출은 계속되며 다시 열어 결과를 확인할 수 있습니다.
|
||||
|
||||
배포 빌드를 로컬에서 실행하려면 `npm run build` 후 `npm run preview -- --host 127.0.0.1`을 사용합니다. 도면추출은 이 PC의 Windows 로컬 서버와 포함된 `도면추출/app` 엔진을 사용하므로, `dist`만 올린 정적 웹사이트에서는 추출을 실행할 수 없습니다.
|
||||
|
||||
## 유지하는 폴더
|
||||
|
||||
- `src/`, `index.html`: 실제 교각 프로그램
|
||||
- `랜딩페이지/`: 랜딩 화면과 지도 포함 통합 샘플 12개
|
||||
- `pierzainer_ground/`: 지반 생성 프로그램, 원본 자료, 최종 지반 JSON 및 재현에 필요한 데이터
|
||||
- `도면추출_연동패키지_20261102/`: 도면 추출 프로그램과 교각 샘플 Excel
|
||||
- `public/`: 프로그램 리소스 및 기본 Excel 샘플
|
||||
- `tests/`, `scripts/`, `verify/`: 자동 검사와 유지보수 스크립트
|
||||
- `도면추출/`: 도면 추출 프로그램과 교각 샘플 Excel (기본 P1 샘플 포함)
|
||||
- `tests/`: 현재 교각·Excel·지도 기능의 자동 검사
|
||||
|
||||
`node_modules/`, `dist/`, `.verify/`, 지반 `cache/`는 실행·검증 중 재생성되는 파일이며 Git에 추가하지 않습니다.
|
||||
|
||||
## 2026-11-02 혼합 파일 복구
|
||||
## 정리 기준
|
||||
|
||||
혼합 전 Pierzainer 커밋 `d6735a6`에서 로컬 브랜치 `recovery/pierzainer-20261102`를 만들었습니다. π형 Excel 인식, 전·후열 받침 수 불일치 허용, 랜딩페이지 샘플 연결을 포함합니다. 기존 ITAM 브랜치와 원격 기록은 변경하지 않았습니다.
|
||||
|
||||
복구본과 분리한 파일은 상위 `_recovery/20261102_mixed_projects/`에 보관했습니다. 기존 `master`는 ITAM 코드이므로 그 브랜치로 전환하면 화면과 파일이 다시 바뀝니다. 현재 복구 브랜치에서 작업하세요. 이 작업에서는 원격 push를 수행하지 않았습니다.
|
||||
실행에 필요한 코드·원본 도면·샘플 Excel·최종 지반 JSON은 유지합니다. 과거 개발용 도구와 옛 좌표 기준의 검증 파일은 정리했으며 백업 목록은 상위 `_recovery/20261103_cleanup/`에 있습니다.
|
||||
@@ -24,7 +24,6 @@
|
||||
<span id="save-status" class="savest">저장 전</span>
|
||||
<button id="home-from-app" class="btn-s" type="button" hidden>홈으로</button>
|
||||
<button id="save-project" class="btn-s" type="button" disabled title="프로젝트 파일 저장 (Ctrl+S)">저장</button>
|
||||
<button id="open-import" class="btn-s" type="button">엑셀 불러오기</button>
|
||||
<button id="open-project" class="btn-s" type="button">프로젝트 열기</button>
|
||||
<button id="regen" class="btn-p" type="button" disabled>선택 교각 형상 생성</button>
|
||||
<input id="project-file" type="file" accept=".json" hidden />
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"description": "교각 3D 형상 생성 웹앱 (1단계: 형상 생성)",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"preview": "vite preview",
|
||||
"build": "tsc --noEmit && vite build",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"test": "vitest run"
|
||||
|
||||
@@ -16,7 +16,7 @@ import traceback
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
OUTPUT = ROOT / 'data/output/samples_20261102'
|
||||
PACKAGE = ROOT.parent / '도면추출_연동패키지_20261102'
|
||||
PACKAGE = ROOT.parent / '도면추출'
|
||||
|
||||
|
||||
def save(path, value):
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5183",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "CSSAA14",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플01_산외교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플01_산외교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 1,
|
||||
"bridge": "산외교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플01_산외교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플01_산외교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample1)_π형교각_산외교\\02.종평면도(울산)_2017.0619-수정.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample1)_π형교각_산외교\\02.종평면도(울산)_2017.0619-수정.dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플02_운곡교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플02_운곡교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "CA002,CA0021,CAA001,CAA002",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 2,
|
||||
"bridge": "운곡교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플02_운곡교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플02_운곡교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample2)_T형교각_운곡교\\C0050202-001-운곡교 종평면도(완도방향).dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample2)_T형교각_운곡교\\C0050202-001-운곡교 종평면도(완도방향).dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "*Model_Space",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플03_대호지교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플03_대호지교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "PDF_SOUNDING",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 3,
|
||||
"bridge": "대호지교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플03_대호지교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플03_대호지교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\03_original_pdf_soundings.dxf",
|
||||
"candidates": [],
|
||||
"output": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\output\\samples_20261102\\03_대호지교",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플04_목동교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플04_목동교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "CA002,CA0021,CAA001,CAA002",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 4,
|
||||
"bridge": "목동교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플04_목동교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플04_목동교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\04_@서울-세종 9공구 1000현황.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample4)_π형교각_목동교\\01 공통사항(목동교 종평면도).dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플05_승천천교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플05_승천천교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "F0017111,F0017114,F0027217,F0027132",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 5,
|
||||
"bridge": "승천천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플05_승천천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플05_승천천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\05_project_topography_original.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample5)_π형교각_승천천교\\01 승천천교(DR) 종평면도.dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "xref-현황(191219)",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플06_계문철교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플06_계문철교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 6,
|
||||
"bridge": "계문철교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플06_계문철교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플06_계문철교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\06_서수평장1-현황+선형+노리-20200410.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample6)_π형교각_계문철교\\01 계문철교 종평면도.dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "xref-현황(191219)",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플07_기양천교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플07_기양천교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 7,
|
||||
"bridge": "기양천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플07_기양천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플07_기양천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\06_서수평장1-현황+선형+노리-20200410.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample7)_π형교각_기양천교\\01 기양천교종평면도.dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "XR_현황",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플08_옥성교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플08_옥성교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 8,
|
||||
"bridge": "옥성교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플08_옥성교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플08_옥성교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample8)_T형교각_옥성교\\01 옥성교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample8)_T형교각_옥성교\\01 옥성교 종평면도.dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "*Model_Space",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플09_새재1교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플09_새재1교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "XR_현황-수정$0$Point",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 9,
|
||||
"bridge": "새재1교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플09_새재1교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플09_새재1교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample9)_T형교각_새재1교\\01 새재1교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample9)_T형교각_새재1교\\01 새재1교 종평면도.dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "*Model_Space",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플10_도하4교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플10_도하4교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "CA002,CA0021,CAA001,CAA002",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 10,
|
||||
"bridge": "도하4교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플10_도하4교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플10_도하4교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample10)_T형교각_도하4교\\01.종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample10)_T형교각_도하4교\\01.종평면도.dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5186",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "*Model_Space",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플11_곡천교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플11_곡천교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "CA002,CA0021,CAA001,CAA002",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 11,
|
||||
"bridge": "곡천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플11_곡천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플11_곡천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample11)_π형교각_곡천교\\01 종평면도_곡천교.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample11)_π형교각_곡천교\\01 종평면도_곡천교.dwg"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"terrain_crs": "EPSG:5181",
|
||||
"cad_axes": "YX",
|
||||
"terrain_block": "",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플12_감북교_교각입력데이터.xlsx",
|
||||
"piers": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플12_감북교_교각입력데이터.xlsx",
|
||||
"boreholes": "",
|
||||
"layers": "CAA001,CAA002",
|
||||
"margin": 100.0,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"sample": 12,
|
||||
"bridge": "감북교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플12_감북교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플12_감북교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample12)_π형교각_감북교\\01 감북교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample12)_π형교각_감북교\\01 감북교 종평면도.dwg"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{
|
||||
"sample": 1,
|
||||
"bridge": "산외교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플01_산외교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플01_산외교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample1)_π형교각_산외교\\02.종평면도(울산)_2017.0619-수정.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample1)_π형교각_산외교\\02.종평면도(울산)_2017.0619-수정.dwg"
|
||||
@@ -12,7 +12,7 @@
|
||||
{
|
||||
"sample": 2,
|
||||
"bridge": "운곡교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플02_운곡교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플02_운곡교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample2)_T형교각_운곡교\\C0050202-001-운곡교 종평면도(완도방향).dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample2)_T형교각_운곡교\\C0050202-001-운곡교 종평면도(완도방향).dwg"
|
||||
@@ -22,7 +22,7 @@
|
||||
{
|
||||
"sample": 3,
|
||||
"bridge": "대호지교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플03_대호지교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플03_대호지교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\03_original_pdf_soundings.dxf",
|
||||
"candidates": [],
|
||||
"output": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\output\\samples_20261102\\03_대호지교",
|
||||
@@ -930,7 +930,7 @@
|
||||
{
|
||||
"sample": 4,
|
||||
"bridge": "목동교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플04_목동교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플04_목동교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\04_@서울-세종 9공구 1000현황.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample4)_π형교각_목동교\\01 공통사항(목동교 종평면도).dwg"
|
||||
@@ -956,7 +956,7 @@
|
||||
{
|
||||
"sample": 5,
|
||||
"bridge": "승천천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플05_승천천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플05_승천천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\05_project_topography_original.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample5)_π형교각_승천천교\\01 승천천교(DR) 종평면도.dwg"
|
||||
@@ -984,7 +984,7 @@
|
||||
{
|
||||
"sample": 6,
|
||||
"bridge": "계문철교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플06_계문철교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플06_계문철교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\06_서수평장1-현황+선형+노리-20200410.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample6)_π형교각_계문철교\\01 계문철교 종평면도.dwg"
|
||||
@@ -1011,7 +1011,7 @@
|
||||
{
|
||||
"sample": 7,
|
||||
"bridge": "기양천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플07_기양천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플07_기양천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\06_서수평장1-현황+선형+노리-20200410.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample7)_π형교각_기양천교\\01 기양천교종평면도.dwg"
|
||||
@@ -1038,7 +1038,7 @@
|
||||
{
|
||||
"sample": 8,
|
||||
"bridge": "옥성교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플08_옥성교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플08_옥성교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample8)_T형교각_옥성교\\01 옥성교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample8)_T형교각_옥성교\\01 옥성교 종평면도.dwg"
|
||||
@@ -1048,7 +1048,7 @@
|
||||
{
|
||||
"sample": 9,
|
||||
"bridge": "새재1교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플09_새재1교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플09_새재1교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample9)_T형교각_새재1교\\01 새재1교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample9)_T형교각_새재1교\\01 새재1교 종평면도.dwg"
|
||||
@@ -1058,7 +1058,7 @@
|
||||
{
|
||||
"sample": 10,
|
||||
"bridge": "도하4교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플10_도하4교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플10_도하4교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample10)_T형교각_도하4교\\01.종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample10)_T형교각_도하4교\\01.종평면도.dwg"
|
||||
@@ -1068,7 +1068,7 @@
|
||||
{
|
||||
"sample": 11,
|
||||
"bridge": "곡천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플11_곡천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플11_곡천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample11)_π형교각_곡천교\\01 종평면도_곡천교.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample11)_π형교각_곡천교\\01 종평면도_곡천교.dwg"
|
||||
@@ -1078,7 +1078,7 @@
|
||||
{
|
||||
"sample": 12,
|
||||
"bridge": "감북교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플12_감북교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플12_감북교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample12)_π형교각_감북교\\01 감북교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample12)_π형교각_감북교\\01 감북교 종평면도.dwg"
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
{
|
||||
"sample": 1,
|
||||
"bridge": "산외교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플01_산외교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플01_산외교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample1)_π형교각_산외교\\02.종평면도(울산)_2017.0619-수정.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample1)_π형교각_산외교\\02.종평면도(울산)_2017.0619-수정.dwg"
|
||||
@@ -41,7 +41,7 @@
|
||||
{
|
||||
"sample": 2,
|
||||
"bridge": "운곡교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플02_운곡교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플02_운곡교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample2)_T형교각_운곡교\\C0050202-001-운곡교 종평면도(완도방향).dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample2)_T형교각_운곡교\\C0050202-001-운곡교 종평면도(완도방향).dwg"
|
||||
@@ -75,7 +75,7 @@
|
||||
{
|
||||
"sample": 3,
|
||||
"bridge": "대호지교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플03_대호지교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플03_대호지교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\03_original_pdf_soundings.dxf",
|
||||
"candidates": [],
|
||||
"output": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\output\\samples_20261102\\03_대호지교",
|
||||
@@ -1007,7 +1007,7 @@
|
||||
{
|
||||
"sample": 4,
|
||||
"bridge": "목동교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플04_목동교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플04_목동교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\04_@서울-세종 9공구 1000현황.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample4)_π형교각_목동교\\01 공통사항(목동교 종평면도).dwg"
|
||||
@@ -1057,7 +1057,7 @@
|
||||
{
|
||||
"sample": 5,
|
||||
"bridge": "승천천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플05_승천천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플05_승천천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\05_project_topography_original.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample5)_π형교각_승천천교\\01 승천천교(DR) 종평면도.dwg"
|
||||
@@ -1109,7 +1109,7 @@
|
||||
{
|
||||
"sample": 6,
|
||||
"bridge": "계문철교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플06_계문철교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플06_계문철교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\06_서수평장1-현황+선형+노리-20200410.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample6)_π형교각_계문철교\\01 계문철교 종평면도.dwg"
|
||||
@@ -1160,7 +1160,7 @@
|
||||
{
|
||||
"sample": 7,
|
||||
"bridge": "기양천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플07_기양천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플07_기양천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\pierzainer_ground\\data\\input\\samples_20261102\\recovered\\06_서수평장1-현황+선형+노리-20200410.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample7)_π형교각_기양천교\\01 기양천교종평면도.dwg"
|
||||
@@ -1211,7 +1211,7 @@
|
||||
{
|
||||
"sample": 8,
|
||||
"bridge": "옥성교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플08_옥성교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플08_옥성교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample8)_T형교각_옥성교\\01 옥성교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample8)_T형교각_옥성교\\01 옥성교 종평면도.dwg"
|
||||
@@ -1245,7 +1245,7 @@
|
||||
{
|
||||
"sample": 9,
|
||||
"bridge": "새재1교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플09_새재1교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플09_새재1교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample9)_T형교각_새재1교\\01 새재1교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample9)_T형교각_새재1교\\01 새재1교 종평면도.dwg"
|
||||
@@ -1279,7 +1279,7 @@
|
||||
{
|
||||
"sample": 10,
|
||||
"bridge": "도하4교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플10_도하4교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플10_도하4교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample10)_T형교각_도하4교\\01.종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample10)_T형교각_도하4교\\01.종평면도.dwg"
|
||||
@@ -1313,7 +1313,7 @@
|
||||
{
|
||||
"sample": 11,
|
||||
"bridge": "곡천교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플11_곡천교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플11_곡천교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample11)_π형교각_곡천교\\01 종평면도_곡천교.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample11)_π형교각_곡천교\\01 종평면도_곡천교.dwg"
|
||||
@@ -1347,7 +1347,7 @@
|
||||
{
|
||||
"sample": 12,
|
||||
"bridge": "감북교",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출_연동패키지_20261102\\samples\\샘플12_감북교_교각입력데이터.xlsx",
|
||||
"workbook": "C:\\Users\\User\\Desktop\\Pier_v1-main\\Pier_v1\\도면추출\\samples\\샘플12_감북교_교각입력데이터.xlsx",
|
||||
"drawing": "C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample12)_π형교각_감북교\\01 감북교 종평면도.dwg",
|
||||
"candidates": [
|
||||
"C:\\Users\\User\\Desktop\\도면추출\\엔지니어(sample12)_π형교각_감북교\\01 감북교 종평면도.dwg"
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Headless Chrome screenshot of the sample page (WSL2 → Windows Chrome).
|
||||
# Usage: scripts/capture-sample.sh <output.png> [url]
|
||||
# Requires the dev server: npm run dev -- --host 127.0.0.1 --port 5173
|
||||
set -euo pipefail
|
||||
OUT_WSL="${1:?output png path (WSL path)}"
|
||||
URL="${2:-http://127.0.0.1:5173/?sample=1}"
|
||||
CHROME="/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"
|
||||
mkdir -p "$(dirname "$OUT_WSL")"
|
||||
timeout 200 "$CHROME" --headless=new --no-sandbox --use-gl=angle --use-angle=swiftshader \
|
||||
--enable-unsafe-swiftshader --enable-logging=stderr --v=0 --window-size=1600,1000 \
|
||||
--timeout=45000 --screenshot="$(wslpath -w "$OUT_WSL")" "$URL"
|
||||
@@ -1,43 +0,0 @@
|
||||
// Clicks the template download button in the import dialog through Chrome DevTools
|
||||
// and reports the saved file. Run with Windows Node (same machine as Chrome):
|
||||
// node verify-template-download.cjs "C:\\Users\\...\\Temp\\verify-downloads"
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const DL_DIR = process.argv[2];
|
||||
const CDP = 'http://127.0.0.1:9444';
|
||||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
|
||||
async function main() {
|
||||
fs.mkdirSync(DL_DIR, { recursive: true });
|
||||
const page = (await (await fetch(`${CDP}/json`)).json()).find((t) => t.type === 'page');
|
||||
const ws = new WebSocket(page.webSocketDebuggerUrl);
|
||||
await new Promise((res, rej) => { ws.onopen = res; ws.onerror = rej; });
|
||||
let seq = 0;
|
||||
const waiting = new Map();
|
||||
ws.onmessage = (ev) => {
|
||||
const m = JSON.parse(ev.data);
|
||||
if (m.id && waiting.has(m.id)) { waiting.get(m.id)(m); waiting.delete(m.id); }
|
||||
};
|
||||
const send = (method, params = {}) => new Promise((res) => {
|
||||
const id = ++seq; waiting.set(id, res); ws.send(JSON.stringify({ id, method, params }));
|
||||
});
|
||||
const evalJs = async (expression) => {
|
||||
const r = await send('Runtime.evaluate', { expression, awaitPromise: true, returnByValue: true });
|
||||
if (r.result.exceptionDetails) throw new Error(JSON.stringify(r.result.exceptionDetails).slice(0, 300));
|
||||
return r.result.result.value;
|
||||
};
|
||||
await send('Page.enable');
|
||||
await send('Runtime.enable');
|
||||
await send('Browser.setDownloadBehavior', { behavior: 'allow', downloadPath: DL_DIR, eventsEnabled: false });
|
||||
await send('Page.navigate', { url: 'http://127.0.0.1:5173/' });
|
||||
await sleep(4000);
|
||||
await evalJs(`document.getElementById('open-import').click()`);
|
||||
await sleep(500);
|
||||
await evalJs(`document.getElementById('download-template').click()`);
|
||||
await sleep(4000);
|
||||
const files = fs.readdirSync(DL_DIR);
|
||||
console.log('DOWNLOADED', JSON.stringify(files));
|
||||
for (const f of files) console.log('SIZE', f, fs.statSync(path.join(DL_DIR, f)).size);
|
||||
ws.close();
|
||||
}
|
||||
main().catch((e) => { console.error('FAILED', e); process.exit(1); });
|
||||
@@ -1,113 +0,0 @@
|
||||
// UI verification driven through the Chrome DevTools Protocol.
|
||||
// Run with Windows Node (same machine as Chrome), e.g.:
|
||||
// node verify-ui.cjs "C:\\Users\\...\\input.xlsx" "\\\\wsl.localhost\\Ubuntu\\...\\shots"
|
||||
// Chrome must be started with --remote-debugging-port=9444 (see DOC/05_검증).
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const APP_URL = process.env.APP_URL || 'http://127.0.0.1:5173/';
|
||||
const CDP = process.env.CDP || 'http://127.0.0.1:9444';
|
||||
const INPUT_FILE = process.argv[2];
|
||||
const OUT_DIR = process.argv[3];
|
||||
if (!INPUT_FILE || !OUT_DIR) throw new Error('INPUT_FILE and OUT_DIR are required');
|
||||
|
||||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
|
||||
async function main() {
|
||||
const targets = await (await fetch(`${CDP}/json`)).json();
|
||||
const page = targets.find((t) => t.type === 'page');
|
||||
if (!page) throw new Error('no page target');
|
||||
const ws = new WebSocket(page.webSocketDebuggerUrl);
|
||||
await new Promise((res, rej) => {
|
||||
ws.onopen = res;
|
||||
ws.onerror = rej;
|
||||
});
|
||||
|
||||
let seq = 0;
|
||||
const waiting = new Map();
|
||||
// Console and exception events, collected from the first navigation onward (V10 ③).
|
||||
const consoleEvents = [];
|
||||
ws.onmessage = (ev) => {
|
||||
const m = JSON.parse(ev.data);
|
||||
if (m.id && waiting.has(m.id)) {
|
||||
waiting.get(m.id)(m);
|
||||
waiting.delete(m.id);
|
||||
} else if (m.method === 'Runtime.consoleAPICalled' && ['error', 'warning'].includes(m.params.type)) {
|
||||
const text = m.params.args.map((a) => a.value ?? a.description ?? '').join(' ');
|
||||
consoleEvents.push(`console.${m.params.type}: ${text}`);
|
||||
} else if (m.method === 'Runtime.exceptionThrown') {
|
||||
const d = m.params.exceptionDetails;
|
||||
consoleEvents.push(`exception: ${d.exception?.description || d.text}`);
|
||||
} else if (m.method === 'Log.entryAdded' && ['error', 'warning'].includes(m.params.entry.level)) {
|
||||
consoleEvents.push(`log.${m.params.entry.level}: ${m.params.entry.text} ${m.params.entry.url || ''}`.trim());
|
||||
}
|
||||
};
|
||||
const send = (method, params = {}) =>
|
||||
new Promise((res) => {
|
||||
const id = ++seq;
|
||||
waiting.set(id, res);
|
||||
ws.send(JSON.stringify({ id, method, params }));
|
||||
});
|
||||
const evalJs = async (expression) => {
|
||||
const r = await send('Runtime.evaluate', { expression, awaitPromise: true, returnByValue: true });
|
||||
if (r.result.exceptionDetails) throw new Error(JSON.stringify(r.result.exceptionDetails).slice(0, 400));
|
||||
return r.result.result.value;
|
||||
};
|
||||
const shot = async (name) => {
|
||||
const r = await send('Page.captureScreenshot', { format: 'png' });
|
||||
fs.writeFileSync(path.join(OUT_DIR, name), Buffer.from(r.result.data, 'base64'));
|
||||
console.log(`SHOT ${name}`);
|
||||
};
|
||||
|
||||
await send('Page.enable');
|
||||
await send('Runtime.enable');
|
||||
await send('Log.enable');
|
||||
await send('DOM.enable');
|
||||
await send('Emulation.setDeviceMetricsOverride', { width: 1600, height: 1000, deviceScaleFactor: 1, mobile: false });
|
||||
await send('Page.navigate', { url: APP_URL });
|
||||
await sleep(4000);
|
||||
|
||||
// V11 — dialog with the user's three-sheet workbook.
|
||||
await evalJs(`document.getElementById('open-import').click()`);
|
||||
await sleep(500);
|
||||
await evalJs(`(() => { const i = document.getElementById('project-name'); i.value = '운곡교 검증';
|
||||
i.dispatchEvent(new Event('input')); return true; })()`);
|
||||
const doc = await send('DOM.getDocument', { depth: -1 });
|
||||
const q = await send('DOM.querySelector', { nodeId: doc.result.root.nodeId, selector: '#file' });
|
||||
await send('DOM.setFileInputFiles', { nodeId: q.result.nodeId, files: [INPUT_FILE] });
|
||||
await sleep(3000);
|
||||
|
||||
console.log('SHEETS_TEXT_BEGIN');
|
||||
console.log(await evalJs(`document.getElementById('sheets').innerText`));
|
||||
console.log('SHEETS_TEXT_END');
|
||||
console.log('SELECTED', await evalJs(`document.getElementById('dlg-selected').textContent`));
|
||||
console.log('APPLY', await evalJs(`(() => { const b = document.getElementById('dlg-apply');
|
||||
return b.textContent + ' | disabled=' + b.disabled; })()`));
|
||||
await shot('v11_dialog_user_file.png');
|
||||
|
||||
await evalJs(`document.getElementById('dlg-apply').click()`);
|
||||
await sleep(2000);
|
||||
console.log('STATUS', await evalJs(`document.getElementById('status').textContent`));
|
||||
console.log('PIERS', await evalJs(`[...document.querySelectorAll('#pier-items li')].map(li => li.textContent.trim()).join(' | ')`));
|
||||
console.log('RESULT_AXIS', await evalJs(`document.getElementById('res-axis').innerText.replace(/\\n+/g, ' / ')`));
|
||||
console.log('RESULT_FOUND', await evalJs(`document.getElementById('res-found').innerText.replace(/\\n+/g, ' / ')`));
|
||||
await shot('v11_main_user_file.png');
|
||||
|
||||
// V10 ② — the four view presets.
|
||||
for (const label of ['정면', '측면', '평면', '아이소']) {
|
||||
await evalJs(`[...document.querySelectorAll('#views button')].find((b) => b.textContent === '${label}').click()`);
|
||||
await sleep(1500);
|
||||
await shot(`v10_view_${label}.png`);
|
||||
console.log('PRESSED', label, await evalJs(`[...document.querySelectorAll('#views button')].filter((b) => b.getAttribute('aria-pressed') === 'true').map((b) => b.textContent).join(',')`));
|
||||
}
|
||||
|
||||
// V10 ③ — every console error/warning and uncaught exception seen during the run above.
|
||||
console.log(`CONSOLE_EVENTS ${consoleEvents.length}`);
|
||||
for (const e of consoleEvents) console.log(` ${e}`);
|
||||
ws.close();
|
||||
}
|
||||
|
||||
main().catch((e) => {
|
||||
console.error('FAILED', e);
|
||||
process.exit(1);
|
||||
});
|
||||
+1
-21
@@ -3214,16 +3214,8 @@ function applyImport(): void {
|
||||
setStatus(`${state.piers.length}기 형상을 생성했습니다. 정보·경고는 오른쪽 알림에서 확인하세요.`);
|
||||
}
|
||||
|
||||
function openImport(): void {
|
||||
const landing = document.querySelector<HTMLDivElement>('.landing-overlay');
|
||||
if (landing && !landing.hidden) return;
|
||||
const dlg = $<HTMLDialogElement>('import-dialog');
|
||||
if (!dlg.open) dlg.showModal();
|
||||
$<HTMLInputElement>('project-name').focus();
|
||||
}
|
||||
|
||||
async function fetchSample(): Promise<Uint8Array> {
|
||||
const res = await fetch(new URL('samples/운곡교P1입력.xlsx', document.baseURI));
|
||||
const res = await fetch(new URL('../도면추출/samples/운곡교P1입력.xlsx', import.meta.url));
|
||||
if (!res.ok) throw new Error(`샘플 응답 ${res.status}`);
|
||||
return new Uint8Array(await res.arrayBuffer());
|
||||
}
|
||||
@@ -3232,7 +3224,6 @@ declare global {
|
||||
interface Window {
|
||||
loadBytesToApp?: (bytes: Uint8Array, fileName: string) => void;
|
||||
openSampleProject?: () => Promise<void>;
|
||||
openDrawingFlow?: () => void;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3254,16 +3245,6 @@ window.openSampleProject = async () => {
|
||||
setError(error instanceof Error ? error.message : '샘플 교량 모델을 불러오지 못했습니다.');
|
||||
}
|
||||
};
|
||||
window.openDrawingFlow = () => {
|
||||
const app = document.querySelector<HTMLElement>('.app');
|
||||
const landing = document.querySelector<HTMLDivElement>('.landing-overlay');
|
||||
if (app) {
|
||||
app.hidden = false;
|
||||
app.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
if (landing) landing.hidden = true;
|
||||
setStatus('도면 입력은 현재 개발 중입니다. 기존 도면 분석 모듈과 연결되기 전까지는 파일 선택 흐름만 유지합니다.');
|
||||
};
|
||||
|
||||
/** Piers that need a (re)build: never generated, or with changes not yet in the 3D model. */
|
||||
function generationTargets(): Pier[] {
|
||||
@@ -3285,7 +3266,6 @@ function regenerateChanged(): void {
|
||||
}
|
||||
|
||||
// --- events -----------------------------------------------------------------------------
|
||||
$<HTMLButtonElement>('open-import').addEventListener('click', openImport);
|
||||
$<HTMLButtonElement>('dlg-close').addEventListener('click', () => {
|
||||
$<HTMLDialogElement>('import-dialog').close();
|
||||
document.querySelector<HTMLElement>('.landing-overlay')?.classList.remove('modal-open');
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
import { EventEmitter } from 'node:events';
|
||||
import { PassThrough, Readable } from 'node:stream';
|
||||
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
||||
import type { ChildProcess } from 'node:child_process';
|
||||
import type { IncomingMessage, ServerResponse } from 'node:http';
|
||||
import path from 'node:path';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
import { DRAWING_API_PATH, drawingLauncherPlugin } from '../랜딩페이지/drawing-launcher';
|
||||
|
||||
class Worker extends EventEmitter {
|
||||
stdout = new PassThrough(); stderr = new PassThrough(); kill = vi.fn();
|
||||
send(value: object) { this.stdout.write(JSON.stringify(value) + '\n'); }
|
||||
}
|
||||
const base = path.resolve('.verify');
|
||||
const roots: string[] = [];
|
||||
function fixture(options: { missing?: boolean; fail?: boolean; platform?: NodeJS.Platform } = {}) {
|
||||
mkdirSync(base, { recursive: true });
|
||||
const root = mkdtempSync(path.join(base, 'drawing-api-')); roots.push(root);
|
||||
const folder = path.join(root, 'DWG & 도면'); mkdirSync(folder);
|
||||
const workers: Worker[] = [];
|
||||
const start = vi.fn((_file: string, args: string[]) => {
|
||||
const worker = new Worker(); workers.push(worker);
|
||||
queueMicrotask(() => {
|
||||
if (options.fail) worker.emit('error', new Error('worker unavailable'));
|
||||
else if (args[2] === 'choose') { worker.send({ type: 'folder', folder }); worker.emit('close', 0); }
|
||||
});
|
||||
return worker as unknown as ChildProcess;
|
||||
});
|
||||
const plugin = drawingLauncherPlugin(root, {
|
||||
platform: options.platform ?? 'win32', start,
|
||||
exists: file => options.missing ? false : file.endsWith('python.exe') || file.endsWith('drawing-worker.py') || existsSync(file),
|
||||
});
|
||||
let handle!: (req: IncomingMessage, res: ServerResponse, next: () => void) => void;
|
||||
(plugin.configureServer as Function)({ middlewares: { use(fn: typeof handle) { handle = fn; } } });
|
||||
const request = (action: string, body: object = {}, overrides: { method?: string; origin?: string; action?: string; address?: string; host?: string; raw?: string } = {}) => new Promise<{ status: number; body: any; bytes?: Buffer }>(resolve => {
|
||||
const req = Readable.from([overrides.raw ?? JSON.stringify(body)]) as unknown as IncomingMessage;
|
||||
Object.assign(req, { url: `${DRAWING_API_PATH}/${action}`, method: overrides.method ?? 'POST', headers: {
|
||||
host: overrides.host ?? '127.0.0.1:5173', origin: overrides.origin ?? 'http://127.0.0.1:5173', 'x-pierzainer-action': overrides.action ?? 'drawing-extractor',
|
||||
}, socket: { remoteAddress: overrides.address ?? '127.0.0.1' } });
|
||||
let status = 0, json = true, sent = false;
|
||||
const res = { get headersSent() { return sent; }, writeHead(code: number, headers: Record<string, string>) { status = code; json = headers['Content-Type'].includes('application/json'); sent = true; },
|
||||
end(text: string | Buffer) { resolve(json ? { status, body: JSON.parse(String(text)) } : { status, body: null, bytes: Buffer.from(text) }); } } as unknown as ServerResponse;
|
||||
handle(req, res, () => resolve({ status: 404, body: {} }));
|
||||
});
|
||||
const finish = (outside = false) => {
|
||||
const args = start.mock.calls[start.mock.calls.length - 1][1];
|
||||
const output = args[args.indexOf('--output')+1];
|
||||
const file = path.join(outside ? root : output, '결과.xlsx'); writeFileSync(file, 'test-workbook');
|
||||
const worker = workers[workers.length-1]; worker.send({ type: 'log', message: '도면 판독 완료' });
|
||||
worker.send({ type: 'result', result: { status: 'needs_review', output_dir: output, review_count: 2, failed_file_count: 0,
|
||||
workbooks: [{ name: '테스트 교량', xlsx_path: file, review_count: 2 }] } });
|
||||
worker.emit('close', 0);
|
||||
return file;
|
||||
};
|
||||
return { root, folder, request, start, workers, finish };
|
||||
}
|
||||
afterEach(() => {
|
||||
for (const root of roots.splice(0)) {
|
||||
if (!root.startsWith(base + path.sep)) throw new Error('Unsafe test fixture path');
|
||||
rmSync(root, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
describe('in-app drawing extraction API', () => {
|
||||
it('only accepts local same-origin POST requests with the application header', async () => {
|
||||
const f = fixture();
|
||||
expect((await f.request('start', {}, { method: 'GET' })).status).toBe(405);
|
||||
for (const headers of [{ origin: 'https://other.example' }, { action: '' }, { address: '192.168.0.2' }, { host: 'other.example' }])
|
||||
expect((await f.request('start', {}, headers)).status).toBe(403);
|
||||
expect(f.start).not.toHaveBeenCalled();
|
||||
});
|
||||
it('returns folder selection without starting the standalone GUI', async () => {
|
||||
const f = fixture(); expect((await f.request('choose-folder')).body.folder).toBe(f.folder);
|
||||
expect(f.start.mock.calls[0][1][2]).toBe('choose');
|
||||
expect(f.start.mock.calls[0][1].join(' ')).not.toContain('desktop_app.py');
|
||||
expect((await f.request('status')).body.job).toBeNull();
|
||||
});
|
||||
it('tracks progress, preserves review warnings, and serves only its generated workbook', async () => {
|
||||
const f = fixture(); const response = await f.request('start', { folder: f.folder });
|
||||
expect(response.status).toBe(202); const jobId = response.body.job.id;
|
||||
expect(f.start.mock.calls[0][1][3]).toBe(f.folder);
|
||||
expect((await f.request('workbook', { jobId, index: 0 })).status).toBe(400);
|
||||
const file = f.finish();
|
||||
const state = (await f.request('status', { jobId })).body.job;
|
||||
expect(state.status).toBe('needs_review'); expect(state.logs).toContain('도면 판독 완료');
|
||||
expect(state.result.reviewCount).toBe(2);
|
||||
const download = await f.request('workbook', { jobId, index: 0, path: 'unrelated.txt' });
|
||||
expect(download.status).toBe(200); expect(download.bytes).toEqual(readFileSync(file));
|
||||
expect((await f.request('workbook', { jobId, index: -1 })).status).toBe(400);
|
||||
expect((await f.request('workbook', { jobId, index: 20 })).status).toBe(404);
|
||||
});
|
||||
it('does not run two extraction jobs concurrently', async () => {
|
||||
const f = fixture(); const states = await Promise.all([f.request('start', { folder: f.folder }), f.request('start', { folder: f.folder })]);
|
||||
expect(states.map(s => s.status).sort()).toEqual([202, 409]); expect(f.start).toHaveBeenCalledTimes(1); f.finish();
|
||||
});
|
||||
it('refuses files outside the controlled output even if a worker lists them', async () => {
|
||||
const f = fixture(); const { body } = await f.request('start', { folder: f.folder }); f.finish(true);
|
||||
expect((await f.request('workbook', { jobId: body.job.id, index: 0 })).status).toBe(403);
|
||||
});
|
||||
it('reports worker failures so the popup can retry', async () => {
|
||||
const f = fixture({ fail: true }); const { body } = await f.request('start', { folder: f.folder });
|
||||
const job = (await f.request('status', { jobId: body.job.id })).body.job;
|
||||
expect(job.status).toBe('error'); expect(job.error).toContain('worker unavailable');
|
||||
});
|
||||
it('validates folders, JSON, and request size before starting a worker', async () => {
|
||||
const f = fixture();
|
||||
expect((await f.request('start', { folder: 'missing-folder' })).status).toBe(400);
|
||||
expect((await f.request('start', {}, { raw: 'bad-json' })).status).toBe(400);
|
||||
expect((await f.request('start', {}, { raw: 'a'.repeat(8193) })).status).toBe(413);
|
||||
expect(f.start).not.toHaveBeenCalled();
|
||||
expect((await fixture({ missing: true }).request('status')).status).toBe(503);
|
||||
expect((await fixture({ platform: 'linux' }).request('status')).status).toBe(501);
|
||||
});
|
||||
});
|
||||
+2
-2
@@ -5,9 +5,9 @@ import { parseWorkbook } from '../src/core/parseWorkbook';
|
||||
import type { PierInput } from '../src/core/types';
|
||||
|
||||
/** Spec workbook (RAG/Pier ui_xxx.xlsx, sheet intent.PR, all tables on one sheet). Used by single-sheet tests. */
|
||||
const SPEC_PATH = fileURLToPath(new URL('../public/samples/P1.xlsx', import.meta.url));
|
||||
const SPEC_PATH = fileURLToPath(new URL('../도면추출/samples/P1.xlsx', import.meta.url));
|
||||
/** User input (RAG/운곡교P1입력.xlsx, three sheets 교각 · IP · 받침). This is the P1 input used by the app and tests. */
|
||||
const INPUT_PATH = fileURLToPath(new URL('../public/samples/운곡교P1입력.xlsx', import.meta.url));
|
||||
const INPUT_PATH = fileURLToPath(new URL('../도면추출/samples/운곡교P1입력.xlsx', import.meta.url));
|
||||
|
||||
export function loadWorkbook(path: string = SPEC_PATH): XLSX.WorkBook {
|
||||
return XLSX.read(readFileSync(path), { type: 'buffer' });
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { buildPier } from '../src/core/geometry';
|
||||
import { loadP1 } from './helpers';
|
||||
|
||||
/**
|
||||
* Regression against spec.md §12 (P1, 운곡교, T형, 말뚝기초).
|
||||
* Coordinates and EL: ±1 mm (0.001 m). Angles: ±0.01°.
|
||||
*/
|
||||
const TOL = 0.001;
|
||||
const model = buildPier(loadP1());
|
||||
|
||||
describe('P1 regression — spec.md §12', () => {
|
||||
it('axis length and azimuth', () => {
|
||||
expect(model.lengthIp).toBeCloseTo(12.166, 3);
|
||||
expect(model.azimuthDeg).toBeCloseTo(350.37, 2);
|
||||
});
|
||||
|
||||
it('BP1, BP2 coordinates (국토좌표 E, N)', () => {
|
||||
expect(model.bp1.e).toBeCloseTo(259866.681, 2);
|
||||
expect(model.bp1.n).toBeCloseTo(179132.173, 2);
|
||||
expect(Math.abs(model.bp2.e - 259864.674)).toBeLessThan(TOL);
|
||||
expect(Math.abs(model.bp2.n - 179144.004)).toBeLessThan(TOL);
|
||||
});
|
||||
|
||||
it('IP2 reference recalculation and d_IP2', () => {
|
||||
expect(Math.abs(model.dIp2 - 1.134)).toBeLessThan(TOL);
|
||||
});
|
||||
|
||||
it('column centre coordinates', () => {
|
||||
expect(Math.abs(model.pivot.e - 259865.677)).toBeLessThan(TOL);
|
||||
expect(Math.abs(model.pivot.n - 179138.089)).toBeLessThan(TOL);
|
||||
});
|
||||
|
||||
it('bearing positions: front row across-axis −0.698, back row +0.600; front s from 0.943 to 10.965', () => {
|
||||
const front = model.bearings.filter((b) => b.row === '전열');
|
||||
const back = model.bearings.filter((b) => b.row === '후열');
|
||||
expect(front[0].n).toBeCloseTo(-0.698, 3);
|
||||
expect(back[0].n).toBeCloseTo(0.6, 3);
|
||||
expect(front[0].s).toBeCloseTo(0.943, 3);
|
||||
expect(front[4].s).toBeCloseTo(10.965, 3);
|
||||
expect(back[0].s).toBeCloseTo(1.029, 3);
|
||||
expect(back[4].s).toBeCloseTo(11.05, 3);
|
||||
});
|
||||
|
||||
it('step boundaries at the midpoints of front bearings: 2.196 / 4.701 / 7.207 / 9.712', () => {
|
||||
const bounds = model.segments.slice(1).map((s) => s.s0);
|
||||
[2.196, 4.701, 7.207, 9.712].forEach((b, i) => expect(Math.abs(bounds[i] - b)).toBeLessThan(TOL));
|
||||
});
|
||||
|
||||
it('front segment tops: 43.411 / 43.483 / 43.555 / 43.626 / 43.698', () => {
|
||||
const tops = model.segments.map((s) => s.top);
|
||||
[43.411, 43.483, 43.555, 43.626, 43.698].forEach((t, i) => expect(Math.abs(tops[i] - t)).toBeLessThan(TOL));
|
||||
});
|
||||
|
||||
it('bearing block heights: h1 = 150, h2 = 200 mm; concrete 100 / 150 mm', () => {
|
||||
expect(model.h1).toBeCloseTo(0.15, 6);
|
||||
expect(model.h2).toBeCloseTo(0.2, 6);
|
||||
expect(model.derived.blockHeightFront).toBeCloseTo(0.1, 6);
|
||||
expect(model.derived.blockHeightBack).toBeCloseTo(0.15, 6);
|
||||
});
|
||||
|
||||
it('no lateral step (front and back tops agree)', () => {
|
||||
expect(model.derived.frontBackDiffSpread).toBeLessThan(0.0051);
|
||||
});
|
||||
|
||||
it('coping bottom: 42.411 at the ends, 40.911 at the Level zone', () => {
|
||||
expect(Math.abs(model.endBottom - 42.411)).toBeLessThan(TOL);
|
||||
expect(Math.abs(model.levelBottom - 40.911)).toBeLessThan(TOL);
|
||||
});
|
||||
|
||||
it('column height 12.703 m and footing top 28.208 m, soil cover 0.723 m', () => {
|
||||
expect(Math.abs(model.derived.columnHeight - 12.703)).toBeLessThan(TOL);
|
||||
expect(Math.abs(model.footings[0].top - 28.208)).toBeLessThan(TOL);
|
||||
expect(Math.abs(model.derived.soilCover - 0.723)).toBeLessThan(TOL);
|
||||
});
|
||||
|
||||
it('piles: 4 rows × 5 = 20, spacing 2250 mm, tip at 2.208 m', () => {
|
||||
expect(model.piles).toHaveLength(20);
|
||||
expect(model.derived.pileCount).toBe(20);
|
||||
expect(Math.abs((model.derived.pileTipEl ?? NaN) - 2.208)).toBeLessThan(TOL);
|
||||
const sValues = [...new Set(model.piles.map((p) => p.s.toFixed(4)))];
|
||||
const nValues = [...new Set(model.piles.map((p) => p.n.toFixed(4)))];
|
||||
expect(sValues).toHaveLength(5);
|
||||
expect(nValues).toHaveLength(4);
|
||||
expect(Number(nValues[1]) - Number(nValues[0])).toBeCloseTo(2.25, 4);
|
||||
expect(Number(sValues[1]) - Number(sValues[0])).toBeCloseTo(2.25, 4);
|
||||
});
|
||||
|
||||
it('blinding concrete 10600 × 8350 × 100 under the footing', () => {
|
||||
const b = model.blindings[0];
|
||||
expect(b.length).toBeCloseTo(10.6, 4);
|
||||
expect(b.width).toBeCloseTo(8.35, 4);
|
||||
expect(b.thickness).toBeCloseTo(0.1, 4);
|
||||
});
|
||||
|
||||
it('footing 10400 × 8150 × 2000 mm', () => {
|
||||
const f = model.footings[0];
|
||||
expect(f.length).toBeCloseTo(10.4, 4);
|
||||
expect(f.width).toBeCloseTo(8.15, 4);
|
||||
expect(f.top - f.bottom).toBeCloseTo(2.0, 4);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pile layout text (spec §12, §6.8 display)', () => {
|
||||
it('reads 4@2250 × 3@2250 = 20본', () => {
|
||||
expect(model.derived.pileLayout).toBe('4@2250 × 3@2250 = 20본');
|
||||
});
|
||||
});
|
||||
@@ -4,9 +4,9 @@ import { fileURLToPath } from 'node:url';
|
||||
import { parseWorkbook } from '../src/core/parseWorkbook';
|
||||
import { loadWorkbook } from './helpers';
|
||||
|
||||
// The standing input is RAG/운곡교P1입력.xlsx. The app serves a copy in public/samples; the two must stay identical.
|
||||
// The standing input is RAG/운곡교P1입력.xlsx. The app uses the copy in 도면추출/samples.
|
||||
const RAG_INPUT = fileURLToPath(new URL('../../../RAG/운곡교P1입력.xlsx', import.meta.url));
|
||||
const APP_COPY = fileURLToPath(new URL('../public/samples/운곡교P1입력.xlsx', import.meta.url));
|
||||
const APP_COPY = fileURLToPath(new URL('../도면추출/samples/운곡교P1입력.xlsx', import.meta.url));
|
||||
|
||||
describe('표준 입력 파일 (운곡교P1입력.xlsx)', () => {
|
||||
it('the app sample is byte-identical to RAG/운곡교P1입력.xlsx', () => {
|
||||
|
||||
+2
-1
@@ -6,9 +6,10 @@
|
||||
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
"skipLibCheck": true,
|
||||
"isolatedModules": true,
|
||||
"types": ["node"]
|
||||
},
|
||||
"include": ["src", "tests"]
|
||||
"include": ["src", "tests", "랜딩페이지", "vite.config.ts"]
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 87 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 79 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 79 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 84 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 94 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 87 KiB |
@@ -0,0 +1,7 @@
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { defineConfig } from 'vite';
|
||||
import { drawingLauncherPlugin } from './랜딩페이지/drawing-launcher.ts';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [drawingLauncherPlugin(fileURLToPath(new URL('.', import.meta.url)))],
|
||||
});
|
||||
@@ -7,11 +7,11 @@ Windows용 오프라인 DWG → 교각 입력 엑셀 추출기입니다. 이 폴
|
||||
|실행.bat|폴더 선택 화면 실행|
|
||||
|run_extract.bat|다른 프로그램에서 호출할 명령행 진입점|
|
||||
|app|프로그램 소스, DWG 변환기, Python 및 엑셀 라이브러리|
|
||||
|samples|교량별 최종 엑셀 12개. 각 파일에 Pier/IP/Bearing 탭 3개|
|
||||
|samples|교량별 최종 엑셀 12개와 기본 샘플 `운곡교P1입력.xlsx`, 단일 시트 검증 자료 `P1.xlsx`|
|
||||
|integration/bridge_extract.py|Python 연동 함수 및 JSON 출력 CLI|
|
||||
|integration/*.whl|Python 설치형 패키지 0.1.9|
|
||||
|integration/sample_data|최종 샘플과 대응하는 JSON·검토 CSV|
|
||||
|history|샘플 보정 내역, 이전 검증 결과, 재현 스크립트와 개발 안내|
|
||||
|history|샘플 보정 내역, 이전 검증 결과와 출처 기록|
|
||||
|
||||
## 화면에서 실행
|
||||
|
||||
@@ -31,7 +31,7 @@ Python 프로그램에 직접 연결할 수도 있습니다.
|
||||
|
||||
```python
|
||||
import sys
|
||||
sys.path.insert(0, r"C:\배포\도면추출_연동패키지_20261102")
|
||||
sys.path.insert(0, r"C:\배포\도면추출")
|
||||
from integration.bridge_extract import extract_folder
|
||||
|
||||
result = extract_folder(r"C:\도면\교량폴더", output_dir=r"C:\결과")
|
||||
@@ -58,6 +58,6 @@ for book in result.workbooks:
|
||||
|
||||
64교각·652받침, IP4공란·치수산식·엑셀/JSON6484셀 대조를 확인했습니다. 승천천교 방위각12개는 원문과 샘플에 값이 없어 미확인입니다. 기양천교 상충EL 등 이번에 샘플값을 채택한 항목은 history의 보정내역을 확인합니다.
|
||||
|
||||
새로운 DWG에 대해서는 미확정 또는 검토필요 값이 나올 수 있습니다. 이미지 PDF OCR, 임의의 기둥 형상 자동 판독, 복잡한 지시선 및 모든 측점 보간은 완성되지 않았습니다. 셀 상태와 근거를 함께 확인합니다. `history/tools`와 `history/tests`는 기존 작업폴더 기준의 이력용 코드이며 실행 진입점은 위의 두 가지입니다.
|
||||
새로운 DWG에 대해서는 미확정 또는 검토필요 값이 나올 수 있습니다. 이미지 PDF OCR, 임의의 기둥 형상 자동 판독, 복잡한 지시선 및 모든 측점 보간은 완성되지 않았습니다. 셀 상태와 근거를 함께 확인합니다. 과거 작업폴더에 의존하던 개발·검증 스크립트는 정리했으며 실행 진입점은 위의 두 가지입니다.
|
||||
|
||||
포함된 Python·openpyxl·LibreDWG 등 제3자 구성요소의 라이선스 및 안내 파일은 app/runtime 및 app/Code/giyang_extract/libredwg 하위에 보존했습니다.
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 2476 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user