1 #ifndef boxm2_data_traits_h_
2 #define boxm2_data_traits_h_
3 //:
4 // \file
5 // \brief traits for data types
6 //
7 // \author Vishal Jain
8 // \date nov 17, 2010
9
10 #include <string>
11 #include <iostream>
12 #include <cstddef>
13 #ifdef _MSC_VER
14 # include <vcl_msvc_warnings.h>
15 #endif
16 #include <vnl/vnl_vector_fixed.h>
17
18 #include "boxm2_normal_albedo_array.h"
19 #include "boxm2_feature_vector.h"
20
21 class boxm2_mog3_grey_processor;
22 class boxm2_gauss_grey_processor;
23 class boxm2_gauss_rgb_processor;
24 class boxm2_mog6_view_processor;
25 class boxm2_mog6_view_compact_processor;
26
27 /**
28 * dec: Use the "X macro" pattern to define a table of enum values, string ids, and
29 * associated datatypes, and then use the table to actually create the enum and
30 * specializations of the traits classes for each row of the table. It is ugly, but not
31 * as ugly as the many hundreds of lines of copy/pasted code duplication that it replaced.
32 * To add a new boxm2 data type, you now just add a row to the bottom of the table below.
33 * If the type needs a "processor type" associated with it, that is now in a separate table further below.
34 */
35 typedef vnl_vector_fixed<unsigned char, 2> vnl_vector_fixed_unsigned_char_2;
36 typedef vnl_vector_fixed<unsigned char, 8> vnl_vector_fixed_unsigned_char_8;
37 typedef vnl_vector_fixed<unsigned char, 16> vnl_vector_fixed_unsigned_char_16;
38
39 typedef vnl_vector_fixed<unsigned short, 4> vnl_vector_fixed_unsigned_short_2;
40 typedef vnl_vector_fixed<unsigned short, 4> vnl_vector_fixed_unsigned_short_4;
41 typedef vnl_vector_fixed<unsigned short, 8> vnl_vector_fixed_unsigned_short_8;
42
43 typedef vnl_vector_fixed<short, 8> vnl_vector_fixed_short_8;
44
45 typedef vnl_vector_fixed<int, 4> vnl_vector_fixed_int_4;
46 typedef vnl_vector_fixed<int, 8> vnl_vector_fixed_int_8;
47 typedef vnl_vector_fixed<int, 16> vnl_vector_fixed_int_16;
48
49 typedef vnl_vector_fixed<float, 4> vnl_vector_fixed_float_4;
50 typedef vnl_vector_fixed<float, 8> vnl_vector_fixed_float_8;
51 typedef vnl_vector_fixed<float, 9> vnl_vector_fixed_float_9;
52 typedef vnl_vector_fixed<float, 16> vnl_vector_fixed_float_16;
53
54 #define BOXM2_DATATYPE_TABLE \
55 X(BOXM2_ALPHA, "alpha", float) \
56 X(BOXM2_GAMMA, "gamma", float) \
57 X(BOXM2_MOG3_GREY_16, "boxm2_mog3_grey16", vnl_vector_fixed_unsigned_short_8) \
58 X(BOXM2_MOG3_GREY, "boxm2_mog3_grey", vnl_vector_fixed_unsigned_char_8) \
59 X(BOXM2_MOG6_VIEW_COMPACT, "boxm2_mog6_view_compact", vnl_vector_fixed_unsigned_char_16) \
60 X(BOXM2_MOG6_VIEW, "boxm2_mog6_view", vnl_vector_fixed_float_16) \
61 X(BOXM2_BATCH_HISTOGRAM, "boxm2_batch_histogram", vnl_vector_fixed_float_8) \
62 X(BOXM2_GAUSS_RGB_VIEW_COMPACT, "boxm2_gauss_rgb_view_compact", vnl_vector_fixed_int_8) \
63 X(BOXM2_GAUSS_RGB_VIEW, "boxm2_gauss_rgb_view", vnl_vector_fixed_int_16) \
64 X(BOXM2_GAUSS_RGB, "boxm2_gauss_rgb", vnl_vector_fixed_unsigned_char_8) \
65 X(BOXM2_GAUSS_UV_VIEW, "boxm2_gauss_uv_view", vnl_vector_fixed_int_4) \
66 X(BOXM2_MOG2_RGB,"boxm2_mog2_rgb", vnl_vector_fixed_unsigned_char_16) \
67 X(BOXM2_NUM_OBS_VIEW_COMPACT, "boxm2_num_obs_view_compact", vnl_vector_fixed_short_8) \
68 X(BOXM2_NUM_OBS_VIEW, "boxm2_num_obs_view", vnl_vector_fixed_float_8) \
69 X(BOXM2_NUM_OBS_SINGLE_INT, "boxm2_num_obs_single_int", unsigned) \
70 X(BOXM2_NUM_OBS_SINGLE, "boxm2_num_obs_single", unsigned short) \
71 X(BOXM2_NUM_OBS, "boxm2_num_obs", vnl_vector_fixed_unsigned_short_4) \
72 X(BOXM2_LABEL_SHORT, "boxm2_label_short", short) \
73 X(BOXM2_INTENSITY, "boxm2_intensity", float) \
74 X(BOXM2_AUX0, "aux0", float) \
75 X(BOXM2_AUX1, "aux1", float) \
76 X(BOXM2_AUX2, "aux2", float) \
77 X(BOXM2_AUX3, "aux3", float) \
78 X(BOXM2_AUX4, "aux4", float) \
79 X(BOXM2_AUX, "aux", vnl_vector_fixed_float_4) \
80 X(BOXM2_FLOAT16, "float16", vnl_vector_fixed_float_16) \
81 X(BOXM2_FLOAT8, "float8", vnl_vector_fixed_float_8) \
82 X(BOXM2_FLOAT, "float", float) \
83 X(BOXM2_VIS_SPHERE, "boxm2_vis_sphere", vnl_vector_fixed_float_16) \
84 X(BOXM2_POINT, "boxm2_point", vnl_vector_fixed_float_4) \
85 X(BOXM2_VIS_SCORE, "boxm2_vis_score", float) \
86 X(BOXM2_GAUSS_GREY, "boxm2_gauss_grey", vnl_vector_fixed_unsigned_char_2) \
87 X(BOXM2_NORMAL_ALBEDO_ARRAY, "boxm2_normal_albedo_array", boxm2_normal_albedo_array) \
88 X(BOXM2_NORMAL, "boxm2_normal", vnl_vector_fixed_float_4) \
89 X(BOXM2_COVARIANCE, "boxm2_covariance", vnl_vector_fixed_float_9) \
90 X(BOXM2_FEATURE_VECTOR, "boxm2_feature_vector", boxm2_feature_vector) \
91 X(BOXM2_PIXEL, "boxm2_pixel", unsigned char) \
92 X(BOXM2_EXPECTATION, "boxm2_expectation", float) \
93 X(BOXM2_DATA_INDEX, "boxm2_data_index", unsigned int) \
94 X(BOXM2_RAY_DIR, "boxm2_ray_dir", vnl_vector_fixed_float_4) \
95 X(BOXM2_CHAR8, "char8", vnl_vector_fixed_unsigned_char_8) \
96 X(BOXM2_VEC3D, "boxm2_vec3d", vnl_vector_fixed_float_4) \
97 X(BOXM2_VECF_EYELID, "boxm2_vecf_eyelid", vnl_vector_fixed_float_16)
98
99
100
101 // define the boxm2_data_type enum using the X macro pattern and the table above.
102 #define X(enum_val, string_val, datatype_val) enum_val,
103 enum boxm2_data_type {
104 BOXM2_DATATYPE_TABLE
105 BOXM2_UNKNOWN // last enum value, also avoids trialing comma problem
106 };
107 #undef X
108
109 //: voxel datatype traits: will be specialized for each relevant boxm2_data_type val
110 template <boxm2_data_type type>
111 class boxm2_data_traits;
112
113 // specialize the traits class for each boxm2_data_type value in the table above using the X macro pattern
114 #define X(enum_val, string_val, datatype_val) \
115 template<> \
116 class boxm2_data_traits<enum_val> \
117 { \
118 public: \
119 typedef datatype_val datatype; \
120 static std::size_t datasize() { return sizeof(datatype); } \
121 static std::string prefix(const std::string& identifier = "") \
122 { if (!identifier.size()) return string_val; else return string_val + std::string("_") + identifier; } \
123 };
124 BOXM2_DATATYPE_TABLE
125 #undef X
126
127 // A Collection of functions mapping datatypes to properties.
128 // There are handy if you don't know the enum val at compile time.
129 class boxm2_data_info
130 {
131 public:
132
133 // map string prefix to enum val
134 // note that some prefixes are substrings of others.
135 // this could be made more efficient by requiring that the table is sorted
136 // such that types that are substrings are listed last, but that is probably asking for trouble.
data_type(std::string const & prefix)137 static boxm2_data_type data_type(std::string const& prefix) {
138 boxm2_data_type retval = BOXM2_UNKNOWN;
139 #define X(enum_val, string_val, datatype_val) \
140 if (prefix.find(boxm2_data_traits<enum_val>::prefix()) == 0) {\
141 return enum_val; \
142 }
143 BOXM2_DATATYPE_TABLE
144 #undef X
145 return retval;
146 }
147
148 // map enum val to string prefix
149 static std::string prefix(boxm2_data_type data_type, std::string const& identifier="") {
150 switch(data_type) {
151 #define X(enum_val, string_val, datatype_val) \
152 case enum_val: \
153 return boxm2_data_traits<enum_val>::prefix(identifier);
154 BOXM2_DATATYPE_TABLE
155 default:
156 // switch fell through with no match
157 return "unknown";
158 #undef X
159 }
160 // should be unreachable.
161 return "unknown";
162 }
163
164 // map enum to datasize
datasize(boxm2_data_type data_type)165 static std::size_t datasize(boxm2_data_type data_type) {
166 switch (data_type) {
167 #define X(enum_val, string_val, datatype_val) \
168 case enum_val: \
169 return boxm2_data_traits<enum_val>::datasize();
170 BOXM2_DATATYPE_TABLE
171 default:
172 // switch fell through with no match
173 return 0;
174 #undef X
175 }
176 // should be unreachable.
177 return 0;
178 };
179
180 // map string prefix to datasize
datasize(std::string const & prefix)181 static std::size_t datasize(std::string const& prefix) {
182 return datasize(data_type(prefix));
183 }
184
185
186 // TODO: create a table mapping enum to print function, or just require that all types have a stream operator.
print_data(std::string const & prefix,char * cell)187 static void print_data(std::string const& prefix, char *cell)
188 {
189 if (prefix.find(boxm2_data_traits<BOXM2_ALPHA>::prefix()) != std::string::npos) {
190 std::cout << reinterpret_cast<boxm2_data_traits<BOXM2_ALPHA>::datatype*>(cell)[0];
191 return;
192 }
193 if (prefix.find(boxm2_data_traits<BOXM2_AUX0>::prefix()) != std::string::npos) {
194 std::cout << reinterpret_cast<boxm2_data_traits<BOXM2_AUX0>::datatype*>(cell)[0];
195 return;
196 }
197 if (prefix.find(boxm2_data_traits<BOXM2_AUX>::prefix()) != std::string::npos) {
198 std::cout << reinterpret_cast<boxm2_data_traits<BOXM2_AUX>::datatype*>(cell)[0];
199 return;
200 }
201
202 if (prefix.find(boxm2_data_traits<BOXM2_INTENSITY>::prefix()) != std::string::npos) {
203 std::cout << reinterpret_cast<boxm2_data_traits<BOXM2_INTENSITY>::datatype*>(cell)[0];
204 return;
205 }
206
207 if (prefix.find(boxm2_data_traits<BOXM2_POINT>::prefix()) != std::string::npos) {
208 std::cout << reinterpret_cast<boxm2_data_traits<BOXM2_POINT>::datatype*>(cell)[0];
209 return;
210 }
211
212 if (prefix.find(boxm2_data_traits<BOXM2_COVARIANCE>::prefix()) != std::string::npos) {
213 std::cout << reinterpret_cast<boxm2_data_traits<BOXM2_COVARIANCE>::datatype*>(cell)[0];
214 return;
215 }
216
217 std::cerr << "In boxm2_data_info::print_data() -- type: " << prefix << " could not be identified!\n";
218 return;
219 }
220
221 };
222
223
224 // A table mapping boxm2 appearance model types to the class resposible for processing them.
225 // Use the "X macro" pattern to generate the traits-style boxm2_processor_type specializations from the table
226 #define BOXM2_PROCESSOR_TABLE \
227 X(BOXM2_MOG3_GREY, boxm2_mog3_grey_processor) \
228 X(BOXM2_MOG6_VIEW, boxm2_mog6_view_processor) \
229 X(BOXM2_MOG6_VIEW_COMPACT, boxm2_mog6_view_compact_processor) \
230 X(BOXM2_MOG3_GREY_16, boxm2_mog3_grey_processor) \
231 X(BOXM2_GAUSS_RGB, boxm2_gauss_rgb_processor) \
232 X(BOXM2_GAUSS_GREY, boxm2_gauss_grey_processor) \
233 X(BOXM2_GAUSS_UV_VIEW, boxm2_mog6_view_processor) \
234 X(BOXM2_GAUSS_RGB_VIEW, boxm2_mog6_view_processor) \
235 X(BOXM2_GAUSS_RGB_VIEW_COMPACT, boxm2_mog6_view_processor)
236
237 // the empty base declaration. This template will be specialized for each row in the table above.
238 template <boxm2_data_type type>
239 class boxm2_processor_type;
240
241 // define the specialization generically
242 #define X(enum_val, processor_type) \
243 template<> \
244 class boxm2_processor_type<enum_val> \
245 { \
246 public: \
247 typedef processor_type type; \
248 };
249
250 // declare the specializations via the "X macro" pattern.
251 BOXM2_PROCESSOR_TABLE
252 #undef X
253
254 #endif
255