Salome HOME
Make it run with int64 configuration with non regression tests
[modules/paravis.git] / src / Plugins / StaticMesh / vtkStaticPlaneCutter.cxx
1 /*=========================================================================
2
3   Program:   Visualization Toolkit
4   Module:    vtkStaticPlaneCutter.cxx
5
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
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.
13
14 =========================================================================*/
15 #include "vtkStaticPlaneCutter.h"
16
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>
30
31 vtkStandardNewMacro(vtkStaticPlaneCutter);
32
33 static const char* IdsArrayName = "__vtkSPC_Ids";
34
35 //----------------------------------------------------------------------------
36 vtkStaticPlaneCutter::vtkStaticPlaneCutter()
37 {
38   this->InputMeshTime = 0;
39   this->FilterMTime = 0;
40 }
41
42 //----------------------------------------------------------------------------
43 vtkStaticPlaneCutter::~vtkStaticPlaneCutter()
44 {
45   this->ClearWeightsVector();
46 }
47
48 //-----------------------------------------------------------------------------
49 int vtkStaticPlaneCutter::RequestData(
50   vtkInformation* request, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
51 {
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()));
59   if (!mb)
60   {
61     vtkErrorMacro("Ouput information does not contain expected type of data object");
62     return 0;
63   }
64
65   // Recover the first and only block so this works with single block mb
66   if (inputMB && inputMB->GetNumberOfBlocks() == 1)
67   {
68     input = vtkUnstructuredGrid::SafeDownCast(inputMB->GetBlock(0));
69   }
70
71   // Recover the static unstructured grid
72   if (!input)
73   {
74     // For any other type of input, fall back to superclass implementation
75     return this->Superclass::RequestData(request, inputVector, outputVector);
76   }
77
78   // Check cache validity
79   if (this->InputMeshTime == input->GetMeshMTime() && this->FilterMTime == this->GetMTime())
80   {
81     // Cache mesh is up to date, use it to generate data
82     if (this->InterpolateAttributes)
83     {
84       // Update the cache data
85       this->UpdateCacheData(input);
86     }
87
88     // Copy the updated cache into the output
89     mb->SetBlock(0, this->Cache.Get());
90     return 1;
91   }
92   else
93   {
94     // Cache is invalid
95     // Add needed Arrays
96     vtkNew<vtkUnstructuredGrid> tmpInput;
97     this->AddIdsArray(input, tmpInput.Get());
98
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);
107
108     // Update the cache with superclass output
109     vtkMultiPieceDataSet* output = vtkMultiPieceDataSet::SafeDownCast(mb->GetBlock(0));
110     if (!output)
111     {
112       vtkErrorMacro("Output is not of expected type");
113       return 0;
114     }
115
116     this->Cache->ShallowCopy(output);
117     this->InputMeshTime = input->GetMeshMTime();
118     this->FilterMTime = this->GetMTime();
119
120     // Compute the ids to be passed from the input to the cache
121     this->ComputeIds(input);
122     this->RemoveIdsArray(this->Cache);
123     return ret;
124   }
125 }
126
127 //-----------------------------------------------------------------------------
128 void vtkStaticPlaneCutter::AddIdsArray(vtkDataSet* input, vtkDataSet* output)
129 {
130   vtkDataSet* tmpInput = input;
131   vtkNew<vtkIdFilter> generateIdScalars;
132
133   // Check for Ids array
134   vtkIdTypeArray *cellIdsTmp = vtkIdTypeArray::SafeDownCast(input->GetCellData()->GetAbstractArray(IdsArrayName));
135   if (!cellIdsTmp)
136   {
137     // Create Ids array
138     generateIdScalars->SetInputData(tmpInput);
139     generateIdScalars->SetIdsArrayName(IdsArrayName);
140     generateIdScalars->FieldDataOn();
141     generateIdScalars->Update();
142     tmpInput = generateIdScalars->GetOutput();
143   }
144   output->ShallowCopy(tmpInput);
145 }
146
147 //-----------------------------------------------------------------------------
148 void vtkStaticPlaneCutter::RemoveIdsArray(vtkMultiPieceDataSet* output)
149 {
150   vtkSmartPointer<vtkCompositeDataIterator> iter;
151   iter.TakeReference(output->NewIterator());
152   iter->SkipEmptyNodesOn();
153   for (iter->GoToFirstItem(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
154   {
155     vtkPolyData* slice = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject());
156     if (slice)
157     {
158       slice->GetCellData()->RemoveArray(IdsArrayName);
159     }
160   }
161 }
162
163 //-----------------------------------------------------------------------------
164 void vtkStaticPlaneCutter::ClearWeightsVector()
165 {
166   for(auto& weightsVector : this->WeightsVectorCompo)
167   {
168     delete[] weightsVector[0].second;
169   }
170   this->WeightsVectorCompo.clear();
171 }
172
173 //-----------------------------------------------------------------------------
174 void vtkStaticPlaneCutter::ComputeIds(vtkUnstructuredGrid* input)
175 {
176   this->CellToCopyFrom.clear();
177   this->CellToCopyTo.clear();
178   this->ClearWeightsVector();
179
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())
186   {
187     vtkPolyData* slice = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject());
188     vtkIdType sliceNbPoints = slice ? slice->GetNumberOfPoints() : 0;
189     if (sliceNbPoints > 0)
190     {
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);
197
198       vtkIdTypeArray* ids = vtkIdTypeArray::SafeDownCast(slice->GetCellData()->GetArray(IdsArrayName));
199       assert(ids);
200       cellIdsFrom->SetNumberOfIds(ids->GetNumberOfValues());
201       cellIdsTo->SetNumberOfIds(ids->GetNumberOfValues());
202       for (vtkIdType i = 0; i < ids->GetNumberOfValues(); i++)
203       {
204         cellIdsFrom->SetId(i, ids->GetValue(i));
205         cellIdsTo->SetId(i, i);
206       }
207       if (input->GetPointData()->GetNumberOfArrays() > 0)
208       {
209         slice->BuildLinks();
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++)
215         {
216           vtkNew<vtkIdList> ptIds;
217           double *weights = &allWeights[maxCellSize * i];
218           unsigned short ncells;
219           vtkIdType *cells;
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];
226           int subId = 0;
227           slice->GetPoint(i, p);
228           tmpCell->EvaluatePosition(p, x, subId, pcoords, dist, weights);
229           weightsVector[i] = { ptIds, weights };
230         }
231         this->WeightsVectorCompo.push_back(weightsVector);
232       }
233     }
234   }
235 }
236
237 //-----------------------------------------------------------------------------
238 void vtkStaticPlaneCutter::UpdateCacheData(vtkDataSet* input)
239 {
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--)
244   {
245     mpFieldData->RemoveArray(i);
246   }
247
248   // Recover cell/point data
249   vtkCellData* inCD = input->GetCellData();
250   vtkPointData* inPD = input->GetPointData();
251
252   vtkSmartPointer<vtkCompositeDataIterator> iter;
253   iter.TakeReference(this->Cache->NewIterator());
254   iter->SkipEmptyNodesOn();
255   int blockId = 0;
256   for (iter->GoToFirstItem(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
257   {
258     vtkPolyData* slice = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject());
259     if (slice && slice->GetNumberOfPoints() > 0)
260     {
261       vtkCellData* sliceCD = slice->GetCellData();
262       for (int iArr = 0; iArr < inCD->GetNumberOfArrays(); iArr++)
263       {
264         // For each array of the cell data of each slice
265         vtkAbstractArray* arrayToCopyIn = sliceCD->GetAbstractArray(inCD->GetArrayName(iArr));
266         if (arrayToCopyIn)
267         {
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));
271         }
272       }
273
274       if (input->GetPointData()->GetNumberOfArrays() > 0)
275       {
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++)
281         {
282           slicePD->InterpolatePoint(inPD, ptIdx, weightsVector[ptIdx].first, weightsVector[ptIdx].second);
283         }
284       }
285
286       // Update field data
287       slice->GetFieldData()->PassData(input->GetFieldData());
288       blockId++;
289     }
290   }
291 }
292
293 //----------------------------------------------------------------------------
294 void vtkStaticPlaneCutter::PrintSelf(ostream& os, vtkIndent indent)
295 {
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;
300 }