45 void QgsGeometryValidator::checkRingIntersections(
49 for (
int i = 0; !mStop && i < ring0.size() - 1; i++ )
53 for (
int j = 0; !mStop && j < ring1.size() - 1; j++ )
58 if ( intersectLines( ring0[i], v, ring1[j], w, s ) )
60 double d = -distLine2Point( ring0[i], v.
perpVector(), s );
62 if ( d >= 0 && d <= v.
length() )
64 d = -distLine2Point( ring1[j], w.
perpVector(), s );
65 if ( d > 0 && d < w.
length() &&
66 ring0[i+1] != ring1[j+1] && ring0[i+1] != ring1[j] &&
67 ring0[i+0] != ring1[j+1] && ring0[i+0] != ring1[j] )
69 QString msg =
QObject::tr(
"segment %1 of ring %2 of polygon %3 intersects segment %4 of ring %5 of polygon %6 at %7" )
70 .arg( i0 ).arg( i ).arg( p0 )
71 .arg( i1 ).arg( j ).arg( p1 )
83 void QgsGeometryValidator::validatePolyline(
int i,
QgsPolyline line,
bool ring )
87 if ( line.size() < 4 )
89 QString msg =
QObject::tr(
"ring %1 with less than four points" ).arg( i );
96 if ( line[0] != line[ line.size()-1 ] )
98 QString msg =
QObject::tr(
"ring %1 not closed" ).arg( i );
105 else if ( line.size() < 2 )
107 QString msg =
QObject::tr(
"line %1 with less than two points" ).arg( i );
115 while ( j < line.size() - 1 )
118 while ( j < line.size() - 1 && line[j] == line[j+1] )
126 QString msg =
QObject::tr(
"line %1 contains %n duplicate node(s) at %2",
"number of duplicate nodes", n ).arg( i ).arg( j );
135 for ( j = 0; !mStop && j < line.size() - 3; j++ )
140 int n = ( j == 0 && ring ) ? line.size() - 2 : line.size() - 1;
142 for (
int k = j + 2; !mStop && k < n; k++ )
147 if ( !intersectLines( line[j], v, line[k], w, s ) )
150 double d = -distLine2Point( line[j], v.
perpVector(), s );
151 if ( d < 0 || d > vl )
154 d = -distLine2Point( line[k], w.
perpVector(), s );
155 if ( d <= 0 || d >= w.
length() )
158 QString msg =
QObject::tr(
"segments %1 and %2 of line %3 intersect at %4" ).arg( j ).arg( k ).arg( i ).arg( s.
toString() );
166 void QgsGeometryValidator::validatePolygon(
int idx,
const QgsPolygon &polygon )
169 for (
int i = 1; !mStop && i < polygon.size(); i++ )
171 if ( !ringInRing( polygon[i], polygon[0] ) )
173 QString msg =
QObject::tr(
"ring %1 of polygon %2 not in exterior ring" ).arg( i ).arg( idx );
181 for (
int i = 1; !mStop && i < polygon.size(); i++ )
183 for (
int j = i + 1; !mStop && j < polygon.size(); j++ )
185 checkRingIntersections( idx, i, polygon[i], idx, j, polygon[j] );
190 for (
int i = 0; !mStop && i < polygon.size(); i++ )
192 validatePolyline( i, polygon[i],
true );
199 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \ 200 ( (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=3) || GEOS_VERSION_MAJOR>3) 202 if ( settings.value(
"/qgis/digitizing/validate_geometries", 1 ).toInt() == 2 )
205 const GEOSGeometry *g0 = mG.
asGeos();
213 GEOSGeometry *g1 = 0;
214 if ( GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 ) != 1 )
218 const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 );
221 if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 )
224 GEOSCoordSeq_getX_r( handle, cs, 0, &x );
225 GEOSCoordSeq_getY_r( handle, cs, 0, &y );
230 GEOSGeom_destroy_r( handle, g1 );
238 GEOSFree_r( handle, r );
265 for (
int i = 0; !mStop && i < mp.size(); i++ )
266 validatePolyline( i, mp[i] );
281 for (
int i = 0; !mStop && i < mp.size(); i++ )
283 validatePolygon( i, mp[i] );
286 for (
int i = 0; !mStop && i < mp.size(); i++ )
288 if ( mp[i].isEmpty() )
295 for (
int j = i + 1; !mStop && j < mp.size(); j++ )
297 if ( mp[j].isEmpty() )
300 if ( ringInRing( mp[i][0], mp[j][0] ) )
305 else if ( ringInRing( mp[j][0], mp[i][0] ) )
312 checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] );
333 else if ( mErrorCount > 0 )
371 return ( v.
x()*( q.
y() - p.
y() ) - v.
y()*( q.
x() - p.
x() ) ) / v.
length();
376 double d = v.
y() * w.
x() - v.
x() * w.
y();
381 double dx = q.
x() - p.
x();
382 double dy = q.
y() - p.
y();
383 double k = ( dy * w.
x() - dx * w.
y() ) / d;
393 int j = ring.size() - 1;
395 for (
int i = 0; !mStop && i < ring.size(); i++ )
397 if ( ring[i].x() == p.
x() && ring[i].y() == p.
y() )
400 if (( ring[i].y() < p.
y() && ring[j].y() >= p.
y() ) ||
401 ( ring[j].y() < p.
y() && ring[i].y() >= p.
y() ) )
403 if ( ring[i].x() + ( p.
y() - ring[i].y() ) / ( ring[j].y() - ring[i].y() )*( ring[j].x() - ring[i].x() ) <= p.
x() )
415 for (
int i = 0; !mStop && i < inside.size(); i++ )
417 if ( !pointInRing( outside, inside[i] ) )
static void validateGeometry(QgsGeometry *g, QList< QgsGeometry::Error > &errors)
Validate geometry and produce a list of geometry errors.
void addError(QgsGeometry::Error)
QgsMultiPolyline asMultiPolyline() const
return contents of the geometry as a multi linestring if wkbType is WKBMultiLineString, otherwise an empty list
QVector< QgsPoint > QgsPolyline
polyline is represented as a vector of points
QgsPolygon asPolygon() const
return contents of the geometry as a polygon if wkbType is WKBPolygon, otherwise an empty list ...
const GEOSGeometry * asGeos() const
Returns a geos geometry.
QgsMultiPolygon asMultiPolygon() const
return contents of the geometry as a multi polygon if wkbType is WKBMultiPolygon, otherwise an empty ...
QgsVector perpVector() const
QVector< QgsPolygon > QgsMultiPolygon
a collection of QgsPolygons that share a common collection of attributes
QString toString() const
String representation of the point (x,y)
QgsGeometryValidator(QgsGeometry *g, QList< QgsGeometry::Error > *errors=0)
Constructor.
QGis::WkbType wkbType() const
Returns type of wkb (point / linestring / polygon etc.)
QVector< QgsPolyline > QgsPolygon
polygon: first item of the list is outer ring, inner rings (if any) start from second item ...
A class to represent a point.
A class to represent a vector.
QVector< QgsPolyline > QgsMultiPolyline
a collection of QgsPolylines that share a common collection of attributes
QgsPolyline asPolyline() const
return contents of the geometry as a polyline if wkbType is WKBLineString, otherwise an empty list ...
static GEOSContextHandle_t getGEOSHandler()
return GEOS context handle
void errorFound(QgsGeometry::Error)
Defines a qgis exception class.