#include "actors/AnomalyActor.hpp" #include #include #include #include #include #include #include #include #include "model/ColorScale.hpp" namespace geopro::render { namespace { // 虚线点画图案(16 位)与重复因子;dashed 异常用。 constexpr int kDashPattern = 0xF0F0; constexpr int kDashRepeat = 1; // Point 型异常的小球像素直径(RenderPointsAsSpheres 下为球径)。 constexpr float kPointSize = 13.0F; // 把一个异常的 localPts 灌入 points(x, -y, 0:深度取负,与 #18 同坐标系)。 void fillPoints2D(vtkPoints* points, const geopro::core::Anomaly& a) { points->SetNumberOfPoints(static_cast(a.localPts.size())); for (std::size_t i = 0; i < a.localPts.size(); ++i) { points->SetPoint(static_cast(i), a.localPts[i].x, -a.localPts[i].y, 0.0); } } // 把一个异常的 worldPts 灌入 points(世界 3D 坐标,直接用,不翻 y/不压 z)。 void fillPoints3D(vtkPoints* points, const geopro::core::Anomaly& a) { points->SetNumberOfPoints(static_cast(a.worldPts.size())); for (std::size_t i = 0; i < a.worldPts.size(); ++i) { points->SetPoint(static_cast(i), a.worldPts[i].x, a.worldPts[i].y, a.worldPts[i].z); } } // 由已灌点的 points + 异常样式/类型,构建单个 actor(点/折线/闭合多边形 + 颜色/线宽/虚线)。 vtkSmartPointer buildActor(vtkPoints* points, std::size_t n, const geopro::core::Anomaly& a) { vtkNew poly; poly->SetPoints(points); const bool asPoints = (a.markType == geopro::core::AnomalyMarkType::Point); if (asPoints) { vtkNew verts; for (std::size_t i = 0; i < n; ++i) { const auto id = static_cast(i); verts->InsertNextCell(1, &id); } poly->SetVerts(verts); } else { // 线/面型:经各点的折线;面(Polygon)闭合(首尾相连)成轮廓。 const bool closed = (a.markType == geopro::core::AnomalyMarkType::Polygon) && n >= 3; const vtkIdType count = static_cast(n) + (closed ? 1 : 0); vtkNew line; line->GetPointIds()->SetNumberOfIds(count); for (std::size_t i = 0; i < n; ++i) { line->GetPointIds()->SetId(static_cast(i), static_cast(i)); } if (closed) line->GetPointIds()->SetId(static_cast(n), 0); // 回到起点 vtkNew cells; cells->InsertNextCell(line); poly->SetLines(cells); } vtkNew mapper; mapper->SetInputData(poly); mapper->ScalarVisibilityOff(); // 用 actor 单色,不用标量上色 auto actor = vtkSmartPointer::New(); actor->SetMapper(mapper); const auto c = geopro::core::parseColor(a.lineColor, geopro::core::AlphaScale::Bit255); actor->GetProperty()->SetColor(c.r / 255.0, c.g / 255.0, c.b / 255.0); if (asPoints) { actor->GetProperty()->SetPointSize(kPointSize); actor->GetProperty()->SetRenderPointsAsSpheres(true); // 点异常渲染为小球(非扁平方点) } else { actor->GetProperty()->SetLineWidth(a.lineWidth > 0.0 ? a.lineWidth : 1.0); if (a.dashed) { actor->GetProperty()->SetLineStipplePattern(kDashPattern); actor->GetProperty()->SetLineStippleRepeatFactor(kDashRepeat); } } return actor; } } // namespace std::vector> buildAnomalies( const std::vector& anomalies) { std::vector> out; out.reserve(anomalies.size()); for (const auto& a : anomalies) { const std::size_t n = a.localPts.size(); if (n == 0) continue; // 无几何,跳过 vtkNew points; fillPoints2D(points, a); out.push_back(buildActor(points, n, a)); } return out; } vtkSmartPointer buildAnomaly3D(const geopro::core::Anomaly& a) { const std::size_t n = a.worldPts.size(); if (n == 0) return nullptr; // 无 3D 几何 vtkNew points; fillPoints3D(points, a); return buildActor(points, n, a); } } // namespace geopro::render