1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkShrinkFilter.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 "vtkShrinkFilter.h"
16
17 #include "vtkCell.h"
18 #include "vtkCellData.h"
19 #include "vtkIdList.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkObjectFactory.h"
23 #include "vtkPointData.h"
24 #include "vtkSmartPointer.h"
25 #include "vtkUnstructuredGrid.h"
26
27 vtkStandardNewMacro(vtkShrinkFilter);
28
29 //------------------------------------------------------------------------------
vtkShrinkFilter()30 vtkShrinkFilter::vtkShrinkFilter()
31 {
32 this->ShrinkFactor = 0.5;
33 }
34
35 //------------------------------------------------------------------------------
36 vtkShrinkFilter::~vtkShrinkFilter() = default;
37
38 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)39 void vtkShrinkFilter::PrintSelf(ostream& os, vtkIndent indent)
40 {
41 this->Superclass::PrintSelf(os, indent);
42 os << indent << "Shrink Factor: " << this->ShrinkFactor << "\n";
43 }
44
45 //------------------------------------------------------------------------------
FillInputPortInformation(int,vtkInformation * info)46 int vtkShrinkFilter::FillInputPortInformation(int, vtkInformation* info)
47 {
48 // This filter uses the vtkDataSet cell traversal methods so it
49 // suppors any data set type as input.
50 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
51 return 1;
52 }
53
54 //------------------------------------------------------------------------------
RequestData(vtkInformation *,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)55 int vtkShrinkFilter::RequestData(
56 vtkInformation*, vtkInformationVector** inputVector, vtkInformationVector* outputVector)
57 {
58 // Get input and output data.
59 vtkDataSet* input = vtkDataSet::GetData(inputVector[0]);
60 vtkUnstructuredGrid* output = vtkUnstructuredGrid::GetData(outputVector);
61
62 // We are now executing this filter.
63 vtkDebugMacro("Shrinking cells");
64
65 // Skip execution if there is no input geometry.
66 vtkIdType numCells = input->GetNumberOfCells();
67 vtkIdType numPts = input->GetNumberOfPoints();
68 if (numCells < 1 || numPts < 1)
69 {
70 vtkDebugMacro("No data to shrink!");
71 return 1;
72 }
73
74 // Allocate working space for new and old cell point lists.
75 vtkSmartPointer<vtkIdList> ptIds = vtkSmartPointer<vtkIdList>::New();
76 vtkSmartPointer<vtkIdList> newPtIds = vtkSmartPointer<vtkIdList>::New();
77 ptIds->Allocate(VTK_CELL_SIZE);
78 newPtIds->Allocate(VTK_CELL_SIZE);
79
80 // Allocate approximately the space needed for the output cells.
81 output->Allocate(numCells);
82
83 // Allocate space for a new set of points.
84 vtkSmartPointer<vtkPoints> newPts = vtkSmartPointer<vtkPoints>::New();
85 newPts->Allocate(numPts * 8, numPts);
86
87 // Allocate space for data associated with the new set of points.
88 vtkPointData* inPD = input->GetPointData();
89 vtkPointData* outPD = output->GetPointData();
90 outPD->CopyAllocate(inPD, numPts * 8, numPts);
91
92 // Support progress and abort.
93 vtkIdType tenth = (numCells >= 10 ? numCells / 10 : 1);
94 double numCellsInv = 1.0 / numCells;
95 int abort = 0;
96
97 // Point Id map.
98 vtkIdType* pointMap = new vtkIdType[input->GetNumberOfPoints()];
99
100 // Traverse all cells, obtaining node coordinates. Compute "center"
101 // of cell, then create new vertices shrunk towards center.
102 for (vtkIdType cellId = 0; cellId < numCells && !abort; ++cellId)
103 {
104 // Get the list of points for this cell.
105 input->GetCellPoints(cellId, ptIds);
106 vtkIdType numIds = ptIds->GetNumberOfIds();
107
108 // Periodically update progress and check for an abort request.
109 if (cellId % tenth == 0)
110 {
111 this->UpdateProgress((cellId + 1) * numCellsInv);
112 abort = this->GetAbortExecute();
113 }
114
115 // Compute the center of mass of the cell points.
116 double center[3] = { 0, 0, 0 };
117 for (vtkIdType i = 0; i < numIds; ++i)
118 {
119 double p[3];
120 input->GetPoint(ptIds->GetId(i), p);
121 for (int j = 0; j < 3; ++j)
122 {
123 center[j] += p[j];
124 }
125 }
126 for (int j = 0; j < 3; ++j)
127 {
128 center[j] /= numIds;
129 }
130
131 // Create new points for this cell.
132 newPtIds->Reset();
133 for (vtkIdType i = 0; i < numIds; ++i)
134 {
135 // Get the old point location.
136 double p[3];
137 input->GetPoint(ptIds->GetId(i), p);
138
139 // Compute the new point location.
140 double newPt[3];
141 for (int j = 0; j < 3; ++j)
142 {
143 newPt[j] = center[j] + this->ShrinkFactor * (p[j] - center[j]);
144 }
145
146 // Create the new point for this cell.
147 vtkIdType newId = newPts->InsertNextPoint(newPt);
148
149 // Copy point data from the old point.
150 vtkIdType oldId = ptIds->GetId(i);
151 outPD->CopyData(inPD, oldId, newId);
152
153 pointMap[oldId] = newId;
154 }
155
156 // special handling for polyhedron cells
157 if (vtkUnstructuredGrid::SafeDownCast(input) && input->GetCellType(cellId) == VTK_POLYHEDRON)
158 {
159 vtkUnstructuredGrid::SafeDownCast(input)->GetFaceStream(cellId, newPtIds);
160 vtkUnstructuredGrid::ConvertFaceStreamPointIds(newPtIds, pointMap);
161 }
162 else
163 {
164 for (vtkIdType i = 0; i < numIds; ++i)
165 {
166 newPtIds->InsertId(i, pointMap[ptIds->GetId(i)]);
167 }
168 }
169
170 // Store the new cell in the output.
171 output->InsertNextCell(input->GetCellType(cellId), newPtIds);
172 }
173
174 // Store the new set of points in the output.
175 output->SetPoints(newPts);
176
177 // Just pass cell data through because we still have the same number
178 // and type of cells.
179 output->GetCellData()->PassData(input->GetCellData());
180
181 // Avoid keeping extra memory around.
182 output->Squeeze();
183
184 delete[] pointMap;
185
186 return 1;
187 }
188