18#include "moc_qgsgeometryvalidator.cpp" 
   28  : mGeometry( geometry )
 
 
   47void QgsGeometryValidator::checkRingIntersections( 
int partIndex0, 
int ringIndex0, 
const QgsCurve *ring0, 
int partIndex1, 
int ringIndex1, 
const QgsCurve *ring1 )
 
   49  const QgsLineString *ringLine0 = qgsgeometry_cast< const QgsLineString * >( ring0 );
 
   50  std::unique_ptr< QgsLineString > segmentisedRing0;
 
   53    segmentisedRing0.reset( qgsgeometry_cast< QgsLineString * >( ring0->
segmentize() ) );
 
   54    ringLine0 = segmentisedRing0.get();
 
   57  const QgsLineString *ringLine1 = qgsgeometry_cast< const QgsLineString * >( ring1 );
 
   58  std::unique_ptr< QgsLineString > segmentisedRing1;
 
   61    segmentisedRing1.reset( qgsgeometry_cast< QgsLineString * >( ring1->
segmentize() ) );
 
   62    ringLine1 = segmentisedRing1.get();
 
   65  Q_ASSERT( ringLine0 );
 
   66  Q_ASSERT( ringLine1 );
 
   68  for ( 
int i = 0; !mStop && i < ringLine0->
numPoints() - 1; i++ )
 
   70    const double ring0XAti = ringLine0->
xAt( i );
 
   71    const double ring0YAti = ringLine0->
yAt( i );
 
   72    const QgsVector v( ringLine0->
xAt( i + 1 ) - ring0XAti, ringLine0->
yAt( i + 1 ) - ring0YAti );
 
   74    for ( 
int j = 0; !mStop && j < ringLine1->
numPoints() - 1; j++ )
 
   76      const double ring1XAtj = ringLine1->
xAt( j );
 
   77      const double ring1YAtj = ringLine1->
