#include "actors/ScatterActor.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 buildScatter(const geopro::core::ScatterField& s, const geopro::core::ColorScale& cs, float pointSize) { const std::size_t n = s.v.size(); // 退化输入:无值或 x/y 长度不足 → 空 actor(调用方仍可安全 add,mapper 无输入则不绘制)。 if (n == 0 || s.x.size() < n || s.y.size() < n) { return vtkSmartPointer::New(); } vtkNew points; points->SetNumberOfPoints(static_cast(n)); vtkNew verts; // 每点一个 vtkVertex(GL_POINTS),渲染为方块点 vtkNew sc; sc->SetName("v"); sc->SetNumberOfTuples(static_cast(n)); for (std::size_t i = 0; i < n; ++i) { const auto id = static_cast(i); // y=深度(越大越深)→取负,使深部在下、剖面不倒置(与 GridContourActor 一致)。 points->SetPoint(id, s.x[i], -s.y[i], 0.0); verts->InsertNextCell(1, &id); sc->SetValue(id, s.v[i]); } vtkNew poly; poly->SetPoints(points); poly->SetVerts(verts); poly->GetPointData()->SetScalars(sc); // 色阶范围:优先 colorBar 真实分段值(非均匀),否则回退到 v 实测范围。 const std::vector stops = cs.stopValues(); double vmin, vmax; if (stops.size() >= 2) { vmin = stops.front(); vmax = stops.back(); } else { vmin = s.v.front(); vmax = vmin; for (double v : s.v) { if (v < vmin) vmin = v; if (v > vmax) vmax = v; } if (vmin >= vmax) vmax = vmin + 1.0; } auto lut = buildLut(cs, vmin, vmax, kLutLevels); vtkNew mapper; mapper->SetInputData(poly); mapper->SetScalarModeToUsePointData(); mapper->SetLookupTable(lut); mapper->SetScalarRange(vmin, vmax); auto actor = vtkSmartPointer::New(); actor->SetMapper(mapper); actor->GetProperty()->SetPointSize(pointSize); return actor; } } // namespace geopro::render