QGIS API Documentation  2.99.0-Master (5753576)
qgsclipper.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsclipper.h - a class that clips line
3  segments and polygons
4  -------------------
5  begin : March 2004
6  copyright : (C) 2005 by Gavin Macaulay
7  email :
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #ifndef QGSCLIPPER_H
20 #define QGSCLIPPER_H
21 
22 #include "qgis_core.h"
23 #include "qgis.h"
24 #include "qgspoint.h"
25 #include "qgsrectangle.h"
26 
27 #include <QVector>
28 #include <QPolygonF>
29 
30 class QgsCurve;
31 
42 class CORE_EXPORT QgsClipper
43 {
44  public:
45 
46  // Coordinates of the rectangular box that we trim to.
47  //
48  // These are the limits for X11 screen coordinates. The actual
49  // values are +/-32767, but we allow a little bit of space for
50  // rounding errors.
51 
52  // You may wonder why the clipping is done to these coordindates
53  // rather than the boundaries of the qgis canvas. Reasons include:
54  // - making the boundaries static const allows the compiler to
55  // optimise the code that uses these values more than if they changed
56  // for every call to the trim code.
57  // - clipping takes quite a bit of CPU effort, and the less that this is
58  // done the better. More stuff would have to be clipped if the
59  // boundaries were the qgis canvas (but this may be offset by
60  // having less to draw).
61  //
62  // The limit is set to 30,000 instead of 32768 because that things
63  // still go wrong.
64 
65  static const double MAX_X;
66  static const double MIN_X;
67  static const double MAX_Y;
68  static const double MIN_Y;
69 
70 
72  enum Boundary {XMax, XMin, YMax, YMin};
73 
82  static void trimFeature( QVector<double>& x,
83  QVector<double>& y,
84  bool shapeOpen );
85 
86  static void trimPolygon( QPolygonF& pts, const QgsRectangle& clipRect );
87 
93  static QPolygonF clippedLine( const QgsCurve& curve, const QgsRectangle& clipExtent );
94 
95  private:
96 
97  // Used when testing for equivalance to 0.0
98  static const double SMALL_NUM;
99 
100  // Trims the given feature to the given boundary. Returns the
101  // trimmed feature in the outX and outY vectors.
102  static void trimFeatureToBoundary( const QVector<double>& inX,
103  const QVector<double>& inY,
104  QVector<double>& outX,
105  QVector<double>& outY,
106  Boundary b,
107  bool shapeOpen );
108 
109  static void trimPolygonToBoundary( const QPolygonF& inPts, QPolygonF& outPts, const QgsRectangle& rect, Boundary b, double boundaryValue );
110 
111  // Determines if a point is inside or outside the given boundary
112  static bool inside( const double x, const double y, Boundary b );
113 
114  static bool inside( QPointF pt, Boundary b, double val );
115 
116  // Calculates the intersection point between a line defined by a
117  // (x1, y1), and (x2, y2) and the given boundary
118  static QgsPoint intersect( const double x1, const double y1,
119  const double x2, const double y2,
120  Boundary b );
121 
122  static QPointF intersectRect( QPointF pt1,
123  QPointF pt2,
124  Boundary b, const QgsRectangle& rect );
125 
126  //Implementation of 'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
127  static bool clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double& x0, double& y0, double& x1, double& y1 );
128 
137  static void connectSeparatedLines( double x0, double y0, double x1, double y1,
138  const QgsRectangle& clipRect, QPolygonF& pts );
139 
140  //low level clip methods for fast clip algorithm
141  static void clipStartTop( double& x0, double& y0, double x1, double y1, double yMax );
142  static void clipStartBottom( double& x0, double& y0, double x1, double y1, double yMin );
143  static void clipStartRight( double& x0, double& y0, double x1, double y1, double xMax );
144  static void clipStartLeft( double& x0, double& y0, double& x1, double& y1, double xMin );
145  static void clipEndTop( double x0, double y0, double& x1, double& y1, double yMax );
146  static void clipEndBottom( double x0, double y0, double& x1, double& y1, double yMin );
147  static void clipEndRight( double x0, double y0, double& x1, double& y1, double xMax );
148  static void clipEndLeft( double x0, double y0, double& x1, double& y1, double xMin );
149 };
150 
151 // The inline functions
152 
153 // Trim the feature using Sutherland and Hodgman's
154 // polygon-clipping algorithm. See J. D. Foley, A. van Dam,
155 // S. K. Feiner, and J. F. Hughes, Computer Graphics, Principles and
156 // Practice. Addison-Wesley Systems Programming Series,
157 // Addison-Wesley, 2nd ed., 1991.
158 
159 // I understand that this is not the most efficient algorithm, but is
160 // one (the only?) that is guaranteed to always give the correct
161 // result.
162 
163 inline void QgsClipper::trimFeature( QVector<double>& x,
164  QVector<double>& y,
165  bool shapeOpen )
166 {
167  QVector<double> tmpX;
168  QVector<double> tmpY;
169  trimFeatureToBoundary( x, y, tmpX, tmpY, XMax, shapeOpen );
170 
171  x.clear();
172  y.clear();
173  trimFeatureToBoundary( tmpX, tmpY, x, y, YMax, shapeOpen );
174 
175  tmpX.clear();
176  tmpY.clear();
177  trimFeatureToBoundary( x, y, tmpX, tmpY, XMin, shapeOpen );
178 
179  x.clear();
180  y.clear();
181  trimFeatureToBoundary( tmpX, tmpY, x, y, YMin, shapeOpen );
182 }
183 
184 inline void QgsClipper::trimPolygon( QPolygonF& pts, const QgsRectangle& clipRect )
185 {
186  QPolygonF tmpPts;
187  tmpPts.reserve( pts.size() );
188 
189  trimPolygonToBoundary( pts, tmpPts, clipRect, XMax, clipRect.xMaximum() );
190  pts.resize( 0 );
191  trimPolygonToBoundary( tmpPts, pts, clipRect, YMax, clipRect.yMaximum() );
192  tmpPts.resize( 0 );
193  trimPolygonToBoundary( pts, tmpPts, clipRect, XMin, clipRect.xMinimum() );
194  pts.resize( 0 );
195  trimPolygonToBoundary( tmpPts, pts, clipRect, YMin, clipRect.yMinimum() );
196 }
197 
198 // An auxiliary function that is part of the polygon trimming
199 // code. Will trim the given polygon to the given boundary and return
200 // the trimmed polygon in the out pointer. Uses Sutherland and
201 // Hodgman's polygon-clipping algorithm.
202 
203 inline void QgsClipper::trimFeatureToBoundary(
204  const QVector<double>& inX,
205  const QVector<double>& inY,
206  QVector<double>& outX,
207  QVector<double>& outY,
208  Boundary b, bool shapeOpen )
209 {
210  // The shapeOpen parameter selects whether this function treats the
211  // shape as open or closed. False is appropriate for polygons and
212  // true for polylines.
213 
214  int i1 = inX.size() - 1; // start with last point
215 
216  // and compare to the first point initially.
217  for ( int i2 = 0; i2 < inX.size() ; ++i2 )
218  {
219  // look at each edge of the polygon in turn
220 
221  //ignore segments with nan or inf coordinates
222  if ( qIsNaN( inX[i2] ) || qIsNaN( inY[i2] ) || qIsInf( inX[i2] ) || qIsInf( inY[i2] )
223  || qIsNaN( inX[i1] ) || qIsNaN( inY[i1] ) || qIsInf( inX[i1] ) || qIsInf( inY[i1] ) )
224  {
225  i1 = i2;
226  continue;
227  }
228 
229 
230  if ( inside( inX[i2], inY[i2], b ) ) // end point of edge is inside boundary
231  {
232  if ( inside( inX[i1], inY[i1], b ) )
233  {
234  outX.push_back( inX[i2] );
235  outY.push_back( inY[i2] );
236  }
237  else
238  {
239  // edge crosses into the boundary, so trim back to the boundary, and
240  // store both ends of the new edge
241  if ( !( i2 == 0 && shapeOpen ) )
242  {
243  QgsPoint p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
244  outX.push_back( p.x() );
245  outY.push_back( p.y() );
246  }
247 
248  outX.push_back( inX[i2] );
249  outY.push_back( inY[i2] );
250  }
251  }
252  else // end point of edge is outside boundary
253  {
254  // start point is in boundary, so need to trim back
255  if ( inside( inX[i1], inY[i1], b ) )
256  {
257  if ( !( i2 == 0 && shapeOpen ) )
258  {
259  QgsPoint p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
260  outX.push_back( p.x() );
261  outY.push_back( p.y() );
262  }
263  }
264  }
265  i1 = i2;
266  }
267 }
268 
269 inline void QgsClipper::trimPolygonToBoundary( const QPolygonF& inPts, QPolygonF& outPts, const QgsRectangle& rect, Boundary b, double boundaryValue )
270 {
271  int i1 = inPts.size() - 1; // start with last point
272 
273  // and compare to the first point initially.
274  for ( int i2 = 0; i2 < inPts.size() ; ++i2 )
275  { // look at each edge of the polygon in turn
276  if ( inside( inPts[i2], b, boundaryValue ) ) // end point of edge is inside boundary
277  {
278  if ( inside( inPts[i1], b, boundaryValue ) )
279  {
280  outPts.append( inPts[i2] );
281  }
282  else
283  {
284  // edge crosses into the boundary, so trim back to the boundary, and
285  // store both ends of the new edge
286  outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
287  outPts.append( inPts[i2] );
288  }
289  }
290  else // end point of edge is outside boundary
291  {
292  // start point is in boundary, so need to trim back
293  if ( inside( inPts[i1], b, boundaryValue ) )
294  {
295  outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
296  }
297  }
298  i1 = i2;
299  }
300 }
301 
302 // An auxiliary function to trimPolygonToBoundarY() that returns
303 // whether a point is inside or outside the given boundary.
304 
305 inline bool QgsClipper::inside( const double x, const double y, Boundary b )
306 {
307  switch ( b )
308  {
309  case XMax: // x < MAX_X is inside
310  if ( x < MAX_X )
311  return true;
312  break;
313  case XMin: // x > MIN_X is inside
314  if ( x > MIN_X )
315  return true;
316  break;
317  case YMax: // y < MAX_Y is inside
318  if ( y < MAX_Y )
319  return true;
320  break;
321  case YMin: // y > MIN_Y is inside
322  if ( y > MIN_Y )
323  return true;
324  break;
325  }
326  return false;
327 }
328 
329 inline bool QgsClipper::inside( QPointF pt, Boundary b, double val )
330 {
331  switch ( b )
332  {
333  case XMax: // x < MAX_X is inside
334  return ( pt.x() < val );
335  case XMin: // x > MIN_X is inside
336  return ( pt.x() > val );
337  case YMax: // y < MAX_Y is inside
338  return ( pt.y() < val );
339  case YMin: // y > MIN_Y is inside
340  return ( pt.y() > val );
341  }
342  return false;
343 }
344 
345 
346 // An auxiliary function to trimPolygonToBoundarY() that calculates and
347 // returns the intersection of the line defined by the given points
348 // and the given boundary.
349 
350 inline QgsPoint QgsClipper::intersect( const double x1, const double y1,
351  const double x2, const double y2,
352  Boundary b )
353 {
354  // This function assumes that the two given points (x1, y1), and
355  // (x2, y2) cross the given boundary. Making this assumption allows
356  // some optimisations.
357 
358  double r_n = SMALL_NUM, r_d = SMALL_NUM;
359 
360  switch ( b )
361  {
362  case XMax: // x = MAX_X boundary
363  r_n = -( x1 - MAX_X ) * ( MAX_Y - MIN_Y );
364  r_d = ( x2 - x1 ) * ( MAX_Y - MIN_Y );
365  break;
366  case XMin: // x = MIN_X boundary
367  r_n = -( x1 - MIN_X ) * ( MAX_Y - MIN_Y );
368  r_d = ( x2 - x1 ) * ( MAX_Y - MIN_Y );
369  break;
370  case YMax: // y = MAX_Y boundary
371  r_n = ( y1 - MAX_Y ) * ( MAX_X - MIN_X );
372  r_d = -( y2 - y1 ) * ( MAX_X - MIN_X );
373  break;
374  case YMin: // y = MIN_Y boundary
375  r_n = ( y1 - MIN_Y ) * ( MAX_X - MIN_X );
376  r_d = -( y2 - y1 ) * ( MAX_X - MIN_X );
377  break;
378  }
379 
380  QgsPoint p;
381 
382  if ( qAbs( r_d ) > SMALL_NUM && qAbs( r_n ) > SMALL_NUM )
383  { // they cross
384  double r = r_n / r_d;
385  p.set( x1 + r*( x2 - x1 ), y1 + r*( y2 - y1 ) );
386  }
387  else
388  {
389  // Should never get here, but if we do for some reason, cause a
390  // clunk because something else is wrong if we do.
391  Q_ASSERT( qAbs( r_d ) > SMALL_NUM && qAbs( r_n ) > SMALL_NUM );
392  }
393 
394  return p;
395 }
396 
397 inline QPointF QgsClipper::intersectRect( QPointF pt1,
398  QPointF pt2,
399  Boundary b, const QgsRectangle& rect )
400 {
401  // This function assumes that the two given points (x1, y1), and
402  // (x2, y2) cross the given boundary. Making this assumption allows
403  // some optimisations.
404 
405  double r_n = SMALL_NUM, r_d = SMALL_NUM;
406  const double x1 = pt1.x(), x2 = pt2.x();
407  const double y1 = pt1.y(), y2 = pt2.y();
408 
409  switch ( b )
410  {
411  case XMax: // x = MAX_X boundary
412  r_n = -( x1 - rect.xMaximum() ) * ( rect.yMaximum() - rect.yMinimum() );
413  r_d = ( x2 - x1 ) * ( rect.yMaximum() - rect.yMinimum() );
414  break;
415  case XMin: // x = MIN_X boundary
416  r_n = -( x1 - rect.xMinimum() ) * ( rect.yMaximum() - rect.yMinimum() );
417  r_d = ( x2 - x1 ) * ( rect.yMaximum() - rect.yMinimum() );
418  break;
419  case YMax: // y = MAX_Y boundary
420  r_n = ( y1 - rect.yMaximum() ) * ( rect.xMaximum() - rect.xMinimum() );
421  r_d = -( y2 - y1 ) * ( rect.xMaximum() - rect.xMinimum() );
422  break;
423  case YMin: // y = MIN_Y boundary
424  r_n = ( y1 - rect.yMinimum() ) * ( rect.xMaximum() - rect.xMinimum() );
425  r_d = -( y2 - y1 ) * ( rect.xMaximum() - rect.xMinimum() );
426  break;
427  }
428 
429  double r = 0;
430  if ( !qgsDoubleNear( r_d, 0.0 ) )
431  {
432  r = r_n / r_d;
433  }
434  return QPointF( x1 + r*( x2 - x1 ), y1 + r*( y2 - y1 ) );
435 }
436 
437 inline void QgsClipper::clipStartTop( double& x0, double& y0, double x1, double y1, double yMax )
438 {
439  x0 += ( x1 - x0 ) * ( yMax - y0 ) / ( y1 - y0 );
440  y0 = yMax;
441 }
442 
443 inline void QgsClipper::clipStartBottom( double& x0, double& y0, double x1, double y1, double yMin )
444 {
445  x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
446  y0 = yMin;
447 }
448 
449 inline void QgsClipper::clipStartRight( double& x0, double& y0, double x1, double y1, double xMax )
450 {
451  y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
452  x0 = xMax;
453 }
454 
455 inline void QgsClipper::clipStartLeft( double& x0, double& y0, double& x1, double& y1, double xMin )
456 {
457  y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
458  x0 = xMin;
459 }
460 
461 inline void QgsClipper::clipEndTop( double x0, double y0, double& x1, double& y1, double yMax )
462 {
463  x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
464  y1 = yMax;
465 }
466 
467 inline void QgsClipper::clipEndBottom( double x0, double y0, double& x1, double& y1, double yMin )
468 {
469  x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
470  y1 = yMin;
471 }
472 
473 inline void QgsClipper::clipEndRight( double x0, double y0, double& x1, double& y1, double xMax )
474 {
475  y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
476  x1 = xMax;
477 }
478 
479 inline void QgsClipper::clipEndLeft( double x0, double y0, double& x1, double& y1, double xMin )
480 {
481  y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
482  x1 = xMin;
483 }
484 
485 //'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
486 inline bool QgsClipper::clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double& x0, double& y0, double& x1, double& y1 )
487 {
488  int lineCode = 0;
489 
490  if ( y1 < yBottom )
491  lineCode |= 4;
492  else if ( y1 > yTop )
493  lineCode |= 8;
494 
495  if ( x1 > xRight )
496  lineCode |= 2;
497  else if ( x1 < xLeft )
498  lineCode |= 1;
499 
500  if ( y0 < yBottom )
501  lineCode |= 64;
502  else if ( y0 > yTop )
503  lineCode |= 128;
504 
505  if ( x0 > xRight )
506  lineCode |= 32;
507  else if ( x0 < xLeft )
508  lineCode |= 16;
509 
510  switch ( lineCode )
511  {
512  case 0: //completely inside
513  return true;
514 
515  case 1:
516  clipEndLeft( x0, y0, x1, y1, xLeft );
517  return true;
518 
519  case 2:
520  clipEndRight( x0, y0, x1, y1, xRight );
521  return true;
522 
523  case 4:
524  clipEndBottom( x0, y0, x1, y1, yBottom );
525  return true;
526 
527  case 5:
528  clipEndLeft( x0, y0, x1, y1, xLeft );
529  if ( y1 < yBottom )
530  clipEndBottom( x0, y0, x1, y1, yBottom );
531  return true;
532 
533  case 6:
534  clipEndRight( x0, y0, x1, y1, xRight );
535  if ( y1 < yBottom )
536  clipEndBottom( x0, y0, x1, y1, yBottom );
537  return true;
538 
539  case 8:
540  clipEndTop( x0, y0, x1, y1, yTop );
541  return true;
542 
543  case 9:
544  clipEndLeft( x0, y0, x1, y1, xLeft );
545  if ( y1 > yTop )
546  clipEndTop( x0, y0, x1, y1, yTop );
547  return true;
548 
549  case 10:
550  clipEndRight( x0, y0, x1, y1, xRight );
551  if ( y1 > yTop )
552  clipEndTop( x0, y0, x1, y1, yTop );
553  return true;
554 
555  case 16:
556  clipStartLeft( x0, y0, x1, y1, xLeft );
557  return true;
558 
559  case 18:
560  clipStartLeft( x0, y0, x1, y1, xLeft );
561  clipEndRight( x0, y0, x1, y1, xRight );
562  return true;
563 
564  case 20:
565  clipStartLeft( x0, y0, x1, y1, xLeft );
566  if ( y0 < yBottom )
567  return false;
568  clipEndBottom( x0, y0, x1, y1, yBottom );
569  return true;
570 
571  case 22:
572  clipStartLeft( x0, y0, x1, y1, xLeft );
573  if ( y0 < yBottom )
574  return false;
575  clipEndBottom( x0, y0, x1, y1, yBottom );
576  if ( x1 > xRight )
577  clipEndRight( x0, y0, x1, y1, xRight );
578  return true;
579 
580  case 24:
581  clipStartLeft( x0, y0, x1, y1, xLeft );
582  if ( y0 > yTop )
583  return false;
584  clipEndTop( x0, y0, x1, y1, yTop );
585  return true;
586 
587  case 26:
588  clipStartLeft( x0, y0, x1, y1, xLeft );
589  if ( y0 > yTop )
590  return false;
591  clipEndTop( x0, y0, x1, y1, yTop );
592  if ( x1 > xRight )
593  clipEndRight( x0, y0, x1, y1, xRight );
594  return true;
595 
596  case 32:
597  clipStartRight( x0, y0, x1, y1, xRight );
598  return true;
599 
600  case 33:
601  clipStartRight( x0, y0, x1, y1, xRight );
602  clipEndLeft( x0, y0, x1, y1, xLeft );
603  return true;
604 
605  case 36:
606  clipStartRight( x0, y0, x1, y1, xRight );
607  if ( y0 < yBottom )
608  return false;
609  clipEndBottom( x0, y0, x1, y1, yBottom );
610  return true;
611 
612  case 37:
613  clipStartRight( x0, y0, x1, y1, xRight );
614  if ( y0 < yBottom )
615  return false;
616  clipEndBottom( x0, y0, x1, y1, yBottom );
617  if ( x1 < xLeft )
618  clipEndLeft( x0, y0, x1, y1, xLeft );
619  return true;
620 
621  case 40:
622  clipStartRight( x0, y0, x1, y1, xRight );
623  if ( y0 > yTop )
624  return false;
625  clipEndTop( x0, y0, x1, y1, yTop );
626  return true;
627 
628  case 41:
629  clipStartRight( x0, y0, x1, y1, xRight );
630  if ( y0 > yTop )
631  return false;
632  clipEndTop( x0, y0, x1, y1, yTop );
633  if ( x1 < xLeft )
634  clipEndLeft( x0, y0, x1, y1, xLeft );
635  return true;
636 
637  case 64:
638  clipStartBottom( x0, y0, x1, y1, yBottom );
639  return true;
640 
641  case 65:
642  clipStartBottom( x0, y0, x1, y1, yBottom );
643  if ( x0 < xLeft )
644  return false;
645  clipEndLeft( x0, y0, x1, y1, xLeft );
646  if ( y1 < yBottom )
647  clipEndBottom( x0, y0, x1, y1, yBottom );
648  return true;
649 
650  case 66:
651  clipStartBottom( x0, y0, x1, y1, yBottom );
652  if ( x0 > xRight )
653  return false;
654  clipEndRight( x0, y0, x1, y1, xRight );
655  return true;
656 
657  case 72:
658  clipStartBottom( x0, y0, x1, y1, yBottom );
659  clipEndTop( x0, y0, x1, y1, yTop );
660  return true;
661 
662  case 73:
663  clipStartBottom( x0, y0, x1, y1, yBottom );
664  if ( x0 < xLeft )
665  return false;
666  clipEndLeft( x0, y0, x1, y1, xLeft );
667  if ( y1 > yTop )
668  clipEndTop( x0, y0, x1, y1, yTop );
669  return true;
670 
671  case 74:
672  clipStartBottom( x0, y0, x1, y1, yBottom );
673  if ( x0 > xRight )
674  return false;
675  clipEndRight( x0, y0, x1, y1, xRight );
676  if ( y1 > yTop )
677  clipEndTop( x0, y0, x1, y1, yTop );
678  return true;
679 
680  case 80:
681  clipStartLeft( x0, y0, x1, y1, xLeft );
682  if ( y0 < yBottom )
683  clipStartBottom( x0, y0, x1, y1, yBottom );
684  return true;
685 
686  case 82:
687  clipEndRight( x0, y0, x1, y1, xRight );
688  if ( y1 < yBottom )
689  return false;
690  clipStartBottom( x0, y0, x1, y1, yBottom );
691  if ( x0 < xLeft )
692  clipStartLeft( x0, y0, x1, y1, xLeft );
693  return true;
694 
695  case 88:
696  clipEndTop( x0, y0, x1, y1, yTop );
697  if ( x1 < xLeft )
698  return false;
699  clipStartBottom( x0, y0, x1, y1, yBottom );
700  if ( x0 < xLeft )
701  clipStartLeft( x0, y0, x1, y1, xLeft );
702  return true;
703 
704  case 90:
705  clipStartLeft( x0, y0, x1, y1, xLeft );
706  if ( y0 > yTop )
707  return false;
708  clipEndRight( x0, y0, x1, y1, xRight );
709  if ( y1 < yBottom )
710  return false;
711  if ( y0 < yBottom )
712  clipStartBottom( x0, y0, x1, y1, yBottom );
713  if ( y1 > yTop )
714  clipEndTop( x0, y0, x1, y1, yTop );
715  return true;
716 
717  case 96:
718  clipStartRight( x0, y0, x1, y1, xRight );
719  if ( y0 < yBottom )
720  clipStartBottom( x0, y0, x1, y1, yBottom );
721  return true;
722 
723  case 97:
724  clipEndLeft( x0, y0, x1, y1, xLeft );
725  if ( y1 < yBottom )
726  return false;
727  clipStartBottom( x0, y0, x1, y1, yBottom );
728  if ( x0 > xRight )
729  clipStartRight( x0, y0, x1, y1, xRight );
730  return true;
731 
732  case 104:
733  clipEndTop( x0, y0, x1, y1, yTop );
734  if ( x1 > xRight )
735  return false;
736  clipStartRight( x0, y0, x1, y1, xRight );
737  if ( y0 < yBottom )
738  clipStartBottom( x0, y0, x1, y1, yBottom );
739  return true;
740 
741  case 105:
742  clipEndLeft( x0, y0, x1, y1, xLeft );
743  if ( y1 < yBottom )
744  return false;
745  clipStartRight( x0, y0, x1, y1, xRight );
746  if ( y0 > yTop )
747  return false;
748  if ( y1 > yTop )
749  clipEndTop( x0, y0, x1, y1, yTop );
750  if ( y0 < yBottom )
751  clipStartBottom( x0, y0, x1, y1, yBottom );
752  return true;
753 
754  case 128:
755  clipStartTop( x0, y0, x1, y1, yTop );
756  return true;
757 
758  case 129:
759  clipStartTop( x0, y0, x1, y1, yTop );
760  if ( x0 < xLeft )
761  return false;
762  clipEndLeft( x0, y0, x1, y1, xLeft );
763  return true;
764 
765  case 130:
766  clipStartTop( x0, y0, x1, y1, yTop );
767  if ( x0 > xRight )
768  return false;
769  clipEndRight( x0, y0, x1, y1, xRight );
770  return true;
771 
772  case 132:
773  clipStartTop( x0, y0, x1, y1, yTop );
774  clipEndBottom( x0, y0, x1, y1, yBottom );
775  return true;
776 
777  case 133:
778  clipStartTop( x0, y0, x1, y1, yTop );
779  if ( x0 < xLeft )
780  return false;
781  clipEndLeft( x0, y0, x1, y1, xLeft );
782  if ( y1 < yBottom )
783  clipEndBottom( x0, y0, x1, y1, yBottom );
784  return true;
785 
786  case 134:
787  clipStartTop( x0, y0, x1, y1, yTop );
788  if ( x0 > xRight )
789  return false;
790  clipEndRight( x0, y0, x1, y1, xRight );
791  if ( y1 < yBottom )
792  clipEndBottom( x0, y0, x1, y1, yBottom );
793  return true;
794 
795  case 144:
796  clipStartLeft( x0, y0, x1, y1, xLeft );
797  if ( y0 > yTop )
798  clipStartTop( x0, y0, x1, y1, yTop );
799  return true;
800 
801  case 146:
802  clipEndRight( x0, y0, x1, y1, xRight );
803  if ( y1 > yTop )
804  return false;
805  clipStartTop( x0, y0, x1, y1, yTop );
806  if ( x0 < xLeft )
807  clipStartLeft( x0, y0, x1, y1, xLeft );
808  return true;
809 
810  case 148:
811  clipEndBottom( x0, y0, x1, y1, yBottom );
812  if ( x1 < xLeft )
813  return false;
814  clipStartLeft( x0, y0, x1, y1, xLeft );
815  if ( y0 > yTop )
816  clipStartTop( x0, y0, x1, y1, yTop );
817  return true;
818 
819  case 150:
820  clipStartLeft( x0, y0, x1, y1, xLeft );
821  if ( y0 < yBottom )
822  return false;
823  clipEndRight( x0, y0, x1, y1, xRight );
824  if ( y1 > yTop )
825  return false;
826  if ( y0 > yTop )
827  clipStartTop( x0, y0, x1, y1, yTop );
828  if ( y1 < yBottom )
829  clipEndBottom( x0, y0, x1, y1, yBottom );
830  return true;
831 
832  case 160:
833  clipStartRight( x0, y0, x1, y1, xRight );
834  if ( y0 > yTop )
835  clipStartTop( x0, y0, x1, y1, yTop );
836  return true;
837 
838  case 161:
839  clipEndLeft( x0, y0, x1, y1, xLeft );
840  if ( y1 > yTop )
841  return false;
842  clipStartTop( x0, y0, x1, y1, yTop );
843  if ( x0 > xRight )
844  clipStartRight( x0, y0, x1, y1, xRight );
845  return true;
846 
847  case 164:
848  clipEndBottom( x0, y0, x1, y1, yBottom );
849  if ( x1 > xRight )
850  return false;
851  clipStartRight( x0, y0, x1, y1, xRight );
852  if ( y0 > yTop )
853  clipStartTop( x0, y0, x1, y1, yTop );
854  return true;
855 
856  case 165:
857  clipEndLeft( x0, y0, x1, y1, xLeft );
858  if ( y1 > yTop )
859  return false;
860  clipStartRight( x0, y0, x1, y1, xRight );
861  if ( y0 < yBottom )
862  return false;
863  if ( y1 < yBottom )
864  clipEndBottom( x0, y0, x1, y1, yBottom );
865  if ( y0 > yTop )
866  clipStartTop( x0, y0, x1, y1, yTop );
867  return true;
868  }
869 
870  return false;
871 
872 }
873 
874 
875 #endif
static const double MAX_Y
Definition: qgsclipper.h:67
A rectangle specified with double values.
Definition: qgsrectangle.h:36
double y
Definition: qgspoint.h:148
static void trimFeature(QVector< double > &x, QVector< double > &y, bool shapeOpen)
Trims the given feature to a rectangular box.
Definition: qgsclipper.h:163
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Compare two doubles (but allow some difference)
Definition: qgis.h:193
static const double MIN_X
Definition: qgsclipper.h:66
A class to trim lines and polygons to within a rectangular region.
Definition: qgsclipper.h:42
Abstract base class for curved geometry type.
Definition: qgscurve.h:33
void set(double x, double y)
Sets the x and y value of the point.
Definition: qgspoint.h:207
A class to represent a point.
Definition: qgspoint.h:143
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:207
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:192
Boundary
A handy way to refer to the four boundaries.
Definition: qgsclipper.h:72
double xMinimum() const
Get the x minimum value (left side of rectangle)
Definition: qgsrectangle.h:197
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:202
static const double MIN_Y
Definition: qgsclipper.h:68
static void trimPolygon(QPolygonF &pts, const QgsRectangle &clipRect)
Definition: qgsclipper.h:184
static const double MAX_X
Definition: qgsclipper.h:65
double x
Definition: qgspoint.h:147