yAt( j );
 
   78      const QgsVector w( ringLine1->
xAt( j + 1 ) - ring1XAtj, ringLine1->
yAt( j + 1 ) - ring1YAtj );
 
   82      if ( intersectLines( ring0XAti, ring0YAti, v, ring1XAtj, ring1YAtj, w, sX, sY ) )
 
   84        double d = -distLine2Point( ring0XAti, ring0YAti, v.perpVector(), sX, sY );
 
   86        if ( d >= 0 && d <= v.length() )
 
   88          d = -distLine2Point( ring1XAtj, ring1YAtj, w.perpVector(), sX, sY );
 
   89          if ( d > 0 && d < w.length() &&
 
   93            const QString msg = QObject::tr( 
"segment %1 of ring %2 of polygon %3 intersects segment %4 of ring %5 of polygon %6 at %7, %8" )
 
   94                                .arg( i ).arg( ringIndex0 ).arg( partIndex0 )
 
   95                                .arg( j ).arg( ringIndex1 ).arg( partIndex1 )
 
  106void QgsGeometryValidator::validatePolyline( 
int i, 
const QgsLineString *line, 
bool ring )
 
  115      const QString msg = QObject::tr( 
"ring %1 with less than four points" ).arg( i );
 
  129        msg = QObject::tr( 
"ring %1 not closed, Z mismatch: %2 vs %3" ).arg( i ).arg( startPoint.
z() ).arg( endPoint.
z() );
 
  133        msg = QObject::tr( 
"ring %1 not closed" ).arg( i );
 
  143    const QString msg = QObject::tr( 
"line %1 with less than two points" ).arg( i );
 
  150  std::unique_ptr< QgsLineString > noDupes;
 
  155  if ( !duplicateNodes.empty() )
 
  157    noDupes.reset( line->
clone() );
 
  158    for ( 
int j = duplicateNodes.size() - 1; j >= 0; j-- )
 
  160      const QgsVertexId duplicateVertex = duplicateNodes.at( j );
 
  161      const QgsPointXY duplicationLocation = noDupes->vertexAt( duplicateVertex );
 
  162      noDupes->deleteVertex( duplicateVertex );
 
  166      for ( 
int k = j - 1; k >= 0; k-- )
 
  168        const QgsVertexId prevDupe = duplicateNodes.at( k );
 
  183      const QString msg = QObject::tr( 
"line %1 contains %n duplicate node(s) starting at vertex %2", 
"number of duplicate nodes", n + 1 ).arg( i + 1 ).arg( duplicateVertex.
vertex - n + 1 );
 
  188    line = noDupes.get();
 
  192  for ( 
int j = 0; !mStop && j < line->
numPoints() - 3; j++ )
 
  195    for ( 
int k = j + 2; !mStop && k < n; k++ )
 
  197      double intersectionPointX = std::numeric_limits<double>::quiet_NaN();
 
  198      double intersectionPointY = std::numeric_limits<double>::quiet_NaN();
 
  199      bool isIntersection = 
false;
 
  200      if ( 
QgsGeometryUtilsBase::segmentIntersection( line->
xAt( j ), line->
yAt( j ), line->
xAt( j + 1 ), line->
yAt( j + 1 ), line->
xAt( k ), line->
yAt( k ), line->
xAt( k + 1 ), line->
yAt( k + 1 ), intersectionPointX, intersectionPointY, isIntersection ) )
 
  202        const QString msg = QObject::tr( 
"segments %1 and %2 of line %3 intersect at %4, %5" ).arg( j ).arg( k ).arg( i ).arg( intersectionPointX ).arg( intersectionPointY );
 
  211void QgsGeometryValidator::validatePolygon( 
int partIndex, 
const QgsCurvePolygon *polygon )
 
  218      const QString msg = QObject::tr( 
"ring %1 of polygon %2 not in exterior ring" ).arg( i + 1 ).arg( partIndex );
 
  230      checkRingIntersections( partIndex, i + 1, polygon->
interiorRing( i ),
 
  236  validatePolyline( 0, qgsgeometry_cast< const QgsLineString * >( polygon->
exteriorRing() ), 
true );
 
  239    validatePolyline( i + 1, qgsgeometry_cast< const QgsLineString * >( polygon->
interiorRing( i ) ), 
true );
 
  264      if ( !
geos.isValid( &error, 
true, &errorLoc ) )
 
  291          validatePolyline( 0, qgsgeometry_cast< const QgsLineString * >( mGeometry.
constGet() ) );
 
  297          for ( 
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
 
  298            validatePolyline( i, qgsgeometry_cast< const QgsLineString * >( collection->
geometryN( i ) ) );
 
  304          validatePolygon( 0, qgsgeometry_cast< const QgsCurvePolygon * >( mGeometry.
constGet() ) );
 
  317          for ( 
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
 
  318            validatePolygon( i, qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( i ) ) );
 
  320          for ( 
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
 
  330            for ( 
int j = i + 1;  !mStop && j < collection->
numGeometries(); j++ )
 
  373      else if ( mErrorCount > 0 )
 
  375        emit 
validationFinished( QObject::tr( 
"Geometry has %n error(s).", 
nullptr, mErrorCount ) );
 
 
  405double QgsGeometryValidator::distLine2Point( 
double px, 
double py, 
QgsVector v, 
double qX, 
double qY )
 
  407  const double l = v.
length();
 
  413  return ( v.
x() * ( qY - py ) - v.
y() * ( qX - px ) ) / l;
 
  416bool QgsGeometryValidator::intersectLines( 
double px, 
double py, 
QgsVector v, 
double qx, 
double qy, 
QgsVector w, 
double &sX, 
double &sY )
 
  418  const double d = v.
y() * w.
x() - v.
x() * w.
y();
 
  423  const double dx = qx - px;
 
  424  const double dy = qy - py;
 
  425  const double k = ( dy * w.
x() - dx * w.
y() ) / d;
 
  433bool QgsGeometryValidator::pointInRing( 
const QgsCurve *ring, 
double pX, 
double pY )
 
  441  for ( 
int i = 0; !mStop && i < ring->
numPoints(); i++ )
 
  443    const double xAti = ring->
xAt( i );
 
  444    const double yAti = ring->
yAt( i );
 
  445    const double xAtj = ring->
xAt( j );
 
  446    const double yAtj = ring->
yAt( j );
 
  451    if ( ( yAti < pY && yAtj >= pY ) ||
 
  452         ( yAtj < pY && yAti >= pY ) )
 
  454      if ( xAti + ( pY - yAti ) / ( yAtj - yAti ) * ( xAtj - xAti ) <= pX )
 
  464bool QgsGeometryValidator::ringInRing( 
const QgsCurve *inside, 
const QgsCurve *outside )
 
  469  for ( 
int i = 0; !mStop && i < inside->
numPoints(); i++ )
 
  471    if ( !pointInRing( outside, inside->
xAt( i ), inside->
yAt( i ) ) )
 
GeometryValidationEngine
Available engines for validating geometries.
 
@ QgisInternal
Use internal QgsGeometryValidator method.
 
@ Geos
Use GEOS validation methods.
 
QFlags< GeosCreationFlag > GeosCreationFlags
Geos geometry creation behavior flags.
 
@ MultiPolygon
MultiPolygon.
 
@ MultiLineString
MultiLineString.
 
@ CurvePolygon
CurvePolygon.
 
@ MultiSurface
MultiSurface.
 
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
 
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
 
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
 
virtual bool isEmpty() const
Returns true if the geometry is empty.
 
Curve polygon geometry type.
 
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
 
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
 
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
 
Abstract base class for curved geometry type.
 
virtual int numPoints() const =0
Returns the number of points in the curve.
 
QgsCurve * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
 
virtual double xAt(int index) const =0
Returns the x-coordinate of the specified node in the line string.
 
virtual double yAt(int index) const =0
Returns the y-coordinate of the specified node in the line string.
 
Defines a QGIS exception class.
 
int numGeometries() const
Returns the number of geometries within the collection.
 
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
 
static bool segmentIntersection(double p1x, double p1y, double p2x, double p2y, double q1x, double q1y, double q2x, double q2y, double &intersectionPointX, double &intersectionPointY, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
 
Validates geometries using the QGIS geometry validation model.
 
void validationFinished(const QString &summary)
Sent when the validation is finished.
 
void errorFound(const QgsGeometry::Error &error)
Sent when an error has been found during the validation process.
 
QgsGeometryValidator(const QgsGeometry &geometry, QVector< QgsGeometry::Error > *errors=nullptr, Qgis::GeometryValidationEngine method=Qgis::GeometryValidationEngine::QgisInternal)
Constructor for QgsGeometryValidator.
 
static void validateGeometry(const QgsGeometry &geometry, QVector< QgsGeometry::Error > &errors, Qgis::GeometryValidationEngine method=Qgis::GeometryValidationEngine::QgisInternal)
Validate geometry and produce a list of geometry errors.
 
void addError(const QgsGeometry::Error &)
 
~QgsGeometryValidator() override
 
A geometry is the spatial representation of a feature.
 
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
 
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
 
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
 
Does vector analysis using the GEOS library and handles import, export, and exception handling.
 
Line string geometry type, with support for z-dimension and m-values.
 
bool isClosed() const override
Returns true if the curve is closed.
 
QgsPoint startPoint() const override
Returns the starting point of the curve.
 
int numPoints() const override
Returns the number of points in the curve.
 
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
 
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
 
QgsPoint endPoint() const override
Returns the end point of the curve.
 
QVector< QgsVertexId > collectDuplicateNodes(double epsilon=4 *std::numeric_limits< double >::epsilon(), bool useZValues=false) const
Returns a list of any duplicate nodes contained in the geometry, within the specified tolerance.
 
QgsLineString * clone() const override
Clones the geometry by performing a deep copy.
 
bool isClosed2D() const override
Returns true if the curve is closed.
 
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
 
Point geometry type, with support for z-dimension and m-values.
 
QgsPoint vertexAt(QgsVertexId) const override
Returns the point corresponding to a specified vertex id.
 
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
 
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
 
Represent a 2-dimensional vector.
 
double y() const
Returns the vector's y-component.
 
double x() const
Returns the vector's x-component.
 
double length() const
Returns the length of the vector.
 
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
 
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
 
Contains geos related utilities and functions.
 
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
 
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
 
#define QgsDebugMsgLevel(str, level)
 
Utility class for identifying a unique vertex within a geometry.