comac_desk_app/PostProcessing/WidgetCutter.cpp

728 lines
24 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "WidgetCutter.h"
#include <vtkCellData.h>
#include <vtkPointData.h>
#include <vtkDataSet.h>
#include <vtkOutlineFilter.h>
#include <vtkScalarBarRepresentation.h>
#include <vtkPolyDataWriter.h>
#include <vtkCutter.h>
#include <vtkActor.h>
#include <vtkPlane.h>
#include <vtkPlanes.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkLookupTable.h>
#include <vtkScalarBarWidget.h>
#include <vtkScalarBarActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkDoubleArray.h>
namespace pst
{
WidgetCutter::WidgetCutter()
: m_inputData(vtkSmartPointer<vtkPolyData>::New())
, m_inputDataOriginal(vtkSmartPointer<vtkPolyData>::New())
, m_planeWidget(vtkSmartPointer<vtkPlaneWidget>::New())
, m_plane(vtkSmartPointer<vtkPlane>::New())
, m_boxWidget(vtkSmartPointer<vtkBoxWidget>::New())
, m_planes(vtkSmartPointer<vtkPlanes>::New())
, m_cutter(vtkSmartPointer<vtkCutter>::New())
, m_selectedDataMapper(vtkSmartPointer<vtkPolyDataMapper>::New())
, m_cutterDataActor(vtkSmartPointer<vtkActor>::New())
, m_cutterWidgetCall(vtkSmartPointer<vtkWidgetCall>::New())
, m_lookupTable(vtkSmartPointer<vtkLookupTable>::New())
, m_scalarBarWidget(vtkSmartPointer<vtkScalarBarWidget>::New())
, m_scalarBarActor(vtkSmartPointer<vtkScalarBarActor>::New())
, m_dataOutlineActor(vtkSmartPointer<vtkActor>::New())
, m_interactor(vtkSmartPointer<vtkRenderWindowInteractor>::New())
, m_cutterDataToSave(vtkSmartPointer<vtkPolyData>::New())
, m_currentWidgetType(WidgetType::PLANE)
, m_currentAddedPointArrayIndex{ -1 }
, m_currentAddedCellArrayIndex{ -1 }
, m_isScalarAttributeSet{ false }
, m_currentArrayRange{ 0,11 }
{
InitLookupTable();
InitPipeLine();
}
void WidgetCutter::SetInteractor(vtkRenderWindowInteractor* iren)
{
m_planeWidget->SetInteractor(iren);
m_boxWidget->SetInteractor(iren);
m_scalarBarWidget->SetInteractor(iren);
m_interactor = iren;
}
void WidgetCutter::SetInputData(vtkDataSet* dataSet)
{
m_inputData = dataSet;
m_inputDataOriginal->DeepCopy(dataSet);
}
std::vector<WidgetCutter::ArrayInformation>
WidgetCutter::GetPointsArrayIndexAndNames()
{
return GetPointsArrayIndexAndNames(m_inputDataOriginal);
}
std::vector<WidgetCutter::ArrayInformation>
WidgetCutter::GetCellsArrayIndexAndNames()
{
return GetCellsArrayIndexAndNames(m_inputDataOriginal);
}
bool WidgetCutter::SetActiveScalarAttribute(int index,
const StructureType type, const int compIndex)
{
auto polyData = vtkPointSet::SafeDownCast(m_inputData);
//移除上次额外添加的数组
polyData->GetPointData()->RemoveArray(m_currentAddedPointArrayIndex);
polyData->GetCellData()->RemoveArray(m_currentAddedCellArrayIndex);
switch (type)
{
case StructureType::POINTS:
{
if (index >= m_inputData->GetPointData()->GetNumberOfArrays() || index < -1)
{
std::cout << "Error! Index illegal!" << std::endl;
return false;
}
auto activeScalarArray = m_inputData->GetPointData()->GetArray(index);
const auto nComponents = activeScalarArray->GetNumberOfComponents();
auto time1 = clock();
//单组分array,忽略组分提取,直接设置
if (nComponents == 1)
{
m_inputData->GetPointData()->SetActiveAttribute(
index, vtkDataSetAttributes::AttributeTypes::SCALARS);
m_lookupTable->SetTableRange(activeScalarArray->GetRange());
m_currentArrayRange[0] = activeScalarArray->GetRange()[0];
m_currentArrayRange[1] = activeScalarArray->GetRange()[1];
}
else
{
if (compIndex < -1 || compIndex >= nComponents)
{
std::cout << "Error! Extracting component index is " << compIndex
<< ", current array component is " << nComponents << std::endl;
return false;
}
vtkNew<vtkDoubleArray> magArray;
bool isSuccess = GetSingleComponent(activeScalarArray, compIndex, magArray);
if (!isSuccess)
{
std::cout << "Extract component failed!" << std::endl;
return false;
}
m_currentAddedPointArrayIndex = polyData->GetPointData()->AddArray(magArray);
m_inputData->GetPointData()->SetActiveAttribute(
m_currentAddedPointArrayIndex, vtkDataSetAttributes::AttributeTypes::SCALARS);
m_lookupTable->SetTableRange(magArray->GetRange());
m_currentArrayRange[0] = magArray->GetRange()[0];
m_currentArrayRange[1] = magArray->GetRange()[1];
}
auto time2 = clock();
std::cout << "Add scalar time = " << time2 - time1 << std::endl;
m_selectedDataMapper->SetScalarModeToUsePointData();
break;
}
case StructureType::CELLS:
{
if (index >= m_inputData->GetCellData()->GetNumberOfArrays() || index < 0)
{
std::cout << "Error! Index illegal!" << std::endl;
return false;
}
auto activeScalarArray = m_inputData->GetCellData()->GetArray(index);
const auto nComponents = activeScalarArray->GetNumberOfComponents();
auto time1 = clock();
//单组分array,忽略组分提取,直接设置
if (nComponents == 1)
{
m_inputData->GetCellData()->SetActiveAttribute(
index, vtkDataSetAttributes::AttributeTypes::SCALARS);
m_lookupTable->SetTableRange(activeScalarArray->GetRange());
m_currentArrayRange[0] = activeScalarArray->GetRange()[0];
m_currentArrayRange[1] = activeScalarArray->GetRange()[1];
}
else
{
if (compIndex < -1 || compIndex >= nComponents)
{
std::cout << "Error! Extracting component index is " << compIndex
<< ", current array component is " << nComponents << std::endl;
return false;
}
vtkNew<vtkDoubleArray> magArray;
bool isSuccess = GetSingleComponent(activeScalarArray, compIndex, magArray);
if (!isSuccess)
{
std::cout << "Extract component failed!" << std::endl;
return false;
}
m_currentAddedCellArrayIndex = polyData->GetCellData()->AddArray(magArray);
std::cout << "indexxxxx = " << m_currentAddedCellArrayIndex << std::endl;
m_inputData->GetCellData()->SetActiveAttribute(
m_currentAddedCellArrayIndex, vtkDataSetAttributes::AttributeTypes::SCALARS);
m_lookupTable->SetTableRange(magArray->GetRange());
m_currentArrayRange[0] = magArray->GetRange()[0];
m_currentArrayRange[1] = magArray->GetRange()[1];
}
auto time2 = clock();
std::cout << "Add scalar time = " << time2 - time1 << std::endl;
m_selectedDataMapper->SetScalarModeToUseCellData();
// m_currentUsingScalarType = StructureType::CELLS;
break;
}
default:
std::cout << "Wrong structure type" << std::endl;
return false;
break;
}
m_isScalarAttributeSet = true;
return true;
}
void WidgetCutter::SetWidgetType(WidgetType type)
{
m_currentWidgetType = type;
}
void WidgetCutter::SetPlaneNormalDirection(PlaneNormalDirection direction)
{
//PlaceWidget必须先于SetNormal调用但似乎该函数并无效果。
// m_planeWidget->PlaceWidget(m_inputData->GetBounds());
switch (direction)
{
case PlaneNormalDirection::X:
{
m_planeWidget->SetNormal(1, 0, 0);
m_plane->SetNormal(1, 0, 0);
break;
}
case PlaneNormalDirection::Y:
{
m_planeWidget->SetNormal(0, 1, 0);
m_plane->SetNormal(0, 1, 0);
break;
}
case PlaneNormalDirection::Z:
{
m_planeWidget->SetNormal(0, 0, 1);
m_plane->SetNormal(0, 0, 1);
break;
}
default:
{
break;
}
}
}
void WidgetCutter::SetRepresentationType(PlaneRepresentation type)
{
switch (type)
{
// case PlaneRepresentation::OUTLINE:
// {
//// m_planeWidget->SetRepresentationToOutline();
// m_cutterDataActor->GetProperty()->SetRepresentationToPoints();
// break;
// }
case PlaneRepresentation::WIREFRAME:
{
// m_planeWidget->SetRepresentationToWireframe();
m_cutterDataActor->GetProperty()->SetRepresentationToWireframe();
break;
}
case PlaneRepresentation::SURFACE:
{
// m_planeWidget->SetRepresentationToSurface();
m_cutterDataActor->GetProperty()->SetRepresentationToSurface();
break;
}
case PlaneRepresentation::POINTS:
{
m_cutterDataActor->GetProperty()->SetRepresentationToPoints();
break;
}
default:
{
break;
}
}
}
void WidgetCutter::SetCenter(double x[3])
{
m_planeWidget->SetCenter(x);
m_plane->SetOrigin(x);
}
void WidgetCutter::TurnAllWidgetOff()
{
if (m_planeWidget->GetInteractor())
{
m_planeWidget->Off();
}
if (m_boxWidget->GetInteractor())
{
m_boxWidget->Off();
}
}
void WidgetCutter::TurnWidgetOn()
{
switch (m_currentWidgetType)
{
case WidgetType::BOX:
m_boxWidget->On();
break;
case WidgetType::PLANE:
m_planeWidget->On();
break;
default:
break;
}
}
void WidgetCutter::Update()
{
m_boxWidget->SetInputData(m_inputData);
m_boxWidget->PlaceWidget(m_inputData->GetBounds());
m_planes->SetBounds(m_inputData->GetBounds());
//默认开启plane
m_planeWidget->SetInputData(m_inputData);
m_planeWidget->PlaceWidget(m_inputData->GetBounds());
m_planeWidget->On();
m_cutterWidgetCall->SetCallbackWidgetType(vtkWidgetCall::CallbackWidgetType::PLANE);
m_cutter->SetCutFunction(m_plane);
m_cutter->SetInputData(m_inputData);
m_cutter->Update();
m_selectedDataMapper->Update();
m_scalarBarWidget->SetScalarBarActor(m_scalarBarActor);
// m_scalarBarWidget->SetResizable(true);
vtkScalarBarRepresentation* rep =
vtkScalarBarRepresentation::SafeDownCast(m_scalarBarWidget->GetRepresentation());
rep->SetPosition2(0.05, 0.7);
rep->SetPosition(0.01, 0.1);
m_scalarBarWidget->On();
GenerateDataOutlineBox();
}
void WidgetCutter::refreshWidget()
{
switch (m_currentWidgetType)
{
//将widget的interactor置空SetInteractor(NULL)
//是为了能让每个widget都能响应键盘事件否则其只响应最早设置interactor的widget
case WidgetType::BOX:
{
m_planeWidget->Off();
m_planeWidget->SetInteractor(nullptr);
m_boxWidget->SetInteractor(m_interactor);
m_boxWidget->On();
//置空再设置是为了让interactor优先响应m_boxWidget键盘事件
m_scalarBarWidget->SetInteractor(nullptr);
m_scalarBarWidget->SetInteractor(m_interactor);
m_scalarBarWidget->On();
m_cutter->SetCutFunction(m_planes);
m_cutterWidgetCall->SetCallbackWidgetType(vtkWidgetCall::CallbackWidgetType::BOX);
m_cutterWidgetCall->Execute(m_boxWidget, 0, nullptr);
break;
}
case WidgetType::PLANE:
{
m_boxWidget->Off();
m_boxWidget->SetInteractor(nullptr);
m_planeWidget->SetInteractor(m_interactor);
m_planeWidget->On();
//置空再设置是为了让interactor优先响应m_planeWidget键盘事件
m_scalarBarWidget->SetInteractor(nullptr);
m_scalarBarWidget->SetInteractor(m_interactor);
m_scalarBarWidget->On();
m_cutter->SetCutFunction(m_plane);
m_cutterWidgetCall->SetCallbackWidgetType(vtkWidgetCall::CallbackWidgetType::PLANE);
m_cutterWidgetCall->Execute(m_planeWidget, 0, nullptr);
break;
}
default:
break;
}
}
vtkProperty* WidgetCutter::GetWidgetPlaneProperty()
{
return m_planeWidget->GetPlaneProperty();
}
vtkProperty* WidgetCutter::GetWidgetHandelProperty()
{
return m_planeWidget->GetHandleProperty();
}
vtkPlaneWidget* WidgetCutter::GetPlaneWidget()
{
return m_planeWidget;
}
vtkBoxWidget* WidgetCutter::GetBoxWidget()
{
return m_boxWidget;
}
vtkCutter* WidgetCutter::GetCutter()
{
return m_cutter;
}
vtkPolyDataMapper* WidgetCutter::GetMapper()
{
return m_selectedDataMapper;
}
vtkActor* WidgetCutter::GetCutterActor()
{
return m_cutterDataActor;
}
bool WidgetCutter::SetScalarBarRangeToAuto()
{
if (!m_isScalarAttributeSet)
{
std::cout << "Error, scalars attribute must be set !" << std::endl;
return false;
}
m_lookupTable->SetTableRange(m_currentArrayRange[0], m_currentArrayRange[1]);
return true;
}
void WidgetCutter::SetScalarBarRange(const double min, const double max)
{
m_lookupTable->SetTableRange(min, max);
}
void WidgetCutter::SetScalarBarTitle(const std::string& title)
{
m_scalarBarActor->SetTitle(title.c_str());
}
void WidgetCutter::SetScalarBarNumberOfLabel(const int num)
{
m_scalarBarActor->SetNumberOfLabels(num);
}
void WidgetCutter::SetScalarBarDisplayPosition(const int x, const int y)
{
m_scalarBarActor->SetDisplayPosition(x, y);
}
vtkScalarBarActor* WidgetCutter::GetScalarBar()
{
return m_scalarBarActor;
}
void WidgetCutter::SetDataOutlineActorColor(const double r, const double g, const double b)
{
m_dataOutlineActor->GetProperty()->SetColor(r, g, b);
}
vtkActor* WidgetCutter::GetDataOutlineActor()
{
return m_dataOutlineActor;
}
void WidgetCutter::WriteTheCutterData(const std::string& fileName)
{
vtkNew<vtkPolyDataWriter> writer;
writer->SetInputData(m_cutterDataToSave);
writer->SetFileName(fileName.c_str());
try
{
writer->Update();
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
}
}
void WidgetCutter::ResetCurrentWidgetPositon()
{
switch (m_currentWidgetType)
{
case WidgetType::BOX:
m_boxWidget->PlaceWidget(m_inputData->GetBounds());
break;
case WidgetType::PLANE:
m_planeWidget->SetCenter(m_inputData->GetCenter());
m_planeWidget->PlaceWidget(m_inputData->GetBounds());
break;
default:
break;
}
}
vtkLookupTable* WidgetCutter::GetLookupTable()
{
return m_lookupTable;
}
void WidgetCutter::SetLookupTable(vtkLookupTable* lookupTable)
{
m_lookupTable = lookupTable;
}
void WidgetCutter::InitPipeLine()
{
m_planeWidget->SetResolution(10);
m_planeWidget->SetHandleSize(0.001);
m_planeWidget->SetPlaceFactor(0.1);
m_planeWidget->GetPlaneProperty()->SetColor(.9, .4, .4);
m_planeWidget->GetPlaneProperty()->SetPointSize(2);
m_planeWidget->GetHandleProperty()->SetColor(0, .4, .7);
m_planeWidget->GetHandleProperty()->SetLineWidth(1.5);
m_planeWidget->SetRepresentationToOutline();
m_planeWidget->SetPlaceFactor(1);
m_boxWidget->SetPlaceFactor(1);
m_boxWidget->SetHandleSize(0.003);
m_boxWidget->SetPlaceFactor(1);
m_cutterWidgetCall->m_planes = m_planes;
m_scalarBarActor->SetTitle("Cutter");
m_scalarBarActor->SetLookupTable(m_lookupTable);
// m_scalarBarActor->SetDisplayPosition(10,10);
m_scalarBarActor->SetPosition(0.01, 0.1);
m_scalarBarActor->SetPosition2(0.05, 0.7);
m_cutterWidgetCall->m_singlePlane = m_plane;
m_planeWidget->AddObserver(vtkCommand::InteractionEvent, m_cutterWidgetCall);
m_boxWidget->AddObserver(vtkCommand::InteractionEvent, m_cutterWidgetCall);
m_selectedDataMapper->SetInterpolateScalarsBeforeMapping(true);
m_selectedDataMapper->SetColorModeToMapScalars();
m_selectedDataMapper->ScalarVisibilityOn();
m_selectedDataMapper->SetUseLookupTableScalarRange(1);
m_selectedDataMapper->SetInputConnection(m_cutter->GetOutputPort());
m_selectedDataMapper->SetLookupTable(m_lookupTable);
m_cutterDataActor->SetMapper(m_selectedDataMapper);
}
void WidgetCutter::InitLookupTable()
{
//色调范围从蓝色到红色
m_lookupTable->SetNumberOfColors(600);
m_lookupTable->SetHueRange(0.67, 0.0);
m_lookupTable->Build();
}
void WidgetCutter::GenerateDataOutlineBox()
{
vtkNew<vtkOutlineFilter> outline;
outline->SetInputData(m_inputData);
vtkNew<vtkPolyDataMapper> outlineMapper;
outlineMapper->SetInputConnection(outline->GetOutputPort());
outlineMapper->Update();
m_dataOutlineActor->SetMapper(outlineMapper);
}
bool
WidgetCutter::GetSingleComponent(vtkDataArray* array,
const int componentIndex, vtkDoubleArray* returnArray)
{
auto nComponents = array->GetNumberOfComponents();
std::cout << " nComponents = " << nComponents << std::endl;
//检查下标合法性,-1代表取magnitude
if (componentIndex < -1 || componentIndex >= nComponents)
{
return false;
}
//取单个组分的属性的0组分即返回自己
if (componentIndex == 0 && nComponents == 1)
{
returnArray->DeepCopy(vtkDoubleArray::SafeDownCast(array));
return true;
}
const auto nTuples = array->GetNumberOfTuples();
std::cout << " nTuples = " << nTuples << std::endl;
vtkNew<vtkDoubleArray> singleArray;
singleArray->SetNumberOfComponents(1);
singleArray->SetNumberOfTuples(nTuples);
//取magnitude
if (componentIndex == -1)
{
std::cout << "magnitude " << std::endl;
singleArray->SetName("Magnitude");
for (vtkIdType i = 0; i < nTuples; ++i)
{
double mag = 0;
for (int j = 0; j < nComponents; ++j)
{
double tmp = array->GetComponent(i, j);
mag += tmp * tmp;
}
mag = sqrt(mag);
singleArray->InsertTuple1(i, mag);
}
}
else //取现有的单个组件
{
std::cout << "extract comp = " << componentIndex << std::endl;
if (componentIndex == 0)
{
singleArray->SetName("X");
}
else if (componentIndex == 1)
{
singleArray->SetName("Y");
}
else if (componentIndex == 2)
{
singleArray->SetName("Z");
}
else
{
singleArray->SetName(std::to_string(componentIndex).c_str());
}
for (vtkIdType j = 0; j < nTuples; ++j)
{
singleArray->InsertTuple1(j, array->GetComponent(j, componentIndex));
}
}
returnArray->DeepCopy(singleArray);
return true;
}
void
WidgetCutter::SelectFieldsToSaveForCutter(bool useOrigianl,
const std::vector<ArrayInformation>& selectedPointsFiledId,
const std::vector<ArrayInformation>& selectedCellsFiledId)
{
m_cutterDataToSave->DeepCopy(m_cutter->GetOutput());
if (useOrigianl)
{
auto pointsInfoOriginal = GetPointsArrayIndexAndNames(m_inputDataOriginal);
auto cellsInfoOriginal = GetCellsArrayIndexAndNames(m_inputDataOriginal);
SelectArrayFromCutterData(pointsInfoOriginal, cellsInfoOriginal);
}
else
{
SelectArrayFromCutterData(selectedPointsFiledId, selectedCellsFiledId);
}
}
std::vector<WidgetCutter::ArrayInformation>
WidgetCutter::GetPointsArrayIndexAndNames(vtkDataSet* data)
{
std::vector<WidgetCutter::ArrayInformation> arrayInfoVector;
WidgetCutter::ArrayInformation tempInfo;
for (int i = 0; i < data->GetPointData()->GetNumberOfArrays(); ++i)
{
tempInfo.arrayIndex = i;
tempInfo.arrayName = data->GetPointData()->GetArrayName(i);
tempInfo.arrayComponent = data->GetPointData()->GetArray(i)->GetNumberOfComponents();
arrayInfoVector.push_back(tempInfo);
}
return arrayInfoVector;
}
std::vector<WidgetCutter::ArrayInformation>
WidgetCutter::GetCellsArrayIndexAndNames(vtkDataSet* data)
{
std::vector<WidgetCutter::ArrayInformation> arrayInfoVector;
WidgetCutter::ArrayInformation tempInfo;
for (int i = 0; i < data->GetCellData()->GetNumberOfArrays(); ++i)
{
tempInfo.arrayIndex = i;
tempInfo.arrayName = data->GetCellData()->GetArrayName(i);
tempInfo.arrayComponent = data->GetCellData()->GetArray(i)->GetNumberOfComponents();
arrayInfoVector.push_back(tempInfo);
}
return arrayInfoVector;
}
void WidgetCutter::SelectArrayFromCutterData(
const std::vector<ArrayInformation>& selectedPointsFiled,
const std::vector<ArrayInformation>& selectedCellsFiled)
{
auto pointsInfoCutter = GetPointsArrayIndexAndNames(m_cutterDataToSave);
auto cellsInfoCutter = GetCellsArrayIndexAndNames(m_cutterDataToSave);
for (int i = 0; i < pointsInfoCutter.size(); ++i)
{
for (int j = 0; j < selectedPointsFiled.size(); ++j)
{
//在其中,需要保留
if (pointsInfoCutter[i].arrayIndex == selectedPointsFiled[j].arrayIndex)
{
break;
}
//没找到,不在其中,移除多余列
if (j == selectedPointsFiled.size() - 1)
{
m_cutterDataToSave->GetPointData()->RemoveArray(pointsInfoCutter[i].arrayIndex);
}
}
}
for (int i = 0; i < cellsInfoCutter.size(); ++i)
{
for (int j = 0; j < selectedCellsFiled.size(); ++j)
{
//在其中,需要保留
if (cellsInfoCutter[i].arrayIndex == selectedCellsFiled[j].arrayIndex)
{
break;
}
if (j == selectedCellsFiled.size() - 1)
{
m_cutterDataToSave->GetCellData()->RemoveArray(cellsInfoCutter[i].arrayIndex);
}
}
}
}
}