00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef GEOM_UTIL_HPP
00026 #define GEOM_UTIL_HPP
00027
00028 #include <cmath>
00029
00030 #include <boost/tuple/tuple.hpp>
00031
00032 #include <mapnik/envelope.hpp>
00033 #include <mapnik/vertex.hpp>
00034
00035 namespace mapnik
00036 {
00037 template <typename T>
00038 bool clip_test(T p,T q,double& tmin,double& tmax)
00039 {
00040 double r;
00041 bool result=true;
00042 if (p<0.0)
00043 {
00044 r=q/p;
00045 if (r>tmax) result=false;
00046 else if (r>tmin) tmin=r;
00047 }
00048 else if (p>0.0)
00049 {
00050 r=q/p;
00051 if (r<tmin) result=false;
00052 else if (r<tmax) tmax=r;
00053 } else if (q<0.0) result=false;
00054 return result;
00055 }
00056
00057 template <typename T,typename Image>
00058 bool clip_line(T& x0,T& y0,T& x1,T& y1,Envelope<T> const& box)
00059 {
00060 double tmin=0.0;
00061 double tmax=1.0;
00062 double dx=x1-x0;
00063 if (clip_test<double>(-dx,x0,tmin,tmax))
00064 {
00065 if (clip_test<double>(dx,box.width()-x0,tmin,tmax))
00066 {
00067 double dy=y1-y0;
00068 if (clip_test<double>(-dy,y0,tmin,tmax))
00069 {
00070 if (clip_test<double>(dy,box.height()-y0,tmin,tmax))
00071 {
00072 if (tmax<1.0)
00073 {
00074 x1=static_cast<T>(x0+tmax*dx);
00075 y1=static_cast<T>(y0+tmax*dy);
00076 }
00077 if (tmin>0.0)
00078 {
00079 x0+=static_cast<T>(tmin*dx);
00080 y0+=static_cast<T>(tmin*dy);
00081 }
00082 return true;
00083 }
00084 }
00085 }
00086 }
00087 return false;
00088 }
00089
00090 template <typename Iter>
00091 inline bool point_inside_path(double x,double y,Iter start,Iter end)
00092 {
00093 bool inside=false;
00094 double x0=boost::get<0>(*start);
00095 double y0=boost::get<1>(*start);
00096
00097 double x1,y1;
00098 while (++start!=end)
00099 {
00100 if ( boost::get<2>(*start) == SEG_MOVETO)
00101 {
00102 x0 = boost::get<0>(*start);
00103 y0 = boost::get<1>(*start);
00104 continue;
00105 }
00106 x1=boost::get<0>(*start);
00107 y1=boost::get<1>(*start);
00108
00109 if ((((y1 <= y) && (y < y0)) ||
00110 ((y0 <= y) && (y < y1))) &&
00111 ( x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
00112 inside=!inside;
00113 x0=x1;
00114 y0=y1;
00115 }
00116 return inside;
00117 }
00118
00119 inline bool point_in_circle(double x,double y,double cx,double cy,double r)
00120 {
00121 double dx = x - cx;
00122 double dy = y - cy;
00123 double d2 = dx * dx + dy * dy;
00124 return (d2 <= r * r);
00125 }
00126
00127 template <typename T>
00128 inline T sqr(T x)
00129 {
00130 return x * x;
00131 }
00132
00133 inline double distance2(double x0,double y0,double x1,double y1)
00134 {
00135 double dx = x1 - x0;
00136 double dy = y1 - y0;
00137 return sqr(dx) + sqr(dy);
00138 }
00139
00140 inline double distance(double x0,double y0, double x1,double y1)
00141 {
00142 return sqrt(distance2(x0,y0,x1,y1));
00143 }
00144
00145 inline double point_to_segment_distance(double x, double y,
00146 double ax, double ay,
00147 double bx, double by)
00148 {
00149 double len2 = distance2(ax,ay,bx,by);
00150
00151 if (len2 < 1e-14)
00152 {
00153 return distance(x,y,ax,ay);
00154 }
00155
00156 double r = ((x - ax)*(bx - ax) + (y - ay)*(by -ay))/len2;
00157 if ( r < 0 )
00158 {
00159 return distance(x,y,ax,ay);
00160 }
00161 else if (r > 1)
00162 {
00163 return distance(x,y,bx,by);
00164 }
00165 double s = ((ay - y)*(bx - ax) - (ax - x)*(by - ay))/len2;
00166 return fabs(s) * sqrt(len2);
00167 }
00168
00169 template <typename Iter>
00170 inline bool point_on_path(double x,double y,Iter start,Iter end, double tol)
00171 {
00172 double x0=boost::get<0>(*start);
00173 double y0=boost::get<1>(*start);
00174 double x1,y1;
00175 while (++start != end)
00176 {
00177 if ( boost::get<2>(*start) == SEG_MOVETO)
00178 {
00179 x0 = boost::get<0>(*start);
00180 y0 = boost::get<1>(*start);
00181 continue;
00182 }
00183 x1=boost::get<0>(*start);
00184 y1=boost::get<1>(*start);
00185
00186 double distance = point_to_segment_distance(x,y,x0,y0,x1,y1);
00187 if (distance < tol)
00188 return true;
00189 x0=x1;
00190 y0=y1;
00191 }
00192 return false;
00193 }
00194
00195
00196 struct filter_in_box
00197 {
00198 Envelope<double> box_;
00199 explicit filter_in_box(const Envelope<double>& box)
00200 : box_(box) {}
00201
00202 bool pass(const Envelope<double>& extent) const
00203 {
00204 return extent.intersects(box_);
00205 }
00206 };
00207
00208 struct filter_at_point
00209 {
00210 coord2d pt_;
00211 explicit filter_at_point(const coord2d& pt)
00212 : pt_(pt) {}
00213 bool pass(const Envelope<double>& extent) const
00214 {
00215 return extent.contains(pt_);
00216 }
00217 };
00218 }
00219
00220 #endif //GEOM_UTIL_HPP