contrib/gel/gst/gst_polygon_2d.cxx
Go to the documentation of this file.
00001 // This is gel/gst/gst_polygon_2d.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author crossge@crd.ge.com
00008 
00009 #include "gst_polygon_2d.h"
00010 #include "gst_vertex_2d_sptr.h"
00011 #include <vcl_iostream.h>
00012 
00013 bool gst_polygon_2d::check_validity() const
00014 {
00015   // no edge list
00016   if (edges_.size()<1)
00017     return false;
00018 
00019   // cycle through edges, looking for a completed polygon
00020   gst_vertex_2d_sptr start= edges_[0]->get_start();
00021   gst_vertex_2d_sptr end  = edges_[0]->get_end();
00022 
00023   // length of cycle
00024   unsigned int clen= 1;
00025 
00026   while (end.ptr()!= start.ptr())
00027   {
00028       // next edge
00029       bool found= false;
00030 
00031       for (unsigned int i=0; i < edges_.size() && !found; i++)
00032       {
00033           if (edges_[i]->get_start().ptr()== end.ptr())
00034           {
00035               found= true;
00036               end= edges_[i]->get_end();
00037           }
00038       }
00039 
00040       // if !found then the cycle isn't closed
00041       if (!found) return false;
00042 
00043       clen++;
00044   }
00045 
00046   // check we have looked at all the edges
00047   return clen == edges_.size();
00048 }
00049 
00050 // returns the centroid
00051 double gst_polygon_2d::get_centroid_x() const
00052 {
00053   double xsum= 0;
00054 
00055   for (unsigned int i=0; i< edges_.size(); ++i)
00056     xsum+= edges_[i]->get_start()->get_x();
00057 
00058   return xsum/edges_.size();
00059 }
00060 
00061 double gst_polygon_2d::get_centroid_y() const
00062 {
00063   double ysum= 0;
00064 
00065   for (unsigned int i=0; i< edges_.size(); ++i)
00066     ysum+= edges_[i]->get_start()->get_y();
00067 
00068   return ysum/edges_.size();
00069 }
00070 
00071 
00072 // returns the area (signed)
00073 //        2 A( P ) = sum_{i=0}^{n-1} (x_i y_{i+1} - y_i x_{i+1}).
00074 double gst_polygon_2d::area() const
00075 {
00076   double a= 0;
00077 
00078   for (unsigned int i=0; i< edges_.size(); ++i)
00079   {
00080     int ip1=((i+1)==edges_.size())?0:(i+1);
00081 
00082     double dp = edges_[i]->get_start()->get_x()* edges_[ip1]->get_start()->get_y()
00083               - edges_[i]->get_start()->get_x()* edges_[ip1]->get_start()->get_x();
00084 
00085     a+= dp;
00086   }
00087 
00088   return a/2;
00089 }
00090 
00091 
00092 // simple and efficient point in polygon test.
00093 //   from comp.graphics.algorithms faq
00094 //   should only call if validity passes (no check
00095 //   for efficiency)
00096 bool gst_polygon_2d::inside( const double x, const double y) const
00097 {
00098   bool c= false;
00099 
00100   for (unsigned int i=0, j= edges_.size()-1; i< edges_.size(); j= i++)
00101   {
00102     if ((((edges_[i]->get_start()->get_y()<= y) &&
00103           (y< edges_[j]->get_start()->get_y())) ||
00104          ((edges_[j]->get_start()->get_y()<= y) &&
00105           (y< edges_[i]->get_start()->get_y()))) &&
00106         (x< (edges_[j]->get_start()->get_x() -
00107              edges_[i]->get_start()->get_x()) * (y -
00108                                                  edges_[i]->get_start()->get_y()) /
00109          (edges_[j]->get_start()->get_y() - edges_[i]->get_start()->get_y()) +
00110          edges_[i]->get_start()->get_x()))
00111     {
00112       c=!c;
00113     }
00114   }
00115 
00116   return c;
00117 }
00118 
00119 bool gst_polygon_2d::inside( const gst_vertex_2d_sptr v) const
00120 {
00121   return inside( v->get_x(), v->get_y());
00122 }
00123 
00124 
00125 vcl_ostream &operator<<( vcl_ostream &os, gst_polygon_2d &p)
00126 {
00127   for (unsigned int i=0; i< p.edges_.size(); i++)
00128     os << (*p.edges_[i]) << ' ';
00129 
00130   return os << vcl_endl;
00131 }