cgma
|
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 ¢roid, 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