geopro/CLAUDE.md

12 KiB

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.

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:

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

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):

# 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:

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.