97 lines
3.9 KiB
C++
97 lines
3.9 KiB
C++
// 离屏渲染验证:把真实数据渲成 PNG,肉眼核对方向/2D-3D 差异(不靠"进程活着"自欺)。
|
||
// 产出(D:/dev/spike_data/):
|
||
// verify_section.png —— 平面反演剖面(#18, 数据详情), 浅部在上、深部在下, 纵向夸张填满
|
||
// verify_curtain_top.png —— 帘面俯视(二维)
|
||
// verify_curtain_3d.png —— 帘面透视(三维)
|
||
#include <fstream>
|
||
#include <numeric>
|
||
#include <sstream>
|
||
#include <string>
|
||
|
||
#include <vtkActor.h>
|
||
#include <vtkNew.h>
|
||
#include <vtkPNGWriter.h>
|
||
#include <vtkRenderWindow.h>
|
||
#include <vtkRenderer.h>
|
||
#include <vtkWindowToImageFilter.h>
|
||
|
||
#include "CameraPreset.hpp"
|
||
#include "ColorLutBuilder.hpp"
|
||
#include "actors/CurtainActor.hpp"
|
||
#include "actors/GridContourActor.hpp"
|
||
#include "actors/MapLineActor.hpp"
|
||
#include "actors/ScatterActor.hpp"
|
||
#include "geo/GeoLocalFrame.hpp"
|
||
#include "parse/SampleParsers.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<vtkRenderWindow> rw;
|
||
rw->SetOffScreenRendering(1);
|
||
rw->AddRenderer(ren);
|
||
rw->SetSize(w, h);
|
||
rw->Render();
|
||
vtkNew<vtkWindowToImageFilter> w2i; w2i->SetInput(rw);
|
||
vtkNew<vtkPNGWriter> 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); 纵向夸张 1.5x 填满宽面板(物探惯例)
|
||
{
|
||
auto a = render::buildGridContour(g, cs);
|
||
const double exag = 1.5;
|
||
vtkNew<vtkRenderer> ren; ren->SetBackground(1, 1, 1);
|
||
if (a.bands) { a.bands->SetScale(1.0, exag, 1.0); ren->AddActor(a.bands); }
|
||
if (a.edges) { a.edges->SetScale(1.0, exag, 1.0); ren->AddActor(a.edges); }
|
||
render::applyTop2D(ren);
|
||
renderToPng(ren, (dir + "verify_section.png").c_str(), 1100, 360);
|
||
}
|
||
|
||
// 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 line = render::buildSurveyLine(g, frame);
|
||
vtkNew<vtkRenderer> ren; ren->SetBackground(0.96, 0.97, 0.99);
|
||
ren->AddActor(line);
|
||
render::applyTop2D(ren);
|
||
renderToPng(ren, (dir + "verify_map.png").c_str(), 700, 500);
|
||
}
|
||
// 3) 帘面透视(三维);纵向夸张 z*3,使 15m 深度相对 62m 长度更像一道墙
|
||
{
|
||
auto a = render::buildCurtain(g, cs, frame);
|
||
a->SetScale(1.0, 1.0, 3.0);
|
||
vtkNew<vtkRenderer> ren; ren->SetBackground(1, 1, 1);
|
||
ren->AddActor(a);
|
||
render::applyFree3D(ren);
|
||
renderToPng(ren, (dir + "verify_curtain_3d.png").c_str(), 700, 500);
|
||
}
|
||
// 4) 散点 (#17) — 剖面原数据彩色方块散点; x=距离, y=深度(取负向下), face-on 俯视
|
||
{
|
||
core::ScatterField s = data::parseScatter(slurp((dir + "scatter.json").c_str()));
|
||
core::ColorScale scs = data::parseColorScale(slurp((dir + "scatter_colorbar.json").c_str()));
|
||
auto a = render::buildScatter(s, scs, 4.0F);
|
||
vtkNew<vtkRenderer> ren; ren->SetBackground(1, 1, 1);
|
||
ren->AddActor(a);
|
||
render::applyTop2D(ren);
|
||
renderToPng(ren, (dir + "verify_scatter.png").c_str(), 1100, 360);
|
||
std::printf("SCATTER pts=%zu\n", s.v.size());
|
||
}
|
||
|
||
std::printf("RENDER_VERIFY_DONE grid=%dx%d lat0=%.5f lon0=%.5f\n", g.nx(), g.ny(), lat0, lon0);
|
||
return 0;
|
||
}
|