From 96fac3313bab8a95b080408fe86a63a11f5a3f96 Mon Sep 17 00:00:00 2001 From: gaozheng Date: Sun, 7 Jun 2026 23:08:15 +0800 Subject: [PATCH] =?UTF-8?q?wip(render):=20=E6=B7=B1=E5=BA=A6=E6=96=B9?= =?UTF-8?q?=E5=90=91=E4=BF=AE=E6=AD=A3(=E5=8F=96=E8=B4=9F)=20+=20=E7=A6=BB?= =?UTF-8?q?=E5=B1=8F=E6=B8=B2=E6=9F=93=E9=AA=8C=E8=AF=81=E5=B7=A5=E5=85=B7?= =?UTF-8?q?(render=5Fverify->PNG)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 诚实记录: 经离屏PNG肉眼核对, 帘面渲染仍不正确(扭曲飘带/俯视空白), '2D=俯视帘面'模型不成立(竖直帘面俯视仅一条发丝线), 需独立的地图线actor。色阶偏蓝(线性LUT)。详见后续 STATUS。 之前几版'已验证'仅进程级冒烟, 未看像素 -> 漏掉剖面倒置等问题。 --- src/render/actors/CurtainActor.cpp | 3 +- src/render/actors/GridContourActor.cpp | 24 +++++--- tests/spike/CMakeLists.txt | 6 ++ tests/spike/render_verify.cpp | 80 ++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 tests/spike/render_verify.cpp diff --git a/src/render/actors/CurtainActor.cpp b/src/render/actors/CurtainActor.cpp index 7d818ac..f9ed01a 100644 --- a/src/render/actors/CurtainActor.cpp +++ b/src/render/actors/CurtainActor.cpp @@ -56,7 +56,8 @@ vtkSmartPointer buildCurtain(const geopro::core::Grid& g, py = 0.0; } const vtkIdType id = static_cast(j) * nx + i; - points->SetPoint(id, px, py, g.y[j]); // z=深度/高程,VTK Z 向上 + // g.y 是深度(越大越深);VTK Z 向上 → 取负,使深部在下、浅部在上(剖面不倒置)。 + points->SetPoint(id, px, py, -g.y[j]); sc->SetValue(id, g.valueAt(i, j)); } } diff --git a/src/render/actors/GridContourActor.cpp b/src/render/actors/GridContourActor.cpp index 6ae4d1b..15def7b 100644 --- a/src/render/actors/GridContourActor.cpp +++ b/src/render/actors/GridContourActor.cpp @@ -3,11 +3,12 @@ #include #include #include -#include #include #include +#include #include #include +#include #include "ColorLutBuilder.hpp" @@ -31,18 +32,23 @@ GridActors buildGridContour(const geopro::core::Grid& g, const geopro::core::Col return GridActors{}; } - vtkNew img; - img->SetDimensions(nx, ny, 1); - img->SetOrigin(g.x[0], g.y[0], 0.0); - img->SetSpacing(g.x[1] - g.x[0], g.y[1] - g.y[0], 1.0); + // 用显式坐标的 vtkStructuredGrid(不假设等距;y 取负使深部在下、剖面不倒置)。 + vtkNew sgrid; + sgrid->SetDimensions(nx, ny, 1); + vtkNew points; + points->SetNumberOfPoints(static_cast(nx) * ny); vtkNew sc; sc->SetName("v"); sc->SetNumberOfTuples(static_cast(nx) * ny); for (int j = 0; j < ny; ++j) - for (int i = 0; i < nx; ++i) - sc->SetValue(static_cast(j) * nx + i, g.valueAt(i, j)); // i 最快 - img->GetPointData()->SetScalars(sc); + for (int i = 0; i < nx; ++i) { + const vtkIdType id = static_cast(j) * nx + i; // i 最快 + points->SetPoint(id, g.x[i], -g.y[j], 0.0); // y=深度→取负(向下) + sc->SetValue(id, g.valueAt(i, j)); + } + sgrid->SetPoints(points); + sgrid->GetPointData()->SetScalars(sc); // vmin/vmax 来自 Grid;若退化(==)则用数据极值兜底,避免 LUT/contour 退化。 double vmin = g.vmin, vmax = g.vmax; @@ -60,7 +66,7 @@ GridActors buildGridContour(const geopro::core::Grid& g, const geopro::core::Col auto lut = buildLut(cs, vmin, vmax, kLutLevels); vtkNew surf; - surf->SetInputData(img); + surf->SetInputData(sgrid); vtkNew banded; banded->SetInputConnection(surf->GetOutputPort()); diff --git a/tests/spike/CMakeLists.txt b/tests/spike/CMakeLists.txt index 1ccd9e8..9e1956d 100644 --- a/tests/spike/CMakeLists.txt +++ b/tests/spike/CMakeLists.txt @@ -13,3 +13,9 @@ find_package(VTK REQUIRED COMPONENTS add_executable(grid_contour_spike grid_contour_spike.cpp) target_link_libraries(grid_contour_spike PRIVATE ${VTK_LIBRARIES} nlohmann_json::nlohmann_json) vtk_module_autoinit(TARGETS grid_contour_spike MODULES ${VTK_LIBRARIES}) + +# 离屏渲染验证:用真实数据把剖面/帘面渲成 PNG,肉眼核对方向与 2D/3D 差异。 +add_executable(render_verify render_verify.cpp) +target_link_libraries(render_verify PRIVATE + geopro_render geopro_data geopro_core ${VTK_LIBRARIES}) +vtk_module_autoinit(TARGETS render_verify MODULES ${VTK_LIBRARIES}) diff --git a/tests/spike/render_verify.cpp b/tests/spike/render_verify.cpp new file mode 100644 index 0000000..69c1779 --- /dev/null +++ b/tests/spike/render_verify.cpp @@ -0,0 +1,80 @@ +// 离屏渲染验证:把真实数据渲成 PNG,肉眼核对方向/2D-3D 差异(不靠"进程活着"自欺)。 +// 产出(D:/dev/spike_data/): +// verify_section.png —— 平面反演剖面(#18, 数据详情),应浅部在上、深部在下 +// verify_curtain_top.png —— 帘面俯视(二维),应看到一条沿测线的带(像地图线) +// verify_curtain_3d.png —— 帘面透视(三维),应看到立着的彩色断面墙 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "parse/SampleParsers.hpp" +#include "geo/GeoLocalFrame.hpp" +#include "actors/GridContourActor.hpp" +#include "actors/CurtainActor.hpp" +#include "ColorLutBuilder.hpp" +#include "CameraPreset.hpp" + +static std::string slurp(const char* p) { + std::ifstream f(p); + std::stringstream s; s << f.rdbuf(); return s.str(); +} + +static void renderToPng(vtkRenderer* ren, const char* path, int w, int h) { + vtkNew rw; + rw->SetOffScreenRendering(1); + rw->AddRenderer(ren); + rw->SetSize(w, h); + rw->Render(); + vtkNew w2i; w2i->SetInput(rw); + vtkNew png; png->SetFileName(path); + png->SetInputConnection(w2i->GetOutputPort()); png->Write(); +} + +int main() { + using namespace geopro; + const std::string dir = "D:/dev/spike_data/"; + core::Grid g = data::parseGrid(slurp((dir + "grid.json").c_str())); + core::ColorScale cs = data::parseColorScale(slurp((dir + "colorbar.json").c_str())); + + // 1) 平面剖面 (#18) — 俯视看 XY 平面(face-on) + { + auto a = render::buildGridContour(g, cs); + vtkNew ren; ren->SetBackground(1, 1, 1); + if (a.bands) ren->AddActor(a.bands); + if (a.edges) ren->AddActor(a.edges); + render::applyTop2D(ren); + renderToPng(ren, (dir + "verify_section.png").c_str(), 1100, 320); + } + + // GeoLocalFrame:原点取 lat/lon 均值 + double lat0 = std::accumulate(g.lat.begin(), g.lat.end(), 0.0) / (g.lat.empty() ? 1 : g.lat.size()); + 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) 帘面俯视(二维) + { + auto a = render::buildCurtain(g, cs, frame); + vtkNew ren; ren->SetBackground(1, 1, 1); + ren->AddActor(a); + render::applyTop2D(ren); + renderToPng(ren, (dir + "verify_curtain_top.png").c_str(), 700, 500); + } + // 3) 帘面透视(三维) + { + auto a = render::buildCurtain(g, cs, frame); + vtkNew ren; ren->SetBackground(1, 1, 1); + ren->AddActor(a); + render::applyFree3D(ren); + renderToPng(ren, (dir + "verify_curtain_3d.png").c_str(), 700, 500); + } + std::printf("RENDER_VERIFY_DONE grid=%dx%d lat0=%.5f lon0=%.5f\n", g.nx(), g.ny(), lat0, lon0); + return 0; +}