# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Behavioral Guidelines (Binding) **Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment. ### 1. Think Before Coding **Don't assume. Don't hide confusion. Surface tradeoffs.** Before implementing: - State your assumptions explicitly. If uncertain, ask. - If multiple interpretations exist, present them — don't pick silently. - If a simpler approach exists, say so. Push back when warranted. - If something is unclear, stop. Name what's confusing. Ask. ### 2. Simplicity First **Minimum code that solves the problem. Nothing speculative.** - No features beyond what was asked. - No abstractions for single-use code. - No "flexibility" or "configurability" that wasn't requested. - No error handling for impossible scenarios. - If you write 200 lines and it could be 50, rewrite it. ### 3. Surgical Changes **Touch only what you must. Clean up only your own mess.** When editing existing code: - Don't "improve" adjacent code, comments, or formatting. - Don't refactor things that aren't broken. - Match existing style, even if you'd do it differently. - If you notice unrelated dead code, mention it — don't delete it. When your changes create orphans: - Remove imports/variables/functions that YOUR changes made unused. - Don't remove pre-existing dead code unless asked. The test: Every changed line should trace directly to the user's request. **Exception — Tech debt must be fixed, not deferred:** When you discover a real bug, broken behavior, or technical debt while working (even if it predates this change and you didn't introduce it), fix it — do not use "not introduced by this round / pre-existing" as a reason to leave it. Surface it, then handle it. (User directive, 2026-06-25, binding.) This overrides the "don't fix what isn't broken" bias above *for genuine defects* — it does not license cosmetic refactors or unrequested rewrites. **Do it yourself — never offload work you can do (User directive, 2026-06-25, binding):** If you have the tools to do something, DO IT — never tell the user to do it for you. Read the logs yourself (`%LOCALAPPDATA%/Geomative/Geopro3/logs/geopro_*.log` via Bash/grep), inspect data/fixtures yourself, build and link yourself (`build.bat app` via PowerShell), diagnose by adding logging and then reading that log yourself. The ONLY things to ask the user for are: (a) closing a running app so the exe can relink (LNK1104 — a lock only they can release), and (b) genuine product decisions. Do not ask the user to read logs, inspect data, run diagnostics, or interpret output — that is your job. ### 4. Goal-Driven Execution **Define success criteria. Loop until verified.** Transform tasks into verifiable goals: - "Add validation" -> "Write tests for invalid inputs, then make them pass" - "Fix the bug" -> "Write a test that reproduces it, then make it pass" - "Refactor X" -> "Ensure tests pass before and after" For multi-step tasks, state a brief plan: ``` 1. [Step] -> verify: [check] 2. [Step] -> verify: [check] 3. [Step] -> verify: [check] ``` --- ## Project Overview Geopro 3.0 desktop client: a geophysical exploration data visualization application (Qt 6 + VTK 9, C++17, Windows/MSVC). Replicates the core "Project Analysis View" from Geopro 3.0 web. Tech stack: Qt 6.11 (QtWidgets) + VTK 9.6 + CMake/Ninja + MSVC 2022/2026 + vcpkg (non-Qt deps only) + ADS (docking) + GDAL/PROJ + OpenSSL + QtKeychain + Qwt. --- ## Build System **Prerequisites:** Visual Studio 2022/2026 (Desktop C++ workload), Git, vcpkg with `VCPKG_ROOT` env var set. Qt 6.11.1 MSVC kit at `D:/Qt/6.11.1/msvc2022_64`. VTK 9.6.2 prebuilt at `external/vtk-install`. All Qt-dependent libs (VTK/ADS/QtKeychain) link against the official MSVC Qt kit; only non-Qt deps (GDAL/PROJ/OpenSSL/Eigen/gtest/etc.) come from vcpkg. **Rule:** `cmake` / `ninja` / `cl` are NOT on PATH by default. Build only inside an activated MSVC environment. `build.bat` handles this automatically via vswhere. ### Primary: `build.bat` (recommended) Run from repo root in **cmd** (not PowerShell for parameter passing): | Command | Action | |---|---| | `build` or `build app` | Incremental build of `geopro_desktop` (default) | | `build run` | Build and launch `geopro_desktop.exe` | | `build test` | Build and run unit tests via ctest | | `build all` | Build all targets | | `build configure` | Force re-configure CMake (after CMakeLists changes or new sources) | | `build rebuild` | Clean rebuild (`--clean-first`) then launch | ### Alternative: Manual CMake Open "x64 Native Tools Command Prompt for VS", then: ```bat set CMAKE="%VSINSTALLDIR%Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" %CMAKE% --preset msvc-release %CMAKE% --build build/release --target geopro_desktop %CMAKE% --build build/release --target geopro_tests ctest --test-dir build/release --output-on-failure ``` (Debug: replace `msvc-release` with `msvc-debug` and `build/release` with `build/debug`.) ### Build Targets - `geopro_desktop` — Main executable at `build/release/src/app/geopro_desktop.exe` - `geopro_tests` — Unit test executable, discovered by ctest - `render_verify` — Offline PNG render verification (`tests/spike/`) - `grid_contour_spike` / `slice_alpha_probe` — Spike verification tools **Incremental builds:** Changing `.cpp/.hpp` only needs `--build`. Changing `CMakeLists.txt` or adding new source files needs `build configure` or `--preset`. **LNK1104:** If linking fails with "file in use", close any running `geopro_desktop.exe` first (the only thing to ask the user for). --- ## Testing Framework: **Google Test** for core/data/render; **Qt Test** (QSignalSpy) for controller/net. Discovered via `gtest_discover_tests` with `DISCOVERY_MODE PRE_TEST` (because Qt DLLs are copied POST_BUILD; discovering at build time would fail with 0xc0000135). ### Running Tests ```bat build test # All tests via build.bat ctest --test-dir build/release --output-on-failure -R # Filter by regex ``` Running a **single test case** (example): ```bat # After building geopro_tests: build\release\tests\geopro_tests.exe --gtest_filter="*ColorScale*" ``` Some render/data tests require `PROJ_DATA` (set automatically by ctest from the vcpkg install tree). If running the test exe directly, ensure `external/vtk-install/bin` and vcpkg DLLs are on PATH. ### Render Verification Rendering correctness **must be verified with offline PNG pixel checks**, not just "doesn't crash". Use `tests/spike/render_verify.cpp`: ```bat build all # builds render_verify # Ensure PATH includes external/vtk-install/bin and vcpkg_installed/x64-windows/bin # Ensure PROJ_DATA and GDAL_DATA are set if testing terrain/voxel build\release\tests\spike\render_verify.exe # Inspect output PNGs at D:/dev/spike_data/verify_*.png ``` --- ## Code Style - `.clang-format`: BasedOnStyle Google, C++17, 100 column limit, 4-space indent, braces after class/function. - `.clangd`: Compilation database at `build/debug`. Strict unused-include checks. - File encoding: **UTF-8 without BOM**. Do NOT use PowerShell `Set-Content -Encoding UTF8` on source files (it corrupts Chinese comments). --- ## Architecture Six-layer directory structure under `src/`: ``` src/core/ Pure business logic. ZERO Qt/VTK includes. Independently unit-testable. model/ (Project, ColorScale, Grid, ScalarVolume, Anomaly...) geo/ (LocalFrame, GeoLocalFrame, CrsTransform) algo/ (IInterpolator, IdwInterpolator, VolumeBuilder) src/io/ I/O parsers. Pure C++17 where possible. gpr/ (IprbReader, IprHeader, GprSurveyAssembler, GpsTrack) src/data/ Data access layer. Async repository contracts (QFuture/cancel/paging). repo/ (IAsyncProjectRepository, IDatasetRepository, LocalSampleRepository) api/ (ApiDatasetRepository, ApiProjectRepository, NavRequest) dto/ (JSON DTOs + mapping to domain models) store/ (ChunkedVolumeStore, pyramid LOD, streaming writes) src/net/ Network & auth. ApiClient, AuthService, RsaEncryptor, Credential (QtKeychain). src/render/ VTK rendering layer. Owns ALL actors and the single vtkRenderWindow. Scene.hpp is the single owner of the render window. actors/ (ScatterActor, GridContourActor, CurtainActor, VoxelActor, AnomalyActor, TerrainActor, ElectrodeActor) interact/ (InteractionManager, SliceTool, PickInteractorStyle, AnomalyDrawTool) source/ (Volume render sources: WholeVolumeSource, OutOfCoreSource, ViewAdaptiveVolumeSource) ground/ (TileMath for basemap tiles) src/controller/ Orchestration. Signals/slots wired in wireUp() methods. (WorkbenchNavController, DatasetDetailController, VtkSceneController) src/app/ Entry point + MainWindow + all QtWidgets panels and dialogs. panels/ (ObjectTreePanel, DatasetListPanel, DatasetDetailPanel, AnomalyListPanel, etc.) panels/chart/ (Qwt-based detail charts: GridDataChartView, ScatterPlotItem, ContourPlotItem) panels/columns/ (Category analysis tabs) panels/web/ (ProjectWebView with QWebEngineView) ``` **Architecture rules (binding):** - `core` must NEVER `#include` any Qt or VTK header. - VTK actors / `vtkRenderWindow` are created and owned ONLY by `render`. `view`/`app` holds the `QVTKOpenGLStereoWidget` shell but must NOT create actors directly. - Signal/slot connections are concentrated in `*Controller::wireUp()` or `MainWindow`. - All file paths use `QStandardPaths` (Qt) or project-relative logic; no hardcoded paths. ### Coordinate System - Data source CRS: **EPSG:4547** (CGCS2000 / 3-degree Gauss-Kruger CM 114E) for `projectX/projectY` in local survey data. - Project world coordinate: `core::GeoLocalFrame` (lat/lon -> local meters, equidistant cylindrical), shared across all views for registration. - DEM/imagery: EPSG:3857 (Web Mercator), reprojected via PROJ/GDAL at runtime. - Rendering convention: depth `y` increases downward -> VTK `z` is negated. --- ## Key Dependencies & FetchContent - **Qt 6.11.1**: Official MSVC kit at `D:/Qt/6.11.1/msvc2022_64`. `CMAKE_PREFIX_PATH` points here. Only one Qt exists in the build. - **VTK 9.6.2**: Built from source against the same Qt, installed to `external/vtk-install`. Required components include `GUISupportQt`, `RenderingOpenGL2`, `InteractionStyle`, `FiltersSources`, `RenderingVolumeOpenGL2`, `InteractionWidgets`, `FiltersGeometry`, `IOImage`. - **ADS (Qt-Advanced-Docking-System) 4.3.1**: FetchContent from GitHub. Linked as `ads::qt6advanceddocking`. - **QtKeychain 0.14.0**: FetchContent, static-linked. `BUILD_WITH_QT6=ON`. - **Qwt 6.2**: Source expected at `external/qwt-src`. Included via `cmake/qwt.cmake`. - **vcpkg deps**: eigen3, gdal, gtest, nlohmann-json, openssl, proj. --- ## Important Project Conventions - **ColorScale / colorBar values**: Use real non-uniform segment values from the dataset. Uniform grading produces incorrect all-blue renders. - **2D map vs 3D view**: These are **different content**, not the same scene with a different camera. 2D map = `MapLineActor` (survey line trajectories, top-down). 3D view = `CurtainActor` (vertical cross-section walls) + voxel + slice + terrain. - **Data detail** (bottom panel) = single-dataset analysis view (`GridContourActor` for #18 grid, `ScatterActor` for #17 raw data). - **Rendering changes must be verified** with `render_verify` offline PNG before app integration, then manually in-app. - **Build and link yourself** — do not ask the user to run builds, read logs, or inspect data. The only exception is closing a running `geopro_desktop.exe` for LNK1104. --- ## Memory - See `.claude/projects/E--gitea-geopro/memory/MEMORY.md` for persistent project context.