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();
191 for (
int j = 0; !mStop && j < line->
numPoints() - 3; j++ )
193 const double xAtJ = line->
xAt( j );
194 const double yAtJ = line->
yAt( j );
195 const QgsVector v( line->
xAt( j + 1 ) - xAtJ, line->
yAt( j + 1 ) - yAtJ );
196 const double vl = v.length();
200 for (
int k = j + 2; !mStop && k < n; k++ )
202 const double xAtK = line->
xAt( k );
203 const double yAtK = line->
yAt( k );
205 const QgsVector w( line->
xAt( k + 1 ) - xAtK, line->
yAt( k + 1 ) - yAtK );
209 if ( !intersectLines( xAtJ, yAtJ, v, xAtK, yAtK, w, sX, sY ) )
215 d = -distLine2Point( xAtJ, yAtJ, v.perpVector(), sX, sY );
223 if ( d < 0 || d > vl )
228 d = -distLine2Point( xAtK, yAtK, w.perpVector(), sX, sY );
237 if ( d <= 0 || d >= w.length() )
240 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 );
248void QgsGeometryValidator::validatePolygon(
int partIndex,
const QgsCurvePolygon *polygon )
255 const QString msg = QObject::tr(
"ring %1 of polygon %2 not in exterior ring" ).arg( i + 1 ).arg( partIndex );
267 checkRingIntersections( partIndex, i + 1, polygon->
interiorRing( i ),
273 validatePolyline( 0, qgsgeometry_cast< const QgsLineString * >( polygon->
exteriorRing() ),
true );
276 validatePolyline( i + 1, qgsgeometry_cast< const QgsLineString * >( polygon->
interiorRing( i ) ),
true );
290 case Qgis::GeometryValidationEngine::Geos:
301 if ( !
geos.isValid( &error,
true, &errorLoc ) )
319 case Qgis::GeometryValidationEngine::QgisInternal:
328 validatePolyline( 0, qgsgeometry_cast< const QgsLineString * >( mGeometry.
constGet() ) );
334 for (
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
335 validatePolyline( i, qgsgeometry_cast< const QgsLineString * >( collection->
geometryN( i ) ) );
341 validatePolygon( 0, qgsgeometry_cast< const QgsCurvePolygon * >( mGeometry.
constGet() ) );
348 for (
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
349 validatePolygon( i, qgsgeometry_cast< const QgsCurvePolygon * >( collection->
geometryN( i ) ) );
351 for (
int i = 0; !mStop && i < collection->
numGeometries(); i++ )
361 for (
int j = i + 1; !mStop && j < collection->
numGeometries(); j++ )
404 else if ( mErrorCount > 0 )
406 emit
validationFinished( QObject::tr(
"Geometry has %n error(s).",
nullptr, mErrorCount ) );
436double QgsGeometryValidator::distLine2Point(
double px,
double py,
QgsVector v,
double qX,
double qY )
438 const double l = v.
length();
444 return ( v.
x() * ( qY - py ) - v.
y() * ( qX - px ) ) / l;
447bool QgsGeometryValidator::intersectLines(
double px,
double py,
QgsVector v,
double qx,
double qy,
QgsVector w,
double &sX,
double &sY )
449 const double d = v.
y() * w.
x() - v.
x() * w.
y();
454 const double dx = qx - px;
455 const double dy = qy - py;
456 const double k = ( dy * w.
x() - dx * w.
y() ) / d;
464bool QgsGeometryValidator::pointInRing(
const QgsCurve *ring,
double pX,
double pY )
472 for (
int i = 0; !mStop && i < ring->
numPoints(); i++ )
474 const double xAti = ring->
xAt( i );
475 const double yAti = ring->
yAt( i );
476 const double xAtj = ring->
xAt( j );
477 const double yAtj = ring->
yAt( j );
482 if ( ( yAti < pY && yAtj >= pY ) ||
483 ( yAtj < pY && yAti >= pY ) )
485 if ( xAti + ( pY - yAti ) / ( yAtj - yAti ) * ( xAtj - xAti ) <= pX )
495bool QgsGeometryValidator::ringInRing(
const QgsCurve *inside,
const QgsCurve *outside )
500 for (
int i = 0; !mStop && i < inside->
numPoints(); i++ )
502 if ( !pointInRing( outside, inside->
xAt( i ), inside->
yAt( i ) ) )
GeometryValidationEngine
Available engines for validating geometries.
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.
QgsWkbTypes::Type 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.
QgsWkbTypes::Type 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 GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Contains geos related utilities and functions.
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.