geopro/CLAUDE.md

276 lines
12 KiB
Markdown

# 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 <pattern> # 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.