geopro/src/render/actors/AnomalyActor.cpp

123 lines
4.4 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/AnomalyActor.hpp"
#include <cstddef>
#include <vtkCellArray.h>
#include <vtkNew.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkPolyLine.h>
#include <vtkProperty.h>
#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 灌入 pointsx, -y, 0深度取负与 #18 同坐标系)。
void fillPoints2D(vtkPoints* points, const geopro::core::Anomaly& a)
{
points->SetNumberOfPoints(static_cast<vtkIdType>(a.localPts.size()));
for (std::size_t i = 0; i < a.localPts.size(); ++i) {
points->SetPoint(static_cast<vtkIdType>(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<vtkIdType>(a.worldPts.size()));
for (std::size_t i = 0; i < a.worldPts.size(); ++i) {
points->SetPoint(static_cast<vtkIdType>(i), a.worldPts[i].x, a.worldPts[i].y,
a.worldPts[i].z);
}
}
// 由已灌点的 points + 异常样式/类型,构建单个 actor点/折线/闭合多边形 + 颜色/线宽/虚线)。
vtkSmartPointer<vtkActor> buildActor(vtkPoints* points, std::size_t n,
const geopro::core::Anomaly& a)
{
vtkNew<vtkPolyData> poly;
poly->SetPoints(points);
const bool asPoints = (a.markType == geopro::core::AnomalyMarkType::Point);
if (asPoints) {
vtkNew<vtkCellArray> verts;
for (std::size_t i = 0; i < n; ++i) {
const auto id = static_cast<vtkIdType>(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<vtkIdType>(n) + (closed ? 1 : 0);
vtkNew<vtkPolyLine> line;
line->GetPointIds()->SetNumberOfIds(count);
for (std::size_t i = 0; i < n; ++i) {
line->GetPointIds()->SetId(static_cast<vtkIdType>(i), static_cast<vtkIdType>(i));
}
if (closed) line->GetPointIds()->SetId(static_cast<vtkIdType>(n), 0); // 回到起点
vtkNew<vtkCellArray> cells;
cells->InsertNextCell(line);
poly->SetLines(cells);
}
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(poly);
mapper->ScalarVisibilityOff(); // 用 actor 单色,不用标量上色
auto actor = vtkSmartPointer<vtkActor>::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<vtkSmartPointer<vtkActor>> buildAnomalies(
const std::vector<geopro::core::Anomaly>& anomalies)
{
std::vector<vtkSmartPointer<vtkActor>> out;
out.reserve(anomalies.size());
for (const auto& a : anomalies) {
const std::size_t n = a.localPts.size();
if (n == 0) continue; // 无几何,跳过
vtkNew<vtkPoints> points;
fillPoints2D(points, a);
out.push_back(buildActor(points, n, a));
}
return out;
}
vtkSmartPointer<vtkActor> buildAnomaly3D(const geopro::core::Anomaly& a)
{
const std::size_t n = a.worldPts.size();
if (n == 0) return nullptr; // 无 3D 几何
vtkNew<vtkPoints> points;
fillPoints3D(points, a);
return buildActor(points, n, a);
}
} // namespace geopro::render