22 #include "qgis_core.h"
95 static void trimFeature( QVector<double> &x,
101 static void trimPolygon( QPolygonF &pts,
const QgsRectangle &clipRect );
116 static QPolygonF clippedLine(
const QPolygonF &curve,
const QgsRectangle &clipExtent );
121 static const double SMALL_NUM;
125 static inline void trimFeatureToBoundary(
const QVector<double> &inX,
126 const QVector<double> &inY,
127 QVector<double> &outX,
128 QVector<double> &outY,
132 static inline void trimPolygonToBoundary(
const QPolygonF &inPts, QPolygonF &outPts,
const QgsRectangle &rect, Boundary b,
double boundaryValue );
135 static inline bool inside(
double x,
double y, Boundary b );
137 static inline bool inside( QPointF pt, Boundary b,
double val );
141 static inline QgsPointXY intersect(
double x1,
double y1,
142 double x2,
double y2,
145 static inline QPointF intersectRect( QPointF pt1,
150 static bool clipLineSegment(
double xLeft,
double xRight,
double yBottom,
double yTop,
double &x0,
double &y0,
double &x1,
double &y1 );
161 static void connectSeparatedLines(
double x0,
double y0,
double x1,
double y1,
165 static void clipStartTop(
double &x0,
double &y0,
double x1,
double y1,
double yMax );
166 static void clipStartBottom(
double &x0,
double &y0,
double x1,
double y1,
double yMin );
167 static void clipStartRight(
double &x0,
double &y0,
double x1,
double y1,
double xMax );
168 static void clipStartLeft(
double &x0,
double &y0,
double &x1,
double &y1,
double xMin );
169 static void clipEndTop(
double x0,
double y0,
double &x1,
double &y1,
double yMax );
170 static void clipEndBottom(
double x0,
double y0,
double &x1,
double &y1,
double yMin );
171 static void clipEndRight(
double x0,
double y0,
double &x1,
double &y1,
double xMax );
172 static void clipEndLeft(
double x0,
double y0,
double &x1,
double &y1,
double xMin );
192 QVector<double> tmpX;
193 QVector<double> tmpY;
194 trimFeatureToBoundary( x, y, tmpX, tmpY,
XMax, shapeOpen );
198 trimFeatureToBoundary( tmpX, tmpY, x, y,
YMax, shapeOpen );
202 trimFeatureToBoundary( x, y, tmpX, tmpY,
XMin, shapeOpen );
206 trimFeatureToBoundary( tmpX, tmpY, x, y,
YMin, shapeOpen );
212 tmpPts.reserve( pts.size() );
214 trimPolygonToBoundary( pts, tmpPts, clipRect,
XMax, clipRect.
xMaximum() );
216 trimPolygonToBoundary( tmpPts, pts, clipRect,
YMax, clipRect.
yMaximum() );
218 trimPolygonToBoundary( pts, tmpPts, clipRect,
XMin, clipRect.
xMinimum() );
220 trimPolygonToBoundary( tmpPts, pts, clipRect,
YMin, clipRect.
yMinimum() );
228 inline void QgsClipper::trimFeatureToBoundary(
229 const QVector<double> &inX,
230 const QVector<double> &inY,
231 QVector<double> &outX,
232 QVector<double> &outY,
233 Boundary b,
bool shapeOpen )
239 int i1 = inX.size() - 1;
242 for (
int i2 = 0; i2 < inX.size() ; ++i2 )
247 if ( std::isnan( inX[i2] ) || std::isnan( inY[i2] ) || std::isinf( inX[i2] ) || std::isinf( inY[i2] )
248 || std::isnan( inX[i1] ) || std::isnan( inY[i1] ) || std::isinf( inX[i1] ) || std::isinf( inY[i1] ) )
255 if ( inside( inX[i2], inY[i2], b ) )
257 if ( inside( inX[i1], inY[i1], b ) )
259 outX.push_back( inX[i2] );
260 outY.push_back( inY[i2] );
266 if ( !( i2 == 0 && shapeOpen ) )
268 QgsPointXY p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
269 outX.push_back( p.
x() );
270 outY.push_back( p.
y() );
273 outX.push_back( inX[i2] );
274 outY.push_back( inY[i2] );
280 if ( inside( inX[i1], inY[i1], b ) )
282 if ( !( i2 == 0 && shapeOpen ) )
284 QgsPointXY p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
285 outX.push_back( p.
x() );
286 outY.push_back( p.
y() );
294 inline void QgsClipper::trimPolygonToBoundary(
const QPolygonF &inPts, QPolygonF &outPts,
const QgsRectangle &rect, Boundary b,
double boundaryValue )
296 int i1 = inPts.size() - 1;
299 for (
int i2 = 0; i2 < inPts.size() ; ++i2 )
302 if ( inside( inPts[i2], b, boundaryValue ) )
304 if ( inside( inPts[i1], b, boundaryValue ) )
306 outPts.append( inPts[i2] );
312 outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
313 outPts.append( inPts[i2] );
319 if ( inside( inPts[i1], b, boundaryValue ) )
321 outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
331 inline bool QgsClipper::inside(
const double x,
const double y, Boundary b )
355 inline bool QgsClipper::inside( QPointF pt, Boundary b,
double val )
360 return ( pt.x() < val );
362 return ( pt.x() > val );
364 return ( pt.y() < val );
366 return ( pt.y() > val );
376 inline QgsPointXY QgsClipper::intersect(
const double x1,
const double y1,
377 const double x2,
const double y2,
384 double r_n = SMALL_NUM, r_d = SMALL_NUM;
408 if ( std::fabs( r_d ) > SMALL_NUM && std::fabs( r_n ) > SMALL_NUM )
411 double r = r_n / r_d;
412 p.
set( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
418 Q_ASSERT( std::fabs( r_d ) > SMALL_NUM && std::fabs( r_n ) > SMALL_NUM );
424 inline QPointF QgsClipper::intersectRect( QPointF pt1,
432 double r_n = SMALL_NUM, r_d = SMALL_NUM;
433 const double x1 = pt1.x(), x2 = pt2.x();
434 const double y1 = pt1.y(), y2 = pt2.y();
461 return QPointF( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
464 inline void QgsClipper::clipStartTop(
double &x0,
double &y0,
double x1,
double y1,
double yMax )
466 x0 += ( x1 - x0 ) * ( yMax - y0 ) / ( y1 - y0 );
470 inline void QgsClipper::clipStartBottom(
double &x0,
double &y0,
double x1,
double y1,
double yMin )
472 x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
476 inline void QgsClipper::clipStartRight(
double &x0,
double &y0,
double x1,
double y1,
double xMax )
478 y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
482 inline void QgsClipper::clipStartLeft(
double &x0,
double &y0,
double &x1,
double &y1,
double xMin )
484 y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
488 inline void QgsClipper::clipEndTop(
double x0,
double y0,
double &x1,
double &y1,
double yMax )
490 x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
494 inline void QgsClipper::clipEndBottom(
double x0,
double y0,
double &x1,
double &y1,
double yMin )
496 x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
500 inline void QgsClipper::clipEndRight(
double x0,
double y0,
double &x1,
double &y1,
double xMax )
502 y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
506 inline void QgsClipper::clipEndLeft(
double x0,
double y0,
double &x1,
double &y1,
double xMin )
508 y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
513 inline bool QgsClipper::clipLineSegment(
double xLeft,
double xRight,
double yBottom,
double yTop,
double &x0,
double &y0,
double &x1,
double &y1 )
519 else if ( y1 > yTop )
524 else if ( x1 < xLeft )
529 else if ( y0 > yTop )
534 else if ( x0 < xLeft )
543 clipEndLeft( x0, y0, x1, y1, xLeft );
547 clipEndRight( x0, y0, x1, y1, xRight );
551 clipEndBottom( x0, y0, x1, y1, yBottom );
555 clipEndLeft( x0, y0, x1, y1, xLeft );
557 clipEndBottom( x0, y0, x1, y1, yBottom );
561 clipEndRight( x0, y0, x1, y1, xRight );
563 clipEndBottom( x0, y0, x1, y1, yBottom );
567 clipEndTop( x0, y0, x1, y1, yTop );
571 clipEndLeft( x0, y0, x1, y1, xLeft );
573 clipEndTop( x0, y0, x1, y1, yTop );
577 clipEndRight( x0, y0, x1, y1, xRight );
579 clipEndTop( x0, y0, x1, y1, yTop );
583 clipStartLeft( x0, y0, x1, y1, xLeft );
587 clipStartLeft( x0, y0, x1, y1, xLeft );
588 clipEndRight( x0, y0, x1, y1, xRight );
592 clipStartLeft( x0, y0, x1, y1, xLeft );
595 clipEndBottom( x0, y0, x1, y1, yBottom );
599 clipStartLeft( x0, y0, x1, y1, xLeft );
602 clipEndBottom( x0, y0, x1, y1, yBottom );
604 clipEndRight( x0, y0, x1, y1, xRight );
608 clipStartLeft( x0, y0, x1, y1, xLeft );
611 clipEndTop( x0, y0, x1, y1, yTop );
615 clipStartLeft( x0, y0, x1, y1, xLeft );
618 clipEndTop( x0, y0, x1, y1, yTop );
620 clipEndRight( x0, y0, x1, y1, xRight );
624 clipStartRight( x0, y0, x1, y1, xRight );
628 clipStartRight( x0, y0, x1, y1, xRight );
629 clipEndLeft( x0, y0, x1, y1, xLeft );
633 clipStartRight( x0, y0, x1, y1, xRight );
636 clipEndBottom( x0, y0, x1, y1, yBottom );
640 clipStartRight( x0, y0, x1, y1, xRight );
643 clipEndBottom( x0, y0, x1, y1, yBottom );
645 clipEndLeft( x0, y0, x1, y1, xLeft );
649 clipStartRight( x0, y0, x1, y1, xRight );
652 clipEndTop( x0, y0, x1, y1, yTop );
656 clipStartRight( x0, y0, x1, y1, xRight );
659 clipEndTop( x0, y0, x1, y1, yTop );
661 clipEndLeft( x0, y0, x1, y1, xLeft );
665 clipStartBottom( x0, y0, x1, y1, yBottom );
669 clipStartBottom( x0, y0, x1, y1, yBottom );
672 clipEndLeft( x0, y0, x1, y1, xLeft );
674 clipEndBottom( x0, y0, x1, y1, yBottom );
678 clipStartBottom( x0, y0, x1, y1, yBottom );
681 clipEndRight( x0, y0, x1, y1, xRight );
685 clipStartBottom( x0, y0, x1, y1, yBottom );
686 clipEndTop( x0, y0, x1, y1, yTop );
690 clipStartBottom( x0, y0, x1, y1, yBottom );
693 clipEndLeft( x0, y0, x1, y1, xLeft );
695 clipEndTop( x0, y0, x1, y1, yTop );
699 clipStartBottom( x0, y0, x1, y1, yBottom );
702 clipEndRight( x0, y0, x1, y1, xRight );
704 clipEndTop( x0, y0, x1, y1, yTop );
708 clipStartLeft( x0, y0, x1, y1, xLeft );
710 clipStartBottom( x0, y0, x1, y1, yBottom );
714 clipEndRight( x0, y0, x1, y1, xRight );
717 clipStartBottom( x0, y0, x1, y1, yBottom );
719 clipStartLeft( x0, y0, x1, y1, xLeft );
723 clipEndTop( x0, y0, x1, y1, yTop );
726 clipStartBottom( x0, y0, x1, y1, yBottom );
728 clipStartLeft( x0, y0, x1, y1, xLeft );
732 clipStartLeft( x0, y0, x1, y1, xLeft );
735 clipEndRight( x0, y0, x1, y1, xRight );
739 clipStartBottom( x0, y0, x1, y1, yBottom );
741 clipEndTop( x0, y0, x1, y1, yTop );
745 clipStartRight( x0, y0, x1, y1, xRight );
747 clipStartBottom( x0, y0, x1, y1, yBottom );
751 clipEndLeft( x0, y0, x1, y1, xLeft );
754 clipStartBottom( x0, y0, x1, y1, yBottom );
756 clipStartRight( x0, y0, x1, y1, xRight );
760 clipEndTop( x0, y0, x1, y1, yTop );
763 clipStartRight( x0, y0, x1, y1, xRight );
765 clipStartBottom( x0, y0, x1, y1, yBottom );
769 clipEndLeft( x0, y0, x1, y1, xLeft );
772 clipStartRight( x0, y0, x1, y1, xRight );
776 clipEndTop( x0, y0, x1, y1, yTop );
778 clipStartBottom( x0, y0, x1, y1, yBottom );
782 clipStartTop( x0, y0, x1, y1, yTop );
786 clipStartTop( x0, y0, x1, y1, yTop );
789 clipEndLeft( x0, y0, x1, y1, xLeft );
793 clipStartTop( x0, y0, x1, y1, yTop );
796 clipEndRight( x0, y0, x1, y1, xRight );
800 clipStartTop( x0, y0, x1, y1, yTop );
801 clipEndBottom( x0, y0, x1, y1, yBottom );
805 clipStartTop( x0, y0, x1, y1, yTop );
808 clipEndLeft( x0, y0, x1, y1, xLeft );
810 clipEndBottom( x0, y0, x1, y1, yBottom );
814 clipStartTop( x0, y0, x1, y1, yTop );
817 clipEndRight( x0, y0, x1, y1, xRight );
819 clipEndBottom( x0, y0, x1, y1, yBottom );
823 clipStartLeft( x0, y0, x1, y1, xLeft );
825 clipStartTop( x0, y0, x1, y1, yTop );
829 clipEndRight( x0, y0, x1, y1, xRight );
832 clipStartTop( x0, y0, x1, y1, yTop );
834 clipStartLeft( x0, y0, x1, y1, xLeft );
838 clipEndBottom( x0, y0, x1, y1, yBottom );
841 clipStartLeft( x0, y0, x1, y1, xLeft );
843 clipStartTop( x0, y0, x1, y1, yTop );
847 clipStartLeft( x0, y0, x1, y1, xLeft );
850 clipEndRight( x0, y0, x1, y1, xRight );
854 clipStartTop( x0, y0, x1, y1, yTop );
856 clipEndBottom( x0, y0, x1, y1, yBottom );
860 clipStartRight( x0, y0, x1, y1, xRight );
862 clipStartTop( x0, y0, x1, y1, yTop );
866 clipEndLeft( x0, y0, x1, y1, xLeft );
869 clipStartTop( x0, y0, x1, y1, yTop );
871 clipStartRight( x0, y0, x1, y1, xRight );
875 clipEndBottom( x0, y0, x1, y1, yBottom );
878 clipStartRight( x0, y0, x1, y1, xRight );
880 clipStartTop( x0, y0, x1, y1, yTop );
884 clipEndLeft( x0, y0, x1, y1, xLeft );
887 clipStartRight( x0, y0, x1, y1, xRight );
891 clipEndBottom( x0, y0, x1, y1, yBottom );
893 clipStartTop( x0, y0, x1, y1, yTop );