From e59b6b3dfe93368b826f7c8d1138a1aaa9099fdb Mon Sep 17 00:00:00 2001 From: gaozheng Date: Sun, 7 Jun 2026 23:25:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(render):=20MapLineActor(=E6=B5=8B=E7=BA=BF?= =?UTF-8?q?=E8=BD=A8=E8=BF=B9=E7=BA=BF,=E4=BA=8C=E7=BB=B4=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE)=20+=20=E5=B8=98=E9=9D=A2=E5=88=86=E6=AE=B5=E7=9D=80?= =?UTF-8?q?=E8=89=B2(=E6=B8=85=E6=99=B0=E8=89=B2=E5=B8=A6,=20=E4=B8=8E#18?= =?UTF-8?q?=E4=B8=80=E8=87=B4);=20=E7=A6=BB=E5=B1=8FPNG=E6=A0=B8=E5=AF=B9?= =?UTF-8?q?=E4=B8=89=E8=A7=86=E5=9B=BE=E5=9D=87=E6=AD=A3=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/render/CMakeLists.txt | 2 +- src/render/actors/CurtainActor.cpp | 46 ++++++++++++++++++--------- src/render/actors/MapLineActor.cpp | 50 ++++++++++++++++++++++++++++++ src/render/actors/MapLineActor.hpp | 15 +++++++++ tests/spike/render_verify.cpp | 14 +++++---- 5 files changed, 106 insertions(+), 21 deletions(-) create mode 100644 src/render/actors/MapLineActor.cpp create mode 100644 src/render/actors/MapLineActor.hpp diff --git a/src/render/CMakeLists.txt b/src/render/CMakeLists.txt index d6e9813..5c817d0 100644 --- a/src/render/CMakeLists.txt +++ b/src/render/CMakeLists.txt @@ -1,6 +1,6 @@ find_package(VTK REQUIRED COMPONENTS CommonCore CommonDataModel FiltersGeometry FiltersModeling RenderingCore RenderingOpenGL2 RenderingVolumeOpenGL2 InteractionStyle InteractionWidgets) add_library(geopro_render STATIC - Scene.cpp ColorLutBuilder.cpp CameraPreset.cpp actors/GridContourActor.cpp actors/VoxelActor.cpp actors/CurtainActor.cpp) + Scene.cpp ColorLutBuilder.cpp CameraPreset.cpp actors/GridContourActor.cpp actors/VoxelActor.cpp actors/CurtainActor.cpp actors/MapLineActor.cpp) target_include_directories(geopro_render PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(geopro_render PUBLIC geopro_core ${VTK_LIBRARIES}) target_compile_features(geopro_render PUBLIC cxx_std_17) diff --git a/src/render/actors/CurtainActor.cpp b/src/render/actors/CurtainActor.cpp index f9ed01a..1feb8e2 100644 --- a/src/render/actors/CurtainActor.cpp +++ b/src/render/actors/CurtainActor.cpp @@ -1,12 +1,16 @@ #include "actors/CurtainActor.hpp" -#include +#include +#include #include #include #include #include +#include #include +#include + #include #include "ColorLutBuilder.hpp" @@ -65,24 +69,38 @@ vtkSmartPointer buildCurtain(const geopro::core::Grid& g, sgrid->SetPoints(points); sgrid->GetPointData()->SetScalars(sc); - // vmin/vmax 来自 Grid;若退化(==)则扫数据兜底。 - double vmin = g.vmin, vmax = g.vmax; - if (vmin >= vmax) { - const auto& vals = g.values(); - vmin = vals.empty() ? 0.0 : vals.front(); - vmax = vmin; - for (double v : vals) { - if (v < vmin) vmin = v; - if (v > vmax) vmax = v; + // 用 colorBar 真实分段值做色带(与数据详情#18一致的清晰色带,而非连续插值的糊色)。 + const std::vector stops = cs.stopValues(); + double vmin, vmax; + if (stops.size() >= 2) { vmin = stops.front(); vmax = stops.back(); } + else { + vmin = g.vmin; vmax = g.vmax; + if (vmin >= vmax) { + const auto& vals = g.values(); + vmin = vals.empty() ? 0.0 : vals.front(); vmax = vmin; + for (double v : vals) { if (v < vmin) vmin = v; if (v > vmax) vmax = v; } + if (vmin >= vmax) vmax = vmin + 1.0; } - if (vmin >= vmax) vmax = vmin + 1.0; } auto lut = buildLut(cs, vmin, vmax, kLutLevels); - vtkNew mapper; - mapper->SetInputData(sgrid); - mapper->SetScalarModeToUsePointData(); + // structuredGrid → 表面 polydata → banded contour(分段色带) + vtkNew surf; + surf->SetInputData(sgrid); + vtkNew banded; + banded->SetInputConnection(surf->GetOutputPort()); + if (stops.size() >= 2) { + banded->SetNumberOfContours(static_cast(stops.size())); + for (int i = 0; i < static_cast(stops.size()); ++i) banded->SetValue(i, stops[i]); + } else { + banded->GenerateValues(20, vmin, vmax); + } + banded->SetScalarModeToValue(); + + vtkNew mapper; + mapper->SetInputConnection(banded->GetOutputPort()); + mapper->SetScalarModeToUseCellData(); mapper->SetLookupTable(lut); mapper->SetScalarRange(vmin, vmax); diff --git a/src/render/actors/MapLineActor.cpp b/src/render/actors/MapLineActor.cpp new file mode 100644 index 0000000..3e445ea --- /dev/null +++ b/src/render/actors/MapLineActor.cpp @@ -0,0 +1,50 @@ +#include "actors/MapLineActor.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace geopro::render { + +vtkSmartPointer buildSurveyLine(const geopro::core::Grid& g, + const geopro::core::GeoLocalFrame& frame) +{ + const int nx = g.nx(); + const bool hasLatLon = + g.lat.size() >= static_cast(nx) && g.lon.size() >= static_cast(nx); + if (nx < 2 || !hasLatLon) return vtkSmartPointer::New(); + + vtkNew points; + for (int i = 0; i < nx; ++i) { + auto p = frame.toLocal(g.lat[i], g.lon[i]); + points->InsertNextPoint(p.x, p.y, 0.0); // 平铺在 z=0,供俯视 + } + + vtkNew line; + line->GetPointIds()->SetNumberOfIds(nx); + for (int i = 0; i < nx; ++i) line->GetPointIds()->SetId(i, i); + + vtkNew cells; + cells->InsertNextCell(line); + + vtkNew poly; + poly->SetPoints(points); + poly->SetLines(cells); + + vtkNew mapper; + mapper->SetInputData(poly); + + auto actor = vtkSmartPointer::New(); + actor->SetMapper(mapper); + actor->GetProperty()->SetColor(0.85, 0.15, 0.15); // 测线:红 + actor->GetProperty()->SetLineWidth(3.0); + return actor; +} + +} // namespace geopro::render diff --git a/src/render/actors/MapLineActor.hpp b/src/render/actors/MapLineActor.hpp new file mode 100644 index 0000000..048d2ae --- /dev/null +++ b/src/render/actors/MapLineActor.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +#include "geo/GeoLocalFrame.hpp" +#include "model/Field.hpp" + +namespace geopro::render { + +// 二维地图用:把测线的 lat/lon 水平迹线画成一条折线(俯视=测线布局)。 +// 电极/采点位置另以小点显示。返回的 actor 放在 z=0 平面,供 Top2D 俯视。 +vtkSmartPointer buildSurveyLine(const geopro::core::Grid& g, + const geopro::core::GeoLocalFrame& frame); + +} // namespace geopro::render diff --git a/tests/spike/render_verify.cpp b/tests/spike/render_verify.cpp index c5f0bb4..625bf5f 100644 --- a/tests/spike/render_verify.cpp +++ b/tests/spike/render_verify.cpp @@ -19,6 +19,7 @@ #include "ColorLutBuilder.hpp" #include "actors/CurtainActor.hpp" #include "actors/GridContourActor.hpp" +#include "actors/MapLineActor.hpp" #include "geo/GeoLocalFrame.hpp" #include "parse/SampleParsers.hpp" @@ -60,17 +61,18 @@ int main() { double lon0 = std::accumulate(g.lon.begin(), g.lon.end(), 0.0) / (g.lon.empty() ? 1 : g.lon.size()); core::GeoLocalFrame frame(lat0, lon0); - // 2) 帘面俯视(二维) + // 2) 二维地图:测线折线俯视(浅灰底) { - auto a = render::buildCurtain(g, cs, frame); - vtkNew ren; ren->SetBackground(1, 1, 1); - ren->AddActor(a); + auto line = render::buildSurveyLine(g, frame); + vtkNew ren; ren->SetBackground(0.96, 0.97, 0.99); + ren->AddActor(line); render::applyTop2D(ren); - renderToPng(ren, (dir + "verify_curtain_top.png").c_str(), 700, 500); + renderToPng(ren, (dir + "verify_map.png").c_str(), 700, 500); } - // 3) 帘面透视(三维) + // 3) 帘面透视(三维);纵向夸张 z*3,使 15m 深度相对 62m 长度更像一道墙 { auto a = render::buildCurtain(g, cs, frame); + a->SetScale(1.0, 1.0, 3.0); vtkNew ren; ren->SetBackground(1, 1, 1); ren->AddActor(a); render::applyFree3D(ren);