Files
s-canvas/S-CANVAS_brief.md
HYUNJUNGLEE b9342f6726 Import S-CANVAS source + iter=1~7 lint cleanup
S-CANVAS (Saman Corp.) — DXF + DEM + AI 기반 3D 조감도 생성 엔진.
~24k LOC Python (scanvas_maker.py 7072 LOC GUI + 구조물 파서/빌더 다수).

이 커밋은 7-iter cleanup이 적용된 상태로 import:
- F821 8 + B023 6: 비동기 lambda + except/loop 변수 캡처 NameError
  (Py3.13에서 reproduce 확인된 진짜 버그)
- RUF012 4 + RUF013 1: ClassVar / implicit Optional 명시화
- F811/B905/B904/F401/F841/W293/F541/UP/SIM/RUF/PLR 700+ cleanup/modernization

신규 파일:
- ruff.toml: target=py313, Korean unicode/저자 스타일/도메인 복잡도 무력화
- requirements-py313.txt: pyproj>=3.7, scipy>=1.14, numpy>=2.0.2 (Py3.13 wheel)
- .gitignore: gcp-key.json, 캐시, 백업, 생성 이미지 제외

검증: ruff 0 errors, py_compile 0 errors, import 33/33 OK on Py3.13.13.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 10:29:08 +09:00

31 KiB
Raw Blame History

S-CANVAS — 프로그램 핵심 소개 (NotebookLM 발표자료 소스)

목적: 본 문서는 NotebookLM 에 업로드하여 발표 슬라이드, Audio Overview, 마인드맵 등을 자동 생성하기 위한 단일 소스 텍스트 입니다. S-CANVAS 프로그램의 정체성·아키텍처·핵심 기술·워크플로·차별화 포인트를 한 파일에 응축했습니다.


1. 한 줄 요약

S-CANVASGenerative Design & Visualization Engine. CAD 도면(DXF)과 실제 공개 DEM·위성영상·Generative AI 를 결합해 건설/토목 프로젝트의 3D 조감도와 구조물 시각화를 자동 생성하는 데스크톱 엔진. Saman Corp. 자체 개발.

  • 원래 명칭: EG-VIEW (AI 기반 조감도 생성 시스템)
  • 2026-04-24 리브랜딩: S-CANVAS (Generative Design & Visualization Engine)
  • 메인 진입점: scanvas_maker.py
  • 플랫폼: Windows 10/11, Python + CustomTkinter GUI

2. 배경 & 문제 정의

2.1 기존 토목·건설 시각화의 한계

전통적인 CAD 평면도는 2D이며, 등고선·구조물 윤곽만 담겨 있어 실제 지형 맥락(주변 산세, 강, 식생, 도로망)이 빠져 있다. 발주처 보고·주민 설명회에서는 "실제 어떻게 보이는가" 가 중요하지만, 기존 워크플로에서는:

  1. CAD 도면을 3D 모델러(Civil 3D/Revit/Rhino) 로 다시 그리고
  2. GIS 데이터를 별도로 받아 좌표 정합
  3. 위성영상을 매핑하고
  4. 렌더 엔진(Lumion/Twinmotion/V-Ray) 으로 조명·재질·하늘 설정
  5. 카메라 앵글 잡고 이미지 출력

이 과정이 수일에서 수주 걸리며, 변경이 생길 때마다 대부분의 단계를 다시 수행해야 한다.

2.2 S-CANVAS 의 가설

"DXF 등고선·구조물 레이어 + 공개 DEM + 위성타일 + Generative AI 만으로, 클릭 4번에 사실 기반 3D 조감도를 만들 수 있다."

  • DXF 의 등고선 → TIN(Triangulated Irregular Network) 자동 생성
  • DXF 범위 밖 지형 → AWS Open Terrain Tiles(글로벌 DEM) 자동 채움
  • 표면 텍스처 → Google/ArcGIS/Vworld 위성 타일을 UV 매핑
  • 최종 사실감 향상 → Gemini/Stability AI 가 구조 보존 모드로 재렌더

2.3 핵심 가치 제안 (Value Proposition)

기존 S-CANVAS
모델링 수일 TIN 생성 30초
외부 라이선스 GIS 공개 DEM 자동 페치
수동 좌표 정합 4점 매칭 자동 GeoRef
렌더 1회 수시간 AI 렌더 1분 이내
변경 → 재모델링 변경 → 재실행 (캐시 재활용)

3. 시스템 아키텍처

3.1 모듈 구성 (Top Level)

