From fb0586b6e0ce8a449b8bfb5cd3af4be04b250ac8 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Sun, 7 Jun 2026 19:46:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(core):=20=E9=A2=86=E5=9F=9F=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=20ScalarVolume/Grid/ScatterField(=E7=82=B9=E5=BA=8F?= =?UTF-8?q?=20i=20=E6=9C=80=E5=BF=AB)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/model/Field.hpp | 46 +++++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 1 + tests/core/test_model.cpp | 18 +++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/core/model/Field.hpp create mode 100644 tests/core/test_model.cpp diff --git a/src/core/model/Field.hpp b/src/core/model/Field.hpp new file mode 100644 index 0000000..9c2b534 --- /dev/null +++ b/src/core/model/Field.hpp @@ -0,0 +1,46 @@ +#pragma once +#include +#include +namespace geopro::core { + +// 规则三维标量场(IInterpolator 输出;render 层转 vtkImageData)。 +// 点序:i 最快、j 次之、k 最慢(匹配 vtkImageData)。 +class ScalarVolume { +public: + ScalarVolume(int nx, int ny, int nz) + : nx_(nx), ny_(ny), nz_(nz), data_(static_cast(nx) * ny * nz, 0.0) {} + int nx() const { return nx_; } int ny() const { return ny_; } int nz() const { return nz_; } + double& at(int i, int j, int k) { return data_[idx(i, j, k)]; } + double at(int i, int j, int k) const { return data_[idx(i, j, k)]; } + const std::vector& data() const { return data_; } + std::vector& data() { return data_; } +private: + // i 最快、j 次之、k 最慢 ⇒ ((k*ny + j)*nx + i)。 + size_t idx(int i, int j, int k) const { + return (static_cast(k) * ny_ + j) * nx_ + i; + } + int nx_, ny_, nz_; + std::vector data_; +}; + +// 规则二维网格剖面(x=距离 i, y=深度 j)。values 存 [j*nx + i],i 最快。 +class Grid { +public: + Grid(int nx, int ny) : nx_(nx), ny_(ny), values_(static_cast(nx) * ny, 0.0) {} + int nx() const { return nx_; } int ny() const { return ny_; } + double& valueAt(int i, int j) { return values_[static_cast(j) * nx_ + i]; } + double valueAt(int i, int j) const { return values_[static_cast(j) * nx_ + i]; } + const std::vector& values() const { return values_; } + std::vector& values() { return values_; } + std::vector x, y; // 轴坐标(规则) +private: + int nx_, ny_; + std::vector values_; +}; + +// 散点场(剖面原数据):局部坐标 + 值。 +struct ScatterField { + std::vector x, y, z, v; // 对应样本 xlist/ylist/(hlist)/vlist +}; + +} // namespace geopro::core diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 68bb1e5..0174dc6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -10,6 +10,7 @@ include(GoogleTest) gtest_discover_tests(geopro_tests) target_sources(geopro_tests PRIVATE core/test_local_frame.cpp) +target_sources(geopro_tests PRIVATE core/test_model.cpp) target_link_libraries(geopro_tests PRIVATE geopro_core) add_subdirectory(spike) # spike S3: banded contour 渲染验证 diff --git a/tests/core/test_model.cpp b/tests/core/test_model.cpp new file mode 100644 index 0000000..5dc4644 --- /dev/null +++ b/tests/core/test_model.cpp @@ -0,0 +1,18 @@ +#include +#include "model/Field.hpp" +using namespace geopro::core; + +TEST(Model, ScalarVolumeIndexing) { + ScalarVolume v(/*nx=*/2, /*ny=*/3, /*nz=*/4); + v.at(1, 2, 3) = 42.0; + EXPECT_EQ(v.nx(), 2); EXPECT_EQ(v.ny(), 3); EXPECT_EQ(v.nz(), 4); + EXPECT_EQ(v.data().size(), 2u * 3u * 4u); + EXPECT_DOUBLE_EQ(v.at(1, 2, 3), 42.0); +} + +TEST(Model, GridStoresRegularSpec) { + Grid g(/*nx=*/100, /*ny=*/22); + EXPECT_EQ(g.values().size(), 100u * 22u); + g.valueAt(/*i=*/3, /*j=*/5) = 7.5; // i=x(0..99), j=y(0..21) + EXPECT_DOUBLE_EQ(g.valueAt(3, 5), 7.5); +}