22 #include "qgis_core.h"
96 static void trimFeature( QVector<double> &x,
102 static void trimPolygon( QPolygonF &pts,
const QgsRectangle &clipRect );
117 static QPolygonF clippedLine(
const QPolygonF &curve,
const QgsRectangle &clipExtent );
141 static const double SMALL_NUM;
145 static inline void trimFeatureToBoundary(
const QVector<double> &inX,
146 const QVector<double> &inY,
147 QVector<double> &outX,
148 QVector<double> &outY,
152 static inline void trimPolygonToBoundary(
const QPolygonF &inPts, QPolygonF &outPts,
const QgsRectangle &rect, Boundary b,
double boundaryValue );
155 static inline bool inside(
double x,
double y, Boundary b );
157 static inline bool inside( QPointF pt, Boundary b,
double val );
161 static inline QgsPointXY intersect(
double x1,
double y1,
162 double x2,
double y2,
165 static inline QPointF intersectRect( QPointF pt1,
178 static void connectSeparatedLines(
double x0,
double y0,
double x1,
double y1,
182 static void clipStartTop(
double &x0,
double &y0,
double x1,
double y1,
double yMax );
183 static void clipStartBottom(
double &x0,
double &y0,
double x1,
double y1,
double yMin );
184 static void clipStartRight(
double &x0,
double &y0,
double x1,
double y1,
double xMax );
185 static void clipStartLeft(
double &x0,
double &y0,
double &x1,
double &y1,
double xMin );
186 static void clipEndTop(
double x0,
double y0,
double &x1,
double &y1,
double yMax );
187 static void clipEndBottom(
double x0,
double y0,
double &x1,
double &y1,
double yMin );
188 static void clipEndRight(
double x0,
double y0,
double &x1,
double &y1,
double xMax );
189 static void clipEndLeft(
double x0,
double y0,
double &x1,
double &y1,
double xMin );
209 QVector<double> tmpX;
210 QVector<double> tmpY;
211 trimFeatureToBoundary( x, y, tmpX, tmpY,
XMax, shapeOpen );
215 trimFeatureToBoundary( tmpX, tmpY, x, y,
YMax, shapeOpen );
219 trimFeatureToBoundary( x, y, tmpX, tmpY,
XMin, shapeOpen );
223 trimFeatureToBoundary( tmpX, tmpY, x, y,
YMin, shapeOpen );
229 tmpPts.reserve( pts.size() );
231 trimPolygonToBoundary( pts, tmpPts, clipRect,
XMax, clipRect.
xMaximum() );
233 trimPolygonToBoundary( tmpPts, pts, clipRect,
YMax, clipRect.
yMaximum() );
235 trimPolygonToBoundary( pts, tmpPts, clipRect,
XMin, clipRect.
xMinimum() );
237 trimPolygonToBoundary( tmpPts, pts, clipRect,
YMin, clipRect.
yMinimum() );
245 inline void QgsClipper::trimFeatureToBoundary(
246 const QVector<double> &inX,
247 const QVector<double> &inY,
248 QVector<double> &outX,
249 QVector<double> &outY,
250 Boundary b,
bool shapeOpen )
256 int i1 = inX.size() - 1;
259 for (
int i2 = 0; i2 < inX.size() ; ++i2 )
264 if ( std::isnan( inX[i2] ) || std::isnan( inY[i2] ) || std::isinf( inX[i2] ) || std::isinf( inY[i2] )
265 || std::isnan( inX[i1] ) || std::isnan( inY[i1] ) || std::isinf( inX[i1] ) || std::isinf( inY[i1] ) )
272 if ( inside( inX[i2], inY[i2], b ) )
274 if ( inside( inX[i1], inY[i1], b ) )
276 outX.push_back( inX[i2] );
277 outY.push_back( inY[i2] );
283 if ( !( i2 == 0 && shapeOpen ) )
285 const QgsPointXY p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
286 outX.push_back( p.
x() );
287 outY.push_back( p.
y() );
290 outX.push_back( inX[i2] );
291 outY.push_back( inY[i2] );
297 if ( inside( inX[i1], inY[i1], b ) )
299 if ( !( i2 == 0 && shapeOpen ) )
301 const QgsPointXY p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
302 outX.push_back( p.
x() );
303 outY.push_back( p.
y() );
311 inline void QgsClipper::trimPolygonToBoundary(
const QPolygonF &inPts, QPolygonF &outPts,
const QgsRectangle &rect, Boundary b,
double boundaryValue )
313 int i1 = inPts.size() - 1;
316 for (
int i2 = 0; i2 < inPts.size() ; ++i2 )
319 if ( inside( inPts[i2], b, boundaryValue ) )
321 if ( inside( inPts[i1], b, boundaryValue ) )
323 outPts.append( inPts[i2] );
329 outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
330 outPts.append( inPts[i2] );
336 if ( inside( inPts[i1], b, boundaryValue ) )
338 outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
348 inline bool QgsClipper::inside(
const double x,
const double y, Boundary b )
372 inline bool QgsClipper::inside( QPointF pt, Boundary b,
double val )
377 return ( pt.x() < val );
379 return ( pt.x() > val );
381 return ( pt.y() < val );
383 return ( pt.y() > val );
393 inline QgsPointXY QgsClipper::intersect(
const double x1,
const double y1,
394 const double x2,
const double y2,
401 double r_n = SMALL_NUM, r_d = SMALL_NUM;
425 if ( std::fabs( r_d ) > SMALL_NUM && std::fabs( r_n ) > SMALL_NUM )
428 const double r = r_n / r_d;
429 p.
set( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
435 Q_ASSERT( std::fabs( r_d ) > SMALL_NUM && std::fabs( r_n ) > SMALL_NUM );
441 inline QPointF QgsClipper::intersectRect( QPointF pt1,
449 double r_n = SMALL_NUM, r_d = SMALL_NUM;
450 const double x1 = pt1.x(), x2 = pt2.x();
451 const double y1 = pt1.y(), y2 = pt2.y();
478 return QPointF( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
481 inline void QgsClipper::clipStartTop(
double &x0,
double &y0,
double x1,
double y1,
double yMax )
483 x0 += ( x1 - x0 ) * ( yMax - y0 ) / ( y1 - y0 );
487 inline void QgsClipper::clipStartBottom(
double &x0,
double &y0,
double x1,
double y1,
double yMin )
489 x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
493 inline void QgsClipper::clipStartRight(
double &x0,
double &y0,
double x1,
double y1,
double xMax )
495 y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
499 inline void QgsClipper::clipStartLeft(
double &x0,
double &y0,
double &x1,
double &y1,
double xMin )
501 y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
505 inline void QgsClipper::clipEndTop(
double x0,
double y0,
double &x1,
double &y1,
double yMax )
507 x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
511 inline void QgsClipper::clipEndBottom(
double x0,
double y0,
double &x1,
double &y1,
double yMin )
513 x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
517 inline void QgsClipper::clipEndRight(
double x0,
double y0,
double &x1,
double &y1,
double xMax )
519 y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
523 inline void QgsClipper::clipEndLeft(
double x0,
double y0,
double &x1,
double &y1,
double xMin )
525 y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
530 inline bool QgsClipper::clipLineSegment(
double xLeft,
double xRight,
double yBottom,
double yTop,
double &x0,
double &y0,
double &x1,
double &y1 )
536 else if ( y1 > yTop )
541 else if ( x1 < xLeft )
546 else if ( y0 > yTop )
551 else if ( x0 < xLeft )
560 clipEndLeft( x0, y0, x1, y1, xLeft );
564 clipEndRight( x0, y0, x1, y1, xRight );
568 clipEndBottom( x0, y0, x1, y1, yBottom );
572 clipEndLeft( x0, y0, x1, y1, xLeft );
574 clipEndBottom( x0, y0, x1, y1, yBottom );
578 clipEndRight( x0, y0, x1, y1, xRight );
580 clipEndBottom( x0, y0, x1, y1, yBottom );
584 clipEndTop( x0, y0, x1, y1, yTop );
588 clipEndLeft( x0, y0, x1, y1, xLeft );
590 clipEndTop( x0, y0, x1, y1, yTop );
594 clipEndRight( x0, y0, x1, y1, xRight );
596 clipEndTop( x0, y0, x1, y1, yTop );
600 clipStartLeft( x0, y0, x1, y1, xLeft );
604 clipStartLeft( x0, y0, x1, y1, xLeft );
605 clipEndRight( x0, y0, x1, y1, xRight );
609 clipStartLeft( x0, y0, x1, y1, xLeft );
612 clipEndBottom( x0, y0, x1, y1, yBottom );
616 clipStartLeft( x0, y0, x1, y1, xLeft );
619 clipEndBottom( x0, y0, x1, y1, yBottom );
621 clipEndRight( x0, y0, x1, y1, xRight );
625 clipStartLeft( x0, y0, x1, y1, xLeft );
628 clipEndTop( x0, y0, x1, y1, yTop );
632 clipStartLeft( x0, y0, x1, y1, xLeft );
635 clipEndTop( x0, y0, x1, y1, yTop );
637 clipEndRight( x0, y0, x1, y1, xRight );
641 clipStartRight( x0, y0, x1, y1, xRight );
645 clipStartRight( x0, y0, x1, y1, xRight );
646 clipEndLeft( x0, y0, x1, y1, xLeft );
650 clipStartRight( x0, y0, x1, y1, xRight );
653 clipEndBottom( x0, y0, x1, y1, yBottom );
657 clipStartRight( x0, y0, x1, y1, xRight );
660 clipEndBottom( x0, y0, x1, y1, yBottom );
662 clipEndLeft( x0, y0, x1, y1, xLeft );
666 clipStartRight( x0, y0, x1, y1, xRight );
669 clipEndTop( x0, y0, x1, y1, yTop );
673 clipStartRight( x0, y0, x1, y1, xRight );
676 clipEndTop( x0, y0, x1, y1, yTop );
678 clipEndLeft( x0, y0, x1, y1, xLeft );
682 clipStartBottom( x0, y0, x1, y1, yBottom );
686 clipStartBottom( x0, y0, x1, y1, yBottom );
689 clipEndLeft( x0, y0, x1, y1, xLeft );
691 clipEndBottom( x0, y0, x1, y1, yBottom );
695 clipStartBottom( x0, y0, x1, y1, yBottom );
698 clipEndRight( x0, y0, x1, y1, xRight );
702 clipStartBottom( x0, y0, x1, y1, yBottom );
703 clipEndTop( x0, y0, x1, y1, yTop );
707 clipStartBottom( x0, y0, x1, y1, yBottom );
710 clipEndLeft( x0, y0, x1, y1, xLeft );
712 clipEndTop( x0, y0, x1, y1, yTop );
716 clipStartBottom( x0, y0, x1, y1, yBottom );
719 clipEndRight( x0, y0, x1, y1, xRight );
721 clipEndTop( x0, y0, x1, y1, yTop );
725 clipStartLeft( x0, y0, x1, y1, xLeft );
727 clipStartBottom( x0, y0, x1, y1, yBottom );
731 clipEndRight( x0, y0, x1, y1, xRight );
734 clipStartBottom( x0, y0, x1, y1, yBottom );
736 clipStartLeft( x0, y0, x1, y1, xLeft );
740 clipEndTop( x0, y0, x1, y1, yTop );
743 clipStartBottom( x0, y0, x1, y1, yBottom );
745 clipStartLeft( x0, y0, x1, y1, xLeft );
749 clipStartLeft( x0, y0, x1, y1, xLeft );
752 clipEndRight( x0, y0, x1, y1, xRight );
756 clipStartBottom( x0, y0, x1, y1, yBottom );
758 clipEndTop( x0, y0, x1, y1, yTop );
762 clipStartRight( x0, y0, x1, y1, xRight );
764 clipStartBottom( x0, y0, x1, y1, yBottom );
768 clipEndLeft( x0, y0, x1, y1, xLeft );
771 clipStartBottom( x0, y0, x1, y1, yBottom );
773 clipStartRight( x0, y0, x1, y1, xRight );
777 clipEndTop( x0, y0, x1, y1, yTop );
780 clipStartRight( x0, y0, x1, y1, xRight );
782 clipStartBottom( x0, y0, x1, y1, yBottom );
786 clipEndLeft( x0, y0, x1, y1, xLeft );
789 clipStartRight( x0, y0, x1, y1, xRight );
793 clipEndTop( x0, y0, x1, y1, yTop );
795 clipStartBottom( x0, y0, x1, y1, yBottom );
799 clipStartTop( x0, y0, x1, y1, yTop );
803 clipStartTop( x0, y0, x1, y1, yTop );
806 clipEndLeft( x0, y0, x1, y1, xLeft );
810 clipStartTop( x0, y0, x1, y1, yTop );
813 clipEndRight( x0, y0, x1, y1, xRight );
817 clipStartTop( x0, y0, x1, y1, yTop );
818 clipEndBottom( x0, y0, x1, y1, yBottom );
822 clipStartTop( x0, y0, x1, y1, yTop );
825 clipEndLeft( x0, y0, x1, y1, xLeft );
827 clipEndBottom( x0, y0, x1, y1, yBottom );
831 clipStartTop( x0, y0, x1, y1, yTop );
834 clipEndRight( x0, y0, x1, y1, xRight );
836 clipEndBottom( x0, y0, x1, y1, yBottom );
840 clipStartLeft( x0, y0, x1, y1, xLeft );
842 clipStartTop( x0, y0, x1, y1, yTop );
846 clipEndRight( x0, y0, x1, y1, xRight );
849 clipStartTop( x0, y0, x1, y1, yTop );
851 clipStartLeft( x0, y0, x1, y1, xLeft );
855 clipEndBottom( x0, y0, x1, y1, yBottom );
858 clipStartLeft( x0, y0, x1, y1, xLeft );
860 clipStartTop( x0, y0, x1, y1, yTop );
864 clipStartLeft( x0, y0, x1, y1, xLeft );
867 clipEndRight( x0, y0, x1, y1, xRight );
871 clipStartTop( x0, y0, x1, y1, yTop );
873 clipEndBottom( x0, y0, x1, y1, yBottom );
877 clipStartRight( x0, y0, x1, y1, xRight );
879 clipStartTop( x0, y0, x1, y1, yTop );
883 clipEndLeft( x0, y0, x1, y1, xLeft );
886 clipStartTop( x0, y0, x1, y1, yTop );
888 clipStartRight( x0, y0, x1, y1, xRight );
892 clipEndBottom( x0, y0, x1, y1, yBottom );
895 clipStartRight( x0, y0, x1, y1, xRight );
897 clipStartTop( x0, y0, x1, y1, yTop );
901 clipEndLeft( x0, y0, x1, y1, xLeft );
904 clipStartRight( x0, y0, x1, y1, xRight );
908 clipEndBottom( x0, y0, x1, y1, yBottom );
910 clipStartTop( x0, y0, x1, y1, yTop );
A class to trim lines and polygons to within a rectangular region.
static void trimPolygon(QPolygonF &pts, const QgsRectangle &clipRect)
static bool clipLineSegment(double left, double right, double bottom, double top, double &x0, double &y0, double &x1, double &y1)
Clips a line segment to a rectangle.
Boundary
A handy way to refer to the four boundaries.
static const double MAX_X
Maximum X-coordinate of the rectangular box used for clipping.
static const double MIN_Y
Minimum Y-coordinate of the rectangular box used for clipping.
static const double MAX_Y
Maximum Y-coordinate of the rectangular box used for clipping.
static const double MIN_X
Minimum X-coordinate of the rectangular box used for clipping.
static void trimFeature(QVector< double > &x, QVector< double > &y, bool shapeOpen)
Trims the given feature to a rectangular box.
Abstract base class for curved geometry type.
A class to represent a 2D point.
void set(double x, double y) SIP_HOLDGIL
Sets the x and y value of the point.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
#define SIP_IF_FEATURE(feature)
#define SIP_FEATURE(feature)