scanvas_maker.py            # 메인 GUI 엔트리 (~6300 LOC, CustomTkinter)
├── splash.py               # 인트로 MP4 스플래시 (cv2 + Tk Toplevel)
├── dem_extender.py         # AWS Terrarium DEM 페치 + 도넛 링 메시
├── geo_referencing.py      # 4점 매칭 GeoReferencing 워크플로
├── structure_placement.py  # 구조물 위치/방향 자동 인식 + TIN 굴착
├── structure_templates.py  # 구조물 유형 레지스트리 (Registry 패턴)
├── intake_tower_3d_builder.py    # 취수탑 3D
├── intake_tower_parser.py        # 취수탑 DXF 치수 파싱
├── retaining_wall_3d_builder.py  # 옹벽 3D
├── retaining_wall_parser.py
├── gate_3d_builder.py            # 수문 3D
├── gate_parser.py
├── valve_chamber_3d_builder.py   # 제수변실 3D
├── valve_chamber_parser.py
├── detail_parser.py        # 상세도면 DXF 치수 파서 (TEXT/MTEXT/DIMENSION)
├── filename_classifier.py  # 파일명 → 구조물 유형 추정
├── polygon_reconstructor.py
├── dxf_geometry.py         # DXF 엔티티 → 좌표
├── tile_downloader.py      # 위성 XYZ 타일 다운로드
├── view_detector.py / view_reconstructor.py  # 도면 뷰 영역 인식
├── optional_detector.py
├── gemini_renderer.py      # Gemini API/Vertex AI 렌더링 워커
├── structure_vlm_feedback.py  # Gemini Vision 으로 구조물 결과 검증
├── egview_maker.py 의 후신:    # (이전 명칭, 현재 scanvas_maker.py 로 통합/리네임)
│
└── harness/                # 품질·재현성·이력 서브시스템
    ├── seed_manager.py     # DXF 해시 기반 결정론적 seed
    ├── quality_validator.py # OpenCV 기반 이미지 자동 QA
    ├── prompt_registry.py  # 프롬프트 버전 관리 (YAML)
    └── logger.py           # SQLite ORM (JobRecord) + structlog

prompt_templates/prompt_v1.yaml      # 렌더 프롬프트 (시간대/앙각/구조보존)
structure_types/structure_v1.yaml    # 구조물 유형 정의

Design/                              # 브랜딩 자산
├── logo_V2.png              # 로고 (다크 bg → 런타임 스트립)
├── Logo.png                 # 이전 로고 (투명 bg)
├── SAMAN_CI.gif             # Saman Corp 크레딧
├── logo_intro.mp4           # 인트로 스플래시 (8s, 24fps, 1280×720)
├── homepage_sample.png      # UI 디자인 레퍼런스
└── page_sample.png

cache/dem/                   # AWS Terrarium 타일 캐시
scanvas_jobs.db              # SQLite 작업 이력 (Harness)
scanvas_harness.log          # structlog 출력
scanvas_diagnostic.log       # Step 1 진단 로그

3.2 데이터 흐름 (Pipeline)

[DXF 도면] → [레이어 분류] → [등고선/구조물 분리]
                                  ↓
[GeoRef 4점 매칭] → [투영 CRS 결정 (EPSG:5187 등)]
                                  ↓
[TIN 생성 (Delaunay)] → [TIN core 정밀 영역 지정 (선택)]
                                  ↓
[DEM 자동 페치 (AWS Terrarium)] → [도넛 링 메시] → [smoothstep blend]
                                  ↓
[seam-free 통합 메시 (merge_points + compute_normals)]
                                  ↓
[위성 타일 다운로드] → [UV 매핑 (texture_map_to_plane)]
                                  ↓
[3D 미리보기 (PyVista)] → [카메라 앵글 캡처] → [제어맵]
                                  ↓
[Gemini/Stability AI 렌더링 (구조 보존 모드)]
                                  ↓
[QualityValidator 자동 검증] → [scanvas_jobs.db 이력 기록]
                                  ↓
[고해상도 PNG 출력]

3.3 외부 의존성

Python 라이브러리 (주요):

  • customtkinter — 모던 Tk GUI 프레임워크
  • tkintermapview — 위성지도 뷰
  • ezdxf — DXF 파싱
  • numpy, scipy — 수치 연산, Delaunay
  • pyvista + vtk — 3D 메시 렌더링
  • pyproj — 좌표계 변환
  • Pillow (PIL) — 이미지 처리
  • opencv-python (cv2) — 비디오 / 이미지 검증
  • requests — HTTP 타일 페치
  • google-genai — Gemini SDK (Vertex AI 또는 API Key)
  • sqlalchemy + structlog — 이력 추적
  • PyYAML — 프롬프트/구조물 정의

외부 데이터 소스:

  • AWS Open Terrain Tiles (s3.amazonaws.com/elevation-tiles-prod/terrarium) — 글로벌 DEM, ~30m 정확도, API 키 불필요
  • Google Satellite / ArcGIS World Imagery / Bing Aerial / Vworld — 위성 타일 (사용자 선택)
  • Google Vertex AI / Gemini API — 생성형 렌더링
  • (옵션) Stability AI API — img2img 폴백

