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(unsigned char * expected,unsigned char * test)39 int TestColor4uc(unsigned char* expected, 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], *result;
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 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
170 // Note - both below- and above-range colors are enabled at this point
171 TestAssert(table->GetIndex(lo/step) == 0);
172 TestAssert(table->GetIndex(hi*step) == 255);
173 TestAssert(table->GetIndex(lo*step) == 1);
174 TestAssert(table->GetIndex(hi/step) == 254);
175
176 // negative log range
177 double tmp = hi;
178 hi = -lo;
179 lo = -tmp;
180 step = 1.0/step;
181 table->SetScaleToLog10();
182 table->SetTableRange(lo,hi);
183 table->Build();
184 TestAssert(table->GetIndex(lo) == 0);
185 TestAssert(table->GetIndex(hi) == 255);
186 TestAssert(table->GetIndex(lo+tol) == 0);
187 TestAssert(table->GetIndex(hi-tol) == 255);
188 TestAssert(table->GetIndex(lo/step) == 0);
189 TestAssert(table->GetIndex(hi*step) == 255);
190 TestAssert(table->GetIndex(lo*step) == 1);
191 TestAssert(table->GetIndex(hi/step) == 254);
192
193 // == check error reporting ==
194
195 errorObserver observer;
196 unsigned long observerId =
197 table->AddObserver(
198 vtkCommand::ErrorEvent, &observer, &errorObserver::Callback);
199
200 // linear table, range is null, permitted (step function)
201 observer.Reset();
202 table->SetScaleToLinear();
203 table->SetTableRange(0,0);
204 TestAssert(observer.GetEvent() == 0);
205
206 // linear table, range is inverted, illegal
207 observer.Reset();
208 table->SetScaleToLinear();
209 table->SetTableRange(1,-1);
210 TestAssert(observer.GetEvent() != 0);
211
212 // log table, range is null, permitted (step function)
213 observer.Reset();
214 table->SetScaleToLog10();
215 table->SetTableRange(0,0);
216 TestAssert(observer.GetEvent() == 0);
217
218 // log table, zero on upper end of range, permitted
219 observer.Reset();
220 table->SetScaleToLog10();
221 table->SetTableRange(-1.2,0);
222 TestAssert(observer.GetEvent() == 0);
223
224 // log table, zero on lower end of range, permitted
225 observer.Reset();
226 table->SetScaleToLog10();
227 table->SetTableRange(0,1.3);
228 TestAssert(observer.GetEvent() == 0);
229
230 // log table, range straddles zero, illegal
231 observer.Reset();
232 table->SetScaleToLog10();
233 table->SetTableRange(-0.5,1.1);
234 TestAssert(observer.GetEvent() != 0);
235
236 table->RemoveObserver(observerId);
237
238 return rval;
239 }
240