123 lines
4.4 KiB
C++
123 lines
4.4 KiB
C++
#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 灌入 points(x, -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
|