1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    TestLinearToQuadraticCellsFilter.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 
16 #include <vtkActor.h>
17 #include <vtkCamera.h>
18 #include <vtkCellArray.h>
19 #include <vtkCellData.h>
20 #include <vtkCellIterator.h>
21 #include <vtkClipDataSet.h>
22 #include <vtkDataSetSurfaceFilter.h>
23 #include <vtkDoubleArray.h>
24 #include <vtkGenericCell.h>
25 #include <vtkLinearToQuadraticCellsFilter.h>
26 #include <vtkPointData.h>
27 #include <vtkPointLocator.h>
28 #include <vtkPolyDataMapper.h>
29 #include <vtkProperty.h>
30 #include <vtkRegressionTestImage.h>
31 #include <vtkRenderer.h>
32 #include <vtkRenderWindow.h>
33 #include <vtkRenderWindowInteractor.h>
34 #include <vtkSmartPointer.h>
35 #include <vtkTestUtilities.h>
36 #include <vtkTetra.h>
37 #include <vtkUnstructuredGrid.h>
38 #include <vtkVersion.h>
39 
40 namespace
41 {
AddTetra(const double * p0,const double * p1,const double * p2,const double * p3,vtkPointLocator * pointLocator,vtkCellArray * cells)42 void AddTetra(const double* p0,
43               const double* p1,
44               const double* p2,
45               const double* p3,
46               vtkPointLocator* pointLocator,
47               vtkCellArray* cells)
48 {
49   vtkSmartPointer<vtkTetra> t =
50     vtkSmartPointer<vtkTetra>::New();
51   static vtkIdType bIndices[4][4] = {{0,0,0,1},
52                                      {1,0,0,0},
53                                      {0,1,0,0},
54                                      {0,0,1,0}};
55   vtkIdType order = 1;
56   vtkIdType nPoints = 4;
57   t->GetPointIds()->SetNumberOfIds(nPoints);
58   t->GetPoints()->SetNumberOfPoints(nPoints);
59   t->Initialize();
60   double p[3];
61   vtkIdType pId;
62   vtkIdType* bIndex;
63   for (vtkIdType i = 0; i < nPoints; i++)
64   {
65     bIndex = bIndices[i];
66     for (vtkIdType j = 0; j < 3; j++)
67     {
68       p[j] = (p0[j]*bIndex[3])/order + (p1[j]*bIndex[0])/order +
69         (p2[j]*bIndex[1])/order + (p3[j]*bIndex[2])/order;
70     }
71     pointLocator->InsertUniquePoint(p, pId);
72     t->GetPointIds()->SetId(i,pId);
73   }
74   cells->InsertNextCell(t);
75 }
76 }
77 
TestLinearToQuadraticCellsFilter(int argc,char * argv[])78 int TestLinearToQuadraticCellsFilter(int argc, char* argv[])
79 {
80   // This test constructs a meshed cube comprised of linear tetrahedra and
81   // degree elevates the cells to quadratic tetrahedra. The resulting wireframe
82   // image depicts the subsequent linearization of these cells, so it should
83   // look like a <2*nX> x <2*nY> x <2*nZ> tetrahedralized cube.
84 
85   vtkIdType nX = 2;
86   vtkIdType nY = 2;
87   vtkIdType nZ = 2;
88 
89   vtkSmartPointer<vtkUnstructuredGrid> unstructuredGrid =
90     vtkSmartPointer<vtkUnstructuredGrid>::New();
91 
92   vtkSmartPointer<vtkPoints> pointArray =
93     vtkSmartPointer<vtkPoints>::New();
94 
95   vtkSmartPointer<vtkPointLocator> pointLocator =
96     vtkSmartPointer<vtkPointLocator>::New();
97   double bounds[6] = {-1.,1.,-1.,1.,-1.,1.};
98   pointLocator->InitPointInsertion(pointArray,bounds);
99 
100   vtkSmartPointer<vtkCellArray> cellArray =
101     vtkSmartPointer<vtkCellArray>::New();
102 
103   double p[8][3];
104   double dx = (bounds[1] - bounds[0])/nX;
105   double dy = (bounds[3] - bounds[2])/nY;
106   double dz = (bounds[5] - bounds[4])/nZ;
107   for (vtkIdType i = 0; i < 8; i++)
108   {
109     for (vtkIdType j = 0; j < 3; j++)
110     {
111       p[i][j] = bounds[2*j];
112     }
113   }
114   p[1][0] += dx;
115   p[2][0] += dx;
116   p[2][1] += dy;
117   p[3][1] += dy;
118   p[5][0] += dx;
119   p[5][2] += dz;
120   p[6][0] += dx;
121   p[6][1] += dy;
122   p[6][2] += dz;
123   p[7][1] += dy;
124   p[7][2] += dz;
125 
126   for (vtkIdType xInc = 0; xInc < nX; xInc++)
127   {
128     p[0][1] = p[1][1] = p[4][1] = p[5][1] = bounds[2];
129     p[2][1] = p[3][1] = p[6][1] = p[7][1] = bounds[2] + dy;
130 
131     for (vtkIdType yInc = 0; yInc < nY; yInc++)
132     {
133       p[0][2] = p[1][2] = p[2][2] = p[3][2] = bounds[4];
134       p[4][2] = p[5][2] = p[6][2] = p[7][2] = bounds[4] + dz;
135 
136       for (vtkIdType zInc = 0; zInc < nZ; zInc++)
137       {
138         AddTetra(p[0],p[1],p[2],p[5], pointLocator, cellArray);
139         AddTetra(p[0],p[2],p[3],p[7], pointLocator, cellArray);
140         AddTetra(p[0],p[5],p[7],p[4], pointLocator, cellArray);
141         AddTetra(p[2],p[5],p[6],p[7], pointLocator, cellArray);
142         AddTetra(p[0],p[2],p[5],p[7], pointLocator, cellArray);
143 
144         for (vtkIdType i = 0; i < 8; i++)
145         {
146           p[i][2] += dz;
147         }
148       }
149 
150       for (vtkIdType i = 0; i < 8; i++)
151       {
152         p[i][1] += dy;
153       }
154     }
155 
156     for (vtkIdType i = 0; i < 8; i++)
157     {
158       p[i][0] += dx;
159     }
160   }
161 
162   unstructuredGrid->SetPoints(pointArray);
163   unstructuredGrid->SetCells(VTK_TETRA, cellArray);
164 
165   vtkIdType nPoints = unstructuredGrid->GetPoints()->GetNumberOfPoints();
166 
167   vtkSmartPointer<vtkDoubleArray> radiant =
168     vtkSmartPointer<vtkDoubleArray>::New();
169   radiant->SetName("Distance from Origin");
170   radiant->SetNumberOfTuples(nPoints);
171 
172   vtkSmartPointer<vtkDoubleArray> elevation =
173     vtkSmartPointer<vtkDoubleArray>::New();
174   elevation->SetName("Elevation");
175   elevation->SetNumberOfTuples(nPoints);
176 
177 
178   double maxDist = 0;
179   for (vtkIdType i = 0; i < nPoints; i++)
180   {
181     double xyz[3];
182     unstructuredGrid->GetPoints()->GetPoint(i,xyz);
183     double dist = sqrt(xyz[0]*xyz[0] + xyz[1]*xyz[1] + xyz[2]*xyz[2]);
184     maxDist = (dist > maxDist ? dist : maxDist);
185     radiant->SetTypedTuple(i, &dist);
186     elevation->SetTypedTuple(i, &xyz[2]);
187   }
188 
189   unstructuredGrid->GetPointData()->AddArray(radiant);
190   unstructuredGrid->GetPointData()->AddArray(elevation);
191   unstructuredGrid->GetPointData()->SetScalars(radiant);
192 
193   vtkSmartPointer<vtkLinearToQuadraticCellsFilter> degreeElevate =
194     vtkSmartPointer<vtkLinearToQuadraticCellsFilter>::New();
195   degreeElevate->SetInputData(unstructuredGrid);
196 
197   // Visualize
198   vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter =
199     vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
200   surfaceFilter->SetInputConnection(degreeElevate->GetOutputPort());
201 
202   vtkSmartPointer<vtkPolyDataMapper> mapper =
203     vtkSmartPointer<vtkPolyDataMapper>::New();
204   mapper->SetInputConnection(surfaceFilter->GetOutputPort());
205   mapper->SetScalarRange(maxDist*.5,maxDist);
206 
207   vtkSmartPointer<vtkActor> actor =
208     vtkSmartPointer<vtkActor>::New();
209   actor->SetMapper(mapper);
210   actor->GetProperty()->SetRepresentationToWireframe();
211 actor->GetProperty()->SetLineWidth(4);
212 
213   vtkSmartPointer<vtkCamera> camera =
214     vtkSmartPointer<vtkCamera>::New();
215   camera->SetPosition(3.*maxDist, 3.*maxDist, -3.*maxDist);
216   camera->SetFocalPoint(.0, .0, 0.);
217 
218   vtkSmartPointer<vtkRenderer> renderer =
219     vtkSmartPointer<vtkRenderer>::New();
220   renderer->SetActiveCamera(camera);
221 
222    vtkSmartPointer<vtkRenderWindow> renderWindow =
223     vtkSmartPointer<vtkRenderWindow>::New();
224   renderWindow->AddRenderer(renderer);
225   vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
226     vtkSmartPointer<vtkRenderWindowInteractor>::New();
227   renderWindowInteractor->SetRenderWindow(renderWindow);
228 
229   renderer->AddActor(actor);
230 
231   renderWindow->Render();
232 
233   int retVal = vtkRegressionTestImage(renderWindow);
234   if (retVal == vtkRegressionTester::DO_INTERACTOR)
235   {
236     renderWindowInteractor->Start();
237   }
238 
239  return !retVal;
240 }
241