You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmSubWxs/nmPebiResultWellAnnotationL...

251 lines
8.7 KiB
C++

#include "nmPebiResultWellAnnotationLayer.h"
#include "nmPebiResultSnapshot.h"
#include <QCoreApplication>
#include <QSet>
#include <QThread>
#include <vtkActor2D.h>
#include <vtkCellArray.h>
#include <vtkCoordinate.h>
#include <vtkLabeledDataMapper.h>
#include <vtkMath.h>
#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkPropAssembly.h>
#include <vtkProperty2D.h>
#include <vtkStringArray.h>
#include <vtkTextProperty.h>
namespace {
bool isWellAnnotationGuiThread()
{
QCoreApplication* pApplication = QCoreApplication::instance();
return pApplication == nullptr ||
pApplication->thread() == QThread::currentThread();
}
}
nmPebiResultWellAnnotationLayer::nmPebiResultWellAnnotationLayer(
const QString& sLayerId)
: nmVTKRenderLayer(sLayerId),
m_pRootAssembly(vtkSmartPointer<vtkPropAssembly>::New()),
m_pActiveSnapshotAssembly(nullptr),
m_pActiveMarkerGroup(nullptr),
m_pActiveNameGroup(nullptr),
m_pCandidateSnapshotAssembly(nullptr),
m_pCandidateMarkerGroup(nullptr),
m_pCandidateNameGroup(nullptr),
m_bWellMarkersVisible(true),
m_bWellNamesVisible(true)
{
Q_ASSERT(isWellAnnotationGuiThread());
// setRenderProp 只在未挂载时可调用,因此根 Assembly 在构造时一次固定。
setRenderProp(m_pRootAssembly);
}
nmPebiResultWellAnnotationLayer::~nmPebiResultWellAnnotationLayer()
{
Q_ASSERT(isWellAnnotationGuiThread());
detach();
clear();
m_pRootAssembly = nullptr;
}
bool nmPebiResultWellAnnotationLayer::prepareCandidate(
const QSharedPointer<const nmPebiResultSnapshot>& pSnapshot)
{
Q_ASSERT(isWellAnnotationGuiThread());
discardCandidate();
if(!isWellAnnotationGuiThread() || pSnapshot.isNull() ||
!pSnapshot->isComplete()) {
return false;
}
vtkSmartPointer<vtkPoints> pMarkerPoints =
vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkCellArray> pMarkerVertices =
vtkSmartPointer<vtkCellArray>::New();
vtkSmartPointer<vtkPoints> pNamePoints =
vtkSmartPointer<vtkPoints>::New();
vtkSmartPointer<vtkStringArray> pWellNames =
vtkSmartPointer<vtkStringArray>::New();
pWellNames->SetName("WellName");
QSet<QString> setWellIds;
for(int nIndex = 0; nIndex < pSnapshot->getWellCount(); ++nIndex) {
const nmPebiResultWellSnapshot* pWell = pSnapshot->getWellAt(nIndex);
if(pWell == nullptr || pWell->m_sWellInstanceId.isEmpty() ||
pWell->m_sWellName.isEmpty() ||
!vtkMath::IsFinite(pWell->m_oLocation.x()) ||
!vtkMath::IsFinite(pWell->m_oLocation.y()) ||
setWellIds.contains(pWell->m_sWellInstanceId)) {
discardCandidate();
return false;
}
setWellIds.insert(pWell->m_sWellInstanceId);
// 保持快照存储顺序;二维 Overlay 不向业务位置写入虚构 Z 值。
const vtkIdType nPointId = pMarkerPoints->InsertNextPoint(
pWell->m_oLocation.x(), pWell->m_oLocation.y(), 0.0);
pMarkerVertices->InsertNextCell(1);
pMarkerVertices->InsertCellPoint(nPointId);
pNamePoints->InsertNextPoint(
pWell->m_oLocation.x(), pWell->m_oLocation.y(), 0.0);
const QByteArray aWellName = pWell->m_sWellName.toUtf8();
pWellNames->InsertNextValue(aWellName.constData());
}
vtkSmartPointer<vtkPropAssembly> pSnapshotAssembly =
vtkSmartPointer<vtkPropAssembly>::New();
vtkSmartPointer<vtkPropAssembly> pMarkerGroup =
vtkSmartPointer<vtkPropAssembly>::New();
vtkSmartPointer<vtkPropAssembly> pNameGroup =
vtkSmartPointer<vtkPropAssembly>::New();
if(pSnapshot->getWellCount() > 0) {
vtkSmartPointer<vtkPolyData> pMarkerData =
vtkSmartPointer<vtkPolyData>::New();
pMarkerData->SetPoints(pMarkerPoints);
pMarkerData->SetVerts(pMarkerVertices);
vtkSmartPointer<vtkCoordinate> pWorldCoordinate =
vtkSmartPointer<vtkCoordinate>::New();
pWorldCoordinate->SetCoordinateSystemToWorld();
vtkSmartPointer<vtkPolyDataMapper2D> pMarkerMapper =
vtkSmartPointer<vtkPolyDataMapper2D>::New();
pMarkerMapper->SetInputData(pMarkerData);
pMarkerMapper->SetTransformCoordinate(pWorldCoordinate);
pMarkerMapper->ScalarVisibilityOff();
vtkSmartPointer<vtkActor2D> pMarkerActor =
vtkSmartPointer<vtkActor2D>::New();
pMarkerActor->SetMapper(pMarkerMapper);
pMarkerActor->GetProperty()->SetColor(0.12, 0.12, 0.12);
pMarkerActor->GetProperty()->SetPointSize(9.0);
pMarkerGroup->AddPart(pMarkerActor);
vtkSmartPointer<vtkPolyData> pNameData =
vtkSmartPointer<vtkPolyData>::New();
pNameData->SetPoints(pNamePoints);
pNameData->GetPointData()->AddArray(pWellNames);
vtkSmartPointer<vtkLabeledDataMapper> pNameMapper =
vtkSmartPointer<vtkLabeledDataMapper>::New();
pNameMapper->SetInputData(pNameData);
pNameMapper->SetLabelModeToLabelFieldData();
pNameMapper->SetFieldDataName("WellName");
pNameMapper->SetLabelFormat("%s");
pNameMapper->GetLabelTextProperty()->SetFontSize(12);
pNameMapper->GetLabelTextProperty()->SetColor(0.10, 0.10, 0.10);
pNameMapper->GetLabelTextProperty()->BoldOff();
pNameMapper->GetLabelTextProperty()->ItalicOff();
pNameMapper->GetLabelTextProperty()->ShadowOff();
pNameMapper->GetLabelTextProperty()->SetJustificationToLeft();
pNameMapper->GetLabelTextProperty()->SetVerticalJustificationToBottom();
vtkSmartPointer<vtkActor2D> pNameActor =
vtkSmartPointer<vtkActor2D>::New();
pNameActor->SetMapper(pNameMapper);
// Actor2D 的显示坐标偏移固定为像素,不随相机缩放改变。
pNameActor->SetDisplayPosition(7, 6);
pNameGroup->AddPart(pNameActor);
}
pMarkerGroup->SetVisibility(m_bWellMarkersVisible ? 1 : 0);
pNameGroup->SetVisibility(m_bWellNamesVisible ? 1 : 0);
pSnapshotAssembly->AddPart(pMarkerGroup);
pSnapshotAssembly->AddPart(pNameGroup);
// 所有校验和 VTK 对象构造成功后才记录候选;活动子树仍未触碰。
m_pCandidateSnapshotAssembly = pSnapshotAssembly;
m_pCandidateMarkerGroup = pMarkerGroup;
m_pCandidateNameGroup = pNameGroup;
return true;
}
void nmPebiResultWellAnnotationLayer::discardCandidate()
{
Q_ASSERT(isWellAnnotationGuiThread());
m_pCandidateNameGroup = nullptr;
m_pCandidateMarkerGroup = nullptr;
m_pCandidateSnapshotAssembly = nullptr;
}
void nmPebiResultWellAnnotationLayer::commitCandidate()
{
Q_ASSERT(isWellAnnotationGuiThread());
Q_ASSERT(m_pCandidateSnapshotAssembly != nullptr);
if(m_pActiveSnapshotAssembly != nullptr) {
m_pRootAssembly->RemovePart(m_pActiveSnapshotAssembly);
}
m_pActiveSnapshotAssembly = m_pCandidateSnapshotAssembly;
m_pActiveMarkerGroup = m_pCandidateMarkerGroup;
m_pActiveNameGroup = m_pCandidateNameGroup;
m_pRootAssembly->AddPart(m_pActiveSnapshotAssembly);
discardCandidate();
}
void nmPebiResultWellAnnotationLayer::clear()
{
Q_ASSERT(isWellAnnotationGuiThread());
discardCandidate();
if(m_pRootAssembly != nullptr &&
m_pActiveSnapshotAssembly != nullptr) {
m_pRootAssembly->RemovePart(m_pActiveSnapshotAssembly);
}
m_pActiveNameGroup = nullptr;
m_pActiveMarkerGroup = nullptr;
m_pActiveSnapshotAssembly = nullptr;
}
bool nmPebiResultWellAnnotationLayer::hasActiveAnnotations() const
{
return m_pActiveSnapshotAssembly != nullptr;
}
void nmPebiResultWellAnnotationLayer::setWellMarkersVisible(bool bVisible)
{
Q_ASSERT(isWellAnnotationGuiThread());
if(!isWellAnnotationGuiThread()) {
return;
}
m_bWellMarkersVisible = bVisible;
if(m_pActiveMarkerGroup != nullptr) {
m_pActiveMarkerGroup->SetVisibility(bVisible ? 1 : 0);
}
if(m_pCandidateMarkerGroup != nullptr) {
m_pCandidateMarkerGroup->SetVisibility(bVisible ? 1 : 0);
}
}
void nmPebiResultWellAnnotationLayer::setWellNamesVisible(bool bVisible)
{
Q_ASSERT(isWellAnnotationGuiThread());
if(!isWellAnnotationGuiThread()) {
return;
}
m_bWellNamesVisible = bVisible;
if(m_pActiveNameGroup != nullptr) {
m_pActiveNameGroup->SetVisibility(bVisible ? 1 : 0);
}
if(m_pCandidateNameGroup != nullptr) {
m_pCandidateNameGroup->SetVisibility(bVisible ? 1 : 0);
}
}
bool nmPebiResultWellAnnotationLayer::areWellMarkersVisible() const
{
return m_bWellMarkersVisible;
}
bool nmPebiResultWellAnnotationLayer::areWellNamesVisible() const
{
return m_bWellNamesVisible;
}