core/vil/file_formats/vil_nitf2_field_functor.h
Go to the documentation of this file.
00001 // vil_nitf2: Written by Harry Voorhees (hlv@) and Rob Radtke (rob@) of
00002 // Stellar Science Ltd. Co. (stellarscience.com) for
00003 // Air Force Research Laboratory, 2005.
00004 
00005 #ifndef VIL_NITF2_FIELD_FUNCTOR_H
00006 #define VIL_NITF2_FIELD_FUNCTOR_H
00007 
00008 class vil_nitf2_field;
00009 class vil_nitf2_enum_values;
00010 class vil_nitf2_index_vector;
00011 
00012 #include <vcl_string.h>
00013 #include <vcl_vector.h>
00014 #include <vcl_map.h>
00015 #include "vil_nitf2_field_sequence.h"
00016 
00017 //-----------------------------------------------------------------------------
00018 //:
00019 // \file
00020 // \brief Functors used by NITF classes
00021 //
00022 // Base class for functors that define a function that takes a
00023 // vil_nitf2_field_sequence and attempts to compute an "out" parameter of
00024 // type T. The function also returns a bool that specifies whether the
00025 // value could be computed.
00026 //
00027 // These functors are used to evaluate NITF field tags and invariably
00028 // call vil_nitf2_field_sequence::get_value(). When calling this method,
00029 // please be sure to set the argument ignore_extra_indexes to true.
00030 // This will allow the functor to be used within a repeat loop
00031 // and reference any preceding tag, inside or outside the repeat loop.
00032 // For example, to define a field sequence like this:
00033 //   FIELD A;
00034 //   REPEAT i=1..N
00035 //     FIELD B(i)
00036 //     FIELD C(i) exists if B(i) > 0
00037 //     FIELD D(i) exists if A > 0
00038 // the same conditional functor can be used in the definitions of fields
00039 // C and D by simply providing the name of the appropriate tag.  When
00040 // the functor is evaluated, the current index (i) is used to fetch the
00041 // tag. By calling get_value() with ignore_extra_indexes set to true,
00042 // the value of A can be fetched without causing an error.
00043 
00044 template<typename T>
00045 class vil_nitf2_field_functor
00046 {
00047  public:
00048   virtual bool operator() (vil_nitf2_field_sequence* record,
00049                            const vil_nitf2_index_vector& indexes, T& out_value) = 0;
00050   virtual ~vil_nitf2_field_functor() {}
00051 
00052   // Virtual copy method
00053   virtual vil_nitf2_field_functor<T>* copy() const = 0;
00054 };
00055 
00056 //:
00057 // Functor vil_nitf2_field_value defines a function that sets its out parameter
00058 // to a value of a field from a field sequence. The function returns whether
00059 // the field was found. The functor is instantiated with the field's tag.
00060 // The field sequence is passed to the function.
00061 //
00062 // You can override any value by specifying an overrideMap.  For example,
00063 // if 0 was a special value that actually meant 1 but all other values
00064 // (2, 3, 4...) actually meant when they were you could get that effect like this:
00065 // <code>
00066 // vcl_map< int, int > overrides;
00067 // overrides.insert( vcl_make_pair( 0, 1 ) );
00068 // new vil_nitf2_field_value( "FIELD_NAME", overrides );
00069 // </code>
00070 template<typename T>
00071 class vil_nitf2_field_value : public vil_nitf2_field_functor<T>
00072 {
00073  public:
00074   vil_nitf2_field_value(vcl_string tag) : tag(tag) {}
00075 
00076   vil_nitf2_field_value(vcl_string tag, vcl_map<T, T> overrideMap )
00077     : tag(tag), overrides( overrideMap ) {}
00078 
00079   virtual vil_nitf2_field_functor<T>* copy() const {
00080     return new vil_nitf2_field_value(tag, overrides); }
00081 
00082   bool operator() (vil_nitf2_field_sequence* record,
00083                    const vil_nitf2_index_vector& indexes, T& value)
00084   {
00085     bool success = record->get_value(tag, indexes, value, true);
00086     if ( success ) {
00087       //check to see if this value is overridden or not
00088       typename vcl_map<T, T>::const_iterator it = overrides.find( value );
00089       if ( it != overrides.end() ){
00090         //found override, use it
00091         value = (*it).second;
00092       }
00093     }
00094     return success;
00095   }
00096 
00097  private:
00098   vcl_string tag;
00099   vcl_map<T, T> overrides;
00100 };
00101 
00102 //:
00103 // Functor vil_nitf2_multiply_field_values defines a function that sets its out
00104 // parameter to the product of the values of two fields. The predicate
00105 // returns true iff both fields are found or the arg 'use_zero_if_tag_not_found';
00106 // in the latter case, the out parameter is set to 0.
00107 //
00108 class vil_nitf2_multiply_field_values : public vil_nitf2_field_functor<int>
00109 {
00110  public:
00111   vil_nitf2_multiply_field_values(const vcl_string& tag_1,
00112                                   const vcl_string& tag_2,
00113                                   bool use_zero_if_tag_not_found = false)
00114     : tag_1(tag_1),
00115       tag_2(tag_2),
00116       use_zero_if_tag_not_found(use_zero_if_tag_not_found) {}
00117 
00118   vil_nitf2_field_functor<int>* copy() const {
00119     return new vil_nitf2_multiply_field_values(
00120       tag_1, tag_2, use_zero_if_tag_not_found);
00121   }
00122 
00123   bool operator() (vil_nitf2_field_sequence* record,
00124                    const vil_nitf2_index_vector& indexes, int& value);
00125 
00126  private:
00127   vcl_string tag_1;
00128   vcl_string tag_2;
00129   bool use_zero_if_tag_not_found;
00130 };
00131 
00132 //:
00133 // Functor vil_nitf2_max_field_value_plus_offset_and_threshold defines a
00134 // function that sets its out parameter to either the value of a specified
00135 // field plus an offset, or a specified minimum value, whichever is greater.
00136 // The function returns whether the field was found.
00137 //
00138 class vil_nitf2_max_field_value_plus_offset_and_threshold : public vil_nitf2_field_functor<int>
00139 {
00140  public:
00141   vil_nitf2_max_field_value_plus_offset_and_threshold(
00142     vcl_string tag, int offset, int min_threshold = 0, int tag_factor = 1 )
00143     : tag(tag), offset(offset), min_threshold(min_threshold), tag_factor( tag_factor ) {}
00144 
00145   vil_nitf2_field_functor<int>* copy() const {
00146     return new vil_nitf2_max_field_value_plus_offset_and_threshold(
00147       tag, offset, min_threshold, tag_factor); }
00148 
00149   bool operator() (vil_nitf2_field_sequence* record,
00150                    const vil_nitf2_index_vector& indexes, int& value);
00151 
00152  private:
00153   vcl_string tag;
00154   int offset;
00155   int min_threshold;
00156   int tag_factor;
00157 };
00158 
00159 //:
00160 // Functor vil_nitf2_field_value_greater_than defines a comparison predicate that
00161 // sets its out parameter to true if a specified field from a field
00162 // sequence is found and its value is greater than a specified threshold.
00163 // The predicate returns whether the field was found.
00164 //
00165 template<typename T>
00166 class vil_nitf2_field_value_greater_than: public vil_nitf2_field_functor<bool>
00167 {
00168  public:
00169   vil_nitf2_field_value_greater_than(vcl_string tag, T threshold)
00170     : tag(tag), threshold(threshold) {}
00171 
00172   vil_nitf2_field_functor<bool>* copy() const {
00173     return new vil_nitf2_field_value_greater_than(tag, threshold); }
00174 
00175   bool operator() (vil_nitf2_field_sequence* record,
00176                    const vil_nitf2_index_vector& indexes, bool& result) {
00177     T value;
00178     if (record->get_value(tag, indexes, value, true)) {
00179       result = value > threshold;
00180       return true;
00181     }
00182     else {
00183       return false;
00184     }
00185   }
00186  private:
00187   vcl_string tag;
00188   T threshold;
00189 };
00190 
00191 //:
00192 // Functor vil_nitf2_field_specified defines a comparison predicate that sets
00193 // its out parameter to true iff the specified field is not blank.
00194 //
00195 class vil_nitf2_field_specified: public vil_nitf2_field_functor<bool>
00196 {
00197  public:
00198   vil_nitf2_field_specified(vcl_string tag) : tag(tag) {}
00199 
00200   vil_nitf2_field_functor<bool>* copy() const {
00201     return new vil_nitf2_field_specified(tag); }
00202 
00203   bool operator() (vil_nitf2_field_sequence* record,
00204                    const vil_nitf2_index_vector& indexes, bool& result);
00205 
00206  private:
00207   vcl_string tag;
00208 };
00209 
00210 //:
00211 // Functor vil_nitf2_field_value_one_of defines a predicate that sets its out
00212 // parameter to true iff the value of the specified tag equals one of
00213 // the elements of a vcl_vector of acceptable values.
00214 //
00215 template<typename T>
00216 class vil_nitf2_field_value_one_of: public vil_nitf2_field_functor<bool>
00217 {
00218  public:
00219   /// Constructor to specify a vcl_vector of acceptable values
00220   vil_nitf2_field_value_one_of(vcl_string tag, vcl_vector<T> acceptable_values)
00221     : tag(tag), acceptable_values(acceptable_values) {}
00222 
00223   /// Constructor to specify only one acceptable value
00224   vil_nitf2_field_value_one_of(vcl_string tag, T acceptable_value)
00225     : tag(tag), acceptable_values(1, acceptable_value) {}
00226 
00227   vil_nitf2_field_functor<bool>* copy() const {
00228     return new vil_nitf2_field_value_one_of(tag, acceptable_values); }
00229 
00230   bool operator() (vil_nitf2_field_sequence* record,
00231                    const vil_nitf2_index_vector& indexes, bool& result)
00232   {
00233     result = false;
00234     T val;
00235     if (record->get_value(tag, indexes, val, true)) {
00236       typename vcl_vector<T>::iterator it;
00237       for (it = acceptable_values.begin(); it != acceptable_values.end(); ++it) {
00238         if ((*it) == val) {
00239           result = true;
00240           break;
00241         }
00242       }
00243       return true;
00244     }
00245     // Field not defined
00246     return false;
00247   }
00248 
00249  protected:
00250   vcl_string tag;
00251   vcl_vector<T> acceptable_values;
00252 };
00253 
00254 //:
00255 // Functor vil_nitf2_choose_field_value defines a function that sets its out
00256 // parameter to a value of one of two fields of a field sequence. The
00257 // field chosen is determined by the evaluating the functor passed as
00258 // argument 'choose_tag_1_predicate': tag_1 is chosen if it evaluates to true;
00259 // tag_2, otherwise.
00260 //
00261 template<typename T>
00262 class vil_nitf2_choose_field_value : public vil_nitf2_field_functor<T>
00263 {
00264  public:
00265   /// Constructor. I take ownership of inDecider.
00266   vil_nitf2_choose_field_value(const vcl_string& tag_1, const vcl_string& tag_2,
00267                                vil_nitf2_field_functor<bool>* choose_tag_1_predicate)
00268     : tag_1(tag_1), tag_2(tag_2), choose_tag_1_predicate(choose_tag_1_predicate) {}
00269 
00270   vil_nitf2_field_functor<T>* copy() const {
00271     return new vil_nitf2_choose_field_value(
00272       tag_1, tag_2, choose_tag_1_predicate->copy()); }
00273 
00274   virtual ~vil_nitf2_choose_field_value() {
00275     if (choose_tag_1_predicate) delete choose_tag_1_predicate;
00276   }
00277 
00278   bool operator() (vil_nitf2_field_sequence* record,
00279                    const vil_nitf2_index_vector& indexes, T& value) {
00280     bool choose_tag_1;
00281     if ((*choose_tag_1_predicate)(record, indexes, choose_tag_1)) {
00282       if (choose_tag_1) return record->get_value(tag_1, indexes, value, true);
00283       else return record->get_value(tag_2, indexes, value, true);
00284     }
00285     else return false;
00286   }
00287  private:
00288   vcl_string tag_1;
00289   vcl_string tag_2;
00290   vil_nitf2_field_functor<bool>* choose_tag_1_predicate;
00291 };
00292 
00293 // Functor vil_nitf2_constant_functor defines a function that sets its
00294 // output value to a constant that does not depend on the field sequence
00295 // passed to it.
00296 //
00297 template<typename T>
00298 class vil_nitf2_constant_functor : public vil_nitf2_field_functor<T>
00299 {
00300  public:
00301   vil_nitf2_constant_functor(T value) : value_(value) {}
00302 
00303   virtual vil_nitf2_constant_functor* copy() const {
00304     return new vil_nitf2_constant_functor(value_);
00305   }
00306 
00307   virtual ~vil_nitf2_constant_functor() {}
00308 
00309   bool operator() (vil_nitf2_field_sequence* /*record*/,
00310                   const vil_nitf2_index_vector& /*indexes*/, T& value) {
00311     value = value_;
00312     return true;
00313   }
00314 
00315  private:
00316   T value_;
00317 };
00318 
00319 #endif // VIL_NITF2_FIELD_FUNCTOR_H