|
|
|
|
@ -2,22 +2,18 @@
|
|
|
|
|
|
|
|
|
|
#include "nmPebiResultSnapshot.h"
|
|
|
|
|
|
|
|
|
|
#include <QByteArray>
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
#include <QSet>
|
|
|
|
|
#include <QThread>
|
|
|
|
|
|
|
|
|
|
#include <vtkActor2D.h>
|
|
|
|
|
#include <vtkCellArray.h>
|
|
|
|
|
#include <vtkCoordinate.h>
|
|
|
|
|
#include <vtkLabeledDataMapper.h>
|
|
|
|
|
#include <vtkLeaderActor2D.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 <vtkTextMapper.h>
|
|
|
|
|
#include <vtkTextProperty.h>
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
@ -29,6 +25,17 @@ bool isWellAnnotationGuiThread()
|
|
|
|
|
pApplication->thread() == QThread::currentThread();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Saphir 风格标注使用固定像素偏移,缩放相机时文字和引线长度保持不变。
|
|
|
|
|
const int WELL_NAME_FONT_SIZE = 16;
|
|
|
|
|
const int WELL_NAME_OFFSET_X = 18;
|
|
|
|
|
const int WELL_NAME_OFFSET_Y = 40;
|
|
|
|
|
const int WELL_LEADER_OFFSET_X = 14;
|
|
|
|
|
const int WELL_LEADER_OFFSET_Y = 36;
|
|
|
|
|
|
|
|
|
|
const double WELL_LEADER_RED = 140.0 / 255.0;
|
|
|
|
|
const double WELL_LEADER_GREEN = 87.0 / 255.0;
|
|
|
|
|
const double WELL_LEADER_BLUE = 59.0 / 255.0;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nmPebiResultWellAnnotationLayer::nmPebiResultWellAnnotationLayer(
|
|
|
|
|
@ -36,12 +43,9 @@ nmPebiResultWellAnnotationLayer::nmPebiResultWellAnnotationLayer(
|
|
|
|
|
: nmVTKRenderLayer(sLayerId),
|
|
|
|
|
m_pRootAssembly(vtkSmartPointer<vtkPropAssembly>::New()),
|
|
|
|
|
m_pActiveSnapshotAssembly(nullptr),
|
|
|
|
|
m_pActiveMarkerGroup(nullptr),
|
|
|
|
|
m_pActiveNameGroup(nullptr),
|
|
|
|
|
m_pActiveAnnotationGroup(nullptr),
|
|
|
|
|
m_pCandidateSnapshotAssembly(nullptr),
|
|
|
|
|
m_pCandidateMarkerGroup(nullptr),
|
|
|
|
|
m_pCandidateNameGroup(nullptr),
|
|
|
|
|
m_bWellMarkersVisible(true),
|
|
|
|
|
m_pCandidateAnnotationGroup(nullptr),
|
|
|
|
|
m_bWellNamesVisible(true)
|
|
|
|
|
{
|
|
|
|
|
Q_ASSERT(isWellAnnotationGuiThread());
|
|
|
|
|
@ -67,16 +71,6 @@ bool nmPebiResultWellAnnotationLayer::prepareCandidate(
|
|
|
|
|
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);
|
|
|
|
|
@ -89,90 +83,103 @@ bool nmPebiResultWellAnnotationLayer::prepareCandidate(
|
|
|
|
|
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> pAnnotationGroup =
|
|
|
|
|
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);
|
|
|
|
|
for(int nIndex = 0; nIndex < pSnapshot->getWellCount(); ++nIndex) {
|
|
|
|
|
const nmPebiResultWellSnapshot* pWell =
|
|
|
|
|
pSnapshot->getWellAt(nIndex);
|
|
|
|
|
vtkSmartPointer<vtkCoordinate> pWorldAnchor =
|
|
|
|
|
vtkSmartPointer<vtkCoordinate>::New();
|
|
|
|
|
// Z=0 仅表示冻结 XY 所在平面,不表示井深、井斜或井轨迹。
|
|
|
|
|
pWorldAnchor->SetCoordinateSystemToWorld();
|
|
|
|
|
pWorldAnchor->SetValue(
|
|
|
|
|
pWell->m_oLocation.x(),
|
|
|
|
|
pWell->m_oLocation.y(), 0.0);
|
|
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkPropAssembly> pWellAnnotation =
|
|
|
|
|
vtkSmartPointer<vtkPropAssembly>::New();
|
|
|
|
|
vtkSmartPointer<vtkLeaderActor2D> pLeader =
|
|
|
|
|
vtkSmartPointer<vtkLeaderActor2D>::New();
|
|
|
|
|
|
|
|
|
|
// 引线两个端点都引用同一 World 锚点,只叠加固定 Display 像素偏移。
|
|
|
|
|
vtkCoordinate* pStartCoordinate =
|
|
|
|
|
pLeader->GetPositionCoordinate();
|
|
|
|
|
pStartCoordinate->SetCoordinateSystemToDisplay();
|
|
|
|
|
pStartCoordinate->SetReferenceCoordinate(pWorldAnchor);
|
|
|
|
|
pStartCoordinate->SetValue(0.0, 0.0, 0.0);
|
|
|
|
|
vtkCoordinate* pEndCoordinate =
|
|
|
|
|
pLeader->GetPosition2Coordinate();
|
|
|
|
|
pEndCoordinate->SetCoordinateSystemToDisplay();
|
|
|
|
|
pEndCoordinate->SetReferenceCoordinate(pWorldAnchor);
|
|
|
|
|
pEndCoordinate->SetValue(
|
|
|
|
|
WELL_LEADER_OFFSET_X, WELL_LEADER_OFFSET_Y, 0.0);
|
|
|
|
|
|
|
|
|
|
pLeader->AutoLabelOff();
|
|
|
|
|
pLeader->SetLabel("");
|
|
|
|
|
pLeader->SetArrowPlacementToNone();
|
|
|
|
|
pLeader->SetRadius(0.0);
|
|
|
|
|
pLeader->GetProperty()->SetColor(
|
|
|
|
|
WELL_LEADER_RED,
|
|
|
|
|
WELL_LEADER_GREEN,
|
|
|
|
|
WELL_LEADER_BLUE);
|
|
|
|
|
pLeader->GetProperty()->SetLineWidth(1.0);
|
|
|
|
|
// 二维引线始终绘制在三维网格前方,避免被致密单元边线遮挡。
|
|
|
|
|
pLeader->GetProperty()->SetDisplayLocationToForeground();
|
|
|
|
|
pWellAnnotation->AddPart(pLeader);
|
|
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkTextMapper> pNameMapper =
|
|
|
|
|
vtkSmartPointer<vtkTextMapper>::New();
|
|
|
|
|
const QByteArray aWellName = pWell->m_sWellName.toUtf8();
|
|
|
|
|
pNameMapper->SetInput(aWellName.constData());
|
|
|
|
|
vtkTextProperty* pTextProperty =
|
|
|
|
|
pNameMapper->GetTextProperty();
|
|
|
|
|
pTextProperty->SetFontFamilyToArial();
|
|
|
|
|
pTextProperty->SetFontSize(WELL_NAME_FONT_SIZE);
|
|
|
|
|
pTextProperty->SetColor(1.0, 1.0, 0.0);
|
|
|
|
|
pTextProperty->BoldOff();
|
|
|
|
|
pTextProperty->ItalicOff();
|
|
|
|
|
pTextProperty->ShadowOn();
|
|
|
|
|
pTextProperty->SetShadowOffset(1, -1);
|
|
|
|
|
pTextProperty->SetJustificationToLeft();
|
|
|
|
|
pTextProperty->SetVerticalJustificationToBottom();
|
|
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkActor2D> pNameActor =
|
|
|
|
|
vtkSmartPointer<vtkActor2D>::New();
|
|
|
|
|
pNameActor->SetMapper(pNameMapper);
|
|
|
|
|
// 井名与引线使用相同的前景层级,保证顶视图下仍清晰可读。
|
|
|
|
|
pNameActor->GetProperty()->SetDisplayLocationToForeground();
|
|
|
|
|
vtkCoordinate* pNameCoordinate =
|
|
|
|
|
pNameActor->GetPositionCoordinate();
|
|
|
|
|
pNameCoordinate->SetCoordinateSystemToDisplay();
|
|
|
|
|
pNameCoordinate->SetReferenceCoordinate(pWorldAnchor);
|
|
|
|
|
pNameCoordinate->SetValue(
|
|
|
|
|
WELL_NAME_OFFSET_X, WELL_NAME_OFFSET_Y, 0.0);
|
|
|
|
|
pWellAnnotation->AddPart(pNameActor);
|
|
|
|
|
|
|
|
|
|
// 每口井的文字与引线形成一个不可拆分的候选注记单元。
|
|
|
|
|
pAnnotationGroup->AddPart(pWellAnnotation);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pMarkerGroup->SetVisibility(m_bWellMarkersVisible ? 1 : 0);
|
|
|
|
|
pNameGroup->SetVisibility(m_bWellNamesVisible ? 1 : 0);
|
|
|
|
|
pSnapshotAssembly->AddPart(pMarkerGroup);
|
|
|
|
|
pSnapshotAssembly->AddPart(pNameGroup);
|
|
|
|
|
pAnnotationGroup->SetVisibility(m_bWellNamesVisible ? 1 : 0);
|
|
|
|
|
pSnapshotAssembly->AddPart(pAnnotationGroup);
|
|
|
|
|
|
|
|
|
|
// 所有校验和 VTK 对象构造成功后才记录候选;活动子树仍未触碰。
|
|
|
|
|
m_pCandidateSnapshotAssembly = pSnapshotAssembly;
|
|
|
|
|
m_pCandidateMarkerGroup = pMarkerGroup;
|
|
|
|
|
m_pCandidateNameGroup = pNameGroup;
|
|
|
|
|
m_pCandidateAnnotationGroup = pAnnotationGroup;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmPebiResultWellAnnotationLayer::discardCandidate()
|
|
|
|
|
{
|
|
|
|
|
Q_ASSERT(isWellAnnotationGuiThread());
|
|
|
|
|
m_pCandidateNameGroup = nullptr;
|
|
|
|
|
m_pCandidateMarkerGroup = nullptr;
|
|
|
|
|
m_pCandidateAnnotationGroup = nullptr;
|
|
|
|
|
m_pCandidateSnapshotAssembly = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -185,8 +192,7 @@ void nmPebiResultWellAnnotationLayer::commitCandidate()
|
|
|
|
|
m_pRootAssembly->RemovePart(m_pActiveSnapshotAssembly);
|
|
|
|
|
}
|
|
|
|
|
m_pActiveSnapshotAssembly = m_pCandidateSnapshotAssembly;
|
|
|
|
|
m_pActiveMarkerGroup = m_pCandidateMarkerGroup;
|
|
|
|
|
m_pActiveNameGroup = m_pCandidateNameGroup;
|
|
|
|
|
m_pActiveAnnotationGroup = m_pCandidateAnnotationGroup;
|
|
|
|
|
m_pRootAssembly->AddPart(m_pActiveSnapshotAssembly);
|
|
|
|
|
discardCandidate();
|
|
|
|
|
}
|
|
|
|
|
@ -199,8 +205,7 @@ void nmPebiResultWellAnnotationLayer::clear()
|
|
|
|
|
m_pActiveSnapshotAssembly != nullptr) {
|
|
|
|
|
m_pRootAssembly->RemovePart(m_pActiveSnapshotAssembly);
|
|
|
|
|
}
|
|
|
|
|
m_pActiveNameGroup = nullptr;
|
|
|
|
|
m_pActiveMarkerGroup = nullptr;
|
|
|
|
|
m_pActiveAnnotationGroup = nullptr;
|
|
|
|
|
m_pActiveSnapshotAssembly = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -209,21 +214,6 @@ 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());
|
|
|
|
|
@ -231,19 +221,14 @@ void nmPebiResultWellAnnotationLayer::setWellNamesVisible(bool bVisible)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
m_bWellNamesVisible = bVisible;
|
|
|
|
|
if(m_pActiveNameGroup != nullptr) {
|
|
|
|
|
m_pActiveNameGroup->SetVisibility(bVisible ? 1 : 0);
|
|
|
|
|
if(m_pActiveAnnotationGroup != nullptr) {
|
|
|
|
|
m_pActiveAnnotationGroup->SetVisibility(bVisible ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
if(m_pCandidateNameGroup != nullptr) {
|
|
|
|
|
m_pCandidateNameGroup->SetVisibility(bVisible ? 1 : 0);
|
|
|
|
|
if(m_pCandidateAnnotationGroup != nullptr) {
|
|
|
|
|
m_pCandidateAnnotationGroup->SetVisibility(bVisible ? 1 : 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nmPebiResultWellAnnotationLayer::areWellMarkersVisible() const
|
|
|
|
|
{
|
|
|
|
|
return m_bWellMarkersVisible;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nmPebiResultWellAnnotationLayer::areWellNamesVisible() const
|
|
|
|
|
{
|
|
|
|
|
return m_bWellNamesVisible;
|
|
|
|
|
|