|
|
|
|
|
#include "nmPebiGridSceneController.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "nmPebiGridViewData.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "nmVTKMeshLayer.h"
|
|
|
|
|
|
#include "nmVTKRenderLayer.h"
|
|
|
|
|
|
#include "nmVTKScalarBarLayer.h"
|
|
|
|
|
|
#include "nmVTKScene.h"
|
|
|
|
|
|
#include "nmWxVTKRenderContainerWidget.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <QByteArray>
|
|
|
|
|
|
#include <QCoreApplication>
|
|
|
|
|
|
#include <QMap>
|
|
|
|
|
|
#include <QSet>
|
|
|
|
|
|
#include <QtGlobal>
|
|
|
|
|
|
|
|
|
|
|
|
#include <vtkActor.h>
|
|
|
|
|
|
#include <vtkBillboardTextActor3D.h>
|
|
|
|
|
|
#include <vtkCellArray.h>
|
|
|
|
|
|
#include <vtkCellData.h>
|
|
|
|
|
|
#include <vtkDataSetMapper.h>
|
|
|
|
|
|
#include <vtkMath.h>
|
|
|
|
|
|
#include <vtkPoints.h>
|
|
|
|
|
|
#include <vtkPolyData.h>
|
|
|
|
|
|
#include <vtkPolyDataMapper.h>
|
|
|
|
|
|
#include <vtkPropAssembly.h>
|
|
|
|
|
|
#include <vtkProperty.h>
|
|
|
|
|
|
#include <vtkTextProperty.h>
|
|
|
|
|
|
#include <vtkUnsignedCharArray.h>
|
|
|
|
|
|
#include <vtkUnstructuredGrid.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
|
|
QString controllerText(const char* pText)
|
|
|
|
|
|
{
|
|
|
|
|
|
return QCoreApplication::translate(
|
|
|
|
|
|
"nmPebiGridSceneController", pText);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double calculateWellOverlayOffset(vtkUnstructuredGrid* pGrid)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(pGrid == NULL) {
|
|
|
|
|
|
return 0.0001;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double dBounds[6];
|
|
|
|
|
|
pGrid->GetBounds(dBounds);
|
|
|
|
|
|
if(!vtkMath::AreBoundsInitialized(dBounds)) {
|
|
|
|
|
|
return 0.0001;
|
|
|
|
|
|
}
|
|
|
|
|
|
for(int nIndex = 0; nIndex < 6; ++nIndex) {
|
|
|
|
|
|
if(!vtkMath::IsFinite(dBounds[nIndex])) {
|
|
|
|
|
|
return 0.0001;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const double dWidth = dBounds[1] - dBounds[0];
|
|
|
|
|
|
const double dHeight = dBounds[3] - dBounds[2];
|
|
|
|
|
|
const double dSceneScale = std::sqrt(
|
|
|
|
|
|
dWidth * dWidth + dHeight * dHeight);
|
|
|
|
|
|
if(!vtkMath::IsFinite(dSceneScale) || dSceneScale <= 0.0) {
|
|
|
|
|
|
return 0.0001;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用场景尺度的十万分之一,避免千米级网格下偏移小于深度缓冲精度。
|
|
|
|
|
|
return qMax(0.0001, dSceneScale * 0.00001);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** @brief 单个井位 Actor 的 VTK 对象集合,由井位图层独占。 */
|
|
|
|
|
|
struct nmPebiGridWellPointEntry
|
|
|
|
|
|
{
|
|
|
|
|
|
vtkSmartPointer<vtkPoints> m_pPoints;
|
|
|
|
|
|
vtkSmartPointer<vtkPolyData> m_pPolyData;
|
|
|
|
|
|
vtkSmartPointer<vtkPolyDataMapper> m_pMapper;
|
|
|
|
|
|
vtkSmartPointer<vtkActor> m_pActor;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** @brief 单口井全部井筒和裂缝线段的 VTK 对象集合。 */
|
|
|
|
|
|
struct nmPebiGridWellLineEntry
|
|
|
|
|
|
{
|
|
|
|
|
|
vtkSmartPointer<vtkPolyData> m_pPolyData;
|
|
|
|
|
|
vtkSmartPointer<vtkPolyDataMapper> m_pMapper;
|
|
|
|
|
|
vtkSmartPointer<vtkActor> m_pActor;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class nmPebiGridWellPointLayer : public nmVTKRenderLayer
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit nmPebiGridWellPointLayer(const QString& sLayerId)
|
|
|
|
|
|
: nmVTKRenderLayer(sLayerId),
|
|
|
|
|
|
m_pAssembly(vtkSmartPointer<vtkPropAssembly>::New()),
|
|
|
|
|
|
m_dZOffset(0.0)
|
|
|
|
|
|
{
|
|
|
|
|
|
setRenderProp(m_pAssembly);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virtual ~nmPebiGridWellPointLayer()
|
|
|
|
|
|
{
|
|
|
|
|
|
// Scene 删除图层前已 detach;这里仅释放图层独占的逐井 VTK 对象。
|
|
|
|
|
|
clearEntries();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setZOffset(double dZOffset)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_dZOffset = dZOffset;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setWells(const QVector<nmPebiGridWellViewData>& vecWells)
|
|
|
|
|
|
{
|
|
|
|
|
|
QSet<QString> setIncomingCodes;
|
|
|
|
|
|
for(int nIndex = 0; nIndex < vecWells.size(); ++nIndex) {
|
|
|
|
|
|
setIncomingCodes.insert(vecWells[nIndex].m_sWellCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QMap<QString, nmPebiGridWellPointEntry*>::iterator oIterator =
|
|
|
|
|
|
m_mapEntries.begin();
|
|
|
|
|
|
while(oIterator != m_mapEntries.end()) {
|
|
|
|
|
|
if(!setIncomingCodes.contains(oIterator.key())) {
|
|
|
|
|
|
m_pAssembly->RemovePart(oIterator.value()->m_pActor);
|
|
|
|
|
|
delete oIterator.value();
|
|
|
|
|
|
oIterator = m_mapEntries.erase(oIterator);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
++oIterator;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 以稳定井编码查找并更新 Actor,井改名不会被误判为另一口井。
|
|
|
|
|
|
for(int nIndex = 0; nIndex < vecWells.size(); ++nIndex) {
|
|
|
|
|
|
const nmPebiGridWellViewData& oWell = vecWells[nIndex];
|
|
|
|
|
|
nmPebiGridWellPointEntry* pEntry =
|
|
|
|
|
|
m_mapEntries.value(oWell.m_sWellCode, NULL);
|
|
|
|
|
|
if(pEntry == NULL) {
|
|
|
|
|
|
pEntry = createEntry();
|
|
|
|
|
|
m_mapEntries.insert(oWell.m_sWellCode, pEntry);
|
|
|
|
|
|
m_pAssembly->AddPart(pEntry->m_pActor);
|
|
|
|
|
|
}
|
|
|
|
|
|
pEntry->m_pPoints->SetPoint(
|
|
|
|
|
|
0, oWell.m_oPosition.x(),
|
|
|
|
|
|
oWell.m_oPosition.y(), m_dZOffset);
|
|
|
|
|
|
pEntry->m_pPoints->Modified();
|
|
|
|
|
|
pEntry->m_pPolyData->Modified();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
nmPebiGridWellPointEntry* createEntry()
|
|
|
|
|
|
{
|
|
|
|
|
|
nmPebiGridWellPointEntry* pEntry =
|
|
|
|
|
|
new nmPebiGridWellPointEntry();
|
|
|
|
|
|
pEntry->m_pPoints = vtkSmartPointer<vtkPoints>::New();
|
|
|
|
|
|
pEntry->m_pPoints->InsertNextPoint(0.0, 0.0, m_dZOffset);
|
|
|
|
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkCellArray> pVertices =
|
|
|
|
|
|
vtkSmartPointer<vtkCellArray>::New();
|
|
|
|
|
|
pVertices->InsertNextCell(1);
|
|
|
|
|
|
pVertices->InsertCellPoint(0);
|
|
|
|
|
|
|
|
|
|
|
|
pEntry->m_pPolyData = vtkSmartPointer<vtkPolyData>::New();
|
|
|
|
|
|
pEntry->m_pPolyData->SetPoints(pEntry->m_pPoints);
|
|
|
|
|
|
pEntry->m_pPolyData->SetVerts(pVertices);
|
|
|
|
|
|
pEntry->m_pMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
|
|
|
|
|
pEntry->m_pMapper->SetInputData(pEntry->m_pPolyData);
|
|
|
|
|
|
pEntry->m_pActor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
|
|
pEntry->m_pActor->SetMapper(pEntry->m_pMapper);
|
|
|
|
|
|
pEntry->m_pActor->GetProperty()->SetColor(1.0, 0.15, 0.05);
|
|
|
|
|
|
pEntry->m_pActor->GetProperty()->SetPointSize(9.0);
|
|
|
|
|
|
pEntry->m_pActor->PickableOff();
|
|
|
|
|
|
return pEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void clearEntries()
|
|
|
|
|
|
{
|
|
|
|
|
|
QMap<QString, nmPebiGridWellPointEntry*>::iterator oIterator =
|
|
|
|
|
|
m_mapEntries.begin();
|
|
|
|
|
|
while(oIterator != m_mapEntries.end()) {
|
|
|
|
|
|
m_pAssembly->RemovePart(oIterator.value()->m_pActor);
|
|
|
|
|
|
delete oIterator.value();
|
|
|
|
|
|
++oIterator;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_mapEntries.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkPropAssembly> m_pAssembly;
|
|
|
|
|
|
double m_dZOffset;
|
|
|
|
|
|
QMap<QString, nmPebiGridWellPointEntry*> m_mapEntries;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class nmPebiGridWellLineLayer : public nmVTKRenderLayer
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit nmPebiGridWellLineLayer(const QString& sLayerId)
|
|
|
|
|
|
: nmVTKRenderLayer(sLayerId),
|
|
|
|
|
|
m_pAssembly(vtkSmartPointer<vtkPropAssembly>::New()),
|
|
|
|
|
|
m_dZOffset(0.0)
|
|
|
|
|
|
{
|
|
|
|
|
|
setRenderProp(m_pAssembly);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virtual ~nmPebiGridWellLineLayer()
|
|
|
|
|
|
{
|
|
|
|
|
|
clearEntries();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setZOffset(double dZOffset)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_dZOffset = dZOffset;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setWells(const QVector<nmPebiGridWellViewData>& vecWells)
|
|
|
|
|
|
{
|
|
|
|
|
|
QSet<QString> setIncomingCodes;
|
|
|
|
|
|
for(int nIndex = 0; nIndex < vecWells.size(); ++nIndex) {
|
|
|
|
|
|
setIncomingCodes.insert(vecWells[nIndex].m_sWellCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QMap<QString, nmPebiGridWellLineEntry*>::iterator oIterator =
|
|
|
|
|
|
m_mapEntries.begin();
|
|
|
|
|
|
while(oIterator != m_mapEntries.end()) {
|
|
|
|
|
|
if(!setIncomingCodes.contains(oIterator.key())) {
|
|
|
|
|
|
m_pAssembly->RemovePart(oIterator.value()->m_pActor);
|
|
|
|
|
|
delete oIterator.value();
|
|
|
|
|
|
oIterator = m_mapEntries.erase(oIterator);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
++oIterator;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for(int nIndex = 0; nIndex < vecWells.size(); ++nIndex) {
|
|
|
|
|
|
const nmPebiGridWellViewData& oWell = vecWells[nIndex];
|
|
|
|
|
|
nmPebiGridWellLineEntry* pEntry =
|
|
|
|
|
|
m_mapEntries.value(oWell.m_sWellCode, NULL);
|
|
|
|
|
|
if(pEntry == NULL) {
|
|
|
|
|
|
pEntry = createEntry();
|
|
|
|
|
|
m_mapEntries.insert(oWell.m_sWellCode, pEntry);
|
|
|
|
|
|
m_pAssembly->AddPart(pEntry->m_pActor);
|
|
|
|
|
|
}
|
|
|
|
|
|
updateEntry(pEntry, oWell);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
nmPebiGridWellLineEntry* createEntry()
|
|
|
|
|
|
{
|
|
|
|
|
|
nmPebiGridWellLineEntry* pEntry =
|
|
|
|
|
|
new nmPebiGridWellLineEntry();
|
|
|
|
|
|
pEntry->m_pPolyData = vtkSmartPointer<vtkPolyData>::New();
|
|
|
|
|
|
pEntry->m_pMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
|
|
|
|
|
pEntry->m_pMapper->SetInputData(pEntry->m_pPolyData);
|
|
|
|
|
|
pEntry->m_pMapper->SetScalarModeToUseCellData();
|
|
|
|
|
|
pEntry->m_pMapper->SetColorModeToDirectScalars();
|
|
|
|
|
|
pEntry->m_pMapper->ScalarVisibilityOn();
|
|
|
|
|
|
pEntry->m_pActor = vtkSmartPointer<vtkActor>::New();
|
|
|
|
|
|
pEntry->m_pActor->SetMapper(pEntry->m_pMapper);
|
|
|
|
|
|
pEntry->m_pActor->GetProperty()->SetLineWidth(2.0);
|
|
|
|
|
|
pEntry->m_pActor->PickableOff();
|
|
|
|
|
|
return pEntry;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void appendSegment(vtkPoints* pPoints,
|
|
|
|
|
|
vtkCellArray* pLines,
|
|
|
|
|
|
vtkUnsignedCharArray* pColors,
|
|
|
|
|
|
const QLineF& oLine,
|
|
|
|
|
|
bool bFracture)
|
|
|
|
|
|
{
|
|
|
|
|
|
const vtkIdType nFirstPoint = pPoints->InsertNextPoint(
|
|
|
|
|
|
oLine.x1(), oLine.y1(), m_dZOffset);
|
|
|
|
|
|
const vtkIdType nSecondPoint = pPoints->InsertNextPoint(
|
|
|
|
|
|
oLine.x2(), oLine.y2(), m_dZOffset);
|
|
|
|
|
|
pLines->InsertNextCell(2);
|
|
|
|
|
|
pLines->InsertCellPoint(nFirstPoint);
|
|
|
|
|
|
pLines->InsertCellPoint(nSecondPoint);
|
|
|
|
|
|
if(bFracture) {
|
|
|
|
|
|
pColors->InsertNextTuple3(255, 45, 25);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
pColors->InsertNextTuple3(30, 30, 30);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void updateEntry(nmPebiGridWellLineEntry* pEntry,
|
|
|
|
|
|
const nmPebiGridWellViewData& oWell)
|
|
|
|
|
|
{
|
|
|
|
|
|
vtkSmartPointer<vtkPoints> pPoints =
|
|
|
|
|
|
vtkSmartPointer<vtkPoints>::New();
|
|
|
|
|
|
vtkSmartPointer<vtkCellArray> pLines =
|
|
|
|
|
|
vtkSmartPointer<vtkCellArray>::New();
|
|
|
|
|
|
vtkSmartPointer<vtkUnsignedCharArray> pColors =
|
|
|
|
|
|
vtkSmartPointer<vtkUnsignedCharArray>::New();
|
|
|
|
|
|
pColors->SetName("WellLineColors");
|
|
|
|
|
|
pColors->SetNumberOfComponents(3);
|
|
|
|
|
|
|
|
|
|
|
|
int nIndex = 0;
|
|
|
|
|
|
for(nIndex = 0; nIndex < oWell.m_vecWellSegments.size(); ++nIndex) {
|
|
|
|
|
|
appendSegment(pPoints, pLines, pColors,
|
|
|
|
|
|
oWell.m_vecWellSegments[nIndex], false);
|
|
|
|
|
|
}
|
|
|
|
|
|
for(nIndex = 0; nIndex < oWell.m_vecFractureSegments.size(); ++nIndex) {
|
|
|
|
|
|
appendSegment(pPoints, pLines, pColors,
|
|
|
|
|
|
oWell.m_vecFractureSegments[nIndex], true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pEntry->m_pPolyData->SetPoints(pPoints);
|
|
|
|
|
|
pEntry->m_pPolyData->SetLines(pLines);
|
|
|
|
|
|
pEntry->m_pPolyData->GetCellData()->SetScalars(pColors);
|
|
|
|
|
|
pEntry->m_pPolyData->Modified();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void clearEntries()
|
|
|
|
|
|
{
|
|
|
|
|
|
QMap<QString, nmPebiGridWellLineEntry*>::iterator oIterator =
|
|
|
|
|
|
m_mapEntries.begin();
|
|
|
|
|
|
while(oIterator != m_mapEntries.end()) {
|
|
|
|
|
|
m_pAssembly->RemovePart(oIterator.value()->m_pActor);
|
|
|
|
|
|
delete oIterator.value();
|
|
|
|
|
|
++oIterator;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_mapEntries.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkPropAssembly> m_pAssembly;
|
|
|
|
|
|
double m_dZOffset;
|
|
|
|
|
|
QMap<QString, nmPebiGridWellLineEntry*> m_mapEntries;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class nmPebiGridWellNameLayer : public nmVTKRenderLayer
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit nmPebiGridWellNameLayer(const QString& sLayerId)
|
|
|
|
|
|
: nmVTKRenderLayer(sLayerId),
|
|
|
|
|
|
m_pAssembly(vtkSmartPointer<vtkPropAssembly>::New()),
|
|
|
|
|
|
m_dZOffset(0.0)
|
|
|
|
|
|
{
|
|
|
|
|
|
setRenderProp(m_pAssembly);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virtual ~nmPebiGridWellNameLayer()
|
|
|
|
|
|
{
|
|
|
|
|
|
clearEntries();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setZOffset(double dZOffset)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_dZOffset = dZOffset;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setWells(const QVector<nmPebiGridWellViewData>& vecWells)
|
|
|
|
|
|
{
|
|
|
|
|
|
QSet<QString> setIncomingCodes;
|
|
|
|
|
|
for(int nIndex = 0; nIndex < vecWells.size(); ++nIndex) {
|
|
|
|
|
|
setIncomingCodes.insert(vecWells[nIndex].m_sWellCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QMap<QString, vtkSmartPointer<vtkBillboardTextActor3D> >::iterator
|
|
|
|
|
|
oIterator = m_mapActors.begin();
|
|
|
|
|
|
while(oIterator != m_mapActors.end()) {
|
|
|
|
|
|
if(!setIncomingCodes.contains(oIterator.key())) {
|
|
|
|
|
|
m_pAssembly->RemovePart(oIterator.value());
|
|
|
|
|
|
oIterator = m_mapActors.erase(oIterator);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
++oIterator;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for(int nIndex = 0; nIndex < vecWells.size(); ++nIndex) {
|
|
|
|
|
|
const nmPebiGridWellViewData& oWell = vecWells[nIndex];
|
|
|
|
|
|
vtkSmartPointer<vtkBillboardTextActor3D> pActor =
|
|
|
|
|
|
m_mapActors.value(oWell.m_sWellCode);
|
|
|
|
|
|
if(pActor == NULL) {
|
|
|
|
|
|
pActor = vtkSmartPointer<vtkBillboardTextActor3D>::New();
|
|
|
|
|
|
pActor->GetTextProperty()->SetFontSize(14);
|
|
|
|
|
|
pActor->GetTextProperty()->SetColor(1.0, 1.0, 1.0);
|
|
|
|
|
|
pActor->GetTextProperty()->BoldOn();
|
|
|
|
|
|
pActor->PickableOff();
|
|
|
|
|
|
m_mapActors.insert(oWell.m_sWellCode, pActor);
|
|
|
|
|
|
m_pAssembly->AddPart(pActor);
|
|
|
|
|
|
}
|
|
|
|
|
|
const QByteArray aWellName = oWell.m_sWellName.toUtf8();
|
|
|
|
|
|
pActor->SetInput(aWellName.constData());
|
|
|
|
|
|
pActor->SetPosition(oWell.m_oPosition.x(),
|
|
|
|
|
|
oWell.m_oPosition.y(), m_dZOffset);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
void clearEntries()
|
|
|
|
|
|
{
|
|
|
|
|
|
QMap<QString, vtkSmartPointer<vtkBillboardTextActor3D> >::iterator
|
|
|
|
|
|
oIterator = m_mapActors.begin();
|
|
|
|
|
|
while(oIterator != m_mapActors.end()) {
|
|
|
|
|
|
m_pAssembly->RemovePart(oIterator.value());
|
|
|
|
|
|
++oIterator;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_mapActors.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vtkSmartPointer<vtkPropAssembly> m_pAssembly;
|
|
|
|
|
|
double m_dZOffset;
|
|
|
|
|
|
QMap<QString, vtkSmartPointer<vtkBillboardTextActor3D> > m_mapActors;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class nmPebiGridSceneControllerPrivate
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
explicit nmPebiGridSceneControllerPrivate(
|
|
|
|
|
|
nmWxVTKRenderContainerWidget* pRenderContainer)
|
|
|
|
|
|
: m_pContainer(pRenderContainer),
|
|
|
|
|
|
m_pMeshLayer(NULL),
|
|
|
|
|
|
m_pScalarBarLayer(NULL),
|
|
|
|
|
|
m_pWellPointLayer(NULL),
|
|
|
|
|
|
m_pWellLineLayer(NULL),
|
|
|
|
|
|
m_pWellNameLayer(NULL),
|
|
|
|
|
|
m_eDisplayMode(nmPebiGridSceneController::DisplayMode_SurfaceWithEdges),
|
|
|
|
|
|
m_dOpacity(1.0),
|
|
|
|
|
|
m_bWellVisible(true),
|
|
|
|
|
|
m_bWellNameVisible(true),
|
|
|
|
|
|
m_bHasData(false)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ensureBaseLayers()
|
|
|
|
|
|
{
|
|
|
|
|
|
nmVTKScene* pScene = m_pContainer != NULL
|
|
|
|
|
|
? m_pContainer->getScene() : NULL;
|
|
|
|
|
|
if(pScene == NULL) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(m_pMeshLayer == NULL) {
|
|
|
|
|
|
nmVTKMeshLayer* pLayer =
|
|
|
|
|
|
new nmVTKMeshLayer("pebi.grid.mesh");
|
|
|
|
|
|
if(!pScene->addLayer(pLayer)) {
|
|
|
|
|
|
delete pLayer;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pMeshLayer = pLayer;
|
|
|
|
|
|
// 固定色和边线完全沿用旧 PEBI 网格预览外观。
|
|
|
|
|
|
m_pMeshLayer->getActor()->GetProperty()->SetColor(
|
|
|
|
|
|
0.0, 120.0 / 255.0, 215.0 / 255.0);
|
|
|
|
|
|
m_pMeshLayer->getActor()->GetProperty()->SetEdgeColor(
|
|
|
|
|
|
0.0, 0.0, 0.0);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pWellPointLayer == NULL) {
|
|
|
|
|
|
nmPebiGridWellPointLayer* pLayer =
|
|
|
|
|
|
new nmPebiGridWellPointLayer("pebi.grid.well_positions");
|
|
|
|
|
|
if(!pScene->addLayer(pLayer)) {
|
|
|
|
|
|
delete pLayer;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pWellPointLayer = pLayer;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pWellLineLayer == NULL) {
|
|
|
|
|
|
nmPebiGridWellLineLayer* pLayer =
|
|
|
|
|
|
new nmPebiGridWellLineLayer("pebi.grid.well_lines");
|
|
|
|
|
|
if(!pScene->addLayer(pLayer)) {
|
|
|
|
|
|
delete pLayer;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pWellLineLayer = pLayer;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pWellNameLayer == NULL) {
|
|
|
|
|
|
nmPebiGridWellNameLayer* pLayer =
|
|
|
|
|
|
new nmPebiGridWellNameLayer("pebi.grid.well_names");
|
|
|
|
|
|
if(!pScene->addLayer(pLayer)) {
|
|
|
|
|
|
delete pLayer;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pWellNameLayer = pLayer;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ensureScalarBarLayer()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pScalarBarLayer != NULL) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
nmVTKScene* pScene = m_pContainer != NULL
|
|
|
|
|
|
? m_pContainer->getScene() : NULL;
|
|
|
|
|
|
if(pScene == NULL || m_pMeshLayer == NULL) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmVTKScalarBarLayer* pLayer =
|
|
|
|
|
|
new nmVTKScalarBarLayer("pebi.grid.scalar_bar");
|
|
|
|
|
|
pLayer->setLookupTable(m_pMeshLayer->getLookupTable());
|
|
|
|
|
|
pLayer->setPosition(0.86, 0.12);
|
|
|
|
|
|
pLayer->setSize(0.10, 0.76);
|
|
|
|
|
|
if(!pScene->addLayer(pLayer)) {
|
|
|
|
|
|
delete pLayer;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pScalarBarLayer = pLayer;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool applyProperty(const QString& sPropertyName)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pMeshLayer == NULL) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(sPropertyName.isEmpty()) {
|
|
|
|
|
|
m_sPropertyName.clear();
|
|
|
|
|
|
m_pMeshLayer->setScalarVisibility(false);
|
|
|
|
|
|
if(m_pScalarBarLayer != NULL) {
|
|
|
|
|
|
m_pScalarBarLayer->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(sPropertyName != "Material" || !m_oViewData.hasMaterial() ||
|
|
|
|
|
|
!m_pMeshLayer->setScalarArray(
|
|
|
|
|
|
sPropertyName, nmVTKMeshLayer::ScalarAssociation_CellData)) {
|
|
|
|
|
|
// 无效属性不能沿用上一网格的标量范围或可见色标。
|
|
|
|
|
|
m_sPropertyName.clear();
|
|
|
|
|
|
m_pMeshLayer->setScalarVisibility(false);
|
|
|
|
|
|
if(m_pScalarBarLayer != NULL) {
|
|
|
|
|
|
m_pScalarBarLayer->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(!ensureScalarBarLayer()) {
|
|
|
|
|
|
m_sPropertyName.clear();
|
|
|
|
|
|
m_pMeshLayer->setScalarVisibility(false);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_sPropertyName = sPropertyName;
|
|
|
|
|
|
m_pMeshLayer->setScalarVisibility(true);
|
|
|
|
|
|
m_pScalarBarLayer->setLookupTable(
|
|
|
|
|
|
m_pMeshLayer->getLookupTable());
|
|
|
|
|
|
m_pScalarBarLayer->setTitle(sPropertyName);
|
|
|
|
|
|
m_pScalarBarLayer->setVisible(true);
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void releaseGridData()
|
|
|
|
|
|
{
|
|
|
|
|
|
// 普通网格替换只解除 Mapper 和旧 ViewData;井 Actor 留给稳定编码增量更新。
|
|
|
|
|
|
if(m_pMeshLayer != NULL) {
|
|
|
|
|
|
m_pMeshLayer->setScalarVisibility(false);
|
|
|
|
|
|
m_pMeshLayer->setDataSet(NULL);
|
|
|
|
|
|
m_pMeshLayer->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pScalarBarLayer != NULL) {
|
|
|
|
|
|
m_pScalarBarLayer->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
m_oViewData.clear();
|
|
|
|
|
|
m_bHasData = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void releaseViewData()
|
|
|
|
|
|
{
|
|
|
|
|
|
releaseGridData();
|
|
|
|
|
|
// 只有切换分析、显式清空或析构才移除全部井条目。
|
|
|
|
|
|
if(m_pWellPointLayer != NULL) {
|
|
|
|
|
|
m_pWellPointLayer->setWells(
|
|
|
|
|
|
QVector<nmPebiGridWellViewData>());
|
|
|
|
|
|
m_pWellPointLayer->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pWellLineLayer != NULL) {
|
|
|
|
|
|
m_pWellLineLayer->setWells(
|
|
|
|
|
|
QVector<nmPebiGridWellViewData>());
|
|
|
|
|
|
m_pWellLineLayer->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pWellNameLayer != NULL) {
|
|
|
|
|
|
m_pWellNameLayer->setWells(
|
|
|
|
|
|
QVector<nmPebiGridWellViewData>());
|
|
|
|
|
|
m_pWellNameLayer->setVisible(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
m_sPropertyName.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmWxVTKRenderContainerWidget* m_pContainer; ///< 非所有权指针。
|
|
|
|
|
|
nmVTKMeshLayer* m_pMeshLayer; ///< Scene 所有,控制器只观察。
|
|
|
|
|
|
nmVTKScalarBarLayer* m_pScalarBarLayer; ///< Scene 所有,按需创建。
|
|
|
|
|
|
nmPebiGridWellPointLayer* m_pWellPointLayer; ///< Scene 所有。
|
|
|
|
|
|
nmPebiGridWellLineLayer* m_pWellLineLayer; ///< Scene 所有。
|
|
|
|
|
|
nmPebiGridWellNameLayer* m_pWellNameLayer; ///< Scene 所有。
|
|
|
|
|
|
nmPebiGridViewData m_oViewData;
|
|
|
|
|
|
nmPebiGridSceneController::DisplayMode m_eDisplayMode;
|
|
|
|
|
|
double m_dOpacity;
|
|
|
|
|
|
bool m_bWellVisible;
|
|
|
|
|
|
bool m_bWellNameVisible;
|
|
|
|
|
|
bool m_bHasData;
|
|
|
|
|
|
QString m_sPropertyName;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
nmPebiGridSceneController::nmPebiGridSceneController(
|
|
|
|
|
|
nmWxVTKRenderContainerWidget* pContainer)
|
|
|
|
|
|
: m_pPrivate(new nmPebiGridSceneControllerPrivate(pContainer))
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nmPebiGridSceneController::~nmPebiGridSceneController()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pPrivate != NULL) {
|
|
|
|
|
|
// Layer 已归 Scene 所有;这里只解除输入和非所有权指针,不能直接 delete Layer。
|
|
|
|
|
|
m_pPrivate->releaseViewData();
|
|
|
|
|
|
m_pPrivate->m_pContainer = NULL;
|
|
|
|
|
|
m_pPrivate->m_pMeshLayer = NULL;
|
|
|
|
|
|
m_pPrivate->m_pScalarBarLayer = NULL;
|
|
|
|
|
|
m_pPrivate->m_pWellPointLayer = NULL;
|
|
|
|
|
|
m_pPrivate->m_pWellLineLayer = NULL;
|
|
|
|
|
|
m_pPrivate->m_pWellNameLayer = NULL;
|
|
|
|
|
|
delete m_pPrivate;
|
|
|
|
|
|
m_pPrivate = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmPebiGridSceneController::setViewData(
|
|
|
|
|
|
const nmPebiGridViewData& oViewData,
|
|
|
|
|
|
QString* pError)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(pError != NULL) {
|
|
|
|
|
|
pError->clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pPrivate == NULL || m_pPrivate->m_pContainer == NULL ||
|
|
|
|
|
|
!oViewData.isValid()) {
|
|
|
|
|
|
if(pError != NULL) {
|
|
|
|
|
|
*pError = controllerText("The grid preview data is invalid.");
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if(!m_pPrivate->ensureBaseLayers()) {
|
|
|
|
|
|
if(pError != NULL) {
|
|
|
|
|
|
*pError = controllerText("Unable to create the grid render layers.");
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const bool bFirstData = !m_pPrivate->m_bHasData;
|
|
|
|
|
|
QString sRequestedProperty = m_pPrivate->m_sPropertyName;
|
|
|
|
|
|
if(bFirstData && sRequestedProperty.isEmpty() &&
|
|
|
|
|
|
oViewData.hasMaterial()) {
|
|
|
|
|
|
// 与旧预览保持一致:首次存在有效 Material 时直接启用单元着色。
|
|
|
|
|
|
sRequestedProperty = "Material";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更换网格必须先断开旧 Mapper 输入,避免旧分析数据被 Scene 隐式保留。
|
|
|
|
|
|
m_pPrivate->releaseGridData();
|
|
|
|
|
|
m_pPrivate->m_oViewData = oViewData;
|
|
|
|
|
|
m_pPrivate->m_pMeshLayer->setDataSet(oViewData.getGrid());
|
|
|
|
|
|
m_pPrivate->m_pMeshLayer->setDisplayMode(
|
|
|
|
|
|
m_pPrivate->m_eDisplayMode == DisplayMode_SurfaceWithEdges
|
|
|
|
|
|
? nmVTKMeshLayer::DisplayMode_SurfaceWithEdges
|
|
|
|
|
|
: nmVTKMeshLayer::DisplayMode_Surface);
|
|
|
|
|
|
m_pPrivate->m_pMeshLayer->setOpacity(m_pPrivate->m_dOpacity);
|
|
|
|
|
|
m_pPrivate->m_pMeshLayer->setVisible(true);
|
|
|
|
|
|
|
|
|
|
|
|
const double dWellOverlayOffset =
|
|
|
|
|
|
calculateWellOverlayOffset(oViewData.getGrid());
|
|
|
|
|
|
// 三类井图元使用同一场景尺度的分层偏移,只改变显示坐标,不写回井数据。
|
|
|
|
|
|
m_pPrivate->m_pWellLineLayer->setZOffset(dWellOverlayOffset);
|
|
|
|
|
|
m_pPrivate->m_pWellPointLayer->setZOffset(dWellOverlayOffset * 2.0);
|
|
|
|
|
|
m_pPrivate->m_pWellNameLayer->setZOffset(dWellOverlayOffset * 3.0);
|
|
|
|
|
|
m_pPrivate->m_pWellPointLayer->setWells(oViewData.getWells());
|
|
|
|
|
|
m_pPrivate->m_pWellLineLayer->setWells(oViewData.getWells());
|
|
|
|
|
|
m_pPrivate->m_pWellNameLayer->setWells(oViewData.getWells());
|
|
|
|
|
|
m_pPrivate->m_pWellPointLayer->setVisible(m_pPrivate->m_bWellVisible);
|
|
|
|
|
|
m_pPrivate->m_pWellLineLayer->setVisible(m_pPrivate->m_bWellVisible);
|
|
|
|
|
|
m_pPrivate->m_pWellNameLayer->setVisible(
|
|
|
|
|
|
m_pPrivate->m_bWellNameVisible);
|
|
|
|
|
|
m_pPrivate->m_bHasData = true;
|
|
|
|
|
|
|
|
|
|
|
|
m_pPrivate->applyProperty(sRequestedProperty);
|
|
|
|
|
|
|
|
|
|
|
|
// setViewData 只用于几何替换,每次都重新适配;属性刷新走独立接口并保留相机。
|
|
|
|
|
|
m_pPrivate->m_pContainer->fitTopViewWithoutRender();
|
|
|
|
|
|
m_pPrivate->m_pContainer->showReadyState();
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmPebiGridSceneController::clear()
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pPrivate == NULL) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pPrivate->releaseViewData();
|
|
|
|
|
|
m_pPrivate->m_eDisplayMode = DisplayMode_SurfaceWithEdges;
|
|
|
|
|
|
m_pPrivate->m_dOpacity = 1.0;
|
|
|
|
|
|
m_pPrivate->m_bWellVisible = true;
|
|
|
|
|
|
m_pPrivate->m_bWellNameVisible = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmPebiGridSceneController::setDisplayMode(DisplayMode eMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pPrivate == NULL || m_pPrivate->m_pMeshLayer == NULL) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pPrivate->m_eDisplayMode = eMode == DisplayMode_Surface
|
|
|
|
|
|
? DisplayMode_Surface : DisplayMode_SurfaceWithEdges;
|
|
|
|
|
|
m_pPrivate->m_pMeshLayer->setDisplayMode(
|
|
|
|
|
|
m_pPrivate->m_eDisplayMode == DisplayMode_SurfaceWithEdges
|
|
|
|
|
|
? nmVTKMeshLayer::DisplayMode_SurfaceWithEdges
|
|
|
|
|
|
: nmVTKMeshLayer::DisplayMode_Surface);
|
|
|
|
|
|
m_pPrivate->m_pContainer->renderView();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmPebiGridSceneController::setOpacity(double dOpacity)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pPrivate == NULL || m_pPrivate->m_pMeshLayer == NULL ||
|
|
|
|
|
|
!m_pPrivate->m_pMeshLayer->setOpacity(dOpacity)) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pPrivate->m_dOpacity = m_pPrivate->m_pMeshLayer->getOpacity();
|
|
|
|
|
|
m_pPrivate->m_pContainer->renderView();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmPebiGridSceneController::setProperty(const QString& sPropertyName)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pPrivate == NULL || !m_pPrivate->m_bHasData) {
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
const bool bSucceeded = m_pPrivate->applyProperty(sPropertyName);
|
|
|
|
|
|
m_pPrivate->m_pContainer->renderView();
|
|
|
|
|
|
return bSucceeded;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmPebiGridSceneController::setWellVisible(bool bVisible)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pPrivate == NULL) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pPrivate->m_bWellVisible = bVisible;
|
|
|
|
|
|
if(m_pPrivate->m_pWellPointLayer != NULL) {
|
|
|
|
|
|
m_pPrivate->m_pWellPointLayer->setVisible(bVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pPrivate->m_pWellLineLayer != NULL) {
|
|
|
|
|
|
m_pPrivate->m_pWellLineLayer->setVisible(bVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pPrivate->m_pContainer != NULL) {
|
|
|
|
|
|
m_pPrivate->m_pContainer->renderView();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void nmPebiGridSceneController::setWellNameVisible(bool bVisible)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_pPrivate == NULL) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pPrivate->m_bWellNameVisible = bVisible;
|
|
|
|
|
|
if(m_pPrivate->m_pWellNameLayer != NULL) {
|
|
|
|
|
|
m_pPrivate->m_pWellNameLayer->setVisible(bVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
if(m_pPrivate->m_pContainer != NULL) {
|
|
|
|
|
|
m_pPrivate->m_pContainer->renderView();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool nmPebiGridSceneController::hasViewData() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_pPrivate != NULL && m_pPrivate->m_bHasData;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QString nmPebiGridSceneController::getProperty() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_pPrivate != NULL
|
|
|
|
|
|
? m_pPrivate->m_sPropertyName : QString();
|
|
|
|
|
|
}
|