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