4. 핵심 워크플로 (Step-by-Step)

Step 0 — DXF 로드 & 레이어 분류

DXF 를 열면 자동으로 레이어를 분석해 구조물 유형(취수탑/제수변실/옹벽/수문/ 지형 등고선/도로/하천 등)을 추정. filename_classifier.py 가 파일명 패턴(예: "신설 취수탑.dxf") 으로 1차 후보를 제시하고, 사용자가 GUI 다이얼로그에서 최종 확정. 결과는 structure_v1.yaml 의 정의에 따라 빌더로 라우팅.

Step 1 — TIN 생성 (DXF)

지형 레이어의 등고선 점·LINE/LWPOLYLINE 정점을 추출 → Delaunay 삼각화 → zero-basing (원점을 도면 bbox 좌하단으로 평행이동, 부동소수점 정밀도 보존) → PyVista PolyData 메시 생성.

핵심 디테일:

  • 단위 자동 감지 → KATEC 좌표(EPSG:5187 등) 는 항상 m 로 강제 (unit_override="m")
  • DEM datum offset 사전 계산 → 이후 단계에서 공통 offset 재사용으로 seam Z 단차 0 보장
  • DEM 격자도 사전 페치 → _dem_elev_grid / _dem_grid_bounds 로 캐시

Step 1.5 — DEM 으로 TIN 확장

DXF 범위 밖이 절벽처럼 잘리는 문제 해결. AWS Terrarium 에서 외곽 도넛 링을 받아 TIN 과 이어 붙임.

3-Zone 구조 (메모리화된 핵심 결정):

  1. Core (tin_core_bbox 안): 원본 TIN 100% 보존. 사용자가 정밀 영역으로 지정.
  2. Transition (core ~ bbox, blend_width_m): smoothstep 3t² 2t³ 으로 TIN ↔ DEM Z 부드럽게 블렌드.
  3. DEM 외곽 링: AWS DEM 으로 채움.

Seam 처리 (다층 방어):

  • 수직 datum 보정: TIN 경계 근처 점들의 (TIN Z DEM Z) 중앙값을 offset 으로 차감
  • 공유 정점 weld: TIN bbox 변 정점을 DEM 링 inner 경계로 강제 → 동일 XY 공유
  • smoothstep feather: 경계 0 = TIN, feather_m = DEM 으로 C¹ 연속
  • 벽 컷 (slope_ratio 기반): slope_ratio = z_span / max_edge 가 4.0 (≈76°) 초과 + Z스팬 30m + max_edge 5m 충족 시 "벽 삼각형" 으로 컷. 절대 Z 컷은 절대 사용하지 않음 (구멍이 뚫림 — 메모리화된 교훈)
  • 링 Laplacian 1pass: 톱니 fin 마지막 평활. 경계 정점은 pin

Step 2 — 위성지도 결합 (Draping)

선택한 타일 서버에서 확장된 bbox 전체의 위성 이미지 다운로드 → 단일 큰 이미지로 합성 → texture_map_to_plane 으로 UV 매핑 → 텍스처 입힌 3D 메시.

Seam-free 통합 렌더링 (2026-04-24 후속 수정):

  • 이전: tin_meshtin_extension_mesh 가 두 개의 별도 PolyData → 경계에서 쉐이딩 불연속 (사각 선이 보이는 증상)
  • 수정: merge(merge_points=True, tolerance=0.01) 로 공유 정점 weld → 위상적 단일 표면. compute_normals(feature_angle=180) 로 모든 edge smooth → seam 법선 평활. UV 좌표는 _uv_mapping_params 저장 후 merge 후 재적용.

Step 3 — 제어맵 추출

PyVista 카메라 앵글로 오프스크린 캡처:

  • capture_textured.png — 위성+DEM 합성된 control map
  • capture_depth.png — 깊이 맵 (Eye-Dome Lighting 활성화)

이 2개 이미지가 Step 4 의 AI 렌더 입력.

Step 4 — AI 렌더링 (구조 보존 모드)

prompt_templates/prompt_v1.yaml 기반으로 프롬프트 구성:

  • 시간대 프리셋: daytime / sunset / night / dawn / overcast
  • 앙각 프리셋: top_down / high_angle / oblique / low_angle
  • 구조 보존 지시: "maintain exact terrain shape, contours, and layout from the input image"
  • 품질 향상: "8K ultra sharp detail, professional drone photography quality"
  • 네거티브: "blurry, distorted, watermark, changed terrain layout, moved structures..."

