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.
AppFlow/GUIWidget/PickedData.cpp

726 lines
19 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "PickedData.h"
// Qt
#include <QVector>
// VTK
#include <vtkPlanes.h>
#include <vtkUnstructuredGrid.h>
#include <vtkDataSet.h>
#include <vtkActor.h>
#include <vtkActor2D.h>
#include <vtkMapper.h>
#include <vtkSelectionNode.h>
#include <vtkSelection.h>
#include <vtkExtractSelection.h>
#include <vtkIdTypeArray.h>
// APP
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKKeyMouseStates.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
// Global data
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
// Data
#include "FITK_Component/FITKGeoCompOCC/FITKAbstractOCCModel.h"
// Graph
#include "FITK_Interface/FITKVTKAlgorithm/FITKGraphActor.h"
#include "FITK_Interface/FITKVTKAlgorithm/FITKGraphActor2D.h"
#include "FITK_Component/FITKFluidVTKGraphAdaptor/FITKFluidVTKGraphObject3D.h"
// Filter ( Algorithm )
#include "FITK_Interface/FITKVTKAlgorithm/FITKShellFeatureEdges.h"
#include "FITK_Interface/FITKVTKAlgorithm/FITKSurfaceFilter.h"
//#include "FITK_Interface/FITKVTKAlgorithm/FITKDataSetReader.h"
// GUI
#include "GUIPickInfo.h"
// Operator
#include "FITK_Kernel/FITKCore/FITKOperatorRepo.h"
#include "OperatorsInterface/GraphEventOperator.h"
namespace GraphData
{
PickedData::PickedData(GUI::GUIPickInfoStru pickedInfo, vtkActor* pickedActor, int pickedIndex, double* pickedWorldPos, bool isPreview) :
m_pickedInfo(pickedInfo), m_pickedActor(pickedActor), m_pickedIndex(pickedIndex), m_isPreview(isPreview)
{
// 初始化鼠标操作方式。(点击)
m_mouseOper = PickedMouseType::PickedMouseClick;
if (pickedWorldPos)
{
m_pickedWorldPos[0] = pickedWorldPos[0];
m_pickedWorldPos[1] = pickedWorldPos[1];
m_pickedWorldPos[2] = pickedWorldPos[2];
}
// 初始化。
init();
}
PickedData::PickedData(GUI::GUIPickInfoStru pickedInfo, vtkActor* pickedActor, vtkPlanes* cutPlane) :
m_pickedInfo(pickedInfo), m_pickedActor(pickedActor), m_cutPlane(cutPlane)
{
// 初始化鼠标操作方式。(框选)
m_mouseOper = PickedMouseType::PickedMouseRubber;
// 初始化。
init();
}
PickedData::PickedData(GUI::GUIPickInfoStru pickedInfo, vtkActor2D* pickedActor, bool isPreview) :
m_pickedInfo(pickedInfo), m_pickedActor2D(pickedActor), m_isPreview(isPreview)
{
// 初始化鼠标操作方式。(点击)
m_mouseOper = PickedMouseType::PickedMouseClick;
// 初始化。
init2D();
}
PickedData::PickedData(Interface::FITKModelEnum::FITKModelSetType pType, int dataObjectId, QList<int> & indice)
{
// 初始化鼠标操作方式。(点击)
m_mouseOper = PickedMouseType::PickedMouseClick;
// 反向获取拾取类型。
switch (pType)
{
case Interface::FITKModelEnum::FMSNode:
m_type = PickedDataType::MeshNodePick;
break;
case Interface::FITKModelEnum::FMSElem:
m_type = PickedDataType::MeshElementPick;
break;
case Interface::FITKModelEnum::FMSPoint:
m_type = PickedDataType::ModelVertPick;
break;
case Interface::FITKModelEnum::FMSEdge:
m_type = PickedDataType::ModelEdgePick;
break;
case Interface::FITKModelEnum::FMSSurface:
m_type = PickedDataType::ModelFacePick;
break;
case Interface::FITKModelEnum::FMSSolid:
m_type = PickedDataType::ModelSolidPick;
break;
case Interface::FITKModelEnum::FMSNone:
case Interface::FITKModelEnum::FMSMIX:
case Interface::FITKModelEnum::FMSComb:
default:
// 数据不可用。
m_needToCal = false;
m_isValid = false;
return;
}
// 存储数据对象ID与数据索引。
m_dataObjId = dataObjectId;
m_ids = indice;
// 初始化。
initManual();
}
PickedData::PickedData()
{
}
PickedData::~PickedData()
{
// 析构前恢复高亮(参考点、坐标轴)状态。
clearHighlight();
}
PickedData* PickedData::getCopy()
{
if (m_needToCal || !m_isValid)
{
return nullptr;
}
PickedData* data = new PickedData;
data->m_type = m_type;
data->m_dataObjId = m_dataObjId;
data->m_ids = m_ids;
data->m_graphObject = m_graphObject;
data->m_pickedActor = m_pickedActor;
data->m_pickedActor2D = m_pickedActor2D;
data->m_pickedIndex = m_pickedIndex;
data->m_pickedInfo = m_pickedInfo;
return data;
}
void PickedData::sortIds()
{
if (!m_ids.isEmpty())
{
std::sort(m_ids.begin(), m_ids.end());
}
}
bool PickedData::isSameAs(PickedData* data)
{
if (!data)
{
return false;
}
if (data->m_type == m_type &&
data->m_dataObjId == m_dataObjId)
{
return true;
}
else
{
return false;
}
}
void PickedData::sort()
{
std::sort(m_ids.begin(), m_ids.end());
}
void PickedData::add(PickedData* data)
{
if (!data)
{
return;
}
// 首先进行排序获取ID最大值。最后一位ID
sort();
data->sort();
// 获取最大ID开数组存取存在标识。
if (m_ids.count() && data->m_ids.count())
{
int nIdsMax = qMax(m_ids.last(), data->m_ids.last());
QVector<int> idFlag(nIdsMax);
idFlag.fill(-1);
for (const int & id : m_ids)
{
idFlag[id - 1] = 1;
}
// 合并单元或节点ID。
for (const int & id : data->m_ids)
{
if (idFlag[id - 1] == -1)
{
m_ids.push_back(id);
idFlag[id - 1] = 1;
}
}
}
// 排序。
sortIds();
// 合并后析构。
delete data;
}
void PickedData::subtract(PickedData* data)
{
if (!data)
{
return;
}
// 首先进行排序获取ID最大值。最后一位ID
sort();
data->sort();
// 获取最大ID开数组存取存在标识。
if (m_ids.count() && data->m_ids.count())
{
int nIdsMax = qMax(m_ids.last(), data->m_ids.last());
QVector<int> idFlags(nIdsMax);
idFlags.fill(-1);
for (const int & id : m_ids)
{
idFlags[id - 1] = 1;
}
// 移除单元或节点ID。
for (const int & id : data->m_ids)
{
if (idFlags[id - 1] == 1)
{
idFlags[id - 1] = -1;
}
}
m_ids.clear();
for (int i = 0; i < idFlags.count(); i++)
{
int& idFlag = idFlags[i];
if (idFlag == 1)
{
m_ids.push_back(i + 1);
}
}
}
// 合并后析构。
delete data;
}
void PickedData::init()
{
// 尝试转换为自定义Actor。
FITKGraphActor* fActor = FITKGraphActor::SafeDownCast(m_pickedActor);
if (!fActor)
{
return;
}
// 获取演员存储的可视化对象。
Exchange::FITKFluidVTKGraphObject3D* obj = fActor->getGraphObjectAs<Exchange::FITKFluidVTKGraphObject3D>();
if (!obj)
{
return;
}
// 保存可视化对象。
m_graphObject = obj;
m_dataObjId = obj->getDataId();
Exchange::FITKFluidVTKCommons::ShapeInfo sInfo = obj->getShapeInfo();
switch (m_pickedInfo._pickObjType)
{
case GUI::GUIPickInfo::PickObjType::POBJVert:
m_type = ModelVertPick;
break;
case GUI::GUIPickInfo::PickObjType::POBJEdge:
m_type = ModelEdgePick;
break;
case GUI::GUIPickInfo::PickObjType::POBJFace:
m_type = ModelFacePick;
break;
case GUI::GUIPickInfo::PickObjType::POBJSolid:
m_type = ModelSolidPick;
break;
default:
m_type = OtherPick;
break;
}
m_dataObjId = sInfo.DataObjId;
if (m_type == OtherPick)
{
return;
}
m_needToCal = true;
m_isValid = true;
}
void PickedData::init2D()
{
// 尝试转换为自定义Actor。
FITKGraphActor2D* fActor2D = FITKGraphActor2D::SafeDownCast(m_pickedActor2D);
if (!fActor2D)
{
return;
}
// 获取演员存储的可视化对象。
Exchange::FITKFluidVTKGraphObject3D* obj = fActor2D->getGraphObjectAs<Exchange::FITKFluidVTKGraphObject3D>();
if (!obj)
{
return;
}
// 保存可视化对象。
m_graphObject = obj;
m_dataObjId = obj->getDataId();
Exchange::FITKFluidVTKCommons::ShapeInfo sInfo = obj->getShapeInfo();
switch (m_pickedInfo._pickObjType)
{
case GUI::GUIPickInfo::PickObjType::POBJVert:
m_type = ModelVertPick;
break;
case GUI::GUIPickInfo::PickObjType::POBJEdge:
m_type = ModelEdgePick;
break;
case GUI::GUIPickInfo::PickObjType::POBJFace:
m_type = ModelFacePick;
break;
case GUI::GUIPickInfo::PickObjType::POBJSolid:
m_type = ModelSolidPick;
break;
default:
m_type = OtherPick;
break;
}
m_dataObjId = sInfo.DataObjId;
if (m_type == OtherPick)
{
return;
}
m_needToCal = false;
m_isValid = true;
}
void PickedData::initManual()
{
// 通过操作器获取可视化对象。
Core::FITKOperatorRepo* operatorRepo = Core::FITKOperatorRepo::getInstance();
EventOper::GraphEventOperator* operPre = operatorRepo->getOperatorT<EventOper::GraphEventOperator>("GraphPreprocess");
if (!operPre)
{
return;
}
m_graphObject = operPre->getModelGraphObjectByDataId(m_dataObjId);
// 判断数据是否可用。
m_needToCal = false;
m_isValid = m_graphObject != nullptr;
// 排序。
sortIds();
}
void PickedData::setPickedGraphObject(Exchange::FITKFluidVTKGraphObject3D* obj)
{
if (!obj)
{
return;
}
// 断开旧数据信号。
if (m_graphObject)
{
disconnect(m_graphObject, &Exchange::FITKFluidVTKGraphObject3D::destroyed, this, &PickedData::slot_resetGraphObject);
}
// 保存数据,连接信号。
m_graphObject = obj;
connect(m_graphObject, &Exchange::FITKFluidVTKGraphObject3D::destroyed, this, &PickedData::slot_resetGraphObject, Qt::UniqueConnection);
}
void PickedData::slot_resetGraphObject()
{
m_graphObject = nullptr;
}
void PickedData::highlight()
{
if (!m_graphObject)
{
return;
}
// 如果是预选并且没有在高亮则预选。
if (m_isPreview)
{
if (!m_graphObject->isHighlighting())
{
m_graphObject->preHighlight();
}
}
else
{
m_graphObject->highlight();
}
}
void PickedData::clearHighlight()
{
// 取消高亮。
if (!m_graphObject)
{
return;
}
// 如果是预选高亮参考点需要额外判断是否为高亮状态。
if (m_isPreview)
{
// 如果为高亮状态则还原为高亮。
if (m_graphObject->isHighlighting())
{
m_graphObject->highlight();
}
// 否则取消预选高亮。
else
{
m_graphObject->disHighlight();
}
}
// 高亮则直接取消高亮。
else
{
m_graphObject->disHighlight();
}
}
void PickedData::calculateFinsish()
{
m_needToCal = false;
m_mouseOper = PickedMouseType::PickedNoneType;
m_pickedIndex = -1;
m_cutPlane = nullptr;
m_pickedWorldPos[0] = 0;
m_pickedWorldPos[1] = 0;
m_pickedWorldPos[2] = 0;
}
bool PickedData::needToCalculate()
{
return m_needToCal;
}
bool PickedData::isValid()
{
return m_isValid;
}
bool PickedData::isEmpty()
{
// 如果数据对象ID为空则一定为空拾取数据。
if (m_dataObjId < 0)
{
return true;
}
bool isEmpty = m_ids.isEmpty();
return isEmpty;
}
bool PickedData::contains(vtkActor* actor, int index)
{
if (!actor || index < 0 || !m_graphObject)
{
return false;
}
// 首先判断是否为同一演员,参考点直接返回。
if (actor != m_pickedActor)
{
return false;
}
int id = -1;
switch (m_pickedInfo._pickObjType)
{
case GUI::GUIPickInfo::PickObjType::POBJVert:
id = m_graphObject->getShapeIdByVTKCellId(index, Exchange::FITKFluidVTKCommons::ShapeAbsEnum::STA_VERTEX);
break;
case GUI::GUIPickInfo::PickObjType::POBJEdge:
id = m_graphObject->getShapeIdByVTKCellId(index, Exchange::FITKFluidVTKCommons::ShapeAbsEnum::STA_EDGE);
break;
case GUI::GUIPickInfo::PickObjType::POBJFace:
id = m_graphObject->getShapeIdByVTKCellId(index, Exchange::FITKFluidVTKCommons::ShapeAbsEnum::STA_FACE);
break;
case GUI::GUIPickInfo::PickObjType::POBJSolid:
id = m_graphObject->getShapeIdByVTKCellId(index, Exchange::FITKFluidVTKCommons::ShapeAbsEnum::STA_SOLID);
break;
default:
return false;
}
if (id == -1)
{
return false;
}
return m_ids.contains(id);
}
bool PickedData::contains(vtkActor2D* actor)
{
if (!actor || !m_graphObject)
{
return false;
}
// 新版本
//@{
return m_graphObject->contains(actor);
//@}
}
GUI::GUIPickInfoStru PickedData::getPickedInfo()
{
return m_pickedInfo;
}
vtkActor* PickedData::getPickedActor()
{
return m_pickedActor;
}
int PickedData::getPickedIndex()
{
return m_pickedIndex;
}
PickedMouseType PickedData::getPickedMouseType()
{
return m_mouseOper;
}
vtkPlanes* PickedData::getCutPlane()
{
return m_cutPlane;
}
PickedDataType PickedData::getPickedDataType()
{
return m_type;
}
QList<int> & PickedData::getPickedIds()
{
return m_ids;
}
int PickedData::getPickedDataObjId()
{
return m_dataObjId;
}
Exchange::FITKFluidVTKGraphObject3D* PickedData::getPickedGraphObejct()
{
return m_graphObject;
}
void PickedData::getDataSet(vtkUnstructuredGrid* ugrid)
{
// 未计算过的数据直接跳出。
if (m_needToCal || !ugrid || !m_graphObject)
{
return;
}
vtkDataSet* dataSet{ nullptr };
Exchange::FITKFluidVTKCommons::ShapeAbsEnum shapeEnum;
// 根据拾取模型数据类型获取数据集。
switch (m_type)
{
case PickedDataType::ModelVertPick:
{
dataSet = m_graphObject->getMesh(Exchange::FITKFluidVTKCommons::ShapeType::ModelVertex);
shapeEnum = Exchange::FITKFluidVTKCommons::ShapeAbsEnum::STA_VERTEX;
break;
}
case PickedDataType::ModelEdgePick:
{
dataSet = m_graphObject->getMesh(Exchange::FITKFluidVTKCommons::ShapeType::ModelEdge);
shapeEnum = Exchange::FITKFluidVTKCommons::ShapeAbsEnum::STA_EDGE;
break;
}
case PickedDataType::ModelFacePick:
{
dataSet = m_graphObject->getMesh(Exchange::FITKFluidVTKCommons::ShapeType::ModelFace);
shapeEnum = Exchange::FITKFluidVTKCommons::ShapeAbsEnum::STA_FACE;
break;
}
case PickedDataType::ModelSolidPick:
{
dataSet = m_graphObject->getMesh(Exchange::FITKFluidVTKCommons::ShapeType::ModelSolid);
shapeEnum = Exchange::FITKFluidVTKCommons::ShapeAbsEnum::STA_SOLID;
break;
}
default:
return;
}
if (!dataSet)
{
return;
}
int nCell = dataSet->GetNumberOfCells();
// 创建ID数组加速合并数据。
vtkSmartPointer<vtkIntArray> idArray = vtkSmartPointer<vtkIntArray>::New();
idArray->SetNumberOfComponents(1);
idArray->SetNumberOfValues(nCell);
idArray->FillComponent(0, 0);
// 根据OCC形状ID获取所有VTK数据。
for (const int & id : m_ids)
{
const QVector<int> subCellIds = m_graphObject->getVTKCellIdsByShapeId(id, shapeEnum);
for (const int & cId : subCellIds)
{
idArray->SetValue(cId, 1);
}
}
// 通过ID获取实际VTK索引。
vtkIdTypeArray* selectIdArray = vtkIdTypeArray::New();
vtkSelectionNode* selectNode = vtkSelectionNode::New();
vtkExtractSelection* extractSelection = vtkExtractSelection::New();
for (int i = 0; i < nCell; i++)
{
if (idArray->GetValue(i) == 1)
{
selectIdArray->InsertNextValue(i);
}
}
// 从原始网格数据提取。
selectNode->SetFieldType(vtkSelectionNode::SelectionField::CELL);
extractSelection->SetInputData(dataSet);
// 提取VTK数据。
//@{
vtkSelection* section = vtkSelection::New();
selectNode->SetContentType(vtkSelectionNode::INDICES);
section->AddNode(selectNode);
extractSelection->SetInputData(1, section);
selectNode->SetSelectionList(selectIdArray);
extractSelection->Update();
//@}
// 数据拷贝。
ugrid->DeepCopy(extractSelection->GetOutput());
// 析构。
//@{
selectNode->Delete();
section->Delete();
selectIdArray->Delete();
extractSelection->Delete();
//@}
}
void PickedData::getPickedWorldPosition(double* pos)
{
if (!pos)
{
return;
}
for (int i = 0; i < 3; i++)
{
pos[i] = m_pickedWorldPos[i];
}
}
}