core/vcsl/vcsl_spatial.cxx
Go to the documentation of this file.
00001 // This is core/vcsl/vcsl_spatial.cxx
00002 #include "vcsl_spatial.h"
00003 #include <vcl_cassert.h>
00004 #include <vcsl/vcsl_spatial_transformation.h>
00005 #include <vcsl/vcsl_graph.h>
00006 
00007 //---------------------------------------------------------------------------
00008 // Destructor
00009 //---------------------------------------------------------------------------
00010 vcsl_spatial::~vcsl_spatial()
00011 {
00012   if (graph_)
00013     graph_->remove(this);
00014 }
00015 
00016 //---------------------------------------------------------------------------
00017 // Is `time' between the two time bounds ?
00018 //---------------------------------------------------------------------------
00019 bool vcsl_spatial::valid_time(double time) const
00020 {
00021   if (beat_.size()==0)
00022     return true;
00023   else
00024     return (beat_[0]<=time)&&(time<=beat_[beat_.size()-1]);
00025 }
00026 
00027 //---------------------------------------------------------------------------
00028 // Set the list of parent coordinate system along the time
00029 //---------------------------------------------------------------------------
00030 void vcsl_spatial::set_parent(vcl_vector<vcsl_spatial_sptr> const& new_parent)
00031 {
00032   vcl_vector<vcsl_spatial_sptr>::iterator i, j;
00033 
00034   if (parent_!=new_parent)
00035   {
00036     // Erase 'this' from the list of the old parents' potential children
00037     for (i=parent_.begin();i!=parent_.end();++i)
00038     {
00039       vcl_vector<vcsl_spatial_sptr> children=(*i)->potential_children_;
00040       for (j=children.begin(); j!=children.end()&&(*j).ptr()!=this; ++j)
00041         ;
00042       if ((*j).ptr()==this) children.erase(j);
00043     }
00044     parent_=new_parent;
00045 
00046     // Add 'this' to the list of the new parents' potential children
00047     for (i=parent_.begin();i!=parent_.end();++i)
00048       if (*i)
00049         (*i)->potential_children_.push_back(this);
00050   }
00051 }
00052 
00053 //---------------------------------------------------------------------------
00054 // Set the unique parent and the unique motion
00055 //---------------------------------------------------------------------------
00056 void
00057 vcsl_spatial::set_unique(const vcsl_spatial_sptr &new_parent,
00058                          const vcsl_spatial_transformation_sptr &new_motion)
00059 {
00060   motion_.clear(); motion_.push_back(new_motion);
00061   vcl_vector<vcsl_spatial_sptr> temp_parent; temp_parent.push_back(new_parent);
00062   set_parent(temp_parent);
00063   beat_.clear();
00064 }
00065 
00066 //---------------------------------------------------------------------------
00067 // Return the index of the beat inferior or equal to `time'
00068 // REQUIRE: parent().size()!=0
00069 // REQUIRE: valid_time(time)
00070 //---------------------------------------------------------------------------
00071 int vcsl_spatial::matching_interval(double time) const
00072 {
00073   // require
00074   assert(parent_.size()!=0);
00075   assert(valid_time(time));
00076 
00077   // Dichotomic research of the index
00078   int inf=0;
00079   int sup=beat_.size()-1;
00080   while (sup-inf>1)
00081   {
00082     int mid=(inf+sup)/2;
00083     if (beat_[mid]>time)
00084       sup=mid;
00085     else
00086       inf=mid;
00087   }
00088   return inf;
00089 }
00090 
00091 //---------------------------------------------------------------------------
00092 // Does a path from `this' to `other' exist ?
00093 //---------------------------------------------------------------------------
00094 bool vcsl_spatial::path_from_local_to_cs_exists(const vcsl_spatial_sptr &other,
00095                                                 double time)
00096 {
00097   graph_->init_vertices();
00098 
00099   return recursive_path_from_local_to_cs_exists(other,time);
00100 }
00101 
00102 //---------------------------------------------------------------------------
00103 // Does a path from `this' to `other' exist ? Called only by
00104 // path_to_cs_exists()
00105 //---------------------------------------------------------------------------
00106 bool vcsl_spatial::recursive_path_from_local_to_cs_exists(const vcsl_spatial_sptr &other,
00107                                                           double time)
00108 {
00109   bool result;
00110   int i = -1; // dummy initialisation to avoid compiler warning
00111   vcl_vector<vcsl_spatial_sptr>::const_iterator child;
00112   if (parent_.size()!=0) // If 'this' is not absolute
00113     i=matching_interval(time);
00114   set_reached(true);
00115 
00116   // Check if parent of 'this' (if it exists) is 'other'
00117   result=!is_absolute(time); // true if 'this' has a parent
00118   if (result)
00119     result=parent_[i]==other; // true if parent is 'other' (the cs sought)
00120 
00121   // If 'this' has no parent or its parent is not 'other':
00122   if (!result)
00123   {
00124     // Check if 'other' can be reached through parent
00125     if (!is_absolute(time)) // if 'this' has a parent
00126       // If parent has not already been checked
00127       if (!parent_[i]->reached())
00128         // Check if 'other' can be reached from it
00129         result=parent_[i]->recursive_path_from_local_to_cs_exists(other, time);
00130     // If 'other' not found, check if 'other' can be reached through children of 'this'
00131     if (!result)
00132     {
00133       if (potential_children_.size()!=0)
00134       {
00135         for (child=potential_children_.begin();
00136              !result && child!=potential_children_.end();
00137              ++child)
00138         {
00139           result=!(*child)->reached();
00140           if (result)
00141           {
00142             int j=(*child)->matching_interval(time);
00143             result=(*child)->parent_[j].ptr()==this;
00144             if (result)
00145               result=(*child)->motion_[j]->is_invertible(time);
00146           }
00147           if (result)
00148           {
00149             result=(*child)==other;
00150             if (!result)
00151               result=(*child)->recursive_path_from_local_to_cs_exists(other, time);
00152           }
00153         }
00154       }
00155     }
00156   }
00157   return result;
00158 }
00159 
00160 //---------------------------------------------------------------------------
00161 // Find the sequence of transformations from `this' to `other'
00162 // REQUIRE: path.size()==0 and sens.size()==0
00163 // REQUIRE: path_from_local_to_cs_exists(other,time)
00164 //---------------------------------------------------------------------------
00165 void vcsl_spatial::path_from_local_to_cs(const vcsl_spatial_sptr &other,
00166                                          double time,
00167                                          vcl_vector<vcsl_spatial_transformation_sptr> &path,
00168                                          VCSL_SPATIAL_VECTOR_BOOL &sens)
00169 {
00170   // require
00171   assert(path.size()==0);
00172   assert(sens.size()==0);
00173   assert(path_from_local_to_cs_exists(other,time));
00174 
00175   //unused bool path_exists;
00176 
00177   graph_->init_vertices();
00178   /*path_exists=*/ recursive_path_from_local_to_cs(other,time,path,sens);
00179 }
00180 
00181 //---------------------------------------------------------------------------
00182 // Find the sequence of transformations from `this' to `other'
00183 // Called only by path_from_local_to_cs()
00184 //---------------------------------------------------------------------------
00185 bool
00186 vcsl_spatial::recursive_path_from_local_to_cs(const vcsl_spatial_sptr &other,
00187                                               double time,
00188                                               vcl_vector<vcsl_spatial_transformation_sptr> &path,
00189                                               VCSL_SPATIAL_VECTOR_BOOL &sens)
00190 {
00191   bool result;
00192   int i = -1; // dummy initialisation to avoid compiler warning
00193   vcl_vector<vcsl_spatial_sptr>::const_iterator child;
00194 
00195   if (parent_.size()!=0)
00196     i=matching_interval(time);
00197 
00198   set_reached(true);
00199 
00200   result=!is_absolute(time);
00201   if (result)
00202     result=parent_[i]==other;
00203 
00204   if (result)
00205   {
00206     path.push_back(motion_[i]);
00207     sens.push_back(false);
00208   }
00209 
00210   if (!result)
00211   {
00212     if (!is_absolute(time))
00213       if (!parent_[i]->reached())
00214       {
00215         path.push_back(motion_[i]);
00216         sens.push_back(false);
00217         result=parent_[i]->recursive_path_from_local_to_cs(other,time,path,sens);
00218         if (!result)
00219         {
00220           path.pop_back();
00221           sens.pop_back();
00222         }
00223       }
00224     if (!result)
00225     {
00226       if (potential_children_.size()!=0)
00227       {
00228         for (child=potential_children_.begin();
00229              !result && child!=potential_children_.end();
00230              ++child)
00231         {
00232           result=!(*child)->reached();
00233           if (result)
00234           {
00235             int j=(*child)->matching_interval(time);
00236             result=(*child)->parent_[j].ptr()==this;
00237             if (result)
00238               result=(*child)->motion_[j]->is_invertible(time);
00239             if (result)
00240             {
00241               result=(*child)==other;
00242               path.push_back((*child)->motion_[j]);
00243               sens.push_back(true);
00244               if (!result)
00245               {
00246                 result=(*child)->recursive_path_from_local_to_cs(other,time,
00247                                                                  path,sens);
00248                 if (!result)
00249                 {
00250                   path.pop_back();
00251                   sens.pop_back();
00252                 }
00253               }
00254             }
00255           }
00256         }
00257       }
00258     }
00259   }
00260 
00261   return result;
00262 }
00263 
00264 //---------------------------------------------------------------------------
00265 // Is `this' an absolute spatial coordinate system at time `time'?
00266 // REQUIRE: valid_time(time)
00267 //---------------------------------------------------------------------------
00268 bool vcsl_spatial::is_absolute(double time) const
00269 {
00270   // require
00271   assert(valid_time(time));
00272 
00273   // If list of parents is NULL, 'this' must be absolute
00274   if (parent_.size()==0)
00275     return true;
00276   else
00277   {
00278     // If parent at given interval is NULL, 'this' must be absolute
00279     int i=matching_interval(time);
00280     return !parent_[i];
00281   }
00282 }
00283 
00284 //---------------------------------------------------------------------------
00285 // From a vector `v' expressed in `this',
00286 // return a vector expressed in the spatial coordinate system `other'
00287 // REQUIRE: path_from_local_to_cs_exists(other,time)
00288 //---------------------------------------------------------------------------
00289 vnl_vector<double>
00290 vcsl_spatial::from_local_to_cs(const vnl_vector<double> &v,
00291                                const vcsl_spatial_sptr &other,
00292                                double time)
00293 {
00294   // require
00295   assert(path_from_local_to_cs_exists(other,time));
00296 
00297   vcl_vector<vcsl_spatial_transformation_sptr> path;
00298   VCSL_SPATIAL_VECTOR_BOOL sens;
00299 
00300   vcl_vector<vcsl_spatial_transformation_sptr>::const_iterator i;
00301   VCSL_SPATIAL_VECTOR_BOOL::const_iterator j;
00302 
00303   path_from_local_to_cs(other,time,path,sens);
00304 
00305   vnl_vector<double> tmp=from_cs_to_standard_units(v);
00306 
00307   j=sens.begin();
00308 
00309   for (i=path.begin();i!=path.end();++i,++j)
00310   {
00311     if (*j)
00312       tmp=(*i)->inverse(tmp,time);
00313     else
00314       tmp=(*i)->execute(tmp,time);
00315   }
00316   return other->from_standard_units_to_cs(tmp);
00317 }
00318 
00319 void vcsl_spatial::set_graph(const vcsl_graph_sptr &new_graph)
00320 {
00321   if (graph_)
00322     graph_->remove(this);
00323   graph_=new_graph;
00324   graph_->put(this);
00325 }