렌더 엔진 3종:

  1. Gemini (Vertex AI) — google-genai SDK, GCP 인증
  2. Gemini (API Key) — google-genai SDK, AI Studio 키
  3. Stability AI (API) — 3단계 폴백:
    1. Conservative Upscale (원본 보존 최우선)
    2. Creative Upscale (조금 더 창의적)
    3. img2img 초저강도 (strength=0.2)

각 렌더 호출은 Harness 가 결정론적 seed + prompt 버전 + 품질 점수를 자동 기록 → 동일 입력에 동일 출력 보장.


5. 핵심 기술 컴포넌트 / 혁신 포인트

5.1 DEM 자동 통합 (dem_extender.py)

  • AWS Open Terrain Tiles terrarium PNG 디코딩: elev_m = (R*256 + G + B/256) - 32768
  • 좌표계 변환: 투영 CRS(예: EPSG:5187) → WGS84 → 타일 좌표 (Web Mercator z/x/y)
  • 캐시: SHA1(bbox+zoom) 으로 PNG 캐시 → 재실행 시 네트워크 0
  • 로컬 GeoTIFF 우선: cache/dem/local.tif 가 있으면 NGII 5m DEM 등 고정밀 데이터 우선 사용 (rasterio 필요)

5.2 Seam-free 메시 통합 (Render-fix 2026-04-24)

원래 메모리: "벽 이슈는 create_tin_from_dxf 부터 점검. 판정은 slope_ratio 만, 절대 Z 컷은 구멍 낸다."

문제: TIN+DEM 을 두 개 별도 PolyData 로 add_mesh 하면 normal 평균이 메시 경계를 못 넘어 사각 쉐이딩 선이 보임.

해결 (1순위 + 2순위 동시):

merged = target.merge(ext_mesh, merge_points=True, tolerance=0.01)
if not isinstance(merged, pv.PolyData):
    merged = merged.extract_surface()
# 텍스처 모드: UV 재적용 (TCoords 가 merge 에서 소실되므로)
if textured and uv_params:
    merged = merged.texture_map_to_plane(origin=..., point_u=..., point_v=...,
                                          inplace=False)
merged.compute_normals(feature_angle=180.0, auto_orient_normals=True,
                       consistent_normals=True, inplace=True)
  • merge_points=True → 공유 경계 정점 물리적 weld (1순위 unified Delaunay 효과)
  • feature_angle=180 → 모든 edge smooth, 경계 normal 평균 (2순위 normal averaging 효과)
  • 폴백: 실패 시 기존 2-mesh 렌더 경로 유지

5.3 구조물 자동 빌드 (structure_*_3d_builder.py)

유형 빌더 입력
취수탑 intake_tower_3d_builder.py DXF 평면도 → 외곽 폴리곤 + 높이
옹벽 retaining_wall_3d_builder.py DXF 단면도 → 단면 + 길이
수문 gate_3d_builder.py DXF 정면도 → 게이트 형상 + 슬라브
제수변실 valve_chamber_3d_builder.py DXF 평면도 → 박스 + 슬래브 + 점검구

구조물 위치인식 → 굴착 → TIN수정 → 3D배치 (메모리화된 워크플로):

  1. DXF 레이어에서 폴리곤 인식
  2. PCA 로 frame 방향 결정 (compute_orientation_from_points)
  3. TIN 에 굴착 pad 영역 평탄화 + smoothstep 전이 + Delaunay 재계산
  4. 메시 4개 quad 코너에 fit (fit_meshes_to_quad)
  5. 구조물 메시를 embed_offset 으로 약간 묻어 TIN 관통 방지

메시 방향 보정 (메모리화된 디테일):

  • CW(시계방향) picks + Y-flip + detail/TIN 상대회전 + PCA frame_angle → 앞뒤 뒤집힘 문제 해결

5.4 VLM 피드백 루프 (structure_vlm_feedback.py)

Gemini Vision 으로 빌더 결과물의 시각적 정합성을 자동 검증.

  • Render 후 이미지 + 원본 DXF 평면도를 함께 모델에 보냄
  • 차이점 자연어로 응답 받음
  • 사용자에게 표시해 재시도 결정

5.5 Geo-Referencing 3단계 (geo_referencing.py)

메모리: "미리보기 → 위치설정(4점 매칭) → 확정"

  1. 미리보기: DXF bbox 를 위성지도에 임시 투영 (대략 위치)
  2. 위치설정: 사용자가 DXF 의 4 모서리를 실제 위성지도 위치와 매칭 클릭
  3. 확정: Affine transform 행렬 계산 → 투영 CRS(EPSG:5187 등) 자동 결정

5.6 Harness — 재현성 + 품질 + 이력

세 컴포넌트가 모든 AI 렌더 호출을 감싼다:

SeedManager: SHA256(dxf_file_hash)[:4] → uint32 seed. 같은 DXF → 같은 seed.

QualityValidator: 3개 게이트

  1. 해상도 ≥ 1024px
  2. Laplacian variance ≥ 50.0 (선명도)
  3. HSV saturation 평균 ≥ 0.15 (단색 평면 출력 탐지)

JobLogger + SQLite JobRecord ORM:

id · dxf_path · dxf_hash · timestamp
seed · prompt_version · prompt_hash       ← 재현성 3종
status (pending/running/done/failed)
output_path · quality_score · latency_ms
error_message

PromptRegistry: prompt_v*.yaml 버전 관리. 비교/저장/해시 역조회 API.


6. GUI 디자인 & 브랜딩

6.1 디자인 철학 (homepage_sample 참고)

  • Light 기본 테마 (사용자가 Dark 토글 가능)
  • 카드형 시각 계층화: 헤더 → SETTINGS → WORKFLOW → OPTIONS → 크레딧 푸터
  • 1px 구분선: ("#DEE2E6", "#3F3F3F") 테마 쌍으로 자동 스위칭
  • uppercase 섹션 헤더: 10pt bold muted gray
  • 메인 액션 강조: Step 4 버튼만 Saman 오렌지 #E67E22, 나머지는 blue 테마 파생

6.2 사이드바 구조

[ S-CANVAS Logo (logo_V2.png, 다크 bg 소프트 스트립) ]
  Generative Design & Visualization Engine
  ─────────────────────────────────
  SETTINGS
    Satellite Source / Vworld Key (프리필 완료) / AI Engine /
    GCP/API Key / Vertex Location / Project CRS
  ─────────────────────────────────
  WORKFLOW
    1. TIN 생성 (DXF) [filled blue]
    🎯 TIN 이용 범위 (정밀 구역) [outlined]
    1.5 DEM으로 TIN 확장 [outlined]
    2. 위성지도 결합 [outlined]
    3. 제어맵 추출 [outlined]
    4. AI 렌더링 [filled ORANGE — primary CTA]
    구조물 상세 3D 빌드 [filled green]
    간단 치수 추가 (구) [muted]
    🗔 3D 뷰 다시 열기 [filled dark]
  ─────────────────────────────────
  OPTIONS
    □ 와이어프레임 보기
    뷰 버퍼 (%) [Step2/3]
    □ 지형 확장 (DEM)
    [Light ▼]
  ─────────────────────────────────
[ Saman CI (흰배경 알파 변환) ]

6.3 메인 영역

  • map_frame: tkintermapview, corner_radius=12, border_color 테마쌍
  • textbox: Consolas 12pt 로그
  • status_bar: ● READY 인디케이터 + 한 줄 상태

6.4 인트로 스플래시 (splash.py)

  • 트리거: __main__ 에서 SCanvasApp() 생성 직전
  • 재생: cv2 VideoCapture 로 logo_intro.mp4 (24fps, 8s, 1280×720) 프레임 디코드 → PIL → Tk Label
  • 효과:
    • 알파 0→1 페이드인 400ms
    • MP4 자체 애니메이션 재생
    • 알파 1→0 페이드아웃 400ms 후 destroy
    • frameless overrideredirect, topmost, 화면 중앙 배치
    • 비디오 아래 44px 오렌지 italic tagline bar
  • 안정성:
    • max_duration_s=12 safety cap
    • 비디오 끝 자동 감지 → 페이드아웃
    • 임시 tk.Tk → 완전 destroy → SCanvasApp() 의 새 ctk.CTk 충돌 없음
    • 파일 없음/cv2 실패 → silent skip

6.5 자산 처리 헬퍼

_load_image_strip_white_bg(path, threshold=240)  # 흰 배경 → 알파 0 (SAMAN_CI)
_load_image_strip_dark_bg(path, v_low=30, v_high=80)  # 어두운 bg 소프트 전이 (logo_V2)

logo_V2 결과: 36.7% 완전투명 / 49.5% 부분알파 / 13.8% 불투명 → halo 없는 부드러운 엣지.


7. AI 렌더링 파이프라인 상세

7.1 프롬프트 구성 (prompt_v1.yaml)

time_presets:
  daytime: "bright daylight, clear blue sky, sharp shadows, vivid green vegetation"
  sunset: "golden hour sunset, warm orange light, long dramatic shadows"
  night: "nighttime aerial view, moonlight reflections, city lights in distance"
  dawn: "early dawn, soft pink and purple sky, morning mist over valleys"
  overcast: "overcast sky, diffused soft light, muted colors, atmospheric fog"

angle_presets:
  top_down: "top-down overhead aerial view, directly above"
  high_angle: "high-angle bird's-eye view, slightly tilted"
  oblique: "oblique aerial perspective, 3/4 view showing terrain depth"
  low_angle: "low-angle dramatic perspective, cinematic sweep"

