1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkRotationFilter.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 "vtkRotationFilter.h"
16 
17 #include "vtkCellData.h"
18 #include "vtkGenericCell.h"
19 #include "vtkIdList.h"
20 #include "vtkInformation.h"
21 #include "vtkInformationVector.h"
22 #include "vtkMath.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkPointData.h"
25 #include "vtkTransform.h"
26 #include "vtkUnstructuredGrid.h"
27 
28 vtkStandardNewMacro(vtkRotationFilter);
29 
30 //------------------------------------------------------------------------------
vtkRotationFilter()31 vtkRotationFilter::vtkRotationFilter()
32 {
33   this->Axis = 2;
34   this->CopyInput = 0;
35   this->Center[0] = this->Center[1] = this->Center[2] = 0;
36   this->NumberOfCopies = 0;
37   this->Angle = 0;
38 }
39 
40 //------------------------------------------------------------------------------
41 vtkRotationFilter::~vtkRotationFilter() = default;
42 
43 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)44 void vtkRotationFilter::PrintSelf(ostream& os, vtkIndent indent)
45 {
46   this->Superclass::PrintSelf(os, indent);
47 
48   os << indent << "Axis: " << this->Axis << endl;
49   os << indent << "CopyInput: " << this->CopyInput << endl;
50   os << indent << "Center: (" << this->Center[0] << "," << this->Center[1] << "," << this->Center[2]
51      << ")" << endl;
52   os << indent << "NumberOfCopies: " << this->NumberOfCopies << endl;
53   os << indent << "Angle: " << this->Angle << endl;
54 }
55 
56 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)57 int vtkRotationFilter::RequestData(vtkInformation* vtkNotUsed(request),
58   vtkInformationVector** inputVector, vtkInformationVector* outputVector)
59 {
60   // get the info objects
61   vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
62   vtkInformation* outInfo = outputVector->GetInformationObject(0);
63 
64   // get the input and output
65   vtkDataSet* input = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
66   vtkUnstructuredGrid* output =
67     vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
68 
69   vtkPointData* inPD = input->GetPointData();
70   vtkPointData* outPD = output->GetPointData();
71   vtkCellData* inCD = input->GetCellData();
72   vtkCellData* outCD = output->GetCellData();
73 
74   if (!this->GetNumberOfCopies())
75   {
76     vtkErrorMacro("No number of copy set!");
77     return 1;
78   }
79 
80   double tuple[3];
81   vtkPoints* outPoints;
82   double point[3], center[3], negativCenter[3];
83   vtkIdType ptId, cellId;
84   vtkGenericCell* cell = vtkGenericCell::New();
85   vtkIdList* ptIds = vtkIdList::New();
86 
87   outPoints = vtkPoints::New();
88 
89   vtkIdType numPts = input->GetNumberOfPoints();
90   vtkIdType numCells = input->GetNumberOfCells();
91 
92   if (this->CopyInput)
93   {
94     outPoints->Allocate((this->CopyInput + this->GetNumberOfCopies()) * numPts);
95     output->Allocate((this->CopyInput + this->GetNumberOfCopies()) * numPts);
96   }
97   else
98   {
99     outPoints->Allocate(this->GetNumberOfCopies() * numPts);
100     output->Allocate(this->GetNumberOfCopies() * numPts);
101   }
102 
103   outPD->CopyAllocate(inPD);
104   outCD->CopyAllocate(inCD);
105 
106   vtkDataArray *inPtVectors, *outPtVectors;
107   vtkDataArray *inCellVectors, *outCellVectors;
108 
109   inPtVectors = inPD->GetVectors();
110   outPtVectors = outPD->GetVectors();
111   inCellVectors = inCD->GetVectors();
112   outCellVectors = outCD->GetVectors();
113 
114   // Copy first points.
115   if (this->CopyInput)
116   {
117     for (vtkIdType i = 0; i < numPts; ++i)
118     {
119       input->GetPoint(i, point);
120       ptId = outPoints->InsertNextPoint(point);
121       outPD->CopyData(inPD, i, ptId);
122     }
123   }
124   vtkTransform* localTransform = vtkTransform::New();
125   // Rotate points.
126   this->GetCenter(center);
127   negativCenter[0] = -center[0];
128   negativCenter[1] = -center[1];
129   negativCenter[2] = -center[2];
130 
131   for (int k = 0; k < this->GetNumberOfCopies(); ++k)
132   {
133     localTransform->Identity();
134     localTransform->Translate(center);
135     switch (this->Axis)
136     {
137       case USE_X:
138         localTransform->RotateX((k + 1) * this->GetAngle());
139         break;
140 
141       case USE_Y:
142         localTransform->RotateY((k + 1) * this->GetAngle());
143         break;
144 
145       case USE_Z:
146         localTransform->RotateZ((k + 1) * this->GetAngle());
147         break;
148     }
149     localTransform->Translate(negativCenter);
150     for (vtkIdType i = 0; i < numPts; ++i)
151     {
152       input->GetPoint(i, point);
153       localTransform->TransformPoint(point, point);
154       ptId = outPoints->InsertNextPoint(point);
155       outPD->CopyData(inPD, i, ptId);
156       if (inPtVectors)
157       {
158         inPtVectors->GetTuple(i, tuple);
159         outPtVectors->SetTuple(ptId, tuple);
160       }
161     }
162   }
163 
164   localTransform->Delete();
165 
166   // Copy original cells.
167   if (this->CopyInput)
168   {
169     for (vtkIdType i = 0; i < numCells; ++i)
170     {
171       input->GetCellPoints(i, ptIds);
172       output->InsertNextCell(input->GetCellType(i), ptIds);
173       outCD->CopyData(inCD, i, i);
174     }
175   }
176 
177   vtkIdType* newCellPts;
178   vtkIdList* cellPts;
179 
180   // Generate rotated cells.
181   for (int k = 0; k < this->GetNumberOfCopies(); ++k)
182   {
183     for (vtkIdType i = 0; i < numCells; ++i)
184     {
185       input->GetCellPoints(i, ptIds);
186       input->GetCell(i, cell);
187       vtkIdType numCellPts = cell->GetNumberOfPoints();
188       int cellType = cell->GetCellType();
189       cellPts = cell->GetPointIds();
190 
191       vtkDebugMacro(<< "celltype " << cellType << " numCellPts " << numCellPts);
192       newCellPts = new vtkIdType[numCellPts];
193       for (vtkIdType j = 0; j < numCellPts; ++j)
194       {
195         newCellPts[j] = cellPts->GetId(j) + numPts * k;
196         if (this->CopyInput)
197         {
198           newCellPts[j] += numPts;
199         }
200       }
201 
202       cellId = output->InsertNextCell(cellType, numCellPts, newCellPts);
203       delete[] newCellPts;
204       outCD->CopyData(inCD, i, cellId);
205       if (inCellVectors)
206       {
207         inCellVectors->GetTuple(i, tuple);
208         outCellVectors->SetTuple(cellId, tuple);
209       }
210     }
211   }
212 
213   cell->Delete();
214   ptIds->Delete();
215   output->SetPoints(outPoints);
216   outPoints->Delete();
217   output->CheckAttributes();
218 
219   return 1;
220 }
221 
FillInputPortInformation(int,vtkInformation * info)222 int vtkRotationFilter::FillInputPortInformation(int, vtkInformation* info)
223 {
224   info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
225   return 1;
226 }
227