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 );
122 static const double SMALL_NUM;
126 static inline void trimFeatureToBoundary(
const QVector<double> &inX,
127 const QVector<double> &inY,
128 QVector<double> &outX,
129 QVector<double> &outY,
133 static inline void trimPolygonToBoundary(
const QPolygonF &inPts, QPolygonF &outPts,
const QgsRectangle &rect, Boundary b,
double boundaryValue );
136 static inline bool inside(
double x,
double y, Boundary b );
138 static inline bool inside( QPointF pt, Boundary b,
double val );
142 static inline QgsPointXY intersect(
double x1,
double y1,
143 double x2,
double y2,
146 static inline QPointF intersectRect( QPointF pt1,
151 static bool clipLineSegment(
double xLeft,
double xRight,
double yBottom,
double yTop,
double &x0,
double &y0,
double &x1,
double &y1 );
162 static void connectSeparatedLines(
double x0,
double y0,
double x1,
double y1,
166 static void clipStartTop(
double &x0,
double &y0,
double x1,
double y1,
double yMax );
167 static void clipStartBottom(
double &x0,
double &y0,
double x1,
double y1,
double yMin );
168 static void clipStartRight(
double &x0,
double &y0,
double x1,
double y1,
double xMax );
169 static void clipStartLeft(
double &x0,
double &y0,
double &x1,
double &y1,
double xMin );
170 static void clipEndTop(
double x0,
double y0,
double &x1,
double &y1,
double yMax );
171 static void clipEndBottom(
double x0,
double y0,
double &x1,
double &y1,
double yMin );
172 static void clipEndRight(
double x0,
double y0,
double &x1,
double &y1,
double xMax );
173 static void clipEndLeft(
double x0,
double y0,
double &x1,
double &y1,
double xMin );
193 QVector<double> tmpX;
194 QVector<double> tmpY;
195 trimFeatureToBoundary( x, y, tmpX, tmpY,
XMax, shapeOpen );
199 trimFeatureToBoundary( tmpX, tmpY, x, y,
YMax, shapeOpen );
203 trimFeatureToBoundary( x, y, tmpX, tmpY,
XMin, shapeOpen );
207 trimFeatureToBoundary( tmpX, tmpY, x, y,
YMin, shapeOpen );
213 tmpPts.reserve( pts.size() );
215 trimPolygonToBoundary( pts, tmpPts, clipRect,
XMax, clipRect.
xMaximum() );
217 trimPolygonToBoundary( tmpPts, pts, clipRect,
YMax, clipRect.
yMaximum() );
219 trimPolygonToBoundary( pts, tmpPts, clipRect,
XMin, clipRect.
xMinimum() );
221 trimPolygonToBoundary( tmpPts, pts, clipRect,
YMin, clipRect.
yMinimum() );
229 inline void QgsClipper::trimFeatureToBoundary(
230 const QVector<double> &inX,
231 const QVector<double> &inY,
232 QVector<double> &outX,
233 QVector<double> &outY,
234 Boundary b,
bool shapeOpen )
240 int i1 = inX.size() - 1;
243 for (
int i2 = 0; i2 < inX.size() ; ++i2 )
248 if ( std::isnan( inX[i2] ) || std::isnan( inY[i2] ) || std::isinf( inX[i2] ) || std::isinf( inY[i2] )
249 || std::isnan( inX[i1] ) || std::isnan( inY[i1] ) || std::isinf( inX[i1] ) || std::isinf( inY[i1] ) )
256 if ( inside( inX[i2], inY[i2], b ) )
258 if ( inside( inX[i1], inY[i1], b ) )
260 outX.push_back( inX[i2] );
261 outY.push_back( inY[i2] );
267 if ( !( i2 == 0 && shapeOpen ) )
269 const QgsPointXY p = intersect( inX[i1], inY[i1], inX[i2], inY[i2], b );
270 outX.push_back( p.
x() );
271 outY.push_back( p.
y() );
274 outX.push_back( inX[i2] );
275 outY.push_back( inY[i2] );
281 if ( inside( inX[i1], inY[i1], b ) )
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() );
295 inline void QgsClipper::trimPolygonToBoundary(
const QPolygonF &inPts, QPolygonF &outPts,
const QgsRectangle &rect, Boundary b,
double boundaryValue )
297 int i1 = inPts.size() - 1;
300 for (
int i2 = 0; i2 < inPts.size() ; ++i2 )
303 if ( inside( inPts[i2], b, boundaryValue ) )
305 if ( inside( inPts[i1], b, boundaryValue ) )
307 outPts.append( inPts[i2] );
313 outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
314 outPts.append( inPts[i2] );
320 if ( inside( inPts[i1], b, boundaryValue ) )
322 outPts.append( intersectRect( inPts[i1], inPts[i2], b, rect ) );
332 inline bool QgsClipper::inside(
const double x,
const double y, Boundary b )
356 inline bool QgsClipper::inside( QPointF pt, Boundary b,
double val )
361 return ( pt.x() < val );
363 return ( pt.x() > val );
365 return ( pt.y() < val );
367 return ( pt.y() > val );
377 inline QgsPointXY QgsClipper::intersect(
const double x1,
const double y1,
378 const double x2,
const double y2,
385 double r_n = SMALL_NUM, r_d = SMALL_NUM;
409 if ( std::fabs( r_d ) > SMALL_NUM && std::fabs( r_n ) > SMALL_NUM )
412 const double r = r_n / r_d;
413 p.
set( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
419 Q_ASSERT( std::fabs( r_d ) > SMALL_NUM && std::fabs( r_n ) > SMALL_NUM );
425 inline QPointF QgsClipper::intersectRect( QPointF pt1,
433 double r_n = SMALL_NUM, r_d = SMALL_NUM;
434 const double x1 = pt1.x(), x2 = pt2.x();
435 const double y1 = pt1.y(), y2 = pt2.y();
462 return QPointF( x1 + r * ( x2 - x1 ), y1 + r * ( y2 - y1 ) );
465 inline void QgsClipper::clipStartTop(
double &x0,
double &y0,
double x1,
double y1,
double yMax )
467 x0 += ( x1 - x0 ) * ( yMax - y0 ) / ( y1 - y0 );
471 inline void QgsClipper::clipStartBottom(
double &x0,
double &y0,
double x1,
double y1,
double yMin )
473 x0 += ( x1 - x0 ) * ( yMin - y0 ) / ( y1 - y0 );
477 inline void QgsClipper::clipStartRight(
double &x0,
double &y0,
double x1,
double y1,
double xMax )
479 y0 += ( y1 - y0 ) * ( xMax - x0 ) / ( x1 - x0 );
483 inline void QgsClipper::clipStartLeft(
double &x0,
double &y0,
double &x1,
double &y1,
double xMin )
485 y0 += ( y1 - y0 ) * ( xMin - x0 ) / ( x1 - x0 );
489 inline void QgsClipper::clipEndTop(
double x0,
double y0,
double &x1,
double &y1,
double yMax )
491 x1 += ( x1 - x0 ) * ( yMax - y1 ) / ( y1 - y0 );
495 inline void QgsClipper::clipEndBottom(
double x0,
double y0,
double &x1,
double &y1,
double yMin )
497 x1 += ( x1 - x0 ) * ( yMin - y1 ) / ( y1 - y0 );
501 inline void QgsClipper::clipEndRight(
double x0,
double y0,
double &x1,
double &y1,
double xMax )
503 y1 += ( y1 - y0 ) * ( xMax - x1 ) / ( x1 - x0 );
507 inline void QgsClipper::clipEndLeft(
double x0,
double y0,
double &x1,
double &y1,
double xMin )
509 y1 += ( y1 - y0 ) * ( xMin - x1 ) / ( x1 - x0 );
514 inline bool QgsClipper::clipLineSegment(
double xLeft,
double xRight,
double yBottom,
double yTop,
double &x0,
double &y0,
double &x1,
double &y1 )
520 else if ( y1 > yTop )
525 else if ( x1 < xLeft )
530 else if ( y0 > yTop )
535 else if ( x0 < xLeft )
544 clipEndLeft( x0, y0, x1, y1, xLeft );
548 clipEndRight( x0, y0, x1, y1, xRight );
552 clipEndBottom( x0, y0, x1, y1, yBottom );
556 clipEndLeft( x0, y0, x1, y1, xLeft );
558 clipEndBottom( x0, y0, x1, y1, yBottom );
562 clipEndRight( x0, y0, x1, y1, xRight );
564 clipEndBottom( x0, y0, x1, y1, yBottom );
568 clipEndTop( x0, y0, x1, y1, yTop );
572 clipEndLeft( x0, y0, x1, y1, xLeft );
574 clipEndTop( x0, y0, x1, y1, yTop );
578 clipEndRight( x0, y0, x1, y1, xRight );
580 clipEndTop( x0, y0, x1, y1, yTop );
584 clipStartLeft( x0, y0, x1, y1, xLeft );
588 clipStartLeft( x0, y0, x1, y1, xLeft );
589 clipEndRight( x0, y0, x1, y1, xRight );
593 clipStartLeft( x0, y0, x1, y1, xLeft );
596 clipEndBottom( x0, y0, x1, y1, yBottom );
600 clipStartLeft( x0, y0, x1, y1, xLeft );
603 clipEndBottom( x0, y0, x1, y1, yBottom );
605 clipEndRight( x0, y0, x1, y1, xRight );
609 clipStartLeft( x0, y0, x1, y1, xLeft );
612 clipEndTop( x0, y0, x1, y1, yTop );
616 clipStartLeft( x0, y0, x1, y1, xLeft );
619 clipEndTop( x0, y0, x1, y1, yTop );
621 clipEndRight( x0, y0, x1, y1, xRight );
625 clipStartRight( x0, y0, x1, y1, xRight );
629 clipStartRight( x0, y0, x1, y1, xRight );
630 clipEndLeft( x0, y0, x1, y1, xLeft );
634 clipStartRight( x0, y0, x1, y1, xRight );
637 clipEndBottom( x0, y0, x1, y1, yBottom );
641 clipStartRight( x0, y0, x1, y1, xRight );
644 clipEndBottom( x0, y0, x1, y1, yBottom );
646 clipEndLeft( x0, y0, x1, y1, xLeft );
650 clipStartRight( x0, y0, x1, y1, xRight );
653 clipEndTop( x0, y0, x1, y1, yTop );
657 clipStartRight( x0, y0, x1, y1, xRight );
660 clipEndTop( x0, y0, x1, y1, yTop );
662 clipEndLeft( x0, y0, x1, y1, xLeft );
666 clipStartBottom( x0, y0, x1, y1, yBottom );
670 clipStartBottom( x0, y0, x1, y1, yBottom );
673 clipEndLeft( x0, y0, x1, y1, xLeft );
675 clipEndBottom( x0, y0, x1, y1, yBottom );
679 clipStartBottom( x0, y0, x1, y1, yBottom );
682 clipEndRight( x0, y0, x1, y1, xRight );
686 clipStartBottom( x0, y0, x1, y1, yBottom );
687 clipEndTop( x0, y0, x1, y1, yTop );
691 clipStartBottom( x0, y0, x1, y1, yBottom );
694 clipEndLeft( x0, y0, x1, y1, xLeft );
696 clipEndTop( x0, y0, x1, y1, yTop );
700 clipStartBottom( x0, y0, x1, y1, yBottom );
703 clipEndRight( x0, y0, x1, y1, xRight );
705 clipEndTop( x0, y0, x1, y1, yTop );
709 clipStartLeft( x0, y0, x1, y1, xLeft );
711 clipStartBottom( x0, y0, x1, y1, yBottom );
715 clipEndRight( x0, y0, x1, y1, xRight );
718 clipStartBottom( x0, y0, x1, y1, yBottom );
720 clipStartLeft( x0, y0, x1, y1, xLeft );
724 clipEndTop( x0, y0, x1, y1, yTop );
727 clipStartBottom( x0, y0, x1, y1, yBottom );
729 clipStartLeft( x0, y0, x1, y1, xLeft );
733 clipStartLeft( x0, y0, x1, y1, xLeft );
736 clipEndRight( x0, y0, x1, y1, xRight );
740 clipStartBottom( x0, y0, x1, y1, yBottom );
742 clipEndTop( x0, y0, x1, y1, yTop );
746 clipStartRight( x0, y0, x1, y1, xRight );
748 clipStartBottom( x0, y0, x1, y1, yBottom );
752 clipEndLeft( x0, y0, x1, y1, xLeft );
755 clipStartBottom( x0, y0, x1, y1, yBottom );
757 clipStartRight( x0, y0, x1, y1, xRight );
761 clipEndTop( x0, y0, x1, y1, yTop );
764 clipStartRight( x0, y0, x1, y1, xRight );
766 clipStartBottom( x0, y0, x1, y1, yBottom );
770 clipEndLeft( x0, y0, x1, y1, xLeft );
773 clipStartRight( x0, y0, x1, y1, xRight );
777 clipEndTop( x0, y0, x1, y1, yTop );
779 clipStartBottom( x0, y0, x1, y1, yBottom );
783 clipStartTop( x0, y0, x1, y1, yTop );
787 clipStartTop( x0, y0, x1, y1, yTop );
790 clipEndLeft( x0, y0, x1, y1, xLeft );
794 clipStartTop( x0, y0, x1, y1, yTop );
797 clipEndRight( x0, y0, x1, y1, xRight );
801 clipStartTop( x0, y0, x1, y1, yTop );
802 clipEndBottom( x0, y0, x1, y1, yBottom );
806 clipStartTop( x0, y0, x1, y1, yTop );
809 clipEndLeft( x0, y0, x1, y1, xLeft );
811 clipEndBottom( x0, y0, x1, y1, yBottom );
815 clipStartTop( x0, y0, x1, y1, yTop );
818 clipEndRight( x0, y0, x1, y1, xRight );
820 clipEndBottom( x0, y0, x1, y1, yBottom );
824 clipStartLeft( x0, y0, x1, y1, xLeft );
826 clipStartTop( x0, y0, x1, y1, yTop );
830 clipEndRight( x0, y0, x1, y1, xRight );
833 clipStartTop( x0, y0, x1, y1, yTop );
835 clipStartLeft( x0, y0, x1, y1, xLeft );
839 clipEndBottom( x0, y0, x1, y1, yBottom );
842 clipStartLeft( x0, y0, x1, y1, xLeft );
844 clipStartTop( x0, y0, x1, y1, yTop );
848 clipStartLeft( x0, y0, x1, y1, xLeft );
851 clipEndRight( x0, y0, x1, y1, xRight );
855 clipStartTop( x0, y0, x1, y1, yTop );
857 clipEndBottom( x0, y0, x1, y1, yBottom );
861 clipStartRight( x0, y0, x1, y1, xRight );
863 clipStartTop( x0, y0, x1, y1, yTop );
867 clipEndLeft( x0, y0, x1, y1, xLeft );
870 clipStartTop( x0, y0, x1, y1, yTop );
872 clipStartRight( x0, y0, x1, y1, xRight );
876 clipEndBottom( x0, y0, x1, y1, yBottom );
879 clipStartRight( x0, y0, x1, y1, xRight );
881 clipStartTop( x0, y0, x1, y1, yTop );
885 clipEndLeft( x0, y0, x1, y1, xLeft );
888 clipStartRight( x0, y0, x1, y1, xRight );
892 clipEndBottom( x0, y0, x1, y1, yBottom );
894 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)
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)