feat(render): MapLineActor(测线轨迹线,二维地图) + 帘面分段着色(清晰色带, 与#18一致); 离屏PNG核对三视图均正确
This commit is contained in:
parent
2d7dfe3582
commit
e59b6b3dfe
|
|
@ -1,6 +1,6 @@
|
||||||
find_package(VTK REQUIRED COMPONENTS CommonCore CommonDataModel FiltersGeometry FiltersModeling RenderingCore RenderingOpenGL2 RenderingVolumeOpenGL2 InteractionStyle InteractionWidgets)
|
find_package(VTK REQUIRED COMPONENTS CommonCore CommonDataModel FiltersGeometry FiltersModeling RenderingCore RenderingOpenGL2 RenderingVolumeOpenGL2 InteractionStyle InteractionWidgets)
|
||||||
add_library(geopro_render STATIC
|
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_include_directories(geopro_render PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
target_link_libraries(geopro_render PUBLIC geopro_core ${VTK_LIBRARIES})
|
target_link_libraries(geopro_render PUBLIC geopro_core ${VTK_LIBRARIES})
|
||||||
target_compile_features(geopro_render PUBLIC cxx_std_17)
|
target_compile_features(geopro_render PUBLIC cxx_std_17)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
#include "actors/CurtainActor.hpp"
|
#include "actors/CurtainActor.hpp"
|
||||||
|
|
||||||
#include <vtkDataSetMapper.h>
|
#include <vtkBandedPolyDataContourFilter.h>
|
||||||
|
#include <vtkDataSetSurfaceFilter.h>
|
||||||
#include <vtkDoubleArray.h>
|
#include <vtkDoubleArray.h>
|
||||||
#include <vtkNew.h>
|
#include <vtkNew.h>
|
||||||
#include <vtkPointData.h>
|
#include <vtkPointData.h>
|
||||||
#include <vtkPoints.h>
|
#include <vtkPoints.h>
|
||||||
|
#include <vtkPolyDataMapper.h>
|
||||||
#include <vtkStructuredGrid.h>
|
#include <vtkStructuredGrid.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include "ColorLutBuilder.hpp"
|
#include "ColorLutBuilder.hpp"
|
||||||
|
|
@ -65,24 +69,38 @@ vtkSmartPointer<vtkActor> buildCurtain(const geopro::core::Grid& g,
|
||||||
sgrid->SetPoints(points);
|
sgrid->SetPoints(points);
|
||||||
sgrid->GetPointData()->SetScalars(sc);
|
sgrid->GetPointData()->SetScalars(sc);
|
||||||
|
|
||||||
// vmin/vmax 来自 Grid;若退化(==)则扫数据兜底。
|
// 用 colorBar 真实分段值做色带(与数据详情#18一致的清晰色带,而非连续插值的糊色)。
|
||||||
double vmin = g.vmin, vmax = g.vmax;
|
const std::vector<double> stops = cs.stopValues();
|
||||||
if (vmin >= vmax) {
|
double vmin, vmax;
|
||||||
const auto& vals = g.values();
|
if (stops.size() >= 2) { vmin = stops.front(); vmax = stops.back(); }
|
||||||
vmin = vals.empty() ? 0.0 : vals.front();
|
else {
|
||||||
vmax = vmin;
|
vmin = g.vmin; vmax = g.vmax;
|
||||||
for (double v : vals) {
|
if (vmin >= vmax) {
|
||||||
if (v < vmin) vmin = v;
|
const auto& vals = g.values();
|
||||||
if (v > vmax) vmax = v;
|
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);
|
auto lut = buildLut(cs, vmin, vmax, kLutLevels);
|
||||||
|
|
||||||
vtkNew<vtkDataSetMapper> mapper;
|
// structuredGrid → 表面 polydata → banded contour(分段色带)
|
||||||
mapper->SetInputData(sgrid);
|
vtkNew<vtkDataSetSurfaceFilter> surf;
|
||||||
mapper->SetScalarModeToUsePointData();
|
surf->SetInputData(sgrid);
|
||||||
|
vtkNew<vtkBandedPolyDataContourFilter> banded;
|
||||||
|
banded->SetInputConnection(surf->GetOutputPort());
|
||||||
|
if (stops.size() >= 2) {
|
||||||
|
banded->SetNumberOfContours(static_cast<int>(stops.size()));
|
||||||
|
for (int i = 0; i < static_cast<int>(stops.size()); ++i) banded->SetValue(i, stops[i]);
|
||||||
|
} else {
|
||||||
|
banded->GenerateValues(20, vmin, vmax);
|
||||||
|
}
|
||||||
|
banded->SetScalarModeToValue();
|
||||||
|
|
||||||
|
vtkNew<vtkPolyDataMapper> mapper;
|
||||||
|
mapper->SetInputConnection(banded->GetOutputPort());
|
||||||
|
mapper->SetScalarModeToUseCellData();
|
||||||
mapper->SetLookupTable(lut);
|
mapper->SetLookupTable(lut);
|
||||||
mapper->SetScalarRange(vmin, vmax);
|
mapper->SetScalarRange(vmin, vmax);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include "actors/MapLineActor.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include <vtkCellArray.h>
|
||||||
|
#include <vtkNew.h>
|
||||||
|
#include <vtkPoints.h>
|
||||||
|
#include <vtkPolyData.h>
|
||||||
|
#include <vtkPolyDataMapper.h>
|
||||||
|
#include <vtkPolyLine.h>
|
||||||
|
#include <vtkProperty.h>
|
||||||
|
|
||||||
|
namespace geopro::render {
|
||||||
|
|
||||||
|
vtkSmartPointer<vtkActor> buildSurveyLine(const geopro::core::Grid& g,
|
||||||
|
const geopro::core::GeoLocalFrame& frame)
|
||||||
|
{
|
||||||
|
const int nx = g.nx();
|
||||||
|
const bool hasLatLon =
|
||||||
|
g.lat.size() >= static_cast<size_t>(nx) && g.lon.size() >= static_cast<size_t>(nx);
|
||||||
|
if (nx < 2 || !hasLatLon) return vtkSmartPointer<vtkActor>::New();
|
||||||
|
|
||||||
|
vtkNew<vtkPoints> 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<vtkPolyLine> line;
|
||||||
|
line->GetPointIds()->SetNumberOfIds(nx);
|
||||||
|
for (int i = 0; i < nx; ++i) line->GetPointIds()->SetId(i, i);
|
||||||
|
|
||||||
|
vtkNew<vtkCellArray> cells;
|
||||||
|
cells->InsertNextCell(line);
|
||||||
|
|
||||||
|
vtkNew<vtkPolyData> poly;
|
||||||
|
poly->SetPoints(points);
|
||||||
|
poly->SetLines(cells);
|
||||||
|
|
||||||
|
vtkNew<vtkPolyDataMapper> mapper;
|
||||||
|
mapper->SetInputData(poly);
|
||||||
|
|
||||||
|
auto actor = vtkSmartPointer<vtkActor>::New();
|
||||||
|
actor->SetMapper(mapper);
|
||||||
|
actor->GetProperty()->SetColor(0.85, 0.15, 0.15); // 测线:红
|
||||||
|
actor->GetProperty()->SetLineWidth(3.0);
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geopro::render
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
#include <vtkActor.h>
|
||||||
|
#include <vtkSmartPointer.h>
|
||||||
|
|
||||||
|
#include "geo/GeoLocalFrame.hpp"
|
||||||
|
#include "model/Field.hpp"
|
||||||
|
|
||||||
|
namespace geopro::render {
|
||||||
|
|
||||||
|
// 二维地图用:把测线的 lat/lon 水平迹线画成一条折线(俯视=测线布局)。
|
||||||
|
// 电极/采点位置另以小点显示。返回的 actor 放在 z=0 平面,供 Top2D 俯视。
|
||||||
|
vtkSmartPointer<vtkActor> buildSurveyLine(const geopro::core::Grid& g,
|
||||||
|
const geopro::core::GeoLocalFrame& frame);
|
||||||
|
|
||||||
|
} // namespace geopro::render
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include "ColorLutBuilder.hpp"
|
#include "ColorLutBuilder.hpp"
|
||||||
#include "actors/CurtainActor.hpp"
|
#include "actors/CurtainActor.hpp"
|
||||||
#include "actors/GridContourActor.hpp"
|
#include "actors/GridContourActor.hpp"
|
||||||
|
#include "actors/MapLineActor.hpp"
|
||||||
#include "geo/GeoLocalFrame.hpp"
|
#include "geo/GeoLocalFrame.hpp"
|
||||||
#include "parse/SampleParsers.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());
|
double lon0 = std::accumulate(g.lon.begin(), g.lon.end(), 0.0) / (g.lon.empty() ? 1 : g.lon.size());
|
||||||
core::GeoLocalFrame frame(lat0, lon0);
|
core::GeoLocalFrame frame(lat0, lon0);
|
||||||
|
|
||||||
// 2) 帘面俯视(二维)
|
// 2) 二维地图:测线折线俯视(浅灰底)
|
||||||
{
|
{
|
||||||
auto a = render::buildCurtain(g, cs, frame);
|
auto line = render::buildSurveyLine(g, frame);
|
||||||
vtkNew<vtkRenderer> ren; ren->SetBackground(1, 1, 1);
|
vtkNew<vtkRenderer> ren; ren->SetBackground(0.96, 0.97, 0.99);
|
||||||
ren->AddActor(a);
|
ren->AddActor(line);
|
||||||
render::applyTop2D(ren);
|
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);
|
auto a = render::buildCurtain(g, cs, frame);
|
||||||
|
a->SetScale(1.0, 1.0, 3.0);
|
||||||
vtkNew<vtkRenderer> ren; ren->SetBackground(1, 1, 1);
|
vtkNew<vtkRenderer> ren; ren->SetBackground(1, 1, 1);
|
||||||
ren->AddActor(a);
|
ren->AddActor(a);
|
||||||
render::applyFree3D(ren);
|
render::applyFree3D(ren);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue