QGIS API Documentation  2.99.0-Master (b8fd1fd)
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  {
276  // look at each edge of the polygon in turn
277  if ( inside( inPts[i2], b, boundaryValue ) ) // end point of edge is inside boundary
278  {
279  if ( inside( inPts[i1], b, boundaryValue ) )
280  {
281  outPts.append( inPts[i2] );
282  }
283  else
284  {
285  // edge crosses into the boundary, so trim back to the boundary, and
286  // store both ends of the new edge
287  outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
288  outPts.append( inPts[i2] );
289  }
290  }
291  else // end point of edge is outside boundary
292  {
293  // start point is in boundary, so need to trim back
294  if ( inside( inPts[i1], b, boundaryValue ) )
295  {
296  outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
297  }
298  }
299  i1 = i2;
300  }
301 }
302 
303 // An auxiliary function to trimPolygonToBoundarY() that returns
304 // whether a point is inside or outside the given boundary.
305 
306 inline bool QgsClipper::inside( const double x, const double y, Boundary b )
307 {
308  switch ( b )
309  {
310  case XMax: // x < MAX_X is inside
311  if ( x < MAX_X )
312  return true;
313  break;
314  case XMin: // x > MIN_X is inside
315  if ( x > MIN_X )
316  return true;
317  break;
318  case YMax: // y < MAX_Y is inside
319  if ( y < MAX_Y )
320  return true;
321  break;
322  case YMin: // y > MIN_Y is inside
323  if ( y > MIN_Y )
324  return true;
325  break;
326  }
327  return false;
328 }
329 
330 inline bool QgsClipper::inside( QPointF pt, Boundary b, double val )
331 {
332  switch ( b )
333  {
334  case XMax: // x < MAX_X is inside
335  return ( pt.x() < val );
336  case XMin: // x > MIN_X is inside
337  return ( pt.x() > val );
338  case YMax: // y < MAX_Y is inside
339  return ( pt.y() < val );
340  case YMin: // y > MIN_Y is inside
341  return ( pt.y() > val );
342  }
343  return false;
344 }
345 
346 
347 // An auxiliary function to trimPolygonToBoundarY() that calculates and
348 // returns the intersection of the line defined by the given points
349 // and the given boundary.
350 
351 inline QgsPoint QgsClipper::intersect( const double x1, const double y1,
352  const double x2, const double y2,
353  Boundary b )
354 {
355  // This function assumes that the two given points (x1, y1), and
356  // (x2, y2) cross the given boundary. Making this assumption allows
357  // some optimisations.
358 
359  double r_n = SMALL_NUM, r_d = SMALL_NUM;
360 
361  switch ( b )
362  {
363  case XMax: // x = MAX_X boundary
364  r_n = -( x1 - MAX_X ) * ( MAX_Y - MIN_Y );
365  r_d = ( x2 - x1 ) * ( MAX_Y - MIN_Y );
366  break;
367  case XMin: // x = MIN_X boundary
368  r_n = -( x1 - MIN_X ) * ( MAX_Y - MIN_Y );
369  r_d = ( x2 - x1 ) * ( MAX_Y - MIN_Y );
370  break;
371  case YMax: // y = MAX_Y boundary
372  r_n = ( y1 - MAX_Y ) * ( MAX_X - MIN_X );
373  r_d = -( y2 - y1 ) * ( MAX_X - MIN_X );
374  break;
375  case YMin: // y = MIN_Y boundary
376  r_n = ( y1 - MIN_Y ) * ( MAX_X - MIN_X );
377  r_d = -( y2 - y1 ) * ( MAX_X - MIN_X );
378  break;
379  }
380 
381  QgsPoint p;
382 
383  if ( qAbs( r_d ) > SMALL_NUM && qAbs( r_n ) > SMALL_NUM )
384  {
385  // they cross
386  double r = r_n / r_d;
387  p.set( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
388  }
389  else
390  {
391  // Should never get here, but if we do for some reason, cause a
392  // clunk because something else is wrong if we do.
393  Q_ASSERT( qAbs( r_d ) > SMALL_NUM && qAbs( r_n ) > SMALL_NUM );
394  }
395 
396  return p;
397 }
398 
399 inline QPointF QgsClipper::intersectRect( QPointF pt1,
400  QPointF pt2,
401  Boundary b, const QgsRectangle &rect )
402 {
403  // This function assumes that the two given points (x1, y1), and
404  // (x2, y2) cross the given boundary. Making this assumption allows
405  // some optimisations.
406 
407  double r_n = SMALL_NUM, r_d = SMALL_NUM;
408  const double x1 = pt1.x(), x2 = pt2.x();
409  const double y1 = pt1.y(), y2 = pt2.y();
410 
411  switch ( b )
412  {
413  case XMax: // x = MAX_X boundary
414  r_n = -( x1 - rect.xMaximum() ) * ( rect.yMaximum() - rect.yMinimum() );
415  r_d = ( x2 - x1 ) * ( rect.yMaximum() - rect.yMinimum() );
416  break;
417  case XMin: // x = MIN_X boundary
418  r_n = -( x1 - rect.xMinimum() ) * ( rect.yMaximum() - rect.yMinimum() );
419  r_d = ( x2 - x1 ) * ( rect.yMaximum() - rect.yMinimum() );
420  break;
421  case YMax: // y = MAX_Y boundary
422  r_n = ( y1 - rect.yMaximum() ) * ( rect.xMaximum() - rect.xMinimum() );
423  r_d = -( y2 - y1 ) * ( rect.xMaximum() - rect.xMinimum() );
424  break;
425  case YMin: // y = MIN_Y boundary
426  r_n = ( y1 - rect.yMinimum() ) * ( rect.xMaximum() - rect.xMinimum() );
427  r_d = -( y2 - y1 ) * ( rect.xMaximum() - rect.xMinimum() );
428  break;
429  }
430 
431  double r = 0;
432  if ( !qgsDoubleNear( r_d, 0.0 ) )
433  {
434  r = r_n / r_d;
435  }
436  return QPointF( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
437 }
438 
439 inline void QgsClipper::clipStartTop( double &x0, double &y0, double x1, double y1, double yMax )
440 {
441  x0 += ( x1 - x0 ) * ( yMax - y0 ) / ( y1 - y0 );
442  y0 = yMax;
443 }
444 
445 inline void QgsClipper::clipStartBottom( double &x0, double &y0, double x1, double y1, double yMin )
446 {
447  x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
448  y0 = yMin;
449 }
450 
451 inline void QgsClipper::clipStartRight( double &x0, double &y0, double x1, double y1, double xMax )
452 {
453  y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
454  x0 = xMax;
455 }
456 
457 inline void QgsClipper::clipStartLeft( double &x0, double &y0, double &x1, double &y1, double xMin )
458 {
459  y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
460  x0 = xMin;
461 }
462 
463 inline void QgsClipper::clipEndTop( double x0, double y0, double &x1, double &y1, double yMax )
464 {
465  x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
466  y1 = yMax;
467 }
468 
469 inline void QgsClipper::clipEndBottom( double x0, double y0, double &x1, double &y1, double yMin )
470 {
471  x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
472  y1 = yMin;
473 }
474 
475 inline void QgsClipper::clipEndRight( double x0, double y0, double &x1, double &y1, double xMax )
476 {
477  y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
478  x1 = xMax;
479 }
480 
481 inline void QgsClipper::clipEndLeft( double x0, double y0, double &x1, double &y1, double xMin )
482 {
483  y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
484  x1 = xMin;
485 }
486 
487 //'Fast clipping' algorithm (Sobkow et al. 1987, Computers & Graphics Vol.11, 4, p.459-467)
488 inline bool QgsClipper::clipLineSegment( double xLeft, double xRight, double yBottom, double yTop, double &x0, double &y0, double &x1, double &y1 )
489 {
490  int lineCode = 0;
491 
492  if ( y1 < yBottom )
493  lineCode |= 4;
494  else if ( y1 > yTop )
495  lineCode |= 8;
496 
497  if ( x1 > xRight )
498  lineCode |= 2;
499  else if ( x1 < xLeft )
500  lineCode |= 1;
501 
502  if ( y0 < yBottom )
503  lineCode |= 64;
504  else if ( y0 > yTop )
505  lineCode |= 128;
506 
507  if ( x0 > xRight )
508  lineCode |= 32;
509  else if ( x0 < xLeft )
510  lineCode |= 16;
511 
512  switch ( lineCode )
513  {
514  case 0: //completely inside
515  return true;
516 
517  case 1:
518  clipEndLeft( x0, y0, x1, y1, xLeft );
519  return true;
520 
521  case 2:
522  clipEndRight( x0, y0, x1, y1, xRight );
523  return true;
524 
525  case 4:
526  clipEndBottom( x0, y0, x1, y1, yBottom );
527  return true;
528 
529  case 5:
530  clipEndLeft( x0, y0, x1, y1, xLeft );
531  if ( y1 < yBottom )
532  clipEndBottom( x0, y0, x1, y1, yBottom );
533  return true;
534 
535  case 6:
536  clipEndRight( x0, y0, x1, y1, xRight );
537  if ( y1 < yBottom )
538  clipEndBottom( x0, y0, x1, y1, yBottom );
539  return true;
540 
541  case 8:
542  clipEndTop( x0, y0, x1, y1, yTop );
543  return true;
544 
545  case 9:
546  clipEndLeft( x0, y0, x1, y1, xLeft );
547  if ( y1 > yTop )
548  clipEndTop( x0, y0, x1, y1, yTop );
549  return true;
550 
551  case 10:
552  clipEndRight( x0, y0, x1, y1, xRight );
553  if ( y1 > yTop )
554  clipEndTop( x0, y0, x1, y1, yTop );
555  return true;
556 
557  case 16:
558  clipStartLeft( x0, y0, x1, y1, xLeft );
559  return true;
560 
561  case 18:
562  clipStartLeft( x0, y0, x1, y1, xLeft );
563  clipEndRight( x0, y0, x1, y1, xRight );
564  return true;
565 
566  case 20:
567  clipStartLeft( x0, y0, x1, y1, xLeft );
568  if ( y0 < yBottom )
569  return false;
570  clipEndBottom( x0, y0, x1, y1, yBottom );
571  return true;
572 
573  case 22:
574  clipStartLeft( x0, y0, x1, y1, xLeft );
575  if ( y0 < yBottom )
576  return false;
577  clipEndBottom( x0, y0, x1, y1, yBottom );
578  if ( x1 > xRight )
579  clipEndRight( x0, y0, x1, y1, xRight );
580  return true;
581 
582  case 24:
583  clipStartLeft( x0, y0, x1, y1, xLeft );
584  if ( y0 > yTop )
585  return false;
586  clipEndTop( x0, y0, x1, y1, yTop );
587  return true;
588 
589  case 26:
590  clipStartLeft( x0, y0, x1, y1, xLeft );
591  if ( y0 > yTop )
592  return false;
593  clipEndTop( x0, y0, x1, y1, yTop );
594  if ( x1 > xRight )
595  clipEndRight( x0, y0, x1, y1, xRight );
596  return true;
597 
598  case 32:
599  clipStartRight( x0, y0, x1, y1, xRight );
600  return true;
601 
602  case 33:
603  clipStartRight( x0, y0, x1, y1, xRight );
604  clipEndLeft( x0, y0, x1, y1, xLeft );
605  return true;
606 
607  case 36:
608  clipStartRight( x0, y0, x1, y1, xRight );
609  if ( y0 < yBottom )
610  return false;
611  clipEndBottom( x0, y0, x1, y1, yBottom );
612  return true;
613 
614  case 37:
615  clipStartRight( x0, y0, x1, y1, xRight );
616  if ( y0 < yBottom )
617  return false;
618  clipEndBottom( x0, y0, x1, y1, yBottom );
619  if ( x1 < xLeft )
620  clipEndLeft( x0, y0, x1, y1, xLeft );
621  return true;
622 
623  case 40:
624  clipStartRight( x0, y0, x1, y1, xRight );
625  if ( y0 > yTop )
626  return false;
627  clipEndTop( x0, y0, x1, y1, yTop );
628  return true;
629 
630  case 41:
631  clipStartRight( x0, y0, x1, y1, xRight );
632  if ( y0 > yTop )
633  return false;
634  clipEndTop( x0, y0, x1, y1, yTop );
635  if ( x1 < xLeft )
636  clipEndLeft( x0, y0, x1, y1, xLeft );
637  return true;
638 
639  case 64:
640  clipStartBottom( x0, y0, x1, y1, yBottom );
641  return true;
642 
643  case 65:
644  clipStartBottom( x0, y0, x1, y1, yBottom );
645  if ( x0 < xLeft )
646  return false;
647  clipEndLeft( x0, y0, x1, y1, xLeft );
648  if ( y1 < yBottom )
649  clipEndBottom( x0, y0, x1, y1, yBottom );
650  return true;
651 
652  case 66:
653  clipStartBottom( x0, y0, x1, y1, yBottom );
654  if ( x0 > xRight )
655  return false;
656  clipEndRight( x0, y0, x1, y1, xRight );
657  return true;
658 
659  case 72:
660  clipStartBottom( x0, y0, x1, y1, yBottom );
661  clipEndTop( x0, y0, x1, y1, yTop );
662  return true;
663 
664  case 73:
665  clipStartBottom( x0, y0, x1, y1, yBottom );
666  if ( x0 < xLeft )
667  return false;
668  clipEndLeft( x0, y0, x1, y1, xLeft );
669  if ( y1 > yTop )
670  clipEndTop( x0, y0, x1, y1, yTop );
671  return true;
672 
673  case 74:
674  clipStartBottom( x0, y0, x1, y1, yBottom );
675  if ( x0 > xRight )
676  return false;
677  clipEndRight( x0, y0, x1, y1, xRight );
678  if ( y1 > yTop )
679  clipEndTop( x0, y0, x1, y1, yTop );
680  return true;
681 
682  case 80:
683  clipStartLeft( x0, y0, x1, y1, xLeft );
684  if ( y0 < yBottom )
685  clipStartBottom( x0, y0, x1, y1, yBottom );
686  return true;
687 
688  case 82:
689  clipEndRight( x0, y0, x1, y1, xRight );
690  if ( y1 < yBottom )
691  return false;
692  clipStartBottom( x0, y0, x1, y1, yBottom );
693  if ( x0 < xLeft )
694  clipStartLeft( x0, y0, x1, y1, xLeft );
695  return true;
696 
697  case 88:
698  clipEndTop( x0, y0, x1, y1, yTop );
699  if ( x1 < xLeft )
700  return false;
701  clipStartBottom( x0, y0, x1, y1, yBottom );
702  if ( x0 < xLeft )
703  clipStartLeft( x0, y0, x1, y1, xLeft );
704  return true;
705 
706  case 90:
707  clipStartLeft( x0, y0, x1, y1, xLeft );
708  if ( y0 > yTop )
709  return false;
710  clipEndRight( x0, y0, x1, y1, xRight );
711  if ( y1 < yBottom )
712  return false;
713  if ( y0 < yBottom )
714  clipStartBottom( x0, y0, x1, y1, yBottom );
715  if ( y1 > yTop )
716  clipEndTop( x0, y0, x1, y1, yTop );
717  return true;
718 
719  case 96:
720  clipStartRight( x0, y0, x1, y1, xRight );
721  if ( y0 < yBottom )
722  clipStartBottom( x0, y0, x1, y1, yBottom );
723  return true;
724 
725  case 97:
726  clipEndLeft( x0, y0, x1, y1, xLeft );
727  if ( y1 < yBottom )
728  return false;
729  clipStartBottom( x0, y0, x1, y1, yBottom );
730  if ( x0 > xRight )
731  clipStartRight( x0, y0, x1, y1, xRight );
732  return true;
733 
734  case 104:
735  clipEndTop( x0, y0, x1, y1, yTop );
736  if ( x1 > xRight )
737  return false;
738  clipStartRight( x0, y0, x1, y1, xRight );
739  if ( y0 < yBottom )
740  clipStartBottom( x0, y0, x1, y1, yBottom );
741  return true;
742 
743  case 105:
744  clipEndLeft( x0, y0, x1, y1, xLeft );
745  if ( y1 < yBottom )
746  return false;
747  clipStartRight( x0, y0, x1, y1, xRight );
748  if ( y0 > yTop )
749  return false;
750  if ( y1 > yTop )
751  clipEndTop( x0, y0, x1, y1, yTop );
752  if ( y0 < yBottom )
753  clipStartBottom( x0, y0, x1, y1, yBottom );
754  return true;
755 
756  case 128:
757  clipStartTop( x0, y0, x1, y1, yTop );
758  return true;
759 
760  case 129:
761  clipStartTop( x0, y0, x1, y1, yTop );
762  if ( x0 < xLeft )
763  return false;
764  clipEndLeft( x0, y0, x1, y1, xLeft );
765  return true;
766 
767  case 130:
768  clipStartTop( x0, y0, x1, y1, yTop );
769  if ( x0 > xRight )
770  return false;
771  clipEndRight( x0, y0, x1, y1, xRight );
772  return true;
773 
774  case 132:
775  clipStartTop( x0, y0, x1, y1, yTop );
776  clipEndBottom( x0, y0, x1, y1, yBottom );
777  return true;
778 
779  case 133:
780  clipStartTop( x0, y0, x1, y1, yTop );
781  if ( x0 < xLeft )
782  return false;
783  clipEndLeft( x0, y0, x1, y1, xLeft );
784  if ( y1 < yBottom )
785  clipEndBottom( x0, y0, x1, y1, yBottom );
786  return true;
787 
788  case 134:
789  clipStartTop( x0, y0, x1, y1, yTop );
790  if ( x0 > xRight )
791  return false;
792  clipEndRight( x0, y0, x1, y1, xRight );
793  if ( y1 < yBottom )
794  clipEndBottom( x0, y0, x1, y1, yBottom );
795  return true;
796 
797  case 144:
798  clipStartLeft( x0, y0, x1, y1, xLeft );
799  if ( y0 > yTop )
800  clipStartTop( x0, y0, x1, y1, yTop );
801  return true;
802 
803  case 146:
804  clipEndRight( x0, y0, x1, y1, xRight );
805  if ( y1 > yTop )
806  return false;
807  clipStartTop( x0, y0, x1, y1, yTop );
808  if ( x0 < xLeft )
809  clipStartLeft( x0, y0, x1, y1, xLeft );
810  return true;
811 
812  case 148:
813  clipEndBottom( x0, y0, x1, y1, yBottom );
814  if ( x1 < xLeft )
815  return false;
816  clipStartLeft( x0, y0, x1, y1, xLeft );
817  if ( y0 > yTop )
818  clipStartTop( x0, y0, x1, y1, yTop );
819  return true;
820 
821  case 150:
822  clipStartLeft( x0, y0, x1, y1, xLeft );
823  if ( y0 < yBottom )
824  return false;
825  clipEndRight( x0, y0, x1, y1, xRight );
826  if ( y1 > yTop )
827  return false;
828  if ( y0 > yTop )
829  clipStartTop( x0, y0, x1, y1, yTop );
830  if ( y1 < yBottom )
831  clipEndBottom( x0, y0, x1, y1, yBottom );
832  return true;
833 
834  case 160:
835  clipStartRight( x0, y0, x1, y1, xRight );
836  if ( y0 > yTop )
837  clipStartTop( x0, y0, x1, y1, yTop );
838  return true;
839 
840  case 161:
841  clipEndLeft( x0, y0, x1, y1, xLeft );
842  if ( y1 > yTop )
843  return false;
844  clipStartTop( x0, y0, x1, y1, yTop );
845  if ( x0 > xRight )
846  clipStartRight( x0, y0, x1, y1, xRight );
847  return true;
848 
849  case 164:
850  clipEndBottom( x0, y0, x1, y1, yBottom );
851  if ( x1 > xRight )
852  return false;
853  clipStartRight( x0, y0, x1, y1, xRight );
854  if ( y0 > yTop )
855  clipStartTop( x0, y0, x1, y1, yTop );
856  return true;
857 
858  case 165:
859  clipEndLeft( x0, y0, x1, y1, xLeft );
860  if ( y1 > yTop )
861  return false;
862  clipStartRight( x0, y0, x1, y1, xRight );
863  if ( y0 < yBottom )
864  return false;
865  if ( y1 < yBottom )
866  clipEndBottom( x0, y0, x1, y1, yBottom );
867  if ( y0 > yTop )
868  clipStartTop( x0, y0, x1, y1, yTop );
869  return true;
870  }
871 
872  return false;
873 
874 }
875 
876 
877 #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:42
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:198
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:109
A class to represent a point.
Definition: qgspoint.h:37
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
Definition: qgsrectangle.h:210
double xMaximum() const
Get the x maximum value (right side of rectangle)
Definition: qgsrectangle.h:195
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:200
double yMaximum() const
Get the y maximum value (top side of rectangle)
Definition: qgsrectangle.h:205
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:41