structure_preservation:
  - "enhance the existing satellite terrain texture and details"
  - "maintain exact terrain shape, contours, and layout from the input image"
  - "preserve water bodies, roads, and structural positions precisely"
  - "do NOT add or remove any major landscape features"

quality_enhancement:
  - "photorealistic architectural visualization"
  - "professional drone photography quality"
  - "8K ultra sharp detail, high dynamic range"
  - "realistic vegetation depth and canopy textures"

negative_prompt: |
  blurry, low quality, distorted, watermark, text, logo,
  cartoon, anime, illustration, painting, sketch,
  oversaturated, underexposed, noisy, artifacts,
  changed terrain layout, moved structures, wrong topology

7.2 Stability AI 3단계 폴백

1단계 — Conservative Upscale

  • mode: "conservative"
  • creativity: UI 슬라이더 값 그대로 (기본 0.3)
  • 목표: 원본 위성 텍스처 최대 보존

2단계 — Creative Upscale

  • mode: "creative"
  • creativity: min(strength, 0.35)
  • 목표: 약간 더 사실적인 디테일 추가

3단계 — img2img 초저강도

  • strength: min(strength, 0.2)
  • 모델: sd3.5-large
  • 목표: 위 2개 실패 시 백업

각 단계 실패 → 다음 단계 자동 폴백. 3개 모두 실패 시 fail_job(error="모든 API 방법 실패").

7.3 Gemini 경로 (gemini_renderer.py)

  • Vertex AI: google-genai SDK, GCP Project ID + gcp-key.json
  • API Key: aistudio.google.com 발급 키
  • 동일 인터페이스로 호출 → 인증만 다름

8. 좌표계 / 단위 / 정밀도

8.1 지원 CRS (사용자 선택)

EPSG 이름 사용 영역
5187 Korea 2000 / Central Belt 2010 한국 중부(서울·경기·충청)
5186 Korea 2000 / Central Belt 한국 중부 (구)
5185 Korea 2000 / West Belt 2010 한국 서부
5181 Korea 2000 / Unified CS 통합 좌표계
3857 Web Mercator 글로벌 (위성 타일 호환)

8.2 단위 강제 (메모리화된 결정)

"extract_tin_shapes 는 unit_override='m' 고정 (자동감지가 KATEC 좌표를 mm 로 오판)"

DXF $INSUNITS 헤더가 부정확한 경우가 많아 항상 m 로 강제. KATEC 류 대형 좌표값(예: x=200000, y=550000) 을 mm 로 오판하면 단위가 1000배 어긋남.

8.3 Zero-Basing

큰 절대좌표(예: EPSG:5187 의 200,000m+)는 float32 정밀도에서 sub-meter 오차 발생 → bbox 좌하단을 origin 으로 평행이동 → 모든 메시는 zero-based. 구조물 빌더는 절대좌표(structure_v1.yaml 의 origin) 와 zero-based 사이를 명시적으로 변환.


9. 메모리화된 핵심 결정 사항 (요약)

이 결정들은 과거 디버깅에서 얻은 교훈으로, 코드 곳곳의 분기 판단 기준이 됨.

  1. Structure Placement Workflow: 위치인식 → 굴착 → TIN수정 → 3D배치 4단계
  2. Geo-Referencing: 미리보기 → 4점 매칭 → 확정 3단계
  3. TIN Shape Unit: extract_tin_shapes 는 항상 unit_override="m" (자동감지 금지)
  4. Excavation: 폴리곤 평탄 pad + smoothstep 전이 + Delaunay 재계산. 구조물은 embed_offset 으로 TIN 관통 방지
  5. Mesh Orientation: CW picks + Y-flip + 상대회전 + PCA frame_angle 로 앞뒤 뒤집힘 해결
  6. TIN/DEM 벽 근본 접근: 벽 이슈는 create_tin_from_dxf 부터 점검. 판정은 slope_ratio (z_span / max_edge) 만 사용. 절대 Z 컷은 구멍 낸다
  7. TIN 3-Zone: core(원본 TIN) / transition(smoothstep) / DEM 확장. tin_core_bbox · blend_width_m 로 제어
  8. CHANGELOG 의무: 모든 수정은 CHANGELOG.md 에 즉시 기록 (역순, 날짜/파일/사유/diff 요지)

10. 최근 주요 수정 이력 (2026-04-24 ~)

[render-fix] DEM 확장 경계 사각 선 제거 (후속)

  • 두 개의 별도 PolyData → seam shading discontinuity 발생
  • merge(merge_points=True, tolerance=0.01) + compute_normals(feature_angle=180) 로 1순위(구조 통합) + 2순위(법선 평활) 동시 달성
  • 텍스처 모드에서 TCoords 소실 → _uv_mapping_params 저장 후 merge 후 재적용

