Phase 0 of expert feedback (#1~#11): infrastructure + design + 1차 fixes
Implementations (즉시 동작): - #1 crash logging: harness/crash_logger.py (sys.excepthook + threading + faulthandler, 회전 파일 logs/scanvas.log). main 진입점 통합. - #2 smooth curves (1차): gate_3d_builder ogee profile를 arc-length parametric CubicSpline로 4× densify (8pt→32pt, 36→132 cells, 60 FPS 안전). - #3 TIN colormap: matplotlib "terrain"의 파란색 범위 제거 → 짙은갈색→황토→ 모래→능선 LinearSegmentedColormap. 9 사이트 교체. 회귀 테스트 추가. - #5 uv: pyproject.toml + UV_GUIDE.md. base/[py313]/[dev]/[build] extras + hatchling. - #6,#7,#8 dev cycle infra: .pre-commit-config.yaml (ruff+secrets+위생), .gitea/workflows/ci.yml (Py3.11+3.13 matrix), tests/test_regressions.py (18 회귀 테스트, iter=1~7 fix 박제), CONTRIBUTING.md (Red→Green 알고리즘). Design docs (다음 세션 마이그레이션 청사진): - #4 UI/UX 전면 수정: UI_REDESIGN_PLAN.md (12 popup→1 inspector, vtkTkRenderWidget embedding 게이트, 4 phase × 7 sessions). - #10 Core/Plugin: ARCHITECTURE_PLAN.md (Core 14 / Plugin 7 구조물 + 2 렌더 + 1 QA, STRUCTURE_REGISTRY 확장, manifest 기반 디스커버리). - #11 perf hotspots: PERFORMANCE_BASELINE.md (19 핫스팟, P1: 타일 직렬DL 5~30s, 캡처 직렬 4.5~15s, numpy 벡터화 가능 Python loops, 텍스처 4회 반복read). Behavior preservation: ruff 0 errors, pytest 17 passed/1 skipped(bpy), import 33/33 OK on Py3.13.13. Item #2 P2/P3 곡선, #4 UI 마이그레이션, #10 Phase 1 추출, #11 P1 최적화는 차기 세션. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
import contextlib
|
||||
import customtkinter as ctk
|
||||
import datetime
|
||||
import hashlib
|
||||
import os
|
||||
import sys
|
||||
import io
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import time as _time
|
||||
from pathlib import Path
|
||||
@@ -26,6 +28,22 @@ import pyproj
|
||||
import requests
|
||||
from PIL import Image, ImageDraw, ImageFilter
|
||||
import tkintermapview
|
||||
from matplotlib.colors import LinearSegmentedColormap
|
||||
|
||||
# 지형(TIN) 컬러맵 — **파란색 금지** (피드백 #3: 물과 헷갈림).
|
||||
# 어두운 토양 → 밝은 모래/건조 톤 → 능선 광택. matplotlib "terrain" 대체.
|
||||
_TIN_EARTH_CMAP = LinearSegmentedColormap.from_list(
|
||||
"scanvas_earth",
|
||||
[
|
||||
(0.00, "#3F2E1A"), # 저지대 — 짙은 갈색 (배수로 음영)
|
||||
(0.20, "#6E5235"), # 토양
|
||||
(0.45, "#9C7B4F"), # 황토
|
||||
(0.70, "#C7AA7C"), # 모래/건조
|
||||
(0.88, "#E5D5B0"), # 고지 능선
|
||||
(1.00, "#F5EBD3"), # 정상 광택
|
||||
],
|
||||
N=256,
|
||||
)
|
||||
|
||||
# Harness 모듈 (동일 디렉토리의 harness/ 폴더)
|
||||
try:
|
||||
@@ -79,9 +97,7 @@ except ImportError as _e:
|
||||
STRUCTURE_VLM_AVAILABLE = False
|
||||
print(f"[Warning] structure_vlm_feedback not available: {_e}")
|
||||
|
||||
# 폰트 에러 방지를 위한 처리
|
||||
import logging
|
||||
import contextlib
|
||||
# 폰트 에러 방지 — matplotlib font_manager 로그 비활성.
|
||||
logging.getLogger('matplotlib.font_manager').disabled = True
|
||||
os.environ['PYTHONIOENCODING'] = 'utf-8'
|
||||
|
||||
@@ -4660,7 +4676,7 @@ class SCanvasApp(ctk.CTk):
|
||||
sample = pts_abs if len(pts_abs) <= 30000 else pts_abs[
|
||||
np.random.RandomState(0).choice(len(pts_abs), 30000, replace=False)]
|
||||
sc = ax.scatter(sample[:, 0], sample[:, 1], c=sample[:, 2],
|
||||
cmap="terrain", s=2, alpha=0.85)
|
||||
cmap=_TIN_EARTH_CMAP, s=2, alpha=0.85)
|
||||
fig.colorbar(sc, ax=ax, label="Elevation (m)")
|
||||
# 도면 bbox 표시
|
||||
ax.add_patch(_MplRect((x0p, y0p), x1p - x0p, y1p - y0p,
|
||||
@@ -5515,7 +5531,7 @@ class SCanvasApp(ctk.CTk):
|
||||
p.add_mesh(unified_mesh, texture=texture_obj,
|
||||
show_edges=self.wireframe_var.get(), edge_color="white")
|
||||
else:
|
||||
p.add_mesh(unified_mesh, scalars="Elevation", cmap="terrain",
|
||||
p.add_mesh(unified_mesh, scalars="Elevation", cmap=_TIN_EARTH_CMAP,
|
||||
show_edges=self.wireframe_var.get(), edge_color="white",
|
||||
scalar_bar_args={'title': 'Elevation (m)'})
|
||||
else:
|
||||
@@ -5524,7 +5540,7 @@ class SCanvasApp(ctk.CTk):
|
||||
p.add_mesh(target_mesh, texture=texture_obj,
|
||||
show_edges=self.wireframe_var.get(), edge_color="white")
|
||||
else:
|
||||
p.add_mesh(target_mesh, scalars="Elevation", cmap="terrain",
|
||||
p.add_mesh(target_mesh, scalars="Elevation", cmap=_TIN_EARTH_CMAP,
|
||||
show_edges=self.wireframe_var.get(), edge_color="white",
|
||||
scalar_bar_args={'title': 'Elevation (m)'})
|
||||
if ext_mesh is not None:
|
||||
@@ -5533,7 +5549,7 @@ class SCanvasApp(ctk.CTk):
|
||||
p.add_mesh(ext_mesh, texture=texture_obj,
|
||||
show_edges=False, lighting=True)
|
||||
else:
|
||||
p.add_mesh(ext_mesh, scalars="Elevation", cmap="terrain",
|
||||
p.add_mesh(ext_mesh, scalars="Elevation", cmap=_TIN_EARTH_CMAP,
|
||||
show_edges=False, lighting=True,
|
||||
show_scalar_bar=False)
|
||||
except Exception as e:
|
||||
@@ -5894,7 +5910,7 @@ class SCanvasApp(ctk.CTk):
|
||||
tex = pv.read_texture("satellite_temp.png")
|
||||
p.add_mesh(target, texture=tex, show_edges=self.wireframe_var.get(), edge_color="#444444")
|
||||
else:
|
||||
p.add_mesh(target, scalars="Elevation", cmap="terrain",
|
||||
p.add_mesh(target, scalars="Elevation", cmap=_TIN_EARTH_CMAP,
|
||||
show_edges=self.wireframe_var.get(), edge_color="#444444")
|
||||
|
||||
# DEM 외곽 확장 메시 — 뷰포인트 선택/캡처/AI에 **같은 장면**을 쓰기 위해 같이 렌더
|
||||
@@ -5904,7 +5920,7 @@ class SCanvasApp(ctk.CTk):
|
||||
if tex is not None and self.tin_extension_textured is not None:
|
||||
p.add_mesh(ext_mesh_view, texture=tex, show_edges=False, lighting=True)
|
||||
else:
|
||||
p.add_mesh(ext_mesh_view, scalars="Elevation", cmap="terrain",
|
||||
p.add_mesh(ext_mesh_view, scalars="Elevation", cmap=_TIN_EARTH_CMAP,
|
||||
show_edges=False, lighting=True, show_scalar_bar=False)
|
||||
except Exception as e:
|
||||
self.log(f" [뷰어] 확장 메시 추가 경고: {e}")
|
||||
@@ -6315,19 +6331,19 @@ class SCanvasApp(ctk.CTk):
|
||||
if textured and tex is not None:
|
||||
p.add_mesh(unified, texture=tex)
|
||||
else:
|
||||
p.add_mesh(unified, scalars="Elevation", cmap="terrain")
|
||||
p.add_mesh(unified, scalars="Elevation", cmap=_TIN_EARTH_CMAP)
|
||||
else:
|
||||
if textured and tex is not None:
|
||||
p.add_mesh(target, texture=tex)
|
||||
else:
|
||||
p.add_mesh(target, scalars="Elevation", cmap="terrain")
|
||||
p.add_mesh(target, scalars="Elevation", cmap=_TIN_EARTH_CMAP)
|
||||
if ext_mesh is not None:
|
||||
try:
|
||||
if textured and tex is not None:
|
||||
p.add_mesh(ext_mesh, texture=tex,
|
||||
show_edges=False, lighting=True)
|
||||
else:
|
||||
p.add_mesh(ext_mesh, scalars="Elevation", cmap="terrain",
|
||||
p.add_mesh(ext_mesh, scalars="Elevation", cmap=_TIN_EARTH_CMAP,
|
||||
show_edges=False, lighting=True,
|
||||
show_scalar_bar=False)
|
||||
except Exception as e:
|
||||
@@ -7000,6 +7016,14 @@ class SCanvasApp(ctk.CTk):
|
||||
self.log(f" 결과 표시 오류: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 크래시 핸들러 — Python 미처리 예외 + thread 예외 + faulthandler. logs/ 에 회전 저장.
|
||||
try:
|
||||
from harness.crash_logger import install_crash_handlers
|
||||
_log_dir = install_crash_handlers()
|
||||
print(f"[crash_logger] logs → {_log_dir}")
|
||||
except Exception as _ch_err:
|
||||
print(f"[crash_logger] 설치 실패 (계속 진행): {_ch_err}")
|
||||
|
||||
# 인트로 스플래시 — Design/logo_intro.mp4 재생 후 메인 앱 기동.
|
||||
# 실패·파일 없음 시 조용히 skip(메인 앱은 항상 뜸).
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user