1 /*=========================================================================
3 Program: Visualization Toolkit
4 Module: vtkStaticPlaneCutter.cxx
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
14 =========================================================================*/
15 #include "vtkStaticPlaneCutter.h"
17 #include <vtkCellData.h>
18 #include <vtkCompositeDataIterator.h>
19 #include <vtkIdFilter.h>
20 #include <vtkIdList.h>
21 #include <vtkInformation.h>
22 #include <vtkInformationVector.h>
23 #include <vtkMultiBlockDataSet.h>
24 #include <vtkMultiPieceDataSet.h>
25 #include <vtkObjectFactory.h>
26 #include <vtkPointData.h>
27 #include <vtkPolyData.h>
28 #include <vtkUnstructuredGrid.h>
29 #include <vtkGenericCell.h>
31 vtkStandardNewMacro(vtkStaticPlaneCutter);
33 static const char* IdsArrayName = "__vtkSPC_Ids";
35 //----------------------------------------------------------------------------
36 vtkStaticPlaneCutter::vtkStaticPlaneCutter()
38 this->InputMeshTime = 0;
39 this->FilterMTime = 0;
42 //----------------------------------------------------------------------------
43 vtkStaticPlaneCutter::~vtkStaticPlaneCutter()
45 this->ClearWeightsVector();
48 //-----------------------------------------------------------------------------
49 int vtkStaticPlaneCutter::RequestData(
50 vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
52 // get the inputs and outputs
53 vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
54 vtkInformation* outInfo = outputVector->GetInformationObject(0);
55 vtkUnstructuredGrid* input = vtkUnstructuredGrid::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
56 vtkMultiBlockDataSet* inputMB = vtkMultiBlockDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
57 vtkMultiBlockDataSet* mb =
58 vtkMultiBlockDataSet::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
61 vtkErrorMacro("Ouput information does not contain expected type of data object");
65 // Recover the first and only block so this works with single block mb
66 if (inputMB && inputMB->GetNumberOfBlocks() == 1)
68 input = vtkUnstructuredGrid::SafeDownCast(inputMB->GetBlock(0));
71 // Recover the static unstructured grid
74 // For any other type of input, fall back to superclass implementation
75 return this->Superclass::RequestData(request, inputVector, outputVector);
78 // Check cache validity
79 if (this->InputMeshTime == input->GetMeshMTime() && this->FilterMTime == this->GetMTime())
81 // Cache mesh is up to date, use it to generate data
82 if (this->InterpolateAttributes)
84 // Update the cache data
85 this->UpdateCacheData(input);
88 // Copy the updated cache into the output
89 mb->SetBlock(0, this->Cache.Get());
96 vtkNew<vtkUnstructuredGrid> tmpInput;
97 this->AddIdsArray(input, tmpInput.Get());
99 // Create an input vector to pass the completed input to the superclass
100 // RequestData method
101 vtkNew<vtkInformationVector> tmpInputVec;
102 tmpInputVec->Copy(inputVector[0], 1);
103 vtkInformation* tmpInInfo = tmpInputVec->GetInformationObject(0);
104 tmpInInfo->Set(vtkDataObject::DATA_OBJECT(), tmpInput.Get());
105 vtkInformationVector* tmpInputVecPt = tmpInputVec.Get();
106 int ret = this->Superclass::RequestData(request, &tmpInputVecPt, outputVector);
108 // Update the cache with superclass output
109 vtkMultiPieceDataSet* output = vtkMultiPieceDataSet::SafeDownCast(mb->GetBlock(0));
112 vtkErrorMacro("Output is not of expected type");
116 this->Cache->ShallowCopy(output);
117 this->InputMeshTime = input->GetMeshMTime();
118 this->FilterMTime = this->GetMTime();
120 // Compute the ids to be passed from the input to the cache
121 this->ComputeIds(input);
122 this->RemoveIdsArray(this->Cache);
127 //-----------------------------------------------------------------------------
128 void vtkStaticPlaneCutter::AddIdsArray(vtkDataSet* input, vtkDataSet* output)
130 vtkDataSet* tmpInput = input;
131 vtkNew<vtkIdFilter> generateIdScalars;
133 // Check for Ids array
134 vtkIdTypeArray *cellIdsTmp = vtkIdTypeArray::SafeDownCast(input->GetCellData()->GetAbstractArray(IdsArrayName));
138 generateIdScalars->SetInputData(tmpInput);
139 generateIdScalars->SetIdsArrayName(IdsArrayName);
140 generateIdScalars->FieldDataOn();
141 generateIdScalars->Update();
142 tmpInput = generateIdScalars->GetOutput();
144 output->ShallowCopy(tmpInput);
147 //-----------------------------------------------------------------------------
148 void vtkStaticPlaneCutter::RemoveIdsArray(vtkMultiPieceDataSet* output)
150 vtkSmartPointer<vtkCompositeDataIterator> iter;
151 iter.TakeReference(output->NewIterator());
152 iter->SkipEmptyNodesOn();
153 for (iter->GoToFirstItem(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
155 vtkPolyData* slice = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject());
158 slice->GetCellData()->RemoveArray(IdsArrayName);
163 //-----------------------------------------------------------------------------
164 void vtkStaticPlaneCutter::ClearWeightsVector()
166 for(auto& weightsVector : this->WeightsVectorCompo)
168 delete[] weightsVector[0].second;
170 this->WeightsVectorCompo.clear();
173 //-----------------------------------------------------------------------------
174 void vtkStaticPlaneCutter::ComputeIds(vtkUnstructuredGrid* input)
176 this->CellToCopyFrom.clear();
177 this->CellToCopyTo.clear();
178 this->ClearWeightsVector();
180 // Iterate over each piece of the multipiece output
181 vtkNew<vtkGenericCell> tmpCell;
182 vtkSmartPointer<vtkCompositeDataIterator> iter;
183 iter.TakeReference(this->Cache->NewIterator());
184 iter->SkipEmptyNodesOn();
185 for (iter->GoToFirstItem(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
187 vtkPolyData* slice = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject());
188 vtkIdType sliceNbPoints = slice ? slice->GetNumberOfPoints() : 0;
189 if (sliceNbPoints > 0)
191 // For each piece, recover the Ids of the cells sliced and the corresponding
192 // cellId in the slice
193 vtkSmartPointer<vtkIdList> cellIdsFrom = vtkSmartPointer<vtkIdList>::New();
194 vtkSmartPointer<vtkIdList> cellIdsTo = vtkSmartPointer<vtkIdList>::New();
195 this->CellToCopyFrom.push_back(cellIdsFrom);
196 this->CellToCopyTo.push_back(cellIdsTo);
198 vtkIdTypeArray* ids = vtkIdTypeArray::SafeDownCast(slice->GetCellData()->GetArray(IdsArrayName));
200 cellIdsFrom->SetNumberOfIds(ids->GetNumberOfValues());
201 cellIdsTo->SetNumberOfIds(ids->GetNumberOfValues());
202 for (vtkIdType i = 0; i < ids->GetNumberOfValues(); i++)
204 cellIdsFrom->SetId(i, ids->GetValue(i));
205 cellIdsTo->SetId(i, i);
207 if (input->GetPointData()->GetNumberOfArrays() > 0)
210 vtkIdType maxCellSize = input->GetMaxCellSize();
211 std::vector<std::pair<vtkSmartPointer<vtkIdList>, double*>> weightsVector;
212 weightsVector.resize(sliceNbPoints);
213 double *allWeights = new double[maxCellSize * sliceNbPoints];
214 for (vtkIdType i = 0; i < sliceNbPoints; i++)
216 vtkNew<vtkIdList> ptIds;
217 double *weights = &allWeights[maxCellSize * i];
218 unsigned short ncells;
220 slice->GetPointCells(i, ncells, cells);
221 vtkIdType cellId = cellIdsFrom->GetId(cells[0]);
222 assert(cellId < input->GetNumberOfCells());
223 input->GetCell(cellId, tmpCell);
224 input->GetCellPoints(cellId, ptIds);
225 double dist, pcoords[3], x[3], p[3];
227 slice->GetPoint(i, p);
228 tmpCell->EvaluatePosition(p, x, subId, pcoords, dist, weights);
229 weightsVector[i] = { ptIds, weights };
231 this->WeightsVectorCompo.push_back(weightsVector);
237 //-----------------------------------------------------------------------------
238 void vtkStaticPlaneCutter::UpdateCacheData(vtkDataSet* input)
240 // Remove useless FieldData Array from multipiece
241 // Created by automatic pass data in pipeline
242 vtkFieldData* mpFieldData = this->Cache->GetFieldData();
243 for (int i = mpFieldData->GetNumberOfArrays() - 1; i >= 0; i--)
245 mpFieldData->RemoveArray(i);
248 // Recover cell/point data
249 vtkCellData* inCD = input->GetCellData();
250 vtkPointData* inPD = input->GetPointData();
252 vtkSmartPointer<vtkCompositeDataIterator> iter;
253 iter.TakeReference(this->Cache->NewIterator());
254 iter->SkipEmptyNodesOn();
256 for (iter->GoToFirstItem(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
258 vtkPolyData* slice = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject());
259 if (slice && slice->GetNumberOfPoints() > 0)
261 vtkCellData* sliceCD = slice->GetCellData();
262 for (int iArr = 0; iArr < inCD->GetNumberOfArrays(); iArr++)
264 // For each array of the cell data of each slice
265 vtkAbstractArray* arrayToCopyIn = sliceCD->GetAbstractArray(inCD->GetArrayName(iArr));
268 // Copy the tuples from the input cell ids to the slice cell ids
269 arrayToCopyIn->InsertTuples(this->CellToCopyTo[blockId].Get(), this->CellToCopyFrom[blockId].Get(),
270 inCD->GetAbstractArray(iArr));
274 if (input->GetPointData()->GetNumberOfArrays() > 0)
276 vtkPointData* slicePD = slice->GetPointData();
277 vtkIdType sliceNbPoints = slice->GetNumberOfPoints();
278 slicePD->InterpolateAllocate(inPD, sliceNbPoints);
279 auto& weightsVector = this->WeightsVectorCompo[blockId];
280 for (vtkIdType ptIdx = 0; ptIdx < sliceNbPoints; ptIdx++)
282 slicePD->InterpolatePoint(inPD, ptIdx, weightsVector[ptIdx].first, weightsVector[ptIdx].second);
287 slice->GetFieldData()->PassData(input->GetFieldData());
293 //----------------------------------------------------------------------------
294 void vtkStaticPlaneCutter::PrintSelf(ostream& os, vtkIndent indent)
296 this->Superclass::PrintSelf(os, indent);
297 os << indent << "Cache: " << this->Cache << endl;
298 os << indent << "Input Mesh Time: " << this->InputMeshTime << endl;
299 os << indent << "Filter mTime: " << this->FilterMTime << endl;