[rebrand] EG-VIEW → S-CANVAS 전면 리네이밍

  • 클래스 EGViewApp → SCanvasApp
  • 파일 egview_maker.py → scanvas_maker.py
  • DB/로그 egview_*.db/log → scanvas_*.db/log
  • 144개 문자열 occurrence (43 파일) 일괄 교체

[ui-redesign] Light 기본 테마 + 사이드바 카드형

  • set_appearance_mode("light")
  • 모든 하드코딩 색상을 (light, dark) 튜플 쌍으로 → 자동 테마 스위칭
  • SETTINGS / WORKFLOW / OPTIONS 섹션 헤더 + 1px 구분선
  • SAMAN_CI 흰 배경 68.5% 알파 변환

[feature] Vworld 키 프리필 + logo_V2 + 인트로 스플래시

  • Vworld API 키 하드코딩 (사용자 제공)
  • 로고 Logo.png → logo_V2.png (다크 bg 소프트 스트립)
  • 신규 splash.py — cv2 기반 8초 MP4 스플래시 + 페이드 인/아웃
  • __main__ 에서 show_intro_splash()SCanvasApp() 순차 실행

11. 차별화 포인트 (발표 슬라이드용 강조)

11.1 사실 기반 vs 환각 기반

경쟁 도구가 AI 의 상상으로 지형을 만들 때, S-CANVAS 는 실측 DEM + 실제 위성영상 을 베이스로 깔고 AI 는 사실감 향상만 담당. → 발주처에 실제와 다른 지형을 제출하는 사고 원천 차단.

11.2 Seam-free 통합 메시

TIN(설계 도면) + DEM(실제 지형) + 위성텍스처 + AI 렌더가 모두 하나의 연속 표면으로 합쳐짐. 사용자가 어디까지가 도면이고 어디부터가 실제 지형인지 구분 못 하도록.

11.3 결정론적 재현성 (Harness)

DXF 해시 → seed → AI 렌더. 같은 입력에 항상 같은 출력. 발주처에 제출했던 그림과 1주일 뒤 회의에서 띄울 그림이 픽셀 단위로 동일.

11.4 모듈러 구조물 빌더

취수탑·제수변실·옹벽·수문 4종 즉시 지원. structure_v1.yaml 에 정의 추가하면 새 유형 확장 가능. DXF 단면도 → 자동 치수 파싱 → 3D 배치까지 클릭 1번.

11.5 공개 데이터 + 무료 티어

AWS Open Terrain Tiles · Google Satellite · ArcGIS World Imagery 모두 무료. 유일한 유료 항목은 AI 렌더(Gemini/Stability) — 그것도 사용자 본인 키 사용.

11.6 자동 품질 게이트

모든 렌더 결과를 OpenCV 로 즉시 검증. 흐릿하거나 단색 출력은 자동 PASS/FAIL 표시 → 사용자가 100장을 일일이 확인할 필요 없음.

11.7 Saman Corp 자체 개발

국내 토목·건설 도메인 지식이 코드 곳곳에 — KATEC 단위 처리, 한국 EPSG 코드 프리셋, Vworld 타일 지원, 한글 UI·로그 등.


12. 기술 스택 요약 (한눈에)

[Frontend / GUI]
└─ CustomTkinter (Tk 기반 모던 위젯) + tkintermapview

[3D Engine]
└─ PyVista + VTK (메시 처리·렌더링)

[Geospatial]
├─ ezdxf (DXF 파싱)
├─ pyproj (좌표 변환)
├─ scipy.spatial.Delaunay (TIN)
└─ AWS Open Terrain Tiles (DEM)

[Image / Video]
├─ Pillow (PIL)
├─ OpenCV (cv2)
└─ tkintermapview (위성 타일)

[AI Rendering]
├─ Google google-genai (Vertex AI / API Key)
└─ Stability AI REST API

[Persistence]
├─ SQLAlchemy + SQLite (JobRecord)
├─ structlog (구조화 로깅)
└─ PyYAML (프롬프트/구조물 정의)

[Build / Distribution] (계획)
└─ PyInstaller (단일 .exe 또는 onedir 배포)

13. 배포 / 패키징 계획

PyInstaller 로 Windows .exe 빌드 예정. 주요 챌린지:

  • PyVista + VTK 200MB+ 바이너리 → --collect-all pyvista vtkmodules 필요
  • pyproj PROJ data → 명시적 hook
  • google-genai → hidden imports
  • 런타임 쓰기 경로(DB·로그·캐시) → %LOCALAPPDATA%\S-CANVAS\ 분리 (onedir/onefile 양쪽)
  • 자산 경로 (Design/, prompt_templates/, structure_types/) → sys._MEIPASS 핸들링

배포 형태 (예정): dist/scanvas_maker/ 폴더 통째로 zip → 약 150-200MB 압축. 사용자는 .exe 더블클릭으로 실행, 본인 GCP 키 또는 Stability API 키만 환경변수/UI 입력.


14. 향후 로드맵

  1. 다국어 (i18n): 한국어/영어 토글
  2. 추가 구조물 유형: 배수문·교량·터널·송수관 등
  3. Linux/macOS 지원: 현재 Windows 전용
  4. 클라우드 렌더 큐: 다수 DXF 일괄 처리 후 결과 한꺼번에 ZIP
  5. VR/AR 출력: glTF 익스포트 → Unity/Unreal 연동
  6. 변경 추적: 같은 DXF 의 V1/V2 자동 비교 → 변경 영역 하이라이트

15. 핵심 메시지 (발표 마무리용)

S-CANVAS 는 토목·건설 도면을, "수일짜리 모델링 작업" 에서 "클릭 4번의 자동 파이프라인" 으로 압축한다. 사실 기반(DEM·위성) 위에서 AI 가 사실감만 더하므로 환각 위험 없이, 결정론적 재현성을 보장하면서, 발주처·주민설명회 발표용 조감도를 분 단위로 양산할 수 있다. — Saman Corp.


부록 A. 진입점 / 실행 방법

python scanvas_maker.py

진행 순서:

  1. splash.py 가 logo_intro.mp4 8초 재생 (페이드 인/아웃)
  2. SCanvasApp(ctk.CTk) 메인 창 기동
  3. (사이드바) DXF 파일 선택 → CRS 확인 → Step 1~4 순차 실행
  4. (옵션) 구조물 상세 3D 빌드 / 와이어프레임 / DEM 확장
  5. AI 렌더 결과는 rendered_birdseye.png (와 SQLite 이력)

부록 B. 디렉토리 구조

D:\2026\00_EGVIEW2\
├── scanvas_maker.py              # 메인 진입점
├── splash.py                     # 인트로 스플래시
├── dem_extender.py
├── geo_referencing.py
├── structure_placement.py
├── structure_templates.py
├── intake_tower_parser.py + _3d_builder.py
├── retaining_wall_parser.py + _3d_builder.py
├── gate_parser.py + _3d_builder.py
├── valve_chamber_parser.py + _3d_builder.py
├── detail_parser.py
├── filename_classifier.py
├── polygon_reconstructor.py
├── dxf_geometry.py
├── tile_downloader.py
├── view_detector.py
├── view_reconstructor.py
├── optional_detector.py
├── gemini_renderer.py
├── structure_vlm_feedback.py
│
├── harness/
│   ├── __init__.py
│   ├── seed_manager.py
│   ├── quality_validator.py
│   ├── prompt_registry.py
│   └── logger.py
│
├── prompt_templates/
│   └── prompt_v1.yaml
│
├── structure_types/
│   └── structure_v1.yaml
│
├── Design/
│   ├── Logo.png
│   ├── logo_V2.png         (현재 사용)
│   ├── SAMAN_CI.gif
│   ├── logo_intro.mp4      (8s, 24fps, 1280×720)
│   ├── homepage_sample.png
│   └── page_sample.png
│
├── cache/dem/              (런타임 DEM 캐시)
├── scanvas_jobs.db         (SQLite 이력)
├── scanvas_harness.log     (structlog)
├── scanvas_diagnostic.log  (Step 1 진단)
├── CHANGELOG.md            (수정 이력 역순)
└── Build_log.txt           (사용자 원본 요청 로그)

부록 C. 핵심 메트릭 (발표 슬라이드 숫자용)

  • 메인 모듈: 6300+ LOC (scanvas_maker.py)
  • 지원 구조물 유형: 4종 (취수탑·제수변실·옹벽·수문) + 확장 가능
  • 지원 좌표계: 5종 EPSG (한국 4 + Web Mercator 1)
  • 지원 위성 타일 서버: 9종 (Google·ArcGIS·Bing·OSM·OpenTopo·Vworld 3종 등)
  • 지원 AI 렌더 엔진: 3종 (Gemini Vertex·Gemini API·Stability)
  • DEM 자동 페치: AWS Terrarium 글로벌, ~30m 정확도
  • 인트로 스플래시: 8.0초 (24fps × 192 frames @ 1280×720)
  • 메시 통합 weld 톨러런스: 0.01m (1cm)
  • TIN 3-Zone 블렌드: smoothstep 3t² 2t³
  • 벽 컷 임계: slope_ratio > 4.0 (≈76°) AND z_span > 30m AND e_max > 5m

본 문서는 NotebookLM 의 단일 소스로 사용 가능하도록 자기완결형으로 작성되었습니다. 업로드 후 "Audio Overview", "마인드맵", "발표 슬라이드 초안" 자동 생성을 권장합니다.