22 #include "qgis_core.h" 95 static void trimFeature( QVector<double> &x,
101 static void trimPolygon( QPolygonF &pts,
const QgsRectangle &clipRect );
114 static const double SMALL_NUM;
118 static void trimFeatureToBoundary(
const QVector<double> &inX,
119 const QVector<double> &inY,
120 QVector<double> &outX,
121 QVector<double> &outY,
125 static void trimPolygonToBoundary(
const QPolygonF &inPts, QPolygonF &outPts,
const QgsRectangle &rect,
Boundary b,
double boundaryValue );
128 static bool inside(
double x,
double y,
Boundary b );
130 static bool inside( QPointF pt,
Boundary b,
double val );
134 static QgsPointXY intersect(
double x1,
double y1,
135 double x2,
double y2,
138 static QPointF intersectRect( QPointF pt1,
143 static bool clipLineSegment(
double xLeft,
double xRight,
double yBottom,
double yTop,
double &x0,
double &y0,
double &x1,
double &y1 );
154 static void connectSeparatedLines(
double x0,
double y0,
double x1,
double y1,
158 static void clipStartTop(
double &x0,
double &y0,
double x1,
double y1,
double yMax );
159 static void clipStartBottom(
double &x0,
double &y0,
double x1,
double y1,
double yMin );
160 static void clipStartRight(
double &x0,
double &y0,
double x1,
double y1,
double xMax );
161 static void clipStartLeft(
double &x0,
double &y0,
double &x1,
double &y1,
double xMin );
162 static void clipEndTop(
double x0,
double y0,
double &x1,
double &y1,
double yMax );
163 static void clipEndBottom(
double x0,
double y0,
double &x1,
double &y1,
double yMin );
164 static void clipEndRight(
double x0,
double y0,
double &x1,
double &y1,
double xMax );
165 static void clipEndLeft(
double x0,
double y0,
double &x1,
double &y1,
double xMin );
185 QVector<double> tmpX;
186 QVector<double> tmpY;
187 trimFeatureToBoundary( x, y, tmpX, tmpY,
XMax, shapeOpen );
191 trimFeatureToBoundary( tmpX, tmpY, x, y,
YMax, shapeOpen );
195 trimFeatureToBoundary( x, y, tmpX, tmpY,
XMin, shapeOpen );
199 trimFeatureToBoundary( tmpX, tmpY, x, y,
YMin, shapeOpen );
205 tmpPts.reserve( pts.size() );
207 trimPolygonToBoundary( pts, tmpPts, clipRect,
XMax, clipRect.
xMaximum() );
209 trimPolygonToBoundary( tmpPts, pts, clipRect,
YMax, clipRect.
yMaximum() );
211 trimPolygonToBoundary( pts, tmpPts, clipRect,
XMin, clipRect.
xMinimum() );
213 trimPolygonToBoundary( tmpPts, pts, clipRect,
YMin, clipRect.
yMinimum() );
221 inline void QgsClipper::trimFeatureToBoundary(
222 const QVector<double> &inX,
223 const QVector<double> &inY,
224 QVector<double> &outX,
225 QVector<double> &outY,
232 int i1 = inX.size() - 1;
235 for (
int i2 = 0; i2 < inX.size() ; ++i2 )
240 if ( std::isnan( inX[i2] ) || std::isnan( inY[i2] ) || std::isinf( inX[i2] ) || std::isinf( inY[i2] )
241 || std::isnan( inX[i1] ) || std::isnan( inY[i1] ) || std::isinf( inX[i1] ) || std::isinf( inY[i1] ) )
248 if ( inside( inX[i2], inY[i2], b ) )
250 if ( inside( inX[i1], inY[i1], b ) )
252 outX.push_back( inX[i2] );
253 outY.push_back( inY[i2] );
259 if ( !( i2 == 0 && shapeOpen ) )
261 QgsPointXY p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
262 outX.push_back( p.
x() );
263 outY.push_back( p.
y() );
266 outX.push_back( inX[i2] );
267 outY.push_back( inY[i2] );
273 if ( inside( inX[i1], inY[i1], b ) )
275 if ( !( i2 == 0 && shapeOpen ) )
277 QgsPointXY p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
278 outX.push_back( p.
x() );
279 outY.push_back( p.
y() );
287 inline void QgsClipper::trimPolygonToBoundary(
const QPolygonF &inPts, QPolygonF &outPts,
const QgsRectangle &rect,
Boundary b,
double boundaryValue )
289 int i1 = inPts.size() - 1;
292 for (
int i2 = 0; i2 < inPts.size() ; ++i2 )
295 if ( inside( inPts[i2], b, boundaryValue ) )
297 if ( inside( inPts[i1], b, boundaryValue ) )
299 outPts.append( inPts[i2] );
305 outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
306 outPts.append( inPts[i2] );
312 if ( inside( inPts[i1], b, boundaryValue ) )
314 outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
324 inline bool QgsClipper::inside(
const double x,
const double y,
Boundary b )
348 inline bool QgsClipper::inside( QPointF pt,
Boundary b,
double val )
353 return ( pt.x() < val );
355 return ( pt.x() > val );
357 return ( pt.y() < val );
359 return ( pt.y() > val );
369 inline QgsPointXY QgsClipper::intersect(
const double x1,
const double y1,
370 const double x2,
const double y2,
377 double r_n = SMALL_NUM, r_d = SMALL_NUM;
401 if ( std::fabs( r_d ) > SMALL_NUM && std::fabs( r_n ) > SMALL_NUM )
404 double r = r_n / r_d;
405 p.
set( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
411 Q_ASSERT( std::fabs( r_d ) > SMALL_NUM && std::fabs( r_n ) > SMALL_NUM );
417 inline QPointF QgsClipper::intersectRect( QPointF pt1,
425 double r_n = SMALL_NUM, r_d = SMALL_NUM;
426 const double x1 = pt1.x(), x2 = pt2.x();
427 const double y1 = pt1.y(), y2 = pt2.y();
454 return QPointF( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
457 inline void QgsClipper::clipStartTop(
double &x0,
double &y0,
double x1,
double y1,
double yMax )
459 x0 += ( x1 - x0 ) * ( yMax - y0 ) / ( y1 - y0 );
463 inline void QgsClipper::clipStartBottom(
double &x0,
double &y0,
double x1,
double y1,
double yMin )
465 x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
469 inline void QgsClipper::clipStartRight(
double &x0,
double &y0,
double x1,
double y1,
double xMax )
471 y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
475 inline void QgsClipper::clipStartLeft(
double &x0,
double &y0,
double &x1,
double &y1,
double xMin )
477 y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
481 inline void QgsClipper::clipEndTop(
double x0,
double y0,
double &x1,
double &y1,
double yMax )
483 x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
487 inline void QgsClipper::clipEndBottom(
double x0,
double y0,
double &x1,
double &y1,
double yMin )
489 x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
493 inline void QgsClipper::clipEndRight(
double x0,
double y0,
double &x1,
double &y1,
double xMax )
495 y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
499 inline void QgsClipper::clipEndLeft(
double x0,
double y0,
double &x1,
double &y1,
double xMin )
501 y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
506 inline bool QgsClipper::clipLineSegment(
double xLeft,
double xRight,
double yBottom,
double yTop,
double &x0,
double &y0,
double &x1,
double &y1 )
512 else if ( y1 > yTop )
517 else if ( x1 < xLeft )
522 else if ( y0 > yTop )
527 else if ( x0 < xLeft )
536 clipEndLeft( x0, y0, x1, y1, xLeft );
540 clipEndRight( x0, y0, x1, y1, xRight );
544 clipEndBottom( x0, y0, x1, y1, yBottom );
548 clipEndLeft( x0, y0, x1, y1, xLeft );
550 clipEndBottom( x0, y0, x1, y1, yBottom );
554 clipEndRight( x0, y0, x1, y1, xRight );
556 clipEndBottom( x0, y0, x1, y1, yBottom );
560 clipEndTop( x0, y0, x1, y1, yTop );
564 clipEndLeft( x0, y0, x1, y1, xLeft );
566 clipEndTop( x0, y0, x1, y1, yTop );
570 clipEndRight( x0, y0, x1, y1, xRight );
572 clipEndTop( x0, y0, x1, y1, yTop );
576 clipStartLeft( x0, y0, x1, y1, xLeft );
580 clipStartLeft( x0, y0, x1, y1, xLeft );
581 clipEndRight( x0, y0, x1, y1, xRight );
585 clipStartLeft( x0, y0, x1, y1, xLeft );
588 clipEndBottom( x0, y0, x1, y1, yBottom );
592 clipStartLeft( x0, y0, x1, y1, xLeft );
595 clipEndBottom( x0, y0, x1, y1, yBottom );
597 clipEndRight( x0, y0, x1, y1, xRight );
601 clipStartLeft( x0, y0, x1, y1, xLeft );
604 clipEndTop( x0, y0, x1, y1, yTop );
608 clipStartLeft( x0, y0, x1, y1, xLeft );
611 clipEndTop( x0, y0, x1, y1, yTop );
613 clipEndRight( x0, y0, x1, y1, xRight );
617 clipStartRight( x0, y0, x1, y1, xRight );
621 clipStartRight( x0, y0, x1, y1, xRight );
622 clipEndLeft( x0, y0, x1, y1, xLeft );
626 clipStartRight( x0, y0, x1, y1, xRight );
629 clipEndBottom( x0, y0, x1, y1, yBottom );
633 clipStartRight( x0, y0, x1, y1, xRight );
636 clipEndBottom( x0, y0, x1, y1, yBottom );
638 clipEndLeft( x0, y0, x1, y1, xLeft );
642 clipStartRight( x0, y0, x1, y1, xRight );
645 clipEndTop( x0, y0, x1, y1, yTop );
649 clipStartRight( x0, y0, x1, y1, xRight );
652 clipEndTop( x0, y0, x1, y1, yTop );
654 clipEndLeft( x0, y0, x1, y1, xLeft );
658 clipStartBottom( x0, y0, x1, y1, yBottom );
662 clipStartBottom( x0, y0, x1, y1, yBottom );
665 clipEndLeft( x0, y0, x1, y1, xLeft );
667 clipEndBottom( x0, y0, x1, y1, yBottom );
671 clipStartBottom( x0, y0, x1, y1, yBottom );
674 clipEndRight( x0, y0, x1, y1, xRight );
678 clipStartBottom( x0, y0, x1, y1, yBottom );
679 clipEndTop( x0, y0, x1, y1, yTop );
683 clipStartBottom( x0, y0, x1, y1, yBottom );
686 clipEndLeft( x0, y0, x1, y1, xLeft );
688 clipEndTop( x0, y0, x1, y1, yTop );
692 clipStartBottom( x0, y0, x1, y1, yBottom );
695 clipEndRight( x0, y0, x1, y1, xRight );
697 clipEndTop( x0, y0, x1, y1, yTop );
701 clipStartLeft( x0, y0, x1, y1, xLeft );
703 clipStartBottom( x0, y0, x1, y1, yBottom );
707 clipEndRight( x0, y0, x1, y1, xRight );
710 clipStartBottom( x0, y0, x1, y1, yBottom );
712 clipStartLeft( x0, y0, x1, y1, xLeft );
716 clipEndTop( x0, y0, x1, y1, yTop );
719 clipStartBottom( x0, y0, x1, y1, yBottom );
721 clipStartLeft( x0, y0, x1, y1, xLeft );
725 clipStartLeft( x0, y0, x1, y1, xLeft );
728 clipEndRight( x0, y0, x1, y1, xRight );
732 clipStartBottom( x0, y0, x1, y1, yBottom );
734 clipEndTop( x0, y0, x1, y1, yTop );
738 clipStartRight( x0, y0, x1, y1, xRight );
740 clipStartBottom( x0, y0, x1, y1, yBottom );
744 clipEndLeft( x0, y0, x1, y1, xLeft );
747 clipStartBottom( x0, y0, x1, y1, yBottom );
749 clipStartRight( x0, y0, x1, y1, xRight );
753 clipEndTop( x0, y0, x1, y1, yTop );
756 clipStartRight( x0, y0, x1, y1, xRight );
758 clipStartBottom( x0, y0, x1, y1, yBottom );
762 clipEndLeft( x0, y0, x1, y1, xLeft );
765 clipStartRight( x0, y0, x1, y1, xRight );
769 clipEndTop( x0, y0, x1, y1, yTop );
771 clipStartBottom( x0, y0, x1, y1, yBottom );
775 clipStartTop( x0, y0, x1, y1, yTop );
779 clipStartTop( x0, y0, x1, y1, yTop );
782 clipEndLeft( x0, y0, x1, y1, xLeft );
786 clipStartTop( x0, y0, x1, y1, yTop );
789 clipEndRight( x0, y0, x1, y1, xRight );
793 clipStartTop( x0, y0, x1, y1, yTop );
794 clipEndBottom( x0, y0, x1, y1, yBottom );
798 clipStartTop( x0, y0, x1, y1, yTop );
801 clipEndLeft( x0, y0, x1, y1, xLeft );
803 clipEndBottom( x0, y0, x1, y1, yBottom );
807 clipStartTop( x0, y0, x1, y1, yTop );
810 clipEndRight( x0, y0, x1, y1, xRight );
812 clipEndBottom( x0, y0, x1, y1, yBottom );
816 clipStartLeft( x0, y0, x1, y1, xLeft );
818 clipStartTop( x0, y0, x1, y1, yTop );
822 clipEndRight( x0, y0, x1, y1, xRight );
825 clipStartTop( x0, y0, x1, y1, yTop );
827 clipStartLeft( x0, y0, x1, y1, xLeft );
831 clipEndBottom( x0, y0, x1, y1, yBottom );
834 clipStartLeft( x0, y0, x1, y1, xLeft );
836 clipStartTop( x0, y0, x1, y1, yTop );
840 clipStartLeft( x0, y0, x1, y1, xLeft );
843 clipEndRight( x0, y0, x1, y1, xRight );
847 clipStartTop( x0, y0, x1, y1, yTop );
849 clipEndBottom( x0, y0, x1, y1, yBottom );
853 clipStartRight( x0, y0, x1, y1, xRight );
855 clipStartTop( x0, y0, x1, y1, yTop );
859 clipEndLeft( x0, y0, x1, y1, xLeft );
862 clipStartTop( x0, y0, x1, y1, yTop );
864 clipStartRight( x0, y0, x1, y1, xRight );
868 clipEndBottom( x0, y0, x1, y1, yBottom );
871 clipStartRight( x0, y0, x1, y1, xRight );
873 clipStartTop( x0, y0, x1, y1, yTop );
877 clipEndLeft( x0, y0, x1, y1, xLeft );
880 clipStartRight( x0, y0, x1, y1, xRight );
884 clipEndBottom( x0, y0, x1, y1, yBottom );
886 clipStartTop( x0, y0, x1, y1, yTop );
static const double MAX_Y
Maximum Y-coordinate of the rectangular box used for clipping.
void set(double x, double y)
Sets the x and y value of the point.
A rectangle specified with double values.
static void trimFeature(QVector< double > &x, QVector< double > &y, bool shapeOpen)
Trims the given feature to a rectangular box.
A class to represent a 2D point.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
static const double MIN_X
Minimum X-coordinate of the rectangular box used for clipping.
A class to trim lines and polygons to within a rectangular region.
Abstract base class for curved geometry type.
#define SIP_IF_FEATURE(feature)
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Boundary
A handy way to refer to the four boundaries.
#define SIP_FEATURE(feature)
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
static const double MIN_Y
Minimum Y-coordinate of the rectangular box used for clipping.
static void trimPolygon(QPolygonF &pts, const QgsRectangle &clipRect)
static const double MAX_X
Maximum X-coordinate of the rectangular box used for clipping.