cgma
CubitPolygon.cpp
Go to the documentation of this file.
00001 //- Class: CubitPolygon
00002 //- Description: This file defines the CubitPolygon class.
00003 //- Owner: Steve Storm
00004 //- Checked by:
00005 
00006 #include <math.h>
00007 #include "CubitPolygon.hpp"
00008 #include "CubitMessage.hpp"
00009 
00010 CubitPolygon::CubitPolygon()
00011 {
00012 }
00013 
00014 CubitPolygon::CubitPolygon( Cubit2DPoint &start_pnt)
00015 {
00016    add_point( start_pnt );
00017 }
00018 
00019 CubitPolygon::CubitPolygon( DLIList<Cubit2DPoint*> &point_list )
00020 {
00021    int i;
00022    point_list.reset();
00023    for ( i = point_list.size(); i--; )
00024    {
00025       Cubit2DPoint *pnt = point_list.get_and_step();         
00026       add_point( *pnt );
00027    }
00028 }
00029 
00030 CubitPolygon::~CubitPolygon()
00031 {
00032    int i;
00033    for ( i = pointList.size(); i--; )
00034       delete pointList.get_and_step();
00035 }
00036 
00037 void 
00038 CubitPolygon::add_point( Cubit2DPoint &new_pnt )
00039 {
00040 
00041    // Add the point
00042    pointList.append( new Cubit2DPoint( new_pnt ) );
00043    
00044    // Update bounding box
00045    if( pointList.size() == 1 )
00046    {
00047       minCoord = new_pnt;
00048       maxCoord = new_pnt;
00049    }
00050    else
00051       new_pnt.update_min_max( minCoord, maxCoord );
00052 }
00053 
00054 CubitPointContainment 
00055 CubitPolygon::pnt_containment( Cubit2DPoint &pnt,
00056                                double tol )
00057 {
00058    // Method is to fire a ray in negative x-direction and check the number
00059    // of intersections with the polygon.  Odd - in the loop, Even - outside
00060    // of the loop.
00061    
00062    // Returns: CubitPointContainment ( CUBIT_PNT_OUTSIDE = 0, 
00063    //                                  CUBIT_PNT_INSIDE = 1, 
00064    //                                  CUBIT_PNT_BOUNDARY = 2 )
00065    
00066    int i,
00067       c = 0; // Check variable
00068    
00069    // First check to see if the point is outside of the bounding box
00070    // of the polygon - if so, return OUT.
00071    
00072    if( pnt.x() < minCoord.x()-tol || pnt.y() < minCoord.y()-tol ||
00073       pnt.x() > maxCoord.x()+tol || pnt.y() > maxCoord.y()+tol ) 
00074    {
00075       return CUBIT_PNT_OUTSIDE;
00076    }
00077    
00078    // Loop on line segments of this polygon
00079    Cubit2DPoint *start_pnt, *end_pnt;
00080    pointList.reset();
00081    for ( i=pointList.size(); i--; )
00082    {
00083      start_pnt = pointList.get_and_step();
00084      end_pnt = pointList.get();
00085 
00086      // Check if point lies on the line segment.  This is necessary because
00087      // the "fire-ray" code which checks if the point is inside or outside 
00088      // the polygon would return outside if the point is on the boundary.
00089      if( pnt.is_on_line_segment( start_pnt, end_pnt, tol ) )
00090        return CUBIT_PNT_BOUNDARY;
00091 
00092      // Check if point is in bounds of y of current segment (is it a 
00093        // candidate to cross segment?)
00094      if( (start_pnt->y() <= pnt.y() && pnt.y() < end_pnt->y()) ||
00095          (end_pnt->y() <= pnt.y() && pnt.y() < start_pnt->y()) )
00096      {
00097        // It's a candidate
00098        // Check if ray fired in negative x-direction crosses segment
00099        
00100        if( pnt.x() < (end_pnt->x()-start_pnt->x()) * (pnt.y()-start_pnt->y()) / 
00101            (end_pnt->y()-start_pnt->y()) + start_pnt->x() ) 
00102        {
00103          
00104          // Keeps track of even or odd number of crossings.
00105          //  0-even
00106          //  1-odd
00107          
00108          c = !c;
00109          
00110        }
00111      }
00112    }
00113    
00114    if( c )
00115       // Odd number of crossings
00116       return CUBIT_PNT_INSIDE;
00117    else
00118       // Even number of crossings
00119       return CUBIT_PNT_OUTSIDE;
00120 }
00121 
00122 CubitStatus
00123 CubitPolygon::centroid_area( Cubit2DPoint &centroid, double &area )
00124 {
00125   // Algorithm from Graphics Gems
00126   int n = pointList.size();
00127 
00128   if( pointList.size() < 3 )
00129     return CUBIT_FAILURE;
00130 
00131   double ai, atmp = 0.0, xtmp = 0.0, ytmp = 0.0;
00132 
00133   Cubit2DPoint *p1, *p2;
00134   pointList.reset();
00135   for (int j = 0; j < n; j++)
00136   {
00137     p1 = pointList.get_and_step();
00138     p2 = pointList.get();
00139     ai = p1->x() * p2->y() - p2->x() * p1->y();
00140     atmp += ai;
00141     xtmp += ( p2->x() + p1->x() ) * ai;
00142     ytmp += ( p2->y() + p1->y() ) * ai;
00143   }
00144 
00145   area = atmp / 2.0;
00146   if (atmp != 0.0)
00147   {
00148     centroid.set( xtmp / (3.0 * atmp), ytmp / (3.0 * atmp) );
00149     return CUBIT_SUCCESS;
00150   }
00151 
00152   return CUBIT_FAILURE;
00153 }
00154 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines