Go to Overview over all GrAL packages.
Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Geometry/algebraic-primitives.C

Go to the documentation of this file.
00001 #ifndef NMWR_GB_ALGEBRAIC_PRIMITIVES_C
00002 #define NMWR_GB_ALGEBRAIC_PRIMITIVES_C
00003 
00004 
00005 // $LICENSE
00006 
00007 
00008 #include "Geometry/algebraic-primitives.h"
00009 
00010 //-------------------------------------------------------------------------
00011 //
00012 // calculate centroid and area of a simple polygon, given by the vertices
00013 // [begin, end).
00014 // The centroid (or center of inertia) c of a domain D is defined by
00015 // \int_{D} x_i dx dy / area(D)
00016 //
00017 // Algorithm:
00018 // ----------
00019 // This is adapted from GraphicsGems IV, centroid.c
00020 // It uses the theorem of Stokes to calculate the integral:
00021 // \int_{D} x dx \wedge dy = \int{\partial D} 1/2 x^2 dy
00022 //   ( note: d(1/2 x^2 dy) = x dx \wedge dy )
00023 // if P,Q are two adjacent corners of the polygon, then
00024 // \int{[P,Q]} 1/2 x^2 dy  = (P_1^2 + Q_1^2 +P_1Q_1)(Q_2 - P_2)
00025 //                         = det(P,Q)                  * (P_1 + Q_1) 
00026 //                         = 2 area (\triangle(0,P,Q)) * (P_1 + Q_1)
00027 //
00028 //-------------------------------------------------------------------------
00029 
00030 template<class PIt, class Q>
00031 void get_polygon2d_center_and_area(PIt begin, PIt end, // in:  iterator over polygon vertices
00032                                    Q& center,          // out: centroid
00033                                    double& area)       // out: polygon area
00034 {
00035   typedef point_traits<Q> Qpt;
00036   // should use iterator_traits here to deduce value_type
00037   typedef typename PIt::value_type  P;
00038   typedef point_traits<P> Ppt;
00039 
00040   REQUIRE((begin != end), "empty polygon!\n",1);
00041   PIt v1 = begin;
00042   PIt vi = v1;
00043   ++begin; 
00044   REQUIRE((begin != end), "polygon with only one corner!\n",1);
00045   PIt vi1 = begin;
00046   double area_2 = 0.0, xtmp = 0.0, ytmp = 0.0;
00047   // center_x = \frac{\int_{P} x dx \wedge dy}{ area(P)}
00048   //  = \frac{\sum_{i = 1}^{n} \int{\triangle{0,vi,v_{i+1 (mod n)}} x dx \wedge dy}%
00049   //         {area(P)}
00050   //\int_\triangle(0,v_i,v_{i+1}) x dx \wedge dy 
00051   //  = 2 area(\triangle(0,v_i,v_{i+1})) * 1/6 ((v_i)_x + (v_{i+1})_x)
00052   // NOTE: this uses oriented integrals!
00053   while( vi1 != end) {
00054     P pi=*vi,pi1=*vi1;
00055     double ai = Ppt::x(pi) * Ppt::y(pi1) - Ppt::y(pi) * Ppt::x(pi1);
00056     area_2 += ai;
00057     xtmp += ai * (Ppt::x(pi) + Ppt::x(pi1));
00058     ytmp += ai * (Ppt::y(pi) + Ppt::y(pi1));
00059     ++vi; ++vi1;
00060   }
00061   // wrap around
00062   vi1 = v1;
00063   P pi=*vi,pi1=*vi1;
00064   double ai = Ppt::x(pi) * Ppt::y(pi1) - Ppt::y(pi) * Ppt::x(pi1);
00065   area_2 += ai;
00066   xtmp += ai * (Ppt::x(pi) + Ppt::x(pi1));
00067   ytmp += ai * (Ppt::y(pi) + Ppt::y(pi1));
00068   //  ++vi; ++vi1;
00069   
00070   area = 0.5 * area_2;
00071   // general case: translate center by v1
00072   Qpt::x(center) = xtmp / (3.0 * area_2);
00073   Qpt::y(center) = ytmp / (3.0 * area_2);
00074 }
00075 
00076 #endif

Copyright (c) Guntram Berti 1997-2002. See the GrAL Homepage for up-to-date information.

Generated at Tue Feb 26 15:57:26 2002 for Geometry by doxygen 1.2.11-20011104 written by Dimitri van Heesch, © 1997-2000