Quantum GIS API Documentation  master-693a1fe
src/core/qgsclipper.h
Go to the documentation of this file.
00001 /***************************************************************************
00002                           qgsclipper.h  -  a class that clips line
00003                           segments and polygons
00004                              -------------------
00005     begin                : March 2004
00006     copyright            : (C) 2005 by Gavin Macaulay
00007     email                :
00008  ***************************************************************************/
00009 
00010 /***************************************************************************
00011  *                                                                         *
00012  *   This program is free software; you can redistribute it and/or modify  *
00013  *   it under the terms of the GNU General Public License as published by  *
00014  *   the Free Software Foundation; either version 2 of the License, or     *
00015  *   (at your option) any later version.                                   *
00016  *                                                                         *
00017  ***************************************************************************/
00018 
00019 #ifndef QGSCLIPPER_H
00020 #define QGSCLIPPER_H
00021 
00022 #include "qgis.h"
00023 #include "qgspoint.h"
00024 #include "qgsrectangle.h"
00025 
00026 #include <QVector>
00027 #include <QPolygonF>
00028 
00039 class CORE_EXPORT QgsClipper
00040 {
00041   public:
00042 
00043     // Coordinates of the rectangular box that we trim to.
00044     //
00045     // These are the limits for X11 screen coordinates. The actual
00046     // values are +/-32767, but we allow a little bit of space for
00047     // rounding errors.
00048 
00049     // You may wonder why the clipping is done to these coordindates
00050     // rather than the boundaries of the qgis canvas. Reasons include:
00051     // - making the boundaries static const allows the compiler to
00052     //   optimise the code that uses these values more than if they changed
00053     //   for every call to the trim code.
00054     // - clipping takes quite a bit of CPU effort, and the less that this is
00055     //   done the better. More stuff would have to be clipped if the
00056     //   boundaries were the qgis canvas (but this may be offset by
00057     //   having less to draw).
00058     //
00059     // The limit is set to 30,000 instead of 32768 because that things
00060     // still go wrong.
00061 
00062     static const double MAX_X;
00063     static const double MIN_X;
00064     static const double MAX_Y;
00065     static const double MIN_Y;
00066 
00067 
00068     // A handy way to refer to the four boundaries
00069     enum Boundary {XMax, XMin, YMax, YMin};
00070 
00071     // Trims the given feature to a rectangular box. Returns the trimmed
00072     // feature in x and y. The shapeOpen parameter determines whether
00073     // the function treats the points as a closed shape (polygon), or as
00074     // an open shape (linestring).
00075     static void trimFeature( QVector<double>& x,
00076                              QVector<double>& y,
00077                              bool shapeOpen );
00078 
00079     static void trimPolygon( QPolygonF& pts, const QgsRectangle& clipRect );
00080 
00085     static unsigned char* clippedLineWKB( unsigned char* wkb, const QgsRectangle& clipExtent, QPolygonF& line );
00086 
00087   private:
00088 
00089     // Used when testing for equivalance to 0.0
00090     static const double SMALL_NUM;
00091 
00092     // Trims the given feature to the given boundary. Returns the
00093     // trimmed feature in the outX and outY vectors.
00094     static void trimFeatureToBoundary( const QVector<double>& inX,
00095                                        const QVector<double>& inY,
00096                                        QVector<double>& outX,
00097                                        QVector<double>& outY,
00098                                        Boundary b,
00099                                        bool shapeOpen );
00100 
00101     static void trimPolygonToBoundary( const QPolygonF& inPts, QPolygonF& outPts, const QgsRectangle& rect, Boundary b, double boundaryValue );
00102 
00103     // Determines if a point is inside or outside the given boundary
00104     static bool inside( const double x, const double y, Boundary b );
00105 
00106     static bool inside( const QPointF& pt, Boundary b, double val );
00107 
00108     // Calculates the intersection point between a line defined by a
00109     // (x1, y1), and (x2, y2) and the given boundary
00110     static QgsPoint intersect( const double x1, const double y1,
00111                                const double x2, const double y2,
00112                                Boundary b );
00113 
00114     static QPointF intersectRect( const QPointF& pt1,
00115                                   const QPointF& pt2,
00116                                   Boundary b, const QgsRectangle& rect );
00117 
00118     //Implementation of 'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
00119     static bool clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double& x0, double& y0, double& x1, double& y1 );
00120 
00129     static void connectSeparatedLines( double x0, double y0, double x1, double y1,
00130                                        const QgsRectangle& clipRect, QPolygonF& pts );
00131 
00132     //low level clip methods for fast clip algorithm
00133     static void clipStartTop( double& x0, double& y0, const double& x1, const double& y1, double yMax );
00134     static void clipStartBottom( double& x0, double& y0, const double& x1, const double& y1, double yMin );
00135     static void clipStartRight( double& x0, double& y0, const double& x1, const double& y1, double xMax );
00136     static void clipStartLeft( double& x0, double& y0, const double& x1, const double& y1, double xMin );
00137     static void clipEndTop( const double& x0, const double& y0, double& x1, double& y1, double yMax );
00138     static void clipEndBottom( const double& x0, const double& y0, double& x1, double& y1, double yMin );
00139     static void clipEndRight( const double& x0, const double& y0, double& x1, double& y1, double xMax );
00140     static void clipEndLeft( const double& x0, const double& y0, double& x1, double& y1, double xMin );
00141 };
00142 
00143 // The inline functions
00144 
00145 // Trim the feature using Sutherland and Hodgman's
00146 // polygon-clipping algorithm. See J. D. Foley, A. van Dam,
00147 // S. K. Feiner, and J. F. Hughes, Computer Graphics, Principles and
00148 // Practice. Addison-Wesley Systems Programming Series,
00149 // Addison-Wesley, 2nd ed., 1991.
00150 
00151 // I understand that this is not the most efficient algorithm, but is
00152 // one (the only?) that is guaranteed to always give the correct
00153 // result.
00154 
00155 inline void QgsClipper::trimFeature( QVector<double>& x,
00156                                      QVector<double>& y,
00157                                      bool shapeOpen )
00158 {
00159   QVector<double> tmpX;
00160   QVector<double> tmpY;
00161   trimFeatureToBoundary( x, y, tmpX, tmpY, XMax, shapeOpen );
00162 
00163   x.clear();
00164   y.clear();
00165   trimFeatureToBoundary( tmpX, tmpY, x, y, YMax, shapeOpen );
00166 
00167   tmpX.clear();
00168   tmpY.clear();
00169   trimFeatureToBoundary( x, y, tmpX, tmpY, XMin, shapeOpen );
00170 
00171   x.clear();
00172   y.clear();
00173   trimFeatureToBoundary( tmpX, tmpY, x, y, YMin, shapeOpen );
00174 }
00175 
00176 inline void QgsClipper::trimPolygon( QPolygonF& pts, const QgsRectangle& clipRect )
00177 {
00178   QPolygonF tmpPts;
00179   tmpPts.reserve( pts.size() );
00180 
00181   trimPolygonToBoundary( pts, tmpPts, clipRect, XMax, clipRect.xMaximum() );
00182   pts.clear();
00183   trimPolygonToBoundary( tmpPts, pts, clipRect, YMax, clipRect.yMaximum() );
00184   tmpPts.clear();
00185   trimPolygonToBoundary( pts, tmpPts, clipRect, XMin, clipRect.xMinimum() );
00186   pts.clear();
00187   trimPolygonToBoundary( tmpPts, pts, clipRect, YMin, clipRect.yMinimum() );
00188 }
00189 
00190 // An auxilary function that is part of the polygon trimming
00191 // code. Will trim the given polygon to the given boundary and return
00192 // the trimmed polygon in the out pointer. Uses Sutherland and
00193 // Hodgman's polygon-clipping algorithm.
00194 
00195 inline void QgsClipper::trimFeatureToBoundary(
00196   const QVector<double>& inX,
00197   const QVector<double>& inY,
00198   QVector<double>& outX,
00199   QVector<double>& outY,
00200   Boundary b, bool shapeOpen )
00201 {
00202   // The shapeOpen parameter selects whether this function treats the
00203   // shape as open or closed. False is appropriate for polygons and
00204   // true for polylines.
00205 
00206   int i1 = inX.size() - 1; // start with last point
00207 
00208   // and compare to the first point initially.
00209   for ( int i2 = 0; i2 < inX.size() ; ++i2 )
00210   {
00211     // look at each edge of the polygon in turn
00212 
00213     //ignore segments with nan or inf coordinates
00214     if ( qIsNaN( inX[i2] ) || qIsNaN( inY[i2] ) || qIsInf( inX[i2] ) || qIsInf( inY[i2] )
00215          || qIsNaN( inX[i1] ) || qIsNaN( inY[i1] ) || qIsInf( inX[i1] ) || qIsInf( inY[i1] ) )
00216     {
00217       i1 = i2;
00218       continue;
00219     }
00220 
00221 
00222     if ( inside( inX[i2], inY[i2], b ) ) // end point of edge is inside boundary
00223     {
00224       if ( inside( inX[i1], inY[i1], b ) )
00225       {
00226         outX.push_back( inX[i2] );
00227         outY.push_back( inY[i2] );
00228       }
00229       else
00230       {
00231         // edge crosses into the boundary, so trim back to the boundary, and
00232         // store both ends of the new edge
00233         if ( !( i2 == 0 && shapeOpen ) )
00234         {
00235           QgsPoint p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
00236           outX.push_back( p.x() );
00237           outY.push_back( p.y() );
00238         }
00239 
00240         outX.push_back( inX[i2] );
00241         outY.push_back( inY[i2] );
00242       }
00243     }
00244     else // end point of edge is outside boundary
00245     {
00246       // start point is in boundary, so need to trim back
00247       if ( inside( inX[i1], inY[i1], b ) )
00248       {
00249         if ( !( i2 == 0 && shapeOpen ) )
00250         {
00251           QgsPoint p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
00252           outX.push_back( p.x() );
00253           outY.push_back( p.y() );
00254         }
00255       }
00256     }
00257     i1 = i2;
00258   }
00259 }
00260 
00261 inline void QgsClipper::trimPolygonToBoundary( const QPolygonF& inPts, QPolygonF& outPts, const QgsRectangle& rect, Boundary b, double boundaryValue )
00262 {
00263   int i1 = inPts.size() - 1; // start with last point
00264 
00265   // and compare to the first point initially.
00266   for ( int i2 = 0; i2 < inPts.size() ; ++i2 )
00267   { // look at each edge of the polygon in turn
00268     if ( inside( inPts[i2], b, boundaryValue ) ) // end point of edge is inside boundary
00269     {
00270       if ( inside( inPts[i1], b, boundaryValue ) )
00271       {
00272         outPts.append( inPts[i2] );
00273       }
00274       else
00275       {
00276         // edge crosses into the boundary, so trim back to the boundary, and
00277         // store both ends of the new edge
00278         outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
00279         outPts.append( inPts[i2] );
00280       }
00281     }
00282     else // end point of edge is outside boundary
00283     {
00284       // start point is in boundary, so need to trim back
00285       if ( inside( inPts[i1], b, boundaryValue ) )
00286       {
00287         outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
00288       }
00289     }
00290     i1 = i2;
00291   }
00292 }
00293 
00294 // An auxilary function to trimPolygonToBoundarY() that returns
00295 // whether a point is inside or outside the given boundary.
00296 
00297 inline bool QgsClipper::inside( const double x, const double y, Boundary b )
00298 {
00299   switch ( b )
00300   {
00301     case XMax: // x < MAX_X is inside
00302       if ( x < MAX_X )
00303         return true;
00304       break;
00305     case XMin: // x > MIN_X is inside
00306       if ( x > MIN_X )
00307         return true;
00308       break;
00309     case YMax: // y < MAX_Y is inside
00310       if ( y < MAX_Y )
00311         return true;
00312       break;
00313     case YMin: // y > MIN_Y is inside
00314       if ( y > MIN_Y )
00315         return true;
00316       break;
00317   }
00318   return false;
00319 }
00320 
00321 inline bool QgsClipper::inside( const QPointF& pt, Boundary b, double val )
00322 {
00323   switch ( b )
00324   {
00325     case XMax: // x < MAX_X is inside
00326       return ( pt.x() < val );
00327     case XMin: // x > MIN_X is inside
00328       return ( pt.x() > val );
00329     case YMax: // y < MAX_Y is inside
00330       return ( pt.y() < val );
00331     case YMin: // y > MIN_Y is inside
00332       return ( pt.y() > val );
00333   }
00334   return false;
00335 }
00336 
00337 
00338 // An auxilary function to trimPolygonToBoundarY() that calculates and
00339 // returns the intersection of the line defined by the given points
00340 // and the given boundary.
00341 
00342 inline QgsPoint QgsClipper::intersect( const double x1, const double y1,
00343                                        const double x2, const double y2,
00344                                        Boundary b )
00345 {
00346   // This function assumes that the two given points (x1, y1), and
00347   // (x2, y2) cross the given boundary. Making this assumption allows
00348   // some optimisations.
00349 
00350   double r_n = SMALL_NUM, r_d = SMALL_NUM;
00351 
00352   switch ( b )
00353   {
00354     case XMax: // x = MAX_X boundary
00355       r_n = -( x1 - MAX_X ) * ( MAX_Y - MIN_Y );
00356       r_d = ( x2 - x1 )   * ( MAX_Y - MIN_Y );
00357       break;
00358     case XMin: // x = MIN_X boundary
00359       r_n = -( x1 - MIN_X ) * ( MAX_Y - MIN_Y );
00360       r_d = ( x2 - x1 )   * ( MAX_Y - MIN_Y );
00361       break;
00362     case YMax: // y = MAX_Y boundary
00363       r_n = ( y1 - MAX_Y ) * ( MAX_X - MIN_X );
00364       r_d = -( y2 - y1 )   * ( MAX_X - MIN_X );
00365       break;
00366     case YMin: // y = MIN_Y boundary
00367       r_n = ( y1 - MIN_Y ) * ( MAX_X - MIN_X );
00368       r_d = -( y2 - y1 )   * ( MAX_X - MIN_X );
00369       break;
00370   }
00371 
00372   QgsPoint p;
00373 
00374   if ( qAbs( r_d ) > SMALL_NUM && qAbs( r_n ) > SMALL_NUM )
00375   { // they cross
00376     double r = r_n / r_d;
00377     p.set( x1 + r*( x2 - x1 ), y1 + r*( y2 - y1 ) );
00378   }
00379   else
00380   {
00381     // Should never get here, but if we do for some reason, cause a
00382     // clunk because something else is wrong if we do.
00383     Q_ASSERT( qAbs( r_d ) > SMALL_NUM && qAbs( r_n ) > SMALL_NUM );
00384   }
00385 
00386   return p;
00387 }
00388 
00389 inline QPointF QgsClipper::intersectRect( const QPointF& pt1,
00390     const QPointF& pt2,
00391     Boundary b, const QgsRectangle& rect )
00392 {
00393   // This function assumes that the two given points (x1, y1), and
00394   // (x2, y2) cross the given boundary. Making this assumption allows
00395   // some optimisations.
00396 
00397   double r_n = SMALL_NUM, r_d = SMALL_NUM;
00398   const double x1 = pt1.x(), x2 = pt2.x();
00399   const double y1 = pt1.y(), y2 = pt2.y();
00400 
00401   switch ( b )
00402   {
00403     case XMax: // x = MAX_X boundary
00404       r_n = -( x1 - rect.xMaximum() ) * ( rect.yMaximum() - rect.yMinimum() );
00405       r_d = ( x2 - x1 )   * ( rect.yMaximum() - rect.yMinimum() );
00406       break;
00407     case XMin: // x = MIN_X boundary
00408       r_n = -( x1 - rect.xMinimum() ) * ( rect.yMaximum() - rect.yMinimum() );
00409       r_d = ( x2 - x1 )   * ( rect.yMaximum() - rect.yMinimum() );
00410       break;
00411     case YMax: // y = MAX_Y boundary
00412       r_n = ( y1 - rect.yMaximum() ) * ( rect.xMaximum() - rect.xMinimum() );
00413       r_d = -( y2 - y1 )   * ( rect.xMaximum() - rect.xMinimum() );
00414       break;
00415     case YMin: // y = MIN_Y boundary
00416       r_n = ( y1 - rect.yMinimum() ) * ( rect.xMaximum() - rect.xMinimum() );
00417       r_d = -( y2 - y1 )   * ( rect.xMaximum() - rect.xMinimum() );
00418       break;
00419   }
00420 
00421   double r = 0;
00422   if ( !qgsDoubleNear( r_d, 0.0 ) )
00423   {
00424     r = r_n / r_d;
00425   }
00426   return QPointF( x1 + r*( x2 - x1 ), y1 + r*( y2 - y1 ) );
00427 }
00428 
00429 inline void QgsClipper::clipStartTop( double& x0, double& y0, const double& x1, const double& y1, double yMax )
00430 {
00431   x0 += ( x1 - x0 )  * ( yMax - y0 ) / ( y1 - y0 );
00432   y0 = yMax;
00433 }
00434 
00435 inline void QgsClipper::clipStartBottom( double& x0, double& y0, const double& x1, const double& y1, double yMin )
00436 {
00437   x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
00438   y0 = yMin;
00439 }
00440 
00441 inline void QgsClipper::clipStartRight( double& x0, double& y0, const double& x1, const double& y1, double xMax )
00442 {
00443   y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
00444   x0 = xMax;
00445 }
00446 
00447 inline void QgsClipper::clipStartLeft( double& x0, double& y0, const double& x1, const double& y1, double xMin )
00448 {
00449   y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
00450   x0 = xMin;
00451 }
00452 
00453 inline void QgsClipper::clipEndTop( const double& x0, const double& y0, double& x1, double& y1, double yMax )
00454 {
00455   x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
00456   y1 = yMax;
00457 }
00458 
00459 inline void QgsClipper::clipEndBottom( const double& x0, const double& y0, double& x1, double& y1, double yMin )
00460 {
00461   x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
00462   y1 = yMin;
00463 }
00464 
00465 inline void QgsClipper::clipEndRight( const double& x0, const double& y0, double& x1, double& y1, double xMax )
00466 {
00467   y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
00468   x1 = xMax;
00469 }
00470 
00471 inline void QgsClipper::clipEndLeft( const double& x0, const double& y0, double& x1, double& y1, double xMin )
00472 {
00473   y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
00474   x1 = xMin;
00475 }
00476 
00477 //'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
00478 inline bool QgsClipper::clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double& x0, double& y0, double& x1, double& y1 )
00479 {
00480   int lineCode = 0;
00481 
00482   if ( y1 < yBottom )
00483     lineCode |= 4;
00484   else if ( y1 > yTop )
00485     lineCode |= 8;
00486 
00487   if ( x1 > xRight )
00488     lineCode |= 2;
00489   else if ( x1 < xLeft )
00490     lineCode |= 1;
00491 
00492   if ( y0 < yBottom )
00493     lineCode |= 64;
00494   else if ( y0 > yTop )
00495     lineCode |= 128;
00496 
00497   if ( x0 > xRight )
00498     lineCode |= 32;
00499   else if ( x0 < xLeft )
00500     lineCode |= 16;
00501 
00502   switch ( lineCode )
00503   {
00504     case 0: //completely inside
00505       return true;
00506 
00507     case 1:
00508       clipEndLeft( x0, y0, x1, y1, xLeft );
00509       return true;
00510 
00511     case 2:
00512       clipEndRight( x0, y0, x1, y1, xRight );
00513       return true;
00514 
00515     case 4:
00516       clipEndBottom( x0, y0, x1, y1, yBottom );
00517       return true;
00518 
00519     case 5:
00520       clipEndLeft( x0, y0, x1, y1, xLeft );
00521       if ( y1 < yBottom )
00522         clipEndBottom( x0, y0, x1, y1, yBottom );
00523       return true;
00524 
00525     case 6:
00526       clipEndRight( x0, y0, x1, y1, xRight );
00527       if ( y1 < yBottom )
00528         clipEndBottom( x0, y0, x1, y1, yBottom );
00529       return true;
00530 
00531     case 8:
00532       clipEndTop( x0, y0, x1, y1, yTop );
00533       return true;
00534 
00535     case 9:
00536       clipEndLeft( x0, y0, x1, y1, xLeft );
00537       if ( y1 > yTop )
00538         clipEndTop( x0, y0, x1, y1, yTop );
00539       return true;
00540 
00541     case 10:
00542       clipEndRight( x0, y0, x1, y1, xRight );
00543       if ( y1 > yTop )
00544         clipEndTop( x0, y0, x1, y1, yTop );
00545       return true;
00546 
00547     case 16:
00548       clipStartLeft( x0, y0, x1, y1, xLeft );
00549       return true;
00550 
00551     case 18:
00552       clipStartLeft( x0, y0, x1, y1, xLeft );
00553       clipEndRight( x0, y0, x1, y1, xRight );
00554       return true;
00555 
00556     case 20:
00557       clipStartLeft( x0, y0, x1, y1, xLeft );
00558       if ( y0 < yBottom )
00559         return false;
00560       clipEndBottom( x0, y0, x1, y1, yBottom );
00561       return true;
00562 
00563     case 22:
00564       clipStartLeft( x0, y0, x1, y1, xLeft );
00565       if ( y0 < yBottom )
00566         return false;
00567       clipEndBottom( x0, y0, x1, y1, yBottom );
00568       if ( x1 > xRight )
00569         clipEndRight( x0, y0, x1, y1, xRight );
00570       return true;
00571 
00572     case 24:
00573       clipStartLeft( x0, y0, x1, y1, xLeft );
00574       if ( y0 > yTop )
00575         return false;
00576       clipEndTop( x0, y0, x1, y1, yTop );
00577       return true;
00578 
00579     case 26:
00580       clipStartLeft( x0, y0, x1, y1, xLeft );
00581       if ( y0 > yTop )
00582         return false;
00583       clipEndTop( x0, y0, x1, y1, yTop );
00584       if ( x1 > xRight )
00585         clipEndRight( x0, y0, x1, y1, xRight );
00586       return true;
00587 
00588     case 32:
00589       clipStartRight( x0, y0, x1, y1, xRight );
00590       return true;
00591 
00592     case 33:
00593       clipStartRight( x0, y0, x1, y1, xRight );
00594       clipEndLeft( x0, y0, x1, y1, xLeft );
00595       return true;
00596 
00597     case 36:
00598       clipStartRight( x0, y0, x1, y1, xRight );
00599       if ( y0 < yBottom )
00600         return false;
00601       clipEndBottom( x0, y0, x1, y1, yBottom );
00602       return true;
00603 
00604     case 37:
00605       clipStartRight( x0, y0, x1, y1, xRight );
00606       if ( y0 < yBottom )
00607         return false;
00608       clipEndBottom( x0, y0, x1, y1, yBottom );
00609       if ( x1 < xLeft )
00610         clipEndLeft( x0, y0, x1, y1, xLeft );
00611       return true;
00612 
00613     case 40:
00614       clipStartRight( x0, y0, x1, y1, xRight );
00615       if ( y0 > yTop )
00616         return false;
00617       clipEndTop( x0, y0, x1, y1, yTop );
00618       return true;
00619 
00620     case 41:
00621       clipStartRight( x0, y0, x1, y1, xRight );
00622       if ( y0 > yTop )
00623         return false;
00624       clipEndTop( x0, y0, x1, y1, yTop );
00625       if ( x1 < xLeft )
00626         clipEndLeft( x0, y0, x1, y1, xLeft );
00627       return true;
00628 
00629     case 64:
00630       clipStartBottom( x0, y0, x1, y1, yBottom );
00631       return true;
00632 
00633     case 65:
00634       clipStartBottom( x0, y0, x1, y1, yBottom );
00635       if ( x0 < xLeft )
00636         return false;
00637       clipEndLeft( x0, y0, x1, y1, xLeft );
00638       if ( y1 < yBottom )
00639         clipEndBottom( x0, y0, x1, y1, yBottom );
00640       return true;
00641 
00642     case 66:
00643       clipStartBottom( x0, y0, x1, y1, yBottom );
00644       if ( x0 > xRight )
00645         return false;
00646       clipEndRight( x0, y0, x1, y1, xRight );
00647       return true;
00648 
00649     case 72:
00650       clipStartBottom( x0, y0, x1, y1, yBottom );
00651       clipEndTop( x0, y0, x1, y1, yTop );
00652       return true;
00653 
00654     case 73:
00655       clipStartBottom( x0, y0, x1, y1, yBottom );
00656       if ( x0 < xLeft )
00657         return false;
00658       clipEndLeft( x0, y0, x1, y1, xLeft );
00659       if ( y1 > yTop )
00660         clipEndTop( x0, y0, x1, y1, yTop );
00661       return true;
00662 
00663     case 74:
00664       clipStartBottom( x0, y0, x1, y1, yBottom );
00665       if ( x0 > xRight )
00666         return false;
00667       clipEndRight( x0, y0, x1, y1, xRight );
00668       if ( y1 > yTop )
00669         clipEndTop( x0, y0, x1, y1, yTop );
00670       return true;
00671 
00672     case 80:
00673       clipStartLeft( x0, y0, x1, y1, xLeft );
00674       if ( y0 < yBottom )
00675         clipStartBottom( x0, y0, x1, y1, yBottom );
00676       return true;
00677 
00678     case 82:
00679       clipEndRight( x0, y0, x1, y1, xRight );
00680       if ( y1 < yBottom )
00681         return false;
00682       clipStartBottom( x0, y0, x1, y1, yBottom );
00683       if ( x0 < xLeft )
00684         clipStartLeft( x0, y0, x1, y1, xLeft );
00685       return true;
00686 
00687     case 88:
00688       clipEndTop( x0, y0, x1, y1, yTop );
00689       if ( x1 < xLeft )
00690         return false;
00691       clipStartBottom( x0, y0, x1, y1, yBottom );
00692       if ( x0 < xLeft )
00693         clipStartLeft( x0, y0, x1, y1, xLeft );
00694       return true;
00695 
00696     case 90:
00697       clipStartLeft( x0, y0, x1, y1, xLeft );
00698       if ( y0 > yTop )
00699         return false;
00700       clipEndRight( x0, y0, x1, y1, xRight );
00701       if ( y1 < yBottom )
00702         return false;
00703       if ( y0 < yBottom )
00704         clipStartBottom( x0, y0, x1, y1, yBottom );
00705       if ( y1 > yTop )
00706         clipEndTop( x0, y0, x1, y1, yTop );
00707       return true;
00708 
00709     case 96:
00710       clipStartRight( x0, y0, x1, y1, xRight );
00711       if ( y0 < yBottom )
00712         clipStartBottom( x0, y0, x1, y1, yBottom );
00713       return true;
00714 
00715     case 97:
00716       clipEndLeft( x0, y0, x1, y1, xLeft );
00717       if ( y1 < yBottom )
00718         return false;
00719       clipStartBottom( x0, y0, x1, y1, yBottom );
00720       if ( x0 > xRight )
00721         clipStartRight( x0, y0, x1, y1, xRight );
00722       return true;
00723 
00724     case 104:
00725       clipEndTop( x0, y0, x1, y1, yTop );
00726       if ( x1 > xRight )
00727         return false;
00728       clipStartRight( x0, y0, x1, y1, xRight );
00729       if ( y0 < yBottom )
00730         clipStartBottom( x0, y0, x1, y1, yBottom );
00731       return true;
00732 
00733     case 105:
00734       clipEndLeft( x0, y0, x1, y1, xLeft );
00735       if ( y1 < yBottom )
00736         return false;
00737       clipStartRight( x0, y0, x1, y1, xRight );
00738       if ( y0 > yTop )
00739         return false;
00740       if ( y1 > yTop )
00741         clipEndTop( x0, y0, x1, y1, yTop );
00742       if ( y0 < yBottom )
00743         clipStartBottom( x0, y0, x1, y1, yBottom );
00744       return true;
00745 
00746     case 128:
00747       clipStartTop( x0, y0, x1, y1, yTop );
00748       return true;
00749 
00750     case 129:
00751       clipStartTop( x0, y0, x1, y1, yTop );
00752       if ( x0 < xLeft )
00753         return false;
00754       clipEndLeft( x0, y0, x1, y1, xLeft );
00755       return true;
00756 
00757     case 130:
00758       clipStartTop( x0, y0, x1, y1, yTop );
00759       if ( x0 > xRight )
00760         return false;
00761       clipEndRight( x0, y0, x1, y1, xRight );
00762       return true;
00763 
00764     case 132:
00765       clipStartTop( x0, y0, x1, y1, yTop );
00766       clipEndBottom( x0, y0, x1, y1, yBottom );
00767       return true;
00768 
00769     case 133:
00770       clipStartTop( x0, y0, x1, y1, yTop );
00771       if ( x0 < xLeft )
00772         return false;
00773       clipEndLeft( x0, y0, x1, y1, xLeft );
00774       if ( y1 < yBottom )
00775         clipEndBottom( x0, y0, x1, y1, yBottom );
00776       return true;
00777 
00778     case 134:
00779       clipStartTop( x0, y0, x1, y1, yTop );
00780       if ( x0 > xRight )
00781         return false;
00782       clipEndRight( x0, y0, x1, y1, xRight );
00783       if ( y1 < yBottom )
00784         clipEndBottom( x0, y0, x1, y1, yBottom );
00785       return true;
00786 
00787     case 144:
00788       clipStartLeft( x0, y0, x1, y1, xLeft );
00789       if ( y0 > yTop )
00790         clipStartTop( x0, y0, x1, y1, yTop );
00791       return true;
00792 
00793     case 146:
00794       clipEndRight( x0, y0, x1, y1, xRight );
00795       if ( y1 > yTop )
00796         return false;
00797       clipStartTop( x0, y0, x1, y1, yTop );
00798       if ( x0 < xLeft )
00799         clipStartLeft( x0, y0, x1, y1, xLeft );
00800       return true;
00801 
00802     case 148:
00803       clipEndBottom( x0, y0, x1, y1, yBottom );
00804       if ( x1 < xLeft )
00805         return false;
00806       clipStartLeft( x0, y0, x1, y1, xLeft );
00807       if ( y0 > yTop )
00808         clipStartTop( x0, y0, x1, y1, yTop );
00809       return true;
00810 
00811     case 150:
00812       clipStartLeft( x0, y0, x1, y1, xLeft );
00813       if ( y0 < yBottom )
00814         return false;
00815       clipEndRight( x0, y0, x1, y1, xRight );
00816       if ( y1 > yTop )
00817         return false;
00818       if ( y0 > yTop )
00819         clipStartTop( x0, y0, x1, y1, yTop );
00820       if ( y1 < yBottom )
00821         clipEndBottom( x0, y0, x1, y1, yBottom );
00822       return true;
00823 
00824     case 160:
00825       clipStartRight( x0, y0, x1, y1, xRight );
00826       if ( y0 > yTop )
00827         clipStartTop( x0, y0, x1, y1, yTop );
00828       return true;
00829 
00830     case 161:
00831       clipEndLeft( x0, y0, x1, y1, xLeft );
00832       if ( y1 > yTop )
00833         return false;
00834       clipStartTop( x0, y0, x1, y1, yTop );
00835       if ( x0 > xRight )
00836         clipStartRight( x0, y0, x1, y1, xRight );
00837       return true;
00838 
00839     case 164:
00840       clipEndBottom( x0, y0, x1, y1, yBottom );
00841       if ( x1 > xRight )
00842         return false;
00843       clipStartRight( x0, y0, x1, y1, xRight );
00844       if ( y0 > yTop )
00845         clipStartTop( x0, y0, x1, y1, yTop );
00846       return true;
00847 
00848     case 165:
00849       clipEndLeft( x0, y0, x1, y1, xLeft );
00850       if ( y1 > yTop )
00851         return false;
00852       clipStartRight( x0, y0, x1, y1, xRight );
00853       if ( y0 < yBottom )
00854         return false;
00855       if ( y1 < yBottom )
00856         clipEndBottom( x0, y0, x1, y1, yBottom );
00857       if ( y0 > yTop )
00858         clipStartTop( x0, y0, x1, y1, yTop );
00859       return true;
00860   }
00861 
00862   return false;
00863 
00864 }
00865 
00866 
00867 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines