1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestLookupTable.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 // Test some generic features of vtkLookupTable
16
17 #include "vtkLookupTable.h"
18 #include "vtkMath.h"
19 #include "vtkMathUtilities.h"
20 #include "vtkCommand.h"
21 #include "vtkSmartPointer.h"
22
23 // simple macro for performing tests
24 #define TestAssert(t) \
25 if (!(t)) \
26 { \
27 cerr << "In " << __FILE__ << ":"; \
28 cerr << " Test assertion failed line " << __LINE__ << ": " << #t << "\n"; \
29 rval |= 1; \
30 }
31
32 #define TestVector4d(t1, t2) \
33 TestAssert( \
34 (vtkMathUtilities::FuzzyCompare<double>(t1[0], t2[0]) \
35 && vtkMathUtilities::FuzzyCompare<double>(t1[1], t2[1]) \
36 && vtkMathUtilities::FuzzyCompare<double>(t1[2], t2[2]) \
37 && vtkMathUtilities::FuzzyCompare<double>(t1[3], t2[3])))
38
TestColor4uc(const unsigned char * expected,const unsigned char * test)39 int TestColor4uc(const unsigned char* expected, const unsigned char* test)
40 {
41 int failed = expected[0] != test[0] || expected[1] != test[1] ||
42 expected[2] != test[2] || expected[3] != test[3] ? 1 : 0;
43 if (failed)
44 {
45 std::cerr << "Expected color: " <<
46 static_cast<int>(expected[0]) << ", " <<
47 static_cast<int>(expected[1]) << ", " <<
48 static_cast<int>(expected[2]) << ", " <<
49 static_cast<int>(expected[3]) << std::endl;
50 std::cerr << "Test color: " <<
51 static_cast<int>(test[0]) << ", " <<
52 static_cast<int>(test[1]) << ", " <<
53 static_cast<int>(test[2]) << ", " <<
54 static_cast<int>(test[3]) << std::endl;
55 }
56
57 return !failed;
58 }
59
60 // a simple error observer
61 namespace {
62
63 class errorObserver
64 {
65 public:
errorObserver()66 errorObserver() : EventId(0) {}
67
Reset()68 void Reset() { this->EventId = 0; }
69
GetEvent() const70 unsigned long GetEvent() const { return this->EventId; }
71
Callback(vtkObject *,unsigned long e,void *)72 void Callback(vtkObject *, unsigned long e, void *) {
73 this->EventId = e; }
74
75 private:
76 unsigned long EventId;
77 };
78
79 }
80
TestLookupTable(int,char * [])81 int TestLookupTable(int,char *[])
82 {
83 int rval = 0;
84
85 vtkSmartPointer<vtkLookupTable> table =
86 vtkSmartPointer<vtkLookupTable>::New();
87
88 // == check computation of table index ==
89
90 // basic mapping test
91 double lo = 3.234;
92 double hi = 6.123;
93 double tol = 1e-6;
94 double step = (hi - lo)/255.0;
95 table->SetTableRange(lo,hi);
96 table->Build();
97 TestAssert(table->GetIndex(lo) == 0);
98 TestAssert(table->GetIndex(hi) == 255);
99 TestAssert(table->GetIndex(lo+tol) == 0);
100 TestAssert(table->GetIndex(hi-tol) == 255);
101 TestAssert(table->GetIndex(lo-step) == 0);
102 TestAssert(table->GetIndex(hi+step) == 255);
103 TestAssert(table->GetIndex(lo+step) == 1);
104 TestAssert(table->GetIndex(hi-step) == 254);
105 TestAssert(table->GetIndex(vtkMath::Nan()) == -1);
106
107 double rgba[4];
108 rgba[0] = 0.0; rgba[1] = 0.0; rgba[2] = 0.0; rgba[3] = 1.0;
109 TestVector4d(table->GetBelowRangeColor(), rgba);
110 rgba[0] = 1.0; rgba[1] = 1.0; rgba[2] = 1.0; rgba[3] = 1.0;
111 TestVector4d(table->GetAboveRangeColor(), rgba);
112
113 TestAssert(table->GetUseBelowRangeColor() == 0);
114 TestAssert(table->GetUseAboveRangeColor() == 0);
115
116 unsigned char expected[4];
117
118 // Test handling of below-range colors
119 vtkMath::HSVToRGB(table->GetHueRange()[0],
120 table->GetSaturationRange()[0],
121 table->GetValueRange()[0],
122 &rgba[0], &rgba[1], &rgba[2]);
123 rgba[3] = table->GetAlphaRange()[0];
124
125 vtkLookupTable::GetColorAsUnsignedChars(rgba, expected);
126 table->UseBelowRangeColorOff();
127 table->Build();
128 const unsigned char *result = table->MapValue(lo);
129 TestAssert(TestColor4uc(expected, result));
130
131 table->GetBelowRangeColor(rgba);
132 vtkLookupTable::GetColorAsUnsignedChars(rgba, expected);
133 table->UseBelowRangeColorOn();
134 table->Build();
135 result = table->MapValue(lo-tol);
136 TestAssert(TestColor4uc(expected, result));
137
138 // Test handling of above-range colors
139 vtkMath::HSVToRGB(table->GetHueRange()[1],
140 table->GetSaturationRange()[1],
141 table->GetValueRange()[1],
142 &rgba[0], &rgba[1], &rgba[2]);
143 rgba[3] = table->GetAlphaRange()[1];
144
145 vtkLookupTable::GetColorAsUnsignedChars(rgba, expected);
146 table->UseAboveRangeColorOff();
147 table->Build();
148 result = table->MapValue(hi);
149 TestAssert(TestColor4uc(expected, result));
150
151 table->GetAboveRangeColor(rgba);
152 vtkLookupTable::GetColorAsUnsignedChars(rgba, expected);
153 table->UseAboveRangeColorOn();
154 table->Build();
155 result = table->MapValue(hi+tol);
156 TestAssert(TestColor4uc(expected, result));
157
158 // log range test
159 lo = pow(10.0,lo);
160 hi = pow(10.0,hi);
161 step = pow(10.0,step);
162 table->SetScaleToLog10();
163 table->SetTableRange(lo,hi);
164 table->Build();
165 TestAssert(table->GetIndex(lo) == 0);
166 TestAssert(table->GetIndex(hi) == 255);
167 TestAssert(table->GetIndex(lo+tol) == 0);
168 TestAssert(table->GetIndex(hi-tol) == 255);
169 TestAssert(table->GetIndex(vtkMath::Nan()) == -1);
170
171 // Note - both below- and above-range colors are enabled at this point
172 TestAssert(table->GetIndex(lo/step) == 0);
173 TestAssert(table->GetIndex(hi*step) == 255);
174 TestAssert(table->GetIndex(lo*step) == 1);
175 TestAssert(table->GetIndex(hi/step) == 254);
176
177 // negative log range
178 double tmp = hi;
179 hi = -lo;
180 lo = -tmp;
181 step = 1.0/step;
182 table->SetScaleToLog10();
183 table->SetTableRange(lo,hi);
184 table->Build();
185 TestAssert(table->GetIndex(lo) == 0);
186 TestAssert(table->GetIndex(hi) == 255);
187 TestAssert(table->GetIndex(lo+tol) == 0);
188 TestAssert(table->GetIndex(hi-tol) == 255);
189 TestAssert(table->GetIndex(lo/step) == 0);
190 TestAssert(table->GetIndex(hi*step) == 255);
191 TestAssert(table->GetIndex(lo*step) == 1);
192 TestAssert(table->GetIndex(hi/step) == 254);
193
194 // == check error reporting ==
195
196 errorObserver observer;
197 unsigned long observerId =
198 table->AddObserver(
199 vtkCommand::ErrorEvent, &observer, &errorObserver::Callback);
200
201 // linear table, range is null, permitted (step function)
202 observer.Reset();
203 table->SetScaleToLinear();
204 table->SetTableRange(0,0);
205 TestAssert(observer.GetEvent() == 0);
206
207 // linear table, range is inverted, illegal
208 observer.Reset();
209 table->SetScaleToLinear();
210 table->SetTableRange(1,-1);
211 TestAssert(observer.GetEvent() != 0);
212
213 // log table, range is null, permitted (step function)
214 observer.Reset();
215 table->SetScaleToLog10();
216 table->SetTableRange(0,0);
217 TestAssert(observer.GetEvent() == 0);
218
219 // log table, zero on upper end of range, permitted
220 observer.Reset();
221 table->SetScaleToLog10();
222 table->SetTableRange(-1.2,0);
223 TestAssert(observer.GetEvent() == 0);
224
225 // log table, zero on lower end of range, permitted
226 observer.Reset();
227 table->SetScaleToLog10();
228 table->SetTableRange(0,1.3);
229 TestAssert(observer.GetEvent() == 0);
230
231 // log table, range straddles zero, illegal
232 observer.Reset();
233 table->SetScaleToLog10();
234 table->SetTableRange(-0.5,1.1);
235 TestAssert(observer.GetEvent() != 0);
236
237 table->RemoveObserver(observerId);
238
239 return rval;
240 }
241