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