/home/andreas/src/svn/mapnik/include/mapnik/geometry.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * 
00003  * This file is part of Mapnik (c++ mapping toolkit)
00004  *
00005  * Copyright (C) 2006 Artem Pavlenko
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  *
00021  *****************************************************************************/
00022 
00023 
00024 //$Id: geometry.hpp 39 2005-04-10 20:39:53Z pavlenko $
00025 
00026 #ifndef GEOMETRY_HPP
00027 #define GEOMETRY_HPP
00028 
00029 // boost
00030 #include <boost/shared_ptr.hpp>
00031 #include <boost/utility.hpp>
00032 // mapnik
00033 #include <mapnik/vertex_vector.hpp>
00034 #include <mapnik/ctrans.hpp>
00035 #include <mapnik/geom_util.hpp>
00036 
00037 namespace mapnik {
00038     enum GeomType {
00039         Point = 1,
00040         LineString = 2,
00041         Polygon = 3
00042     };
00043     
00044     template <typename T>
00045     class geometry : private boost::noncopyable
00046     {   
00047     public:
00048         typedef T vertex_type;
00049         typedef typename vertex_type::type value_type;
00050     private:
00051         int srid_;
00052     public:
00053         geometry (int srid=-1)
00054             : srid_(srid) {}    
00055 
00056         int srid() const
00057         {
00058             return srid_;
00059         }
00060         
00061         Envelope<double> envelope()
00062         {
00063             Envelope<double> result;            
00064             double x,y;
00065             rewind(0);
00066             for (unsigned i=0;i<num_points();++i)
00067             {
00068                 vertex(&x,&y);
00069                 if (i==0)
00070                 {
00071                     result.init(x,y,x,y);
00072                 }
00073                 else
00074                 {
00075                     result.expand_to_include(x,y);
00076                 }
00077             }
00078             return result;
00079         }
00080         
00081         virtual int type() const=0;
00082         virtual bool hit_test(value_type x,value_type y, double tol) const=0;   
00083         virtual void label_position(double *x, double *y) const=0;
00084         virtual void move_to(value_type x,value_type y)=0;
00085         virtual void line_to(value_type x,value_type y)=0;
00086         virtual unsigned num_points() const = 0;
00087         virtual unsigned vertex(double* x, double* y)=0;
00088         virtual void rewind(unsigned )=0;
00089         virtual void set_capacity(size_t size)=0;
00090         virtual ~geometry() {}
00091     };
00092     
00093     template <typename T>
00094     class point : public geometry<T>
00095     {
00096         typedef geometry<T> geometry_base;
00097         typedef typename geometry<T>::vertex_type vertex_type;
00098         typedef typename geometry<T>::value_type value_type;
00099     private:
00100         vertex_type pt_;
00101     public:
00102         point(int srid)
00103             : geometry<T>(srid)
00104         {}
00105          
00106         int type() const 
00107         {
00108             return Point;
00109         }
00110         void label_position(double *x, double *y) const
00111         {
00112             *x = pt_.x;
00113             *y = pt_.y;
00114         }
00115         
00116         void move_to(value_type x,value_type y)
00117         {
00118             pt_.x = x;
00119             pt_.y = y;
00120         }
00121         
00122         void line_to(value_type ,value_type ) {}
00123         
00124         unsigned num_points() const
00125         {
00126             return 1;
00127         }
00128         
00129         unsigned vertex(double* x, double* y)
00130         {
00131             *x = pt_.x;
00132             *y = pt_.y;
00133             return SEG_LINETO;
00134         }
00135         
00136         void rewind(unsigned ) {}
00137         
00138         bool hit_test(value_type x,value_type y, double tol) const
00139         {
00140             return point_in_circle(pt_.x,pt_.y, x,y,tol);
00141         }
00142         
00143         void set_capacity(size_t) {}
00144         virtual ~point() {}
00145     };
00146 
00147     template <typename T, template <typename> class Container=vertex_vector2>
00148     class polygon : public geometry<T>
00149     {
00150         typedef geometry<T> geometry_base;
00151         typedef typename geometry<T>::vertex_type vertex_type;
00152         typedef typename geometry_base::value_type value_type;
00153         typedef Container<vertex_type> container_type;
00154     private:
00155         container_type cont_;
00156         mutable unsigned itr_;
00157     public:
00158         polygon(int srid)
00159             : geometry_base(srid),
00160               itr_(0)
00161         {}
00162         
00163         int type() const 
00164         {
00165             return Polygon;
00166         }
00167         
00168         void label_position(double *x, double *y) const
00169         {
00170             
00171             unsigned size = cont_.size();
00172             if (size < 3) 
00173             {
00174                 cont_.get_vertex(0,x,y);
00175                 return;
00176             }
00177               
00178             double ai;
00179             double atmp = 0;
00180             double xtmp = 0;
00181             double ytmp = 0;
00182             double x0 =0;
00183             double y0 =0;
00184             double x1 =0;
00185             double y1 =0;
00186             
00187             unsigned i,j;
00188             for (i = size-1,j = 0; j < size; i = j, ++j)
00189             {
00190                 cont_.get_vertex(i,&x0,&y0);
00191                 cont_.get_vertex(j,&x1,&y1);
00192                 ai = x0 * y1 - x1 * y0;
00193                 atmp += ai;
00194                 xtmp += (x1 + x0) * ai;
00195                 ytmp += (y1 + y0) * ai;
00196             }     
00197             if (atmp != 0)
00198             {
00199                 *x = xtmp/(3*atmp);
00200                 *y = ytmp /(3*atmp);
00201                 return;
00202             }
00203             *x=x0;
00204             *y=y0;                  
00205         }
00206 
00207         void line_to(value_type x,value_type y)
00208         {
00209             cont_.push_back(x,y,SEG_LINETO);
00210         }
00211 
00212         void move_to(value_type x,value_type y)
00213         {
00214             cont_.push_back(x,y,SEG_MOVETO);
00215         }
00216         
00217         unsigned num_points() const
00218         {
00219             return cont_.size();
00220         }
00221         
00222         unsigned vertex(double* x, double* y)
00223         {
00224             return cont_.get_vertex(itr_++,x,y);
00225         }
00226         
00227         void rewind(unsigned )
00228         {
00229             itr_=0;
00230         }
00231         
00232         bool hit_test(value_type x,value_type y, double) const
00233         {           
00234             return point_inside_path(x,y,cont_.begin(),cont_.end());
00235         } 
00236         
00237         void set_capacity(size_t size) 
00238         {
00239             cont_.set_capacity(size);
00240         }
00241         virtual ~polygon() {}
00242     };
00243     
00244     template <typename T, template <typename> class Container=vertex_vector2>
00245     class line_string : public geometry<T>
00246     {
00247         typedef geometry<T> geometry_base;
00248         typedef typename geometry_base::value_type value_type;
00249         typedef typename geometry<T>::vertex_type vertex_type;
00250         typedef Container<vertex_type> container_type;
00251     private:
00252         container_type cont_;
00253         mutable unsigned itr_;
00254     public:
00255         line_string(int srid)
00256             : geometry_base(srid),
00257               itr_(0)
00258         {}
00259         
00260         int type() const 
00261         {
00262             return LineString;
00263         }
00264         void label_position(double *x, double *y) const
00265         {
00266             // calculate mid point on line string
00267             double x0=0;
00268             double y0=0;
00269             double x1=0;
00270             double y1=0;
00271             
00272             unsigned size = cont_.size();
00273             if (size == 1)
00274             {
00275                 cont_.get_vertex(0,x,y); 
00276             }
00277             else if (size == 2)
00278             {
00279 
00280                 cont_.get_vertex(0,&x0,&y0);
00281                 cont_.get_vertex(1,&x1,&y1);
00282                 *x = 0.5 * (x1 + x0);
00283                 *y = 0.5 * (y1 + y0);           
00284             }
00285             else
00286             {
00287                 double len=0.0;
00288                 for (unsigned pos = 1; pos < size; ++pos)
00289                 {
00290                     cont_.get_vertex(pos-1,&x0,&y0);
00291                     cont_.get_vertex(pos,&x1,&y1);
00292                     double dx = x1 - x0;
00293                     double dy = y1 - y0;
00294                     len += sqrt(dx * dx + dy * dy);
00295                 }
00296                 double midlen = 0.5 * len;
00297                 double dist = 0.0;
00298                 for (unsigned pos = 1; pos < size;++pos)
00299                 {
00300                     cont_.get_vertex(pos-1,&x0,&y0);
00301                     cont_.get_vertex(pos,&x1,&y1);
00302                     double dx = x1 - x0;
00303                     double dy = y1 - y0; 
00304                     double seg_len = sqrt(dx * dx + dy * dy);
00305                     if (( dist + seg_len) >= midlen)
00306                     {
00307                         double r = (midlen - dist)/seg_len;
00308                         *x = x0 + (x1 - x0) * r;
00309                         *y = y0 + (y1 - y0) * r;
00310                         break;
00311                     }
00312                     dist += seg_len;
00313                 }
00314             }
00315             
00316         }
00317         void line_to(value_type x,value_type y)
00318         {
00319             cont_.push_back(x,y,SEG_LINETO);
00320         }
00321 
00322         void move_to(value_type x,value_type y)
00323         {
00324             cont_.push_back(x,y,SEG_MOVETO);
00325         }
00326 
00327         unsigned num_points() const
00328         {
00329             return cont_.size();
00330         }
00331         
00332         unsigned vertex(double* x, double* y)
00333         {
00334             return cont_.get_vertex(itr_++,x,y);
00335         }
00336         
00337         void rewind(unsigned )
00338         {
00339             itr_=0;
00340         }
00341         
00342         bool hit_test(value_type x,value_type y, double tol) const
00343         {           
00344             return point_on_path(x,y,cont_.begin(),cont_.end(),tol);
00345         } 
00346         
00347         void set_capacity(size_t size) 
00348         {
00349             cont_.set_capacity(size);
00350         }
00351         virtual ~line_string() {}
00352     };
00353 
00354     typedef point<vertex2d> point_impl;
00355     typedef line_string<vertex2d,vertex_vector2> line_string_impl;
00356     typedef polygon<vertex2d,vertex_vector2> polygon_impl;
00357     
00358     typedef geometry<vertex2d> geometry_type;
00359     typedef boost::shared_ptr<geometry_type> geometry_ptr;
00360 }
00361 
00362 #endif //GEOMETRY_HPP

Generated on Thu Jul 19 17:59:26 2007 for Mapnik by  doxygen 1.4.7