contrib/mul/mfpf/mfpf_region_definer.cxx
Go to the documentation of this file.
00001 #include "mfpf_region_definer.h"
00002 //:
00003 // \file
00004 // \brief Base for objects which generate regions from sets of points
00005 // \author Tim Cootes
00006 
00007 #include <vsl/vsl_indent.h>
00008 #include <vsl/vsl_binary_loader.h>
00009 
00010 #include <mbl/mbl_parse_block.h>
00011 #include <mbl/mbl_read_props.h>
00012 #include <mbl/mbl_cloneables_factory.h>
00013 #include <vcl_sstream.h>
00014 
00015 //=======================================================================
00016 // Dflt ctor
00017 //=======================================================================
00018 
00019 mfpf_region_definer::mfpf_region_definer()
00020 {
00021 }
00022 
00023 //=======================================================================
00024 // Destructor
00025 //=======================================================================
00026 
00027 mfpf_region_definer::~mfpf_region_definer()
00028 {
00029 }
00030 
00031 //: Initialise from a string stream
00032 bool mfpf_region_definer::set_from_stream(vcl_istream &is)
00033 {
00034   // Cycle through string and produce a map of properties
00035   vcl_string s = mbl_parse_block(is);
00036   vcl_istringstream ss(s);
00037   mbl_read_props_type props = mbl_read_props_ws(ss);
00038 
00039   if (props.size()!=0)
00040   {
00041     vcl_cerr<<is_a()<<" does not expect any extra arguments.\n";
00042     mbl_read_props_look_for_unused_props(
00043       "mfpf_region_definer::set_from_stream", props, mbl_read_props_type());
00044   }
00045   return true;
00046 }
00047 
00048 //: Create a concrete object, from a text specification.
00049 vcl_auto_ptr<mfpf_region_definer> mfpf_region_definer::
00050   create_from_stream(vcl_istream &is)
00051 {
00052   vcl_string name;
00053   is >> name;
00054   vcl_auto_ptr<mfpf_region_definer> vcb;
00055   try {
00056     vcb = mbl_cloneables_factory<mfpf_region_definer>::get_clone(name);
00057   }
00058   catch (const mbl_exception_no_name_in_factory & e)
00059   {
00060     throw (mbl_exception_parse_error( e.what() ));
00061   }
00062   vcb->set_from_stream(is);
00063   return vcb;
00064 }
00065 
00066 //=======================================================================
00067 // Method: version_no
00068 //=======================================================================
00069 
00070 short mfpf_region_definer::version_no() const
00071 {
00072   return 1;
00073 }
00074 
00075 //=======================================================================
00076 // Method: is_a
00077 //=======================================================================
00078 
00079 vcl_string mfpf_region_definer::is_a() const
00080 {
00081   return vcl_string("mfpf_region_definer");
00082 }
00083 
00084 //: Allows derived class to be loaded by base-class pointer
00085 void vsl_add_to_binary_loader(const mfpf_region_definer& b)
00086 {
00087   vsl_binary_loader<mfpf_region_definer>::instance().add(b);
00088 }
00089 
00090 //=======================================================================
00091 // Associated function: operator<<
00092 //=======================================================================
00093 
00094 void vsl_b_write(vsl_b_ostream& bfs, const mfpf_region_definer& b)
00095 {
00096   b.b_write(bfs);
00097 }
00098 
00099 //=======================================================================
00100 // Associated function: operator>>
00101 //=======================================================================
00102 
00103 void vsl_b_read(vsl_b_istream& bfs, mfpf_region_definer& b)
00104 {
00105   b.b_read(bfs);
00106 }
00107 
00108 //=======================================================================
00109 // Associated function: operator<<
00110 //=======================================================================
00111 
00112 vcl_ostream& operator<<(vcl_ostream& os,const mfpf_region_definer& b)
00113 {
00114   os << b.is_a() << ": ";
00115   vsl_indent_inc(os);
00116   b.print_summary(os);
00117   vsl_indent_dec(os);
00118   return os;
00119 }
00120 
00121 //=======================================================================
00122 // Associated function: operator<<
00123 //=======================================================================
00124 
00125 vcl_ostream& operator<<(vcl_ostream& os,const mfpf_region_definer* b)
00126 {
00127   if (b)
00128     return os << *b;
00129   else
00130     return os << "No mfpf_region_definer defined.";
00131 }
00132 
00133 //: Generate a new set of points from pts0 using set of definers
00134 void mfpf_points_from_definers(
00135               const vcl_vector<mfpf_region_definer*>& definer,
00136               const vcl_vector<vgl_point_2d<double> >& pts0,
00137               vcl_vector<vgl_point_2d<double> >& new_pts)
00138 {
00139   unsigned n=definer.size();
00140   new_pts.resize(n);
00141   for (unsigned i=0;i<n;++i)
00142     new_pts[i]=definer[i]->get_ref_point(pts0);
00143 }
00144 
00145 //: Change indices in definers to refer to points generated
00146 //  Suppose definer is used to generate a set of n=definer.size()
00147 //  regions/pts (say pts1), by referring to some other set of m points.
00148 //  This sets up self_definer to generate an identical set of
00149 //  regions/pts by using the originally generated points (pts1).
00150 //  This can only be done if there is a region centred on each
00151 //  of the original points used in the definer.
00152 //  The function tests for this case, and returns false if it fails.
00153 //  In particular consider the following
00154 //  \verbatim
00155 //  vcl_vector<vgl_point_2d<double> > pts0,pts1,pts2;
00156 //  // Set up pts0
00157 //  ...
00158 //  // Generate pts1 from pts0
00159 //  mfpf_points_from_definers(definer,pts0,pts1);
00160 //  mfpf_renumber_to_self(definer,pts0.size())
00161 //  // Now generate pts2 from pts1
00162 //  mfpf_points_from_definers(self_definer,pts1,pts2);
00163 //  // pts2 should be the same as pts1
00164 //  \endverbatim
00165 //  Note that objects pointed to by definer are changed.
00166 //  They may be left in an invalid state if this returns false,
00167 //  so caller should ensure a backup retained.
00168 bool mfpf_renumber_to_self(
00169                   vcl_vector<mfpf_region_definer*>& definer,
00170                   unsigned n_pts0)
00171 {
00172   vcl_vector<unsigned> new_index(n_pts0,mfpf_invalid_index);
00173   for (unsigned i=0;i<definer.size();++i)
00174   {
00175     if (definer[i]->is_centred_on_pt())
00176     {
00177       unsigned ri = definer[i]->ref_point_index();
00178       if (ri>=n_pts0)
00179       {
00180         vcl_cerr<<"Index out of range:"<<ri<<vcl_endl;
00181         return false;
00182       }
00183       new_index[ri]=i;
00184     }
00185   }
00186 
00187   for (unsigned i=0;i<definer.size();++i)
00188   {
00189     if (!definer[i]->replace_index(new_index))
00190     {
00191       vcl_cerr<<"Failed to update indices in "<<definer[i]<<vcl_endl;
00192       return false;
00193     }
00194   }
00195 
00196   return true;
00197 }