1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestDispatchers.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 // .NAME Test Dispatchers
16 // .SECTION Description
17 // Tests vtkDispatcher and vtkDoubleDispatcher
18
19 #include "vtkObjectFactory.h"
20 #include "vtkDispatcher.h"
21 #include "vtkDoubleDispatcher.h"
22 #include "vtkDataArrayDispatcher.h"
23 #include "vtkNew.h"
24
25 //classes we will be using in the test
26 #include "vtkCharArray.h"
27 #include "vtkDoubleArray.h"
28 #include "vtkStringArray.h"
29 #include "vtkIntArray.h"
30 #include "vtkPoints.h"
31
32 #include <stdexcept>
33 #include <algorithm>
34 namespace
35 {
36
test_expression(bool valid,const std::string & msg)37 void test_expression(bool valid, const std::string& msg)
38 {
39 if(!valid)
40 {
41 throw std::runtime_error(msg);
42 }
43 }
44
45 template<typename T, typename U>
as(U * u)46 inline T* as(U* u)
47 {
48 return dynamic_cast<T*>(u);
49 }
50
51 struct singleFunctor
52 {
53 int timesCalled;
singleFunctor__anon63e6b6c20111::singleFunctor54 singleFunctor():timesCalled(0){}
55 template<typename T>
operator ()__anon63e6b6c20111::singleFunctor56 int operator()(T&)
57 {
58 return ++timesCalled;
59 }
60 };
61
62 struct doubleFunctor
63 {
64 int timesCalled;
doubleFunctor__anon63e6b6c20111::doubleFunctor65 doubleFunctor():timesCalled(0){}
66 template<typename T, typename U>
operator ()__anon63e6b6c20111::doubleFunctor67 int operator()(T&, U&)
68 {
69 return ++timesCalled;
70 }
71 };
72
73 //type traits for vtkTTFunctor and pointsWrapper
74 template<typename T> struct FieldType;
75 template<> struct FieldType<vtkIntArray>
76 {
77 enum {VTK_DATA_TYPE=VTK_INT};
78 typedef int ValueType;
79 };
80
81 template<> struct FieldType<vtkDoubleArray>
82 {
83 enum {VTK_DATA_TYPE=VTK_DOUBLE};
84 typedef double ValueType;
85 };
86
87 template<> struct FieldType<vtkCharArray>
88 {
89 enum {VTK_DATA_TYPE=VTK_CHAR};
90 typedef char ValueType;
91 };
92
93 //this functor replaces the usage of VTK_TT macro, by showing
94 //how to use template traits
95 struct vtkTTFunctor
96 {
97 template<typename T>
operator ()__anon63e6b6c20111::vtkTTFunctor98 void operator()(T& t) const
99 {
100 //example that sorts, only works on single component
101 typedef typename FieldType<T>::ValueType ValueType;
102 if(t.GetNumberOfComponents() == 1)
103 {
104 ValueType* start = static_cast<ValueType*>(t.GetVoidPointer(0));
105 ValueType* end = static_cast<ValueType*>(t.GetVoidPointer(
106 t.GetNumberOfTuples()));
107 std::sort(start,end);
108 }
109 }
110 };
111
112 struct pointsFunctor
113 {
operator ()__anon63e6b6c20111::pointsFunctor114 vtkPoints* operator()(vtkDoubleArray& dataArray) const
115 {
116 vtkPoints* points = vtkPoints::New();
117 points->SetData(&dataArray);
118 return points;
119 }
120
operator ()__anon63e6b6c20111::pointsFunctor121 vtkPoints* operator()(vtkIntArray& dataArray) const
122 {
123 vtkPoints* points = vtkPoints::New();
124 points->SetNumberOfPoints(dataArray.GetNumberOfTuples());
125 return points;
126 }
127 };
128
129 }
130
TestSingleDispatch()131 bool TestSingleDispatch()
132 {
133 //statefull dispatching
134 singleFunctor functor;
135 vtkDispatcher<vtkObject,int> dispatcher;
136 dispatcher.Add<vtkDoubleArray>(&functor);
137 dispatcher.Add<vtkStringArray>(&functor);
138 dispatcher.Add<vtkIntArray>(&functor);
139
140 //verify the dispatching
141 vtkNew<vtkDoubleArray> doubleArray;
142 vtkNew<vtkStringArray> stringArray;
143 vtkNew<vtkIntArray> intArray;
144 vtkNew<vtkPoints> pointsArray;
145
146 int result = dispatcher.Go(as<vtkObject>(doubleArray.GetPointer()));
147 test_expression(result==1,"double array dispatch failed with statefull functor");
148
149 result = dispatcher.Go(stringArray.GetPointer());
150 test_expression(result==2,"string array dispatch failed with statefull functor");
151
152 result = dispatcher.Go(intArray.GetPointer());
153 test_expression(result==3,"int array dispatch failed with statefull functor");
154
155 result = dispatcher.Go(pointsArray.GetPointer());
156 test_expression(result==0,"points array didn't fail");
157
158 return true;
159 }
160
TestStatelessSingleDispatch()161 bool TestStatelessSingleDispatch()
162 {
163 //stateless dispatching
164 vtkDispatcher<vtkObject,int> dispatcher;
165 dispatcher.Add<vtkDoubleArray>(singleFunctor());
166 dispatcher.Add<vtkStringArray>(singleFunctor());
167
168 //verify the dispatching
169 vtkNew<vtkDoubleArray> doubleArray;
170 vtkNew<vtkStringArray> stringArray;
171
172 int result = dispatcher.Go(doubleArray.GetPointer());
173 test_expression(result==1,"double array dispatch failed with stateless functor");
174
175 result = dispatcher.Go(as<vtkObject>(stringArray.GetPointer()));
176 test_expression(result==1,"string array dispatch failed with stateless functor");
177
178 return true;
179 }
180
TestDoubleDispatch()181 bool TestDoubleDispatch()
182 {
183 //statefull dispatching
184 doubleFunctor functor;
185 vtkDoubleDispatcher<vtkObject,vtkObject,int> dispatcher;
186 dispatcher.Add<vtkDoubleArray,vtkStringArray>(&functor);
187 dispatcher.Add<vtkStringArray,vtkStringArray>(&functor);
188 dispatcher.Add<vtkIntArray,vtkDoubleArray>(&functor);
189
190 //verify the dispatching
191 vtkNew<vtkDoubleArray> doubleArray;
192 vtkNew<vtkStringArray> stringArray;
193 vtkNew<vtkIntArray> intArray;
194 vtkNew<vtkPoints> pointsArray;
195
196 int result = dispatcher.Go(as<vtkObject>(doubleArray.GetPointer()),
197 as<vtkObject>(stringArray.GetPointer()));
198 test_expression(result==1,"double array dispatch failed with statefull functor");
199
200 result = dispatcher.Go(stringArray.GetPointer(),stringArray.GetPointer());
201 test_expression(result==2,"string array dispatch failed with statefull functor");
202
203 result = dispatcher.Go(as<vtkObject>(intArray.GetPointer()),doubleArray.GetPointer());
204 test_expression(result==3,"int array dispatch failed with statefull functor");
205
206 result = dispatcher.Go(intArray.GetPointer(),pointsArray.GetPointer());
207 test_expression(result==0,"points array didn't fail");
208
209 return true;
210 }
211
TestStatelessDoubleDispatch()212 bool TestStatelessDoubleDispatch()
213 {
214 //stateless dispatching
215 vtkDoubleDispatcher<vtkObject,vtkObject,int> dispatcher;
216 dispatcher.Add<vtkDoubleArray,vtkStringArray>(doubleFunctor());
217 dispatcher.Add<vtkStringArray,vtkStringArray>(doubleFunctor());
218 dispatcher.Add<vtkIntArray,vtkDoubleArray>(doubleFunctor());
219
220 //verify the dispatching
221 vtkNew<vtkDoubleArray> doubleArray;
222 vtkNew<vtkStringArray> stringArray;
223 vtkNew<vtkIntArray> intArray;
224 vtkNew<vtkPoints> pointsArray;
225
226 int result = dispatcher.Go(doubleArray.GetPointer(),stringArray.GetPointer());
227 test_expression(result==1,"double array dispatch failed with statefull functor");
228
229 result = dispatcher.Go(stringArray.GetPointer(),stringArray.GetPointer());
230 test_expression(result==1,"string array dispatch failed with statefull functor");
231
232 result = dispatcher.Go(intArray.GetPointer(),doubleArray.GetPointer());
233 test_expression(result==1,"int array dispatch failed with statefull functor");
234
235 result = dispatcher.Go(intArray.GetPointer(),pointsArray.GetPointer());
236 test_expression(result==0,"points array didn't fail");
237
238 return true;
239 }
240
241
TestMixedDispatch()242 bool TestMixedDispatch()
243 {
244 //stateless dispatching
245 singleFunctor functor;
246 vtkDispatcher<vtkDataArray,int> dispatcher;
247 dispatcher.Add<vtkDoubleArray>(&functor);
248 dispatcher.Add<vtkIntArray>(&functor);
249 dispatcher.Add<vtkCharArray>(singleFunctor());
250
251 //verify the dispatching
252 vtkNew<vtkDoubleArray> doubleArray;
253 vtkNew<vtkIntArray> intArray;
254 vtkNew<vtkCharArray> charArray;
255
256 int result = dispatcher.Go(as<vtkDataArray>(doubleArray.GetPointer()));
257 result = dispatcher.Go(intArray.GetPointer());
258 test_expression(result==2,"unexpected");
259 result = dispatcher.Go(doubleArray.GetPointer());
260 test_expression(result==3,"statefull functor failed with int and double");
261
262 result = dispatcher.Go(charArray.GetPointer());
263 test_expression(result==1,"");
264
265
266 return true;
267 }
268
TestVTKTTReplacement()269 bool TestVTKTTReplacement()
270 {
271 //stateless dispatching
272 vtkDispatcher<vtkDataArray> dispatcher; //default return type is void
273 dispatcher.Add<vtkDoubleArray>(vtkTTFunctor());
274 dispatcher.Add<vtkIntArray>(vtkTTFunctor());
275
276 //verify the dispatching
277 vtkNew<vtkDoubleArray> doubleArray;
278 vtkNew<vtkIntArray> intArray;
279
280 doubleArray->SetNumberOfValues(10);
281 intArray->SetNumberOfValues(10);
282
283 for(int i=0; i < 10; ++i)
284 {
285 doubleArray->SetValue(i,10-i);
286 intArray->SetValue(i,-10*i);
287 }
288
289 //sort the array, passing in as vtkObject to show we use RTTI
290 //to get out the derived class info
291 dispatcher.Go(as<vtkDataArray>(doubleArray.GetPointer()));
292 dispatcher.Go(as<vtkDataArray>(intArray.GetPointer()));
293
294 //verify the array is sorted, by checking min & max
295 test_expression(doubleArray->GetValue(0)==1,"double array not sorted");
296 test_expression(doubleArray->GetValue(9)==10,"double array not sorted");
297
298 test_expression(intArray->GetValue(0)==-90,"int array not sorted");
299 test_expression(intArray->GetValue(9)==0,"int array not sorted");
300
301 return true;
302 }
303
TestReturnVtkObject()304 bool TestReturnVtkObject()
305 {
306 //This example shows how to return a vtkObject that is filled by the algorithm
307 //that you passed in.
308 vtkDispatcher<vtkDataArray,vtkPoints*> dispatcher; //default return type is void
309 dispatcher.Add<vtkDoubleArray>(pointsFunctor());
310 dispatcher.Add<vtkIntArray>(pointsFunctor());
311
312 //verify the dispatching
313 vtkNew<vtkDoubleArray> doubleArray;
314 doubleArray->SetNumberOfComponents(3);
315 doubleArray->SetNumberOfTuples(1);
316
317 //make sure the result isn't copied anywhere
318 vtkPoints* result = dispatcher.Go(as<vtkDataArray>(doubleArray.GetPointer()));
319
320 test_expression(result != nullptr, "Returned points not valid");
321 test_expression(result->GetData() == doubleArray.GetPointer(),
322 "Returned points not equal to the passed in double array");
323 result->Delete();
324
325 //on an integer function we should get a whole new points array
326 vtkNew<vtkIntArray> intArray;
327 result = dispatcher.Go(as<vtkDataArray>( intArray.GetPointer() ));
328
329 test_expression(result != nullptr, "Returned points not valid");
330 result->Delete();
331
332 return true;
333 }
334
335
TestDispatchers(int,char * [])336 int TestDispatchers(int /*argc*/, char* /*argv*/[])
337 {
338
339 bool passed = TestSingleDispatch();
340 passed &= TestStatelessSingleDispatch();
341 passed &= TestDoubleDispatch();
342 passed &= TestStatelessDoubleDispatch();
343 passed &= TestMixedDispatch();
344 passed &= TestVTKTTReplacement();
345 passed &= TestReturnVtkObject();
346
347 return passed ? 0 : 1;
348 }
349