00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef QGSCLIPPER_H
00021 #define QGSCLIPPER_H
00022
00023 #include "qgspoint.h"
00024
00025 #include <vector>
00026 #include <utility>
00027 #include <cmath>
00028 #include <iostream>
00029
00040 class CORE_EXPORT QgsClipper
00041 {
00042 public:
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 static const double MAX_X;
00064 static const double MIN_X;
00065 static const double MAX_Y;
00066 static const double MIN_Y;
00067
00068
00069
00070 enum Boundary {XMax, XMin, YMax, YMin};
00071
00072
00073
00074
00075
00076 static void trimFeature( std::vector<double>& x,
00077 std::vector<double>& y,
00078 bool shapeOpen );
00079
00080 private:
00081
00082
00083 static const double SMALL_NUM;
00084
00085
00086
00087 static void trimFeatureToBoundary( const std::vector<double>& inX,
00088 const std::vector<double>& inY,
00089 std::vector<double>& outX,
00090 std::vector<double>& outY,
00091 Boundary b,
00092 bool shapeOpen );
00093
00094
00095 static bool inside( const double x, const double y, Boundary b );
00096
00097
00098
00099 static QgsPoint intersect( const double x1, const double y1,
00100 const double x2, const double y2,
00101 Boundary b );
00102 };
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 inline void QgsClipper::trimFeature( std::vector<double>& x,
00117 std::vector<double>& y,
00118 bool shapeOpen )
00119 {
00120 std::vector<double> tmpX;
00121 std::vector<double> tmpY;
00122 trimFeatureToBoundary( x, y, tmpX, tmpY, XMax, shapeOpen );
00123
00124 x.clear();
00125 y.clear();
00126 trimFeatureToBoundary( tmpX, tmpY, x, y, YMax, shapeOpen );
00127
00128 tmpX.clear();
00129 tmpY.clear();
00130 trimFeatureToBoundary( x, y, tmpX, tmpY, XMin, shapeOpen );
00131
00132 x.clear();
00133 y.clear();
00134 trimFeatureToBoundary( tmpX, tmpY, x, y, YMin, shapeOpen );
00135 }
00136
00137
00138
00139
00140
00141
00142 inline void QgsClipper::trimFeatureToBoundary(
00143 const std::vector<double>& inX,
00144 const std::vector<double>& inY,
00145 std::vector<double>& outX,
00146 std::vector<double>& outY,
00147 Boundary b, bool shapeOpen )
00148 {
00149
00150
00151
00152
00153 unsigned int i1 = inX.size() - 1;
00154
00155
00156 for ( unsigned int i2 = 0; i2 < inX.size() ; ++i2 )
00157 {
00158 if ( inside( inX[i2], inY[i2], b ) )
00159 {
00160 if ( inside( inX[i1], inY[i1], b ) )
00161 {
00162 outX.push_back( inX[i2] );
00163 outY.push_back( inY[i2] );
00164 }
00165 else
00166 {
00167
00168
00169 if ( !( i2 == 0 && shapeOpen ) )
00170 {
00171 QgsPoint p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
00172 outX.push_back( p.x() );
00173 outY.push_back( p.y() );
00174 }
00175
00176 outX.push_back( inX[i2] );
00177 outY.push_back( inY[i2] );
00178 }
00179 }
00180 else
00181 {
00182
00183 if ( inside( inX[i1], inY[i1], b ) )
00184 {
00185 if ( !( i2 == 0 && shapeOpen ) )
00186 {
00187 QgsPoint p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
00188 outX.push_back( p.x() );
00189 outY.push_back( p.y() );
00190 }
00191 }
00192 }
00193 i1 = i2;
00194 }
00195 }
00196
00197
00198
00199
00200 inline bool QgsClipper::inside( const double x, const double y, Boundary b )
00201 {
00202 switch ( b )
00203 {
00204 case XMax:
00205 if ( x < MAX_X )
00206 return true;
00207 break;
00208 case XMin:
00209 if ( x > MIN_X )
00210 return true;
00211 break;
00212 case YMax:
00213 if ( y < MAX_Y )
00214 return true;
00215 break;
00216 case YMin:
00217 if ( y > MIN_Y )
00218 return true;
00219 break;
00220 }
00221 return false;
00222 }
00223
00224
00225
00226
00227
00228
00229 inline QgsPoint QgsClipper::intersect( const double x1, const double y1,
00230 const double x2, const double y2,
00231 Boundary b )
00232 {
00233
00234
00235
00236
00237 double r_n = SMALL_NUM, r_d = SMALL_NUM;
00238
00239 switch ( b )
00240 {
00241 case XMax:
00242 r_n = -( x1 - MAX_X ) * ( MAX_Y - MIN_Y );
00243 r_d = ( x2 - x1 ) * ( MAX_Y - MIN_Y );
00244 break;
00245 case XMin:
00246 r_n = -( x1 - MIN_X ) * ( MAX_Y - MIN_Y );
00247 r_d = ( x2 - x1 ) * ( MAX_Y - MIN_Y );
00248 break;
00249 case YMax:
00250 r_n = ( y1 - MAX_Y ) * ( MAX_X - MIN_X );
00251 r_d = -( y2 - y1 ) * ( MAX_X - MIN_X );
00252 break;
00253 case YMin:
00254 r_n = ( y1 - MIN_Y ) * ( MAX_X - MIN_X );
00255 r_d = -( y2 - y1 ) * ( MAX_X - MIN_X );
00256 break;
00257 }
00258
00259 QgsPoint p;
00260
00261 if ( std::abs( r_d ) > SMALL_NUM && std::abs( r_n ) > SMALL_NUM )
00262 {
00263 double r = r_n / r_d;
00264 p.set( x1 + r*( x2 - x1 ), y1 + r*( y2 - y1 ) );
00265 }
00266 else
00267 {
00268
00269
00270 Q_ASSERT( std::abs( r_d ) > SMALL_NUM && std::abs( r_n ) > SMALL_NUM );
00271 }
00272
00273 return p;
00274 }
00275
00276
00277 #endif