#include "actors/CurtainActor.hpp" #include #include #include #include #include #include #include #include #include #include #include "ColorLutBuilder.hpp" namespace geopro::render { namespace { // LUT 级数。 constexpr int kLutLevels = 256; } // namespace vtkSmartPointer 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(调用方仍可安全 addActor,mapper 无输入则不绘制)。 if (nx < 1 || ny < 1 || g.y.size() < static_cast(ny)) { return vtkSmartPointer::New(); } const bool hasLatLon = g.lat.size() >= static_cast(nx) && g.lon.size() >= static_cast(nx); // 结构化网格:维度 (nx, ny, 1),点序 i 最快、j 次之(id = j*nx + i)。 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) { 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(i)) ? g.x[i] : static_cast(i); py = 0.0; } const vtkIdType id = static_cast(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 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 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); auto actor = vtkSmartPointer::New(); actor->SetMapper(mapper); return actor; } } // namespace geopro::render