geopro/src/render/actors/CurtainActor.cpp

113 lines
3.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "actors/CurtainActor.hpp"
#include <vtkBandedPolyDataContourFilter.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkDoubleArray.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPolyDataMapper.h>
#include <vtkStructuredGrid.h>
#include <vector>
#include <cstddef>
#include "ColorLutBuilder.hpp"
namespace geopro::render {
namespace {
// LUT 级数。
constexpr int kLutLevels = 256;
} // namespace
vtkSmartPointer<vtkActor> buildCurtain(const geopro::core::Grid& g,
const geopro::core::ColorScale& cs,
const geopro::core::GeoLocalFrame& frame)
{
const int nx = g.nx(), ny = g.ny();
// 退化网格:返回空 actor调用方仍可安全 addActormapper 无输入则不绘制)。
if (nx < 1 || ny < 1 || g.y.size() < static_cast<size_t>(ny)) {
return vtkSmartPointer<vtkActor>::New();
}
const bool hasLatLon =
g.lat.size() >= static_cast<size_t>(nx) && g.lon.size() >= static_cast<size_t>(nx);
// 结构化网格:维度 (nx, ny, 1),点序 i 最快、j 次之id = j*nx + i
vtkNew<vtkStructuredGrid> sgrid;
sgrid->SetDimensions(nx, ny, 1);
vtkNew<vtkPoints> points;
points->SetNumberOfPoints(static_cast<vtkIdType>(nx) * ny);
vtkNew<vtkDoubleArray> sc;
sc->SetName("v");
sc->SetNumberOfTuples(static_cast<vtkIdType>(nx) * ny);
for (int j = 0; j < ny; ++j) {
for (int i = 0; i < nx; ++i) {
double px, py;
if (hasLatLon) {
auto p = frame.toLocal(g.lat[i], g.lon[i]);
px = p.x;
py = p.y;
} else {
// 退化:用 g.x[i] 作 x、0 作 y。
px = (g.x.size() > static_cast<size_t>(i)) ? g.x[i] : static_cast<double>(i);
py = 0.0;
}
const vtkIdType id = static_cast<vtkIdType>(j) * nx + i;
// g.y 是深度(越大越深)VTK Z 向上 → 取负,使深部在下、浅部在上(剖面不倒置)。
points->SetPoint(id, px, py, -g.y[j]);
sc->SetValue(id, g.valueAt(i, j));
}
}
sgrid->SetPoints(points);
sgrid->GetPointData()->SetScalars(sc);
// 用 colorBar 真实分段值做色带(与数据详情#18一致的清晰色带而非连续插值的糊色)。
const std::vector<double> 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;
}
}
auto lut = buildLut(cs, vmin, vmax, kLutLevels);
// structuredGrid → 表面 polydata → banded contour(分段色带)
vtkNew<vtkDataSetSurfaceFilter> surf;
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->SetScalarRange(vmin, vmax);
auto actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
return actor;
}
} // namespace geopro::render