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.
570 lines
15 KiB
C++
570 lines
15 KiB
C++
#include "PickedDataProvider.h"
|
|
|
|
// VTK
|
|
#include <vtkPlanes.h>
|
|
#include <vtkActor.h>
|
|
#include <vtkActor2D.h>
|
|
#include <vtkPoints.h>
|
|
#include <vtkUnstructuredGrid.h>
|
|
#include <vtkAppendFilter.h>
|
|
|
|
// Graph
|
|
#include "FITK_Interface/FITKVTKAlgorithm/FITKGraphActor.h"
|
|
#include "FITK_Component/FITKFluidVTKGraphAdaptor/FITKFluidVTKGraphObject3D.h"
|
|
|
|
// APP
|
|
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
|
|
#include "FITK_Kernel/FITKAppFramework/FITKKeyMouseStates.h"
|
|
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
|
|
|
|
// GUI
|
|
#include "GUIPickInfo.h"
|
|
|
|
// Pick
|
|
#include "PickedData.h"
|
|
#include "PickedDataCalculator.h"
|
|
|
|
namespace GraphData
|
|
{
|
|
// 静态变量初始化。
|
|
PickedDataProvider* PickedDataProvider::s_instance{ nullptr };
|
|
|
|
PickedDataProvider* PickedDataProvider::getInstance()
|
|
{
|
|
// 获取实例。
|
|
if (!s_instance)
|
|
{
|
|
s_instance = new PickedDataProvider;
|
|
}
|
|
|
|
return s_instance;
|
|
}
|
|
|
|
void PickedDataProvider::Delete()
|
|
{
|
|
if (s_instance)
|
|
{
|
|
delete s_instance;
|
|
}
|
|
|
|
s_instance = nullptr;
|
|
}
|
|
|
|
PickedDataProvider::PickedDataProvider()
|
|
{
|
|
// 初始化键盘监视器。
|
|
m_settings = FITKAPP->getGlobalData()->getKeyMouseStates();
|
|
|
|
// 创建拾取可视化数据数据。
|
|
m_dataSetPicked = vtkUnstructuredGrid::New();
|
|
|
|
// 创建预选可视化数据。
|
|
m_dataSetPreview = vtkUnstructuredGrid::New();
|
|
}
|
|
|
|
PickedDataProvider::~PickedDataProvider()
|
|
{
|
|
clearPickedData();
|
|
|
|
// 清除VTK数据。
|
|
if (m_dataSetPicked)
|
|
{
|
|
m_dataSetPicked->Delete();
|
|
m_dataSetPicked = nullptr;
|
|
}
|
|
|
|
if (m_dataSetPreview)
|
|
{
|
|
m_dataSetPreview->Delete();
|
|
m_dataSetPreview = nullptr;
|
|
}
|
|
}
|
|
|
|
void PickedDataProvider::addDataManually(Interface::FITKModelEnum::FITKModelSetType type, int dataObjId, QList<int> & indice)
|
|
{
|
|
// 创建拾取数据。
|
|
PickedData* data = new PickedData(type, dataObjId, indice);
|
|
|
|
// 判断是否有效。
|
|
if (data->isValid())
|
|
{
|
|
m_pickedDataList.push_back(data);
|
|
}
|
|
else
|
|
{
|
|
delete data;
|
|
}
|
|
|
|
// 生成拾取数据。
|
|
generatePickedDataSet();
|
|
}
|
|
|
|
void PickedDataProvider::clearPickedData()
|
|
{
|
|
// 清除并析构。
|
|
for (PickedData* data : m_pickedDataList)
|
|
{
|
|
if (data)
|
|
{
|
|
data->clearHighlight();
|
|
delete data;
|
|
}
|
|
}
|
|
|
|
m_pickedDataList.clear();
|
|
|
|
// 同时清空可视化数据。
|
|
if (m_dataSetPicked)
|
|
{
|
|
m_dataSetPicked->Reset();
|
|
m_dataSetPicked->Modified();
|
|
}
|
|
|
|
// 同时清空预选数据。
|
|
clearPickedDataPreview();
|
|
}
|
|
|
|
void PickedDataProvider::clearPickedDataPreview()
|
|
{
|
|
if (m_dataSetPreview)
|
|
{
|
|
m_dataSetPreview->Reset();
|
|
m_dataSetPreview->Modified();
|
|
}
|
|
|
|
if (m_pickedPreviewData)
|
|
{
|
|
delete m_pickedPreviewData;
|
|
m_pickedPreviewData = nullptr;
|
|
}
|
|
}
|
|
|
|
vtkDataSet* PickedDataProvider::getPickedPreviewDataSet()
|
|
{
|
|
return m_dataSetPreview;
|
|
}
|
|
|
|
vtkDataSet* PickedDataProvider::getPickedDataSet()
|
|
{
|
|
return m_dataSetPicked;
|
|
}
|
|
|
|
PickedData* PickedDataProvider::getPickedData(vtkActor* actor, int index, double* pickedWorldPos, bool isPreview)
|
|
{
|
|
// 获取拾取方式及附加信息。
|
|
GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
|
|
|
|
// 创建拾取信息。
|
|
PickedData* pickedData = new PickedData(pickInfo, actor, index, pickedWorldPos, isPreview);
|
|
|
|
// 判断拾取是否有效。
|
|
if (!pickedData->isValid())
|
|
{
|
|
delete pickedData;
|
|
return nullptr;
|
|
}
|
|
|
|
// 创建临时计算器。
|
|
PickedDataCalculator calculator(pickedData);
|
|
calculator.calculate();
|
|
|
|
return pickedData;
|
|
}
|
|
|
|
PickedData* PickedDataProvider::getPickedData(vtkActor2D* actor, bool isPreview)
|
|
{
|
|
// 获取拾取方式及附加信息。
|
|
GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
|
|
|
|
// 创建拾取信息。
|
|
PickedData* pickedData = new PickedData(pickInfo, actor, isPreview);
|
|
|
|
// 判断拾取是否有效。
|
|
if (!pickedData->isValid())
|
|
{
|
|
delete pickedData;
|
|
return nullptr;
|
|
}
|
|
|
|
// 创建临时计算器。
|
|
PickedDataCalculator calculator(pickedData);
|
|
calculator.calculate();
|
|
|
|
return pickedData;
|
|
}
|
|
|
|
bool PickedDataProvider::addPreviewPicked(vtkActor* actor, int index, double* pickedWorldPos)
|
|
{
|
|
if (m_pickedPreviewData)
|
|
{
|
|
// 获取拾取方式及附加信息。
|
|
GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
|
|
|
|
bool isTheSamePick = false;
|
|
|
|
if (m_pickedPreviewData->getPickedInfo()._pickObjType != pickInfo._pickObjType ||
|
|
m_pickedPreviewData->getPickedInfo()._pickMethod != pickInfo._pickMethod ||
|
|
m_pickedPreviewData->getPickedInfo()._pickParam != pickInfo._pickParam)
|
|
{
|
|
// 判断是否与上次预选相同,相同则跳出,节约性能。
|
|
if (m_pickedPreviewData->contains(actor, index))
|
|
{
|
|
isTheSamePick = true;
|
|
}
|
|
}
|
|
|
|
if (isTheSamePick)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
delete m_pickedPreviewData;
|
|
m_pickedPreviewData = nullptr;
|
|
}
|
|
|
|
// 计算生成拾取数据。
|
|
PickedData* pickedData = getPickedData(actor, index, pickedWorldPos, true);
|
|
if (!pickedData)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
m_pickedPreviewData = pickedData;
|
|
|
|
// 生成预选数据。
|
|
generatePickedPreviewDataSet();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PickedDataProvider::addPreviewPicked(vtkActor2D* actor)
|
|
{
|
|
if (m_pickedPreviewData)
|
|
{
|
|
bool isTheSamePick = false;
|
|
|
|
// 判断是否与上次预选相同,相同则跳出,节约性能。
|
|
if (m_pickedPreviewData->contains(actor))
|
|
{
|
|
isTheSamePick = true;
|
|
}
|
|
|
|
if (isTheSamePick)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
delete m_pickedPreviewData;
|
|
m_pickedPreviewData = nullptr;
|
|
}
|
|
|
|
// 计算生成拾取数据。
|
|
PickedData* pickedData = getPickedData(actor, true);
|
|
if (!pickedData)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
m_pickedPreviewData = pickedData;
|
|
|
|
// 生成预选数据。
|
|
generatePickedPreviewDataSet();
|
|
|
|
return true;
|
|
}
|
|
|
|
void PickedDataProvider::addPicked(vtkActor* actor, int index, double* pickedWorldPos)
|
|
{
|
|
PickedData* pickedData{ nullptr };
|
|
|
|
// 如果有预选数据则使用预选数据。
|
|
if (m_pickedPreviewData)
|
|
{
|
|
pickedData = m_pickedPreviewData->getCopy();
|
|
|
|
// 拷贝后析构,防止快速进行多次拾取导致无法预选。
|
|
delete m_pickedPreviewData;
|
|
m_pickedPreviewData = nullptr;
|
|
}
|
|
else
|
|
{
|
|
// 计算生成拾取数据。
|
|
pickedData = getPickedData(actor, index, pickedWorldPos);
|
|
}
|
|
|
|
if (!pickedData)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 处理拾取数据。
|
|
dealPickedData(pickedData);
|
|
|
|
// 生成拾取数据。
|
|
generatePickedDataSet();
|
|
|
|
// 如果有数据被拾取,发送信号。
|
|
if (m_pickedDataList.count() != 0)
|
|
{
|
|
emit sig_dataPicked();
|
|
}
|
|
}
|
|
|
|
void PickedDataProvider::addPicked(vtkActor2D* actor)
|
|
{
|
|
PickedData* pickedData{ nullptr };
|
|
|
|
// 如果有预选数据则使用预选数据。
|
|
if (m_pickedPreviewData)
|
|
{
|
|
pickedData = m_pickedPreviewData->getCopy();
|
|
|
|
// 拷贝后析构,防止快速进行多次拾取导致无法预选。
|
|
delete m_pickedPreviewData;
|
|
m_pickedPreviewData = nullptr;
|
|
}
|
|
else
|
|
{
|
|
// 计算生成拾取数据。
|
|
pickedData = getPickedData(actor);
|
|
}
|
|
|
|
if (!pickedData)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 处理拾取数据。
|
|
dealPickedData(pickedData);
|
|
|
|
// 生成拾取数据。
|
|
generatePickedDataSet();
|
|
|
|
// 如果有数据被拾取,发送信号。
|
|
if (m_pickedDataList.count() != 0)
|
|
{
|
|
emit sig_dataPicked();
|
|
}
|
|
}
|
|
|
|
void PickedDataProvider::addPicked(QList<vtkActor*> actors, vtkPlanes* cutPlane)
|
|
{
|
|
// 获取拾取方式及附加信息。
|
|
GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
|
|
|
|
// Single拾取模式禁止框选。
|
|
if (pickInfo._pickMethod == GUI::GUIPickInfo::PickMethod::PMSingle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 是否需要合并或移除数据。
|
|
bool needAddOrSubData = (m_settings->keyPressed(Qt::Key_Shift) && !m_settings->keyPressed(Qt::Key_Control)) ||
|
|
(!m_settings->keyPressed(Qt::Key_Shift) && m_settings->keyPressed(Qt::Key_Control));
|
|
|
|
// 不需要操作数据说明是普通框选,需要清空历史拾取信息。
|
|
if (!needAddOrSubData)
|
|
{
|
|
clearPickedData();
|
|
}
|
|
|
|
for (vtkActor* actor : actors)
|
|
{
|
|
// 创建拾取信息。
|
|
PickedData* pickedData = new PickedData(pickInfo, actor, cutPlane);
|
|
|
|
// 判断拾取是否有效。
|
|
if (!pickedData->isValid())
|
|
{
|
|
delete pickedData;
|
|
continue;
|
|
}
|
|
|
|
// 创建临时计算器。
|
|
PickedDataCalculator calculator(pickedData);
|
|
calculator.calculate();
|
|
|
|
// 处理拾取数据。
|
|
dealPickedData(pickedData, true);
|
|
}
|
|
|
|
// 生成拾取数据。
|
|
generatePickedDataSet();
|
|
|
|
// 如果有数据被拾取,发送信号。
|
|
if (m_pickedDataList.count() != 0)
|
|
{
|
|
emit sig_dataPicked();
|
|
}
|
|
}
|
|
|
|
void PickedDataProvider::generatePickedPreviewDataSet()
|
|
{
|
|
if (!m_dataSetPreview)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_dataSetPreview->Reset();
|
|
|
|
if (!m_pickedPreviewData)
|
|
{
|
|
m_dataSetPreview->Modified();
|
|
return;
|
|
}
|
|
|
|
// 为空则不进行计算。
|
|
if (m_pickedPreviewData->isEmpty())
|
|
{
|
|
m_dataSetPreview->Modified();
|
|
|
|
delete m_pickedPreviewData;
|
|
m_pickedPreviewData = nullptr;
|
|
return;
|
|
}
|
|
|
|
// 获取预选三维数据。
|
|
vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
|
|
m_pickedPreviewData->getDataSet(ugrid);
|
|
m_dataSetPreview->DeepCopy(ugrid);
|
|
ugrid->Delete();
|
|
m_dataSetPreview->Modified();
|
|
}
|
|
|
|
void PickedDataProvider::generatePickedDataSet()
|
|
{
|
|
// 合并拾取可视化数据。
|
|
vtkAppendFilter* appendFilter = vtkAppendFilter::New();
|
|
|
|
// 析构数据列表。
|
|
QList<vtkUnstructuredGrid*> dataSets;
|
|
|
|
// 移除已经被清空的数据。
|
|
for (int i = m_pickedDataList.count() - 1; i >= 0; i--)
|
|
{
|
|
PickedData* data = m_pickedDataList[i];
|
|
if (data->isEmpty())
|
|
{
|
|
m_pickedDataList.removeAt(i);
|
|
delete data;
|
|
}
|
|
}
|
|
|
|
for (PickedData* data : m_pickedDataList)
|
|
{
|
|
if (!data)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// 外部创建网格数据,内部进行数据填充。
|
|
vtkUnstructuredGrid* ugrid = vtkUnstructuredGrid::New();
|
|
data->getDataSet(ugrid);
|
|
appendFilter->AddInputData(ugrid);
|
|
|
|
dataSets.push_back(ugrid);
|
|
}
|
|
|
|
// 合并数据并拷贝。
|
|
appendFilter->Update();
|
|
|
|
m_dataSetPicked->DeepCopy(appendFilter->GetOutput());
|
|
m_dataSetPicked->Modified();
|
|
|
|
appendFilter->Delete();
|
|
|
|
// 移除并析构子数据集。
|
|
for (vtkUnstructuredGrid* dataSet : dataSets)
|
|
{
|
|
if (dataSet)
|
|
{
|
|
dataSet->Delete();
|
|
}
|
|
}
|
|
|
|
dataSets.clear();
|
|
}
|
|
|
|
void PickedDataProvider::dealPickedData(PickedData* data, bool isAreaPick)
|
|
{
|
|
// 获取拾取方式及附加信息。
|
|
GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
|
|
|
|
// 根据当前键盘按键判断数据处理逻辑。
|
|
// Shift按下则进行增量拾取。
|
|
if (m_settings->keyPressed(Qt::Key_Shift) && !m_settings->keyPressed(Qt::Key_Control) &&
|
|
// Single拾取模式不支持增量拾取。
|
|
pickInfo._pickMethod != GUI::GUIPickInfo::PickMethod::PMSingle)
|
|
{
|
|
// 获取相同模型拾取信息进行合并,否则直接添加。
|
|
PickedData* brotherData = getSameModelPickData(data);
|
|
if (brotherData)
|
|
{
|
|
brotherData->add(data);
|
|
}
|
|
else
|
|
{
|
|
m_pickedDataList.push_back(data);
|
|
}
|
|
}
|
|
// Control按下则擦除。
|
|
else if (!m_settings->keyPressed(Qt::Key_Shift) && m_settings->keyPressed(Qt::Key_Control))
|
|
{
|
|
// 获取相同模型拾取信息进行做差,否则直接跳出。
|
|
PickedData* brotherData = getSameModelPickData(data);
|
|
if (brotherData)
|
|
{
|
|
brotherData->subtract(data);
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
// Shift与Control同时按下或均不按下则清空拾取重新选择。
|
|
else
|
|
{
|
|
if (!isAreaPick)
|
|
{
|
|
clearPickedData();
|
|
}
|
|
|
|
m_pickedDataList.push_back(data);
|
|
}
|
|
|
|
// 移除已经被清空的数据。
|
|
for (int i = m_pickedDataList.count() - 1; i >= 0; i--)
|
|
{
|
|
PickedData* data = m_pickedDataList[i];
|
|
if (data->isEmpty())
|
|
{
|
|
m_pickedDataList.removeAt(i);
|
|
delete data;
|
|
}
|
|
}
|
|
}
|
|
|
|
PickedData* PickedDataProvider::getSameModelPickData(PickedData* data)
|
|
{
|
|
if (!data || m_pickedDataList.isEmpty())
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
// 寻找拾取到的同模型数据。
|
|
for (PickedData* pData : m_pickedDataList)
|
|
{
|
|
if (data->isSameAs(pData))
|
|
{
|
|
return pData;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
QList<PickedData*> PickedDataProvider::getPickedList()
|
|
{
|
|
return m_pickedDataList;
|
|
}
|
|
} |