27 : mGeometry( geometry )
46void QgsGeometryValidator::checkRingIntersections(
int partIndex0,
int ringIndex0,
const QgsCurve *ring0,
int partIndex1,
int ringIndex1,
const QgsCurve *ring1 )
48 const QgsLineString *ringLine0 = qgsgeometry_cast< const QgsLineString * >( ring0 );
49 std::unique_ptr< QgsLineString > segmentisedRing0;
52 segmentisedRing0.reset( qgsgeometry_cast< QgsLineString * >( ring0->
segmentize() ) );
53 ringLine0 = segmentisedRing0.get();
56 const QgsLineString *ringLine1 = qgsgeometry_cast< const QgsLineString * >( ring1 );
57 std::unique_ptr< QgsLineString > segmentisedRing1;
60 segmentisedRing1.reset( qgsgeometry_cast< QgsLineString * >( ring1->
segmentize() ) );
61 ringLine1 = segmentisedRing1.get();
64 Q_ASSERT( ringLine0 );
65 Q_ASSERT( ringLine1 );
67 for (
int i = 0; !mStop && i < ringLine0->
numPoints() - 1; i++ )
69 const double ring0XAti = ringLine0->
xAt( i );
70 const double ring0YAti = ringLine0->
yAt( i );
71 const QgsVector v( ringLine0->
xAt( i + 1 ) - ring0XAti, ringLine0->
yAt( i + 1 ) - ring0YAti );
73 for (
int j = 0; !mStop && j < ringLine1->
numPoints() - 1; j++ )
75 const double ring1XAtj = ringLine1->
xAt( j );
76 const double ring1YAtj = ringLine1->
yAt( j );
77 const QgsVector w( ringLine1->
xAt( j + 1 ) - ring1XAtj, ringLine1->
yAt( j + 1 ) - ring1YAtj );
81 if ( intersectLines( ring0XAti, ring0YAti, v, ring1XAtj, ring1YAtj, w, sX, sY ) )
83 double d = -distLine2Point( ring0XAti, ring0YAti, v.perpVector(), sX, sY );
85 if ( d >= 0 && d <= v.length() )
87 d = -distLine2Point( ring1XAtj, ring1YAtj, w.perpVector(), sX, sY );
88 if ( d > 0 && d < w.length() &&
92 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" )
93 .arg( i ).arg( ringIndex0 ).arg( partIndex0 )
94 .arg( j ).arg( ringIndex1 ).arg( partIndex1 )
105void QgsGeometryValidator::validatePolyline(
int i,
const QgsLineString *line,
bool ring )
114 const QString msg = QObject::tr(
"ring %1 with less than four points" ).arg( i );
128 msg = QObject::tr(
"ring %1 not closed, Z mismatch: %2 vs %3" ).arg( i ).arg( startPoint.
z() ).arg( endPoint.
z() );
132 msg = QObject::tr(
"ring %1 not closed" ).arg( i );
142 const QString msg = QObject::tr(
"line %1 with less than two points" ).arg( i );
149 std::unique_ptr< QgsLineString > noDupes;
154 if ( !duplicateNodes.empty() )
156 noDupes.reset( line->
clone() );
157 for (
int j = duplicateNodes.size() - 1; j >= 0; j-- )
159 const QgsVertexId duplicateVertex = duplicateNodes.at( j );
160 const QgsPointXY duplicationLocation = noDupes->vertexAt( duplicateVertex );
161 noDupes->deleteVertex( duplicateVertex );
165 for (
int k = j - 1; k >= 0; k-- )
167 const QgsVertexId prevDupe = duplicateNodes.at( k );
182 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 );
187 line = noDupes.get();
190 for (
int j = 0; !mStop && j < line->
numPoints() - 3; j++ )
192 const double xAtJ = line->
xAt( j );
193 const double yAtJ = line->
yAt( j );
194 const QgsVector v( line->
xAt( j + 1 ) - xAtJ, line->
yAt( j + 1 ) - yAtJ );
195 const double vl = v.length();
199 for (
int k = j + 2; !mStop && k < n; k++ )
201 const double xAtK = line->
xAt( k );
202 const double yAtK = line->
yAt( k );
204 const QgsVector w( line->
xAt( k + 1 ) - xAtK, line->
yAt( k + 1 ) - yAtK );
208 if ( !intersectLines( xAtJ, yAtJ, v, xAtK, yAtK, w, sX, sY ) )
214 d = -distLine2Point( xAtJ, yAtJ, v.perpVector(), sX, sY );
222 if ( d < 0 || d > vl )
227 d = -distLine2Point( xAtK, yAtK, w.perpVector(), sX, sY );
236 if ( d <= 0 || d >= w.length() )
239 const QString msg = QObject::tr(
"segments %1 and %2 of line %3 intersect at %4, %5" ).arg( j ).arg( k ).arg( i ).arg( sX ).arg( sY );
247void QgsGeometryValidator::validatePolygon(
int partIndex,
const QgsCurvePolygon *polygon )
254 const QString msg = QObject::tr(
"ring %1 of polygon %2 not in exterior ring" ).arg( i + 1 ).arg( partIndex );
266 checkRingIntersections( partIndex, i + 1, polygon->
interiorRing( i ),
272 validatePolyline( 0, qgsgeometry_cast< const QgsLineString * >( polygon->
exteriorRing() ),
true );
275 validatePolyline( i + 1, qgsgeometry_cast< const QgsLineString * >( polygon->
interiorRing( i ) ),
true );
289 case Qgis::GeometryValidationEngine::Geos:
300 if ( !
geos.isValid( &error,
true, &errorLoc ) )
318 case Qgis::GeometryValidationEngine::QgisInternal:
327 validatePolyline( 0, qgsgeometry_cast< const QgsLineString * >( mGeometry.
constGet() ) );
333 for (
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
334 validatePolyline( i, qgsgeometry_cast< const QgsLineString * >( collection->
geometryN( i ) ) );
340 validatePolygon( 0, qgsgeometry_cast< const QgsCurvePolygon * >( mGeometry.
constGet() ) );
347 for (
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
348 validatePolygon( i, qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( i ) ) );
350 for (
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
360 for (
int j = i + 1; !mStop && j < collection->
numGeometries(); j++ )
403 else if ( mErrorCount > 0 )
405 emit
validationFinished( QObject::tr(
"Geometry has %n error(s).",
nullptr, mErrorCount ) );
435double QgsGeometryValidator::distLine2Point(
double px,
double py,
QgsVector v,
double qX,
double qY )
437 const double l = v.
length();
443 return ( v.
x() * ( qY - py ) - v.
y() * ( qX - px ) ) / l;
446bool QgsGeometryValidator::intersectLines(
double px,
double py,
QgsVector v,
double qx,
double qy,
QgsVector w,
double &sX,
double &sY )
448 const double d = v.
y() * w.
x() - v.
x() * w.
y();
453 const double dx = qx - px;
454 const double dy = qy - py;
455 const double k = ( dy * w.
x() - dx * w.
y() ) / d;
463bool QgsGeometryValidator::pointInRing(
const QgsCurve *ring,
double pX,
double pY )
471 for (
int i = 0; !mStop && i < ring->
numPoints(); i++ )
473 const double xAti = ring->
xAt( i );
474 const double yAti = ring->
yAt( i );
475 const double xAtj = ring->
xAt( j );
476 const double yAtj = ring->
yAt( j );
481 if ( ( yAti < pY && yAtj >= pY ) ||
482 ( yAtj < pY && yAti >= pY ) )
484 if ( xAti + ( pY - yAti ) / ( yAtj - yAti ) * ( xAtj - xAti ) <= pX )
494bool QgsGeometryValidator::ringInRing(
const QgsCurve *inside,
const QgsCurve *outside )
499 for (
int i = 0; !mStop && i < inside->
numPoints(); i++ )
501 if ( !pointInRing( outside, inside->
xAt( i ), inside->
yAt( i ) ) )
GeometryValidationEngine
Available engines for validating geometries.
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
@ CurvePolygon
CurvePolygon.
@ MultiSurface
MultiSurface.
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
virtual bool isEmpty() const
Returns true if the geometry is empty.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
Curve polygon geometry type.
const QgsCurve * interiorRing(int i) const SIP_HOLDGIL
Retrieves an interior ring from the curve polygon.
const QgsCurve * exteriorRing() const SIP_HOLDGIL
Returns the curve polygon's exterior ring.
int numInteriorRings() const SIP_HOLDGIL
Returns the number of interior rings contained with the curve polygon.
Abstract base class for curved geometry type.
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
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 SIP_HOLDGIL
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.
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 SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Qgis::WkbType wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
Does vector analysis using the geos library and handles import, export, exception handling*.
Line string geometry type, with support for z-dimension and m-values.
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
bool isClosed() const override SIP_HOLDGIL
Returns true if the curve is closed.
QgsPoint endPoint() const override SIP_HOLDGIL
Returns the end point of the curve.
int numPoints() const override SIP_HOLDGIL
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
bool isClosed2D() const override SIP_HOLDGIL
Returns true if the curve is closed.
double yAt(int index) const override
Returns the y-coordinate of the specified node in the line string.
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.
double xAt(int index) const override
Returns the x-coordinate of the specified node in the line string.
A class to represent a 2D point.
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 SIP_HOLDGIL
Returns true when rectangle contains other rectangle.
A class to represent a vector.
double y() const SIP_HOLDGIL
Returns the vector's y-component.
double x() const SIP_HOLDGIL
Returns the vector's x-component.
double length() const SIP_HOLDGIL
Returns the length of the vector.
static Qgis::GeometryType geometryType(Qgis::WkbType type) SIP_HOLDGIL
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) SIP_HOLDGIL
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)
#define QgsDebugError(str)
Utility class for identifying a unique vertex within a geometry.