Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

computational_geometry.h

Go to the documentation of this file.
00001 /*
00002 Arroyo - software for the simulation of electromagnetic wave propagation
00003 through turbulence and optics.
00004 
00005 Copyright (c) 2000-2004 California Institute of Technology.  Written by
00006 Dr. Matthew Britton.  For comments or questions about this software,
00007 please contact the author at mbritton@astro.caltech.edu.
00008 
00009 This program is free software; you can redistribute it and/or modify it
00010 under the terms of the GNU General Public License as  published by the
00011 Free Software Foundation; either version 2 of the License, or (at your
00012 option) any later version.
00013 
00014 This program is provided "as is" and distributed in the hope that it
00015 will be useful, but WITHOUT ANY WARRANTY; without even the implied
00016 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  In no
00017 event shall California Institute of Technology be liable to any party
00018 for direct, indirect, special, incidental or consequential damages,
00019 including lost profits, arising out of the use of this software and its
00020 documentation, even if the California Institute of Technology has been
00021 advised of the possibility of such damage.   The California Institute of
00022 Technology has no obligation to provide maintenance, support, updates,
00023 enhancements or modifications.  See the GNU General Public License for
00024 more details.
00025 
00026 You should have received a copy of the GNU General Public License along
00027 with this program; if not, write to the Free Software
00028 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00029 */
00030 
00031 #ifndef COMPUTATIONAL_GEOMETRY_H
00032 #define COMPUTATIONAL_GEOMETRY_H
00033 
00034 #include <cmath>
00035 #include <vector>
00036 #include <string> 
00037 #include "AO_cpp.h"
00038 #include "three_frame.h"
00039 
00040 namespace Arroyo {
00041 
00043   // Find the point of intersection between two line segments defined
00044   // by their endpoints a1, a2 and b1, b2.  The result is contained in
00045   // the vector returned by this function, which may have size 0, 1, or
00046   // 2.
00047   //
00048   //  0             No intersection
00049   //  1             Intersection is a single point
00050   //  2             Intersection is a line segment
00051   //
00052   // The last result may only occur if the line segments are collinear.
00053   //
00054   // WARNING:  this function can return inaccurate results due to 
00055   // numerical roundoff.  Quantifying the limits of validity of this
00056   // function is a work in progress.
00057   std::vector<Arroyo::three_point>
00058   get_line_segment_intersection(const three_point & a1, 
00059                                 const three_point & a2, 
00060                                 const three_point & b1,
00061                                 const three_point & b2);
00062 
00063 
00068   //
00069   // WARNING:  this function can return inaccurate results due to 
00070   // numerical roundoff.  Quantifying the limits of validity of this
00071   // function is a work in progress.
00072   Arroyo::three_point get_ray_ray_intersection(
00073                                 const Arroyo::three_point & o_a, 
00074                                 const Arroyo::three_vector & n_a,
00075                                 const Arroyo::three_point & o_b, 
00076                                 const Arroyo::three_vector & n_b);
00077 
00082   //
00083   // WARNING:  this function can return inaccurate results due to 
00084   // numerical roundoff.  Quantifying the limits of validity of this
00085   // function is a work in progress.
00086   Arroyo::three_point get_ray_plane_intersection(
00087                                 const Arroyo::three_point & o_a, 
00088                                 const Arroyo::three_vector & n_a,
00089                                 const Arroyo::three_point & o_b, 
00090                                 const Arroyo::three_vector & n_b);
00091 
00093   // Find the directed area of a polygon specified by its vertices.
00094   // The vector polygon_vertices must have size greater than or equal
00095   // to three, and no three vertices may be collinear.  The vertices
00096   // must be sorted cyclically, with the function returning a positive
00097   // value for counterclockwise sorting and a negative value for
00098   // clockwise sorting.
00099   //
00100   // WARNING:  this function can return inaccurate results due to 
00101   // numerical roundoff.  Quantifying the limits of validity of this
00102   // function is a work in progress.
00103   double get_area_of_polygon(
00104                 const std::vector<Arroyo::three_point> & polygon_vertices);
00105 
00123   bool point_within_polygon(const three_point & tp, 
00124                             const vector<three_point> & vertices,
00125                             bool & point_on_edge,
00126                             bool & point_on_vertex);
00127     
00130   bool point_within_polygon(
00131                 const three_point & tp, const vector<three_point> & vtp);
00132 
00149   vector<three_point> get_convex_polygon_intersection(
00150                         const vector<three_point> & first_polygon_vertices,
00151                         const vector<three_point> & second_polygon_vertices,
00152                         int verbose = 0);
00153 
00155   // Find the point of intersection between a line segment defined by
00156   // its endpoints a1 and a2 and a circle with origin circle_origin
00157   // and the given radius.  The result is contained in the vector of
00158   // three_points returned by this function, which may have size 0, 1,
00159   // or 2.
00160   //
00161   //  0             No intersection
00162   //  1             Intersection is a single point
00163   //  2             Intersection contains two points
00164   //
00165   // WARNING:  this function can return inaccurate results due to 
00166   // numerical roundoff.  Quantifying the limits of validity of this
00167   // function is a work in progress.
00168   vector<three_point> get_line_segment_circle_intersection(
00169                                 const three_point & a1, 
00170                                 const three_point & a2, 
00171                                 const three_point & circle_origin,
00172                                 const double & radius, 
00173                                 vector<bool> & intersection_point_on_boundary,
00174                                 int verbose=0);
00175 
00176 
00191   vector<three_point> get_convex_polygon_circle_intersection(
00192                         const vector<three_point> & polygon_vertices,
00193                         const three_frame & circle_tf, 
00194                         double radius);
00195 
00196 
00207   template<class T>
00208     void convex_polygon_integration(const three_frame & tf,
00209                             const vector<three_point> & polygon_vertices,
00210                             T & x_intgrl,
00211                             T & y_intgrl,
00212                             int verbose = 0){
00213     try{
00214       x_intgrl = y_intgrl = 0;
00215       int nvertices = polygon_vertices.size();
00216 
00217       // If the polygon is degenerate, return zero for the integrand values
00218       if(nvertices<=2) return;
00219 
00220       double slope_b, slope_c;
00221       double intercept_b, intercept_c;
00222       double x_a, y_a, x_b, y_b, x_c, y_c;
00223       double last_x_b, last_y_b, last_x_c, last_y_c;
00224       double xmin, ymin, xmax, ymax;
00225       double sign;
00226       int index;
00227       double tmp;
00228       
00230       //  Perform the x integral //
00232       // Find the point with smallest x coordinate
00233       index = 0;
00234       x_a = polygon_vertices[0].x(tf);
00235       for(int i=1; i<nvertices; i++){
00236         tmp = polygon_vertices[i].x(tf);
00237         if(tmp<x_a){
00238           index = i;
00239           x_a = tmp;
00240         }
00241       }
00242       int indexb=index, indexc=index;
00243 
00244       do {
00245         indexb = (indexb+1)%nvertices;
00246         x_b = polygon_vertices[indexb].x(tf);
00247       } while((x_b-x_a)<three_frame::precision);
00248     
00249       do {
00250         indexc = (indexc-1+nvertices)%nvertices;
00251         x_c = polygon_vertices[indexc].x(tf);
00252       } while((x_c-x_a)<three_frame::precision);
00253 
00254       sign = 1;
00255       if(polygon_vertices[indexc].y(tf)>polygon_vertices[indexb].y(tf))
00256         sign = -1;
00257 
00258       if(verbose) cerr << "x input indices " << indexb
00259                        << "\t" << indexc << endl;
00260 
00261       while(1){
00262         if(indexb==indexc) break;
00263 
00264         y_b = polygon_vertices[indexb].y(tf);
00265         last_x_b = polygon_vertices[(indexb-1+nvertices)%nvertices].x(tf);
00266         last_y_b = polygon_vertices[(indexb-1+nvertices)%nvertices].y(tf);
00267 
00268         slope_b = (y_b-last_y_b)/(x_b-last_x_b);
00269         intercept_b = y_b - slope_b*x_b;
00270 
00271         y_c = polygon_vertices[indexc].y(tf);
00272         last_x_c = polygon_vertices[(indexc+1)%nvertices].x(tf);
00273         last_y_c = polygon_vertices[(indexc+1)%nvertices].y(tf);
00274 
00275         slope_c = (y_c-last_y_c)/(x_c-last_x_c);
00276         intercept_c = y_c - slope_c*x_c;
00277 
00278         xmin = last_x_b > last_x_c ? last_x_b : last_x_c;
00279         xmax = x_b < x_c ? x_b : x_c;
00280         ymin = y_b;
00281         ymax = y_c;
00282         if(y_b>y_c){
00283           ymin = y_c;
00284           ymax = y_b;
00285         }
00286       
00287         x_intgrl += sign*((slope_b-slope_c)*(xmax*xmax*xmax - xmin*xmin*xmin)/3.0 +
00288                           (intercept_b - intercept_c)*(xmax*xmax - xmin*xmin)/2.0);
00289 
00290         if(verbose){
00291           cerr << "\tindices " << indexb << "\t" << indexc << endl; 
00292           cerr << "\tlast indices " << (indexb-1+nvertices)%nvertices
00293                << "\t" << (indexc+1)%nvertices << endl;
00294           cerr << "\tb coords " << x_b << ", " << y_b << "\t"
00295                << " c coords " << x_c << ", " << y_c << endl;
00296           cerr << "\tlast b coords " << last_x_b << ", " << last_y_b << "\t" 
00297                << "  last c coords " << last_x_c << ", " << last_y_c << endl;
00298           cerr << "\tx min " << xmin << "\tx max " << xmax << endl;
00299           cerr << "\tsign " << sign << "\tslopes " << slope_b << "\t"
00300                << slope_c << endl;
00301           cerr << "\tintercepts " << intercept_b << "\t" << intercept_c << endl;
00302           cerr << "\tintgrl " << x_intgrl << endl;
00303         }
00304 
00305         if(fabs(x_b-x_c)<three_frame::precision){
00306           indexb = (indexb+1)%nvertices;
00307           if(indexb==indexc) break;
00308           indexc = (indexc-1+nvertices)%nvertices;
00309         }       else if(x_b<x_c){
00310           indexb = (indexb+1)%nvertices;
00311         } else {
00312           indexc = (indexc-1+nvertices)%nvertices;
00313         }
00314         if(verbose)
00315           cerr << "\tupdated indices " << indexb << "\t"
00316                << indexc << "\t" << y_intgrl << endl;
00317       }
00318 
00319 
00321       //  Perform the y integral //
00323       // Find the point with smallest y coordinate
00324       index = 0;
00325       y_a = polygon_vertices[0].y(tf);
00326       for(int i=1; i<nvertices; i++){
00327         tmp = polygon_vertices[i].y(tf);
00328         if(tmp<y_a){
00329           index = i;
00330           y_a = tmp;
00331         }
00332       }
00333       indexb=index;
00334       indexc=index;
00335 
00336       do {
00337         indexb = (indexb+1)%nvertices;
00338         y_b = polygon_vertices[indexb].y(tf);
00339       } while((y_b-y_a)<three_frame::precision);
00340     
00341       do {
00342         indexc = (indexc-1+nvertices)%nvertices;
00343         y_c = polygon_vertices[indexc].y(tf);
00344       } while((y_c-y_a)<three_frame::precision);
00345 
00346       sign = 1;
00347       if(polygon_vertices[indexc].x(tf)>polygon_vertices[indexb].x(tf))
00348         sign = -1;
00349 
00350       if(verbose) cerr << "y input indices " << indexb << "\t" << indexc << endl;
00351 
00352       while(1){
00353         if(indexb==indexc) break;
00354 
00355         x_b = polygon_vertices[indexb].x(tf);
00356         last_x_b = polygon_vertices[(indexb-1+nvertices)%nvertices].x(tf);
00357         last_y_b = polygon_vertices[(indexb-1+nvertices)%nvertices].y(tf);
00358 
00359         slope_b = (x_b-last_x_b)/(y_b-last_y_b);
00360         intercept_b = x_b - slope_b*y_b;
00361 
00362         x_c = polygon_vertices[indexc].x(tf);
00363         last_x_c = polygon_vertices[(indexc+1)%nvertices].x(tf);
00364         last_y_c = polygon_vertices[(indexc+1)%nvertices].y(tf);
00365 
00366         slope_c = (x_c-last_x_c)/(y_c-last_y_c);
00367         intercept_c = x_c - slope_c*y_c;
00368 
00369         ymin = last_y_b > last_y_c ? last_y_b : last_y_c;
00370         ymax = y_b < y_c ? y_b : y_c;
00371         xmin = x_b;
00372         xmax = x_c;
00373         if(x_b>x_c){
00374           xmin = x_c;
00375           xmax = x_b;
00376         }
00377       
00378         y_intgrl += sign*((slope_b-slope_c)*(ymax*ymax*ymax - ymin*ymin*ymin)/3.0 +
00379                           (intercept_b - intercept_c)*(ymax*ymax - ymin*ymin)/2.0);
00380             
00381         if(verbose){
00382           cerr << "\tindices " << indexb << "\t" << indexc << endl; 
00383           cerr << "\tlast indices " << (indexb-1+nvertices)%nvertices
00384                << "\t" << (indexc+1)%nvertices << endl;
00385           cerr << "\tb coords " << x_b << ", " << y_b << "\t"
00386                << " c coords " << x_c << ", " << y_c << endl;
00387           cerr << "\tlast b coords " << last_x_b << ", " << last_y_b << "\t" 
00388                << "  last c coords " << last_x_c << ", " << last_y_c << endl;
00389           cerr << "\ty min " << ymin << "\ty max " << ymax << endl;
00390           cerr << "\tsign " << sign << "\tslopes " << slope_b << "\t"
00391                << slope_c << endl;
00392           cerr << "\tintercepts " << intercept_b << "\t" << intercept_c << endl;
00393           cerr << "\tintgrl " << y_intgrl << endl;
00394         }
00395 
00396         if(fabs(y_b-y_c)<three_frame::precision){
00397           indexb = (indexb+1)%nvertices;
00398           if(indexb==indexc) break;
00399           indexc = (indexc-1+nvertices)%nvertices;
00400         }       else if(y_b<y_c){
00401           indexb = (indexb+1)%nvertices;
00402         } else {
00403           indexc = (indexc-1+nvertices)%nvertices;
00404         }      
00405         if(verbose)
00406           cerr << "\tupdated indices " << indexb << "\t"
00407                << indexc << "\t" << y_intgrl << endl;
00408       }
00409 
00410       if(verbose)
00411         cerr << "returning " << x_intgrl << "\t" << y_intgrl << endl << endl;
00412     } catch(...) {
00413       cerr << "convex_polygon_integration error\n";
00414       throw(string("convex_polygon_integration"));
00415     }
00416   }
00417 }
00418 
00419 #endif

Generated on Thu Nov 29 17:16:28 2007 for arroyo by  doxygen 1.3.9.1