contrib/gel/vtol/vtol_face_2d.cxx
Go to the documentation of this file.
00001 // This is gel/vtol/vtol_face_2d.cxx
00002 #include "vtol_face_2d.h"
00003 //:
00004 // \file
00005 
00006 #include <vcl_cassert.h>
00007 #include <vtol/vtol_topology_object.h>
00008 #include <vtol/vtol_edge_2d.h>
00009 #include <vtol/vtol_one_chain.h>
00010 #include <vsol/vsol_region_2d.h>
00011 #include <vsol/vsol_rectangle_2d.h>
00012 #include <vsol/vsol_point_2d.h>
00013 
00014 //---------------------------------------------------------------------------
00015 //: Pseudo copy constructor.  Deep copy.
00016 //---------------------------------------------------------------------------
00017 vtol_face_2d::vtol_face_2d(vtol_face_2d_sptr const& other)
00018   : surface_(0)
00019 {
00020   edge_list edgs;    other->edges(edgs);
00021   vertex_list verts; other->vertices(verts);
00022 
00023   topology_list newedges(edgs.size());
00024   topology_list newverts(verts.size());
00025 
00026   int i=0;
00027   for (vertex_list::iterator vi=verts.begin();vi!=verts.end();++vi,++i)
00028   {
00029     vtol_vertex_sptr v=(*vi);
00030     newverts[i]=v->clone()->cast_to_topology_object();
00031     v->set_id(i);
00032   }
00033   int j=0;
00034   for (edge_list::iterator ei=edgs.begin();ei!= edgs.end();++ei,++j)
00035   {
00036     vtol_edge_sptr e=(*ei);
00037 
00038     vtol_topology_object_sptr V1 = newverts[e->v1()->get_id()];
00039     vtol_topology_object_sptr V2 = newverts[e->v2()->get_id()];
00040     if (!V1 || !V2)
00041     {
00042       vcl_cerr << "Inconsistent topology in vtol_face_2d pseudo copy constructor\n";
00043       link_inferior(new vtol_one_chain);
00044       return;
00045      }
00046     // make the topology and geometry match
00047     vtol_edge_sptr newedge=new vtol_edge_2d(V1->cast_to_vertex(),
00048                                             V2->cast_to_vertex());
00049 
00050     newedges[j]=newedge->cast_to_topology_object();
00051     e->set_id(j);
00052   }
00053 
00054   // This is a deep copy of the vtol_face_2d.
00055   topology_list::const_iterator ii;
00056   for (ii=other->inferiors()->begin();ii!= other->inferiors()->end();++ii)
00057     link_inferior((*ii)->cast_to_one_chain()->copy_with_arrays(newverts,newedges));
00058   set_surface(0);
00059   if (other->surface_)
00060     set_surface(other->surface_->clone()->cast_to_region());
00061 }
00062 
00063 //---------------------------------------------------------------------------
00064 //: Clone `this': creation of a new object and initialization.
00065 // See Prototype pattern
00066 //---------------------------------------------------------------------------
00067 vsol_spatial_object_2d* vtol_face_2d::clone() const
00068 {
00069   return new vtol_face_2d(vtol_face_2d_sptr(const_cast<vtol_face_2d*>(this)));
00070 }
00071 
00072 vsol_region_2d_sptr vtol_face_2d::surface() const
00073 {
00074   return surface_;
00075 }
00076 
00077 //: copy with an array
00078 
00079 vtol_face *
00080 vtol_face_2d::copy_with_arrays(topology_list &verts,
00081                                topology_list &edges) const
00082 {
00083   vtol_face_2d *newface=new vtol_face_2d();
00084   topology_list::const_iterator i;
00085   for (i=newface->inferiors()->begin();i!= newface->inferiors()->end();++i )
00086     newface->unlink_inferior((*i)->cast_to_one_chain());
00087   newface->inferiors()->clear();
00088   for (i=inferiors()->begin();i!=inferiors()->end();++i)
00089   {
00090     vtol_one_chain *onech=(*i)->cast_to_one_chain()->copy_with_arrays(verts,edges);
00091     assert(*onech == *(*i));
00092     newface->link_inferior(onech);
00093   }
00094   if (surface_)
00095     newface->set_surface(surface_->clone()->cast_to_region());
00096   return newface;
00097 }
00098 
00099 //---------------------------------------------------------------------------
00100 //: Copy with no links. Only copy the surface if it exists
00101 //---------------------------------------------------------------------------
00102 vtol_face *vtol_face_2d::shallow_copy_with_no_links() const
00103 {
00104   vtol_face_2d *result;
00105   result=new vtol_face_2d;
00106   result->set_surface(0);
00107   if (surface_)
00108     result->set_surface(surface_->clone()->cast_to_region());
00109   return result;
00110 }
00111 
00112 //: Constructor for a planar vtol_face_2d from an ordered list of vertices.
00113 // Edges are constructed by connecting vtol_vertex_2d[i] to vtol_vertex_2d[(i+1)mod L].
00114 // L is the length of the vertex list, verts, and i goes from 0 to L.
00115 // Require: verts.size()>2
00116 
00117 vtol_face_2d::vtol_face_2d(vertex_list const& verts)
00118   :surface_(0)
00119 {
00120   // require
00121   assert(verts.size()>2);
00122 
00123   double xmin=0;
00124   double ymin=0;
00125   double xmax=1;
00126   double ymax=1;
00127 
00128   set_surface(new vsol_rectangle_2d(new vsol_point_2d(xmin,ymin),
00129                                     new vsol_point_2d(xmax,ymin),
00130                                     new vsol_point_2d(xmax,ymax),
00131                                     new vsol_point_2d(xmin,ymax)));
00132 
00133   //generate a list of edges for edge loop
00134   bool done=false;
00135   vertex_list::const_iterator vi=verts.begin();
00136   vtol_vertex_sptr v01=(*vi);
00137   edge_list elist;
00138   vcl_vector<signed char> directions;
00139 
00140   while (!done)
00141   {
00142     // if no next vertex, then use the first vertex by calling
00143     // verts->end() again to wrap around  This will close the loop
00144     ++vi;
00145 
00146     if (vi==verts.end())
00147     {
00148       vi=verts.begin();
00149       done=true;
00150     }
00151 
00152     vtol_vertex_sptr v02=(*vi); // get the next vertex (may be first)
00153 
00154     vtol_edge_sptr newedge=v01->new_edge(v02);
00155     elist.push_back(newedge);
00156 
00157     if (*v02 == *(newedge->v2()))
00158       directions.push_back((signed char)1);
00159     else
00160       directions.push_back((signed char)(-1));
00161     v01=v02; // in the next go around v1 is v2 of the last
00162   }
00163 
00164   link_inferior(new vtol_one_chain(elist,directions,true));
00165 }
00166 
00167 //: Constructor for a planar face from a list of one_chains.
00168 // This method assumes that the first vtol_one_chain on the list is the outside
00169 // boundary vtol_one_chain.  The remaining one_chains are holes boundaries
00170 // on the face.
00171 
00172 vtol_face_2d::vtol_face_2d(one_chain_list const& onechs)
00173   :surface_(0)
00174 {
00175   // 1)  Add one chains to the inferiors list.
00176   //     Assume that the first vtol_one_chain on the
00177   //     list is the outside boundary...the
00178   //     remaining one_chains are holes.
00179 
00180   if (onechs.size()>0)
00181     link_inferior(onechs[0]);
00182 
00183   vtol_one_chain_sptr onech=get_boundary_cycle();
00184 
00185   // 2) This constructor will assume that the
00186   // surface is an ImplicitPlane().
00187 
00188   double xmin=0;
00189   double ymin=0;
00190   double xmax=1;
00191   double ymax=1;
00192 
00193   set_surface(new vsol_rectangle_2d(new vsol_point_2d(xmin,ymin),
00194                                     new vsol_point_2d(xmax,ymin),
00195                                     new vsol_point_2d(xmax,ymax),
00196                                     new vsol_point_2d(xmin,ymax)));
00197 
00198   if (onech)
00199     for (unsigned int i = 1; i < onechs.size(); ++i)
00200       onech->link_chain_inferior(onechs[i]);
00201 }
00202 
00203 //: Constructor of a Planar face from a vtol_one_chain.
00204 //  This method uses the vtol_one_chain, edgeloop, as the outside boundary of the face.
00205 
00206 vtol_face_2d::vtol_face_2d(vtol_one_chain_sptr const& edgeloop)
00207   : surface_(0)
00208 {
00209   link_inferior(edgeloop);
00210 
00211   // TODO - surface is set to bounding box rectangle, which is often too large
00212   set_surface(new vsol_rectangle_2d(new vsol_point_2d(get_min_x(),get_min_y()),
00213                                     new vsol_point_2d(get_max_x(),get_min_y()),
00214                                     new vsol_point_2d(get_max_x(),get_max_y()),
00215                                     new vsol_point_2d(get_min_x(),get_max_y())));
00216 }
00217 
00218 //: Constructor requiring only the underlying geometric surface
00219 vtol_face_2d::vtol_face_2d (vsol_region_2d &facesurf)
00220   : surface_(0)
00221 {
00222   set_surface(&facesurf);
00223 
00224   // not much, but at least it's a start...
00225 }
00226 
00227 //: Set the underlying geometric surface.
00228 void vtol_face_2d::set_surface(vsol_region_2d_sptr const& newsurf)
00229 {
00230   surface_=newsurf;
00231   touch();
00232 }
00233 
00234 bool vtol_face_2d::operator==(const vtol_face_2d &other) const
00235 {
00236   if (this==&other) return true;
00237 
00238   if (numinf()!=other.numinf())
00239     return false;
00240 
00241   if ( (surface_ && ! other.surface_) ||
00242        (other.surface_ && ! surface_))
00243     return false;
00244 
00245   if (surface_ && *surface_!=*(other.surface_))
00246     return false;
00247 
00248   topology_list::const_iterator ti1;
00249   topology_list::const_iterator ti2;
00250 
00251   for (ti1=inferiors()->begin(),ti2=other.inferiors()->begin();
00252        ti1!=inferiors()->end(); ++ti1,++ti2)
00253     if (!(*(*ti1)== *(*ti2)))
00254       return false;
00255 
00256   return true;
00257 }
00258 
00259 bool vtol_face_2d::operator==(const vtol_face &other) const
00260 {
00261   if (! other.cast_to_face_2d() )
00262     return false;
00263   else
00264     return *this == (vtol_face_2d const&) other;
00265 }
00266 
00267 //: spatial object equality
00268 
00269 bool vtol_face_2d::operator==(const vsol_spatial_object_2d& obj) const
00270 {
00271   return
00272    obj.cast_to_topology_object() &&
00273    obj.cast_to_topology_object()->cast_to_face() &&
00274    obj.cast_to_topology_object()->cast_to_face()->cast_to_face_2d() &&
00275    *this == *obj.cast_to_topology_object()->cast_to_face()->cast_to_face_2d();
00276 }
00277 
00278 //:
00279 //  This method describes the data members of the vtol_face_2d including the
00280 // Inferiors.  The blanking argument is used to indent the output in
00281 // a clear fashion.
00282 
00283 void vtol_face_2d::describe(vcl_ostream &strm,
00284                             int blanking) const
00285 {
00286   for (int j=0; j<blanking; ++j) strm << ' ';
00287   print(strm);
00288   for (unsigned int i=0;i<inferiors()->size();++i)
00289   {
00290     if ((inferiors_[i])->cast_to_one_chain()!=0)
00291       inferiors_[i]->cast_to_one_chain()->describe(strm,blanking);
00292     else
00293       strm << "*** Odd inferior for a face\n";
00294   }
00295 }
00296 
00297 //:
00298 // This method prints out a simple text representation for the vtol_face_2d which
00299 // includes its address in memory.
00300 void vtol_face_2d::print(vcl_ostream &strm) const
00301 {
00302   strm << "<vtol_face_2d ";
00303 
00304   topology_list::const_iterator ii;
00305   for (ii=inferiors()->begin();ii!= inferiors()->end();++ii)
00306   {
00307     strm << ' ' << (*ii)->inferiors()->size();
00308   }
00309   strm << "   " << (void const *) this << ">\n";
00310 }
00311 
00312 //: copy the geometry
00313 
00314 void vtol_face_2d::copy_geometry(const vtol_face &other)
00315 {
00316   if (other.cast_to_face_2d())
00317     surface_ = other.cast_to_face_2d()->surface();
00318 }
00319 
00320 //: provide a mechanism to compare geometry
00321 
00322 bool vtol_face_2d::compare_geometry(const vtol_face &other) const
00323 {
00324   if (other.cast_to_face_2d())
00325     return (*surface_)== *(other.cast_to_face_2d()->surface());
00326   else
00327     return false;
00328 }