void QgsHighlight::paintLine( QPainter *p, QgsPolyline line ) { QPolygonF polygon( line.size() ); for ( int i = 0; i < line.size(); i++ ) { polygon[i] = toCanvasCoordinates( line[i] ) - pos(); } p->drawPolyline( polygon ); }
unsigned char* QgsGeometryAnalyzer::locateBetweenWkbString( unsigned char* ptr, QgsMultiPolyline& result, double fromMeasure, double toMeasure ) { int* nPoints = ( int* ) ptr; ptr += sizeof( int ); double prevx = 0.0, prevy = 0.0, prevz = 0.0; double *x, *y, *z; QgsPolyline currentLine; QgsPoint pt1, pt2; bool measureInSegment; //true if measure is contained in the segment bool secondPointClipped; //true if second point is != segment endpoint for ( int i = 0; i < *nPoints; ++i ) { x = ( double* )ptr; ptr += sizeof( double ); y = ( double* )ptr; ptr += sizeof( double ); z = ( double* ) ptr; ptr += sizeof( double ); if ( i > 0 ) { measureInSegment = clipSegmentByRange( prevx, prevy, prevz, *x, *y, *z, fromMeasure, toMeasure, pt1, pt2, secondPointClipped ); if ( measureInSegment ) { if ( currentLine.size() < 1 ) //no points collected yet, so the first point needs to be added to the line { currentLine.append( pt1 ); } if ( pt1 != pt2 ) //avoid duplicated entry if measure value equals m-value of vertex { currentLine.append( pt2 ); } if ( secondPointClipped || i == *nPoints - 1 ) //close current segment { if ( currentLine.size() > 1 ) { result.append( currentLine ); } currentLine.clear(); } } } prevx = *x; prevy = *y; prevz = *z; } return ptr; }
std::unique_ptr<QgsLineString> QgsGeometryFactory::linestringFromPolyline( const QgsPolyline &polyline ) { QVector< double > x; x.reserve( polyline.size() ); QVector< double > y; y.reserve( polyline.size() ); QgsPolyline::const_iterator it = polyline.constBegin(); for ( ; it != polyline.constEnd(); ++it ) { x << it->x(); y << it->y(); } std::unique_ptr< QgsLineString > line( new QgsLineString( x, y ) ); return line; }
void QgsHighlight::paintLine( QPainter *p, QgsPolyline line ) { QPolygonF polygon( line.size() ); for ( int i = 0; i < line.size(); i++ ) { if ( mLayer ) { line[i] = mMapCanvas->mapRenderer()->layerToMapCoordinates( mLayer, line[i] ); } polygon[i] = toCanvasCoordinates( line[i] ) - pos(); } p->drawPolyline( polygon ); }
bool QgsGeometryValidator::ringInRing( const QgsPolyline &inside, const QgsPolyline &outside ) { for ( int i = 0; !mStop && i < inside.size(); i++ ) { if ( !pointInRing( outside, inside[i] ) ) return false; } return true; }
bool QgsGeometryValidator::pointInRing( const QgsPolyline &ring, const QgsPoint &p ) { bool inside = false; int j = ring.size() - 1; for ( int i = 0; !mStop && i < ring.size(); i++ ) { if ( qgsDoubleNear( ring[i].x(), p.x() ) && qgsDoubleNear( ring[i].y(), p.y() ) ) return true; if (( ring[i].y() < p.y() && ring[j].y() >= p.y() ) || ( ring[j].y() < p.y() && ring[i].y() >= p.y() ) ) { if ( ring[i].x() + ( p.y() - ring[i].y() ) / ( ring[j].y() - ring[i].y() )*( ring[j].x() - ring[i].x() ) <= p.x() ) inside = !inside; } j = i; } return inside; }
void QgsGeometryValidator::checkRingIntersections( int p0, int i0, const QgsPolyline &ring0, int p1, int i1, const QgsPolyline &ring1 ) { for ( int i = 0; !mStop && i < ring0.size() - 1; i++ ) { QgsVector v = ring0[i+1] - ring0[i]; for ( int j = 0; !mStop && j < ring1.size() - 1; j++ ) { QgsVector w = ring1[j+1] - ring1[j]; QgsPoint s; if ( intersectLines( ring0[i], v, ring1[j], w, s ) ) { double d = -distLine2Point( ring0[i], v.perpVector(), s ); if ( d >= 0 && d <= v.length() ) { d = -distLine2Point( ring1[j], w.perpVector(), s ); if ( d > 0 && d < w.length() && ring0[i+1] != ring1[j+1] && ring0[i+1] != ring1[j] && ring0[i+0] != ring1[j+1] && ring0[i+0] != ring1[j] ) { QString msg = QObject::tr( "segment %1 of ring %2 of polygon %3 intersects segment %4 of ring %5 of polygon %6 at %7" ) .arg( i0 ).arg( i ).arg( p0 ) .arg( i1 ).arg( j ).arg( p1 ) .arg( s.toString() ); QgsDebugMsg( msg ); emit errorFound( QgsGeometry::Error( msg, s ) ); mErrorCount++; } } } } } }
void QgsDxfExport::writePolylineAC1018( QTextStream& stream, const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width, bool polygon ) { stream << " 0\n"; stream << "LWPOLYLINE\n"; stream << " 5\n"; stream << QString( "%1\n" ).arg( mNextHandleId++ ); stream << " 8\n"; stream << layer << "\n"; stream << "100\n"; stream << "AcDbEntity\n"; stream << "100\n"; stream << "AcDbPolyline\n"; stream << " 6\n"; stream << QString( "%1\n" ).arg( lineStyleName ); stream << " 62\n"; stream << color << "\n"; stream << " 90\n"; stream << QString( "%1\n" ).arg( line.size() ); stream << " 70\n"; int type = polygon ? 1 : 0; stream << type << "\n"; stream << " 43\n"; stream << width << "\n"; QgsPolyline::const_iterator lineIt = line.constBegin(); for ( ; lineIt != line.constEnd(); ++lineIt ) { writeVertexAC1018( stream, *lineIt ); } }
void QgsGeometryValidator::validatePolyline( int i, QgsPolyline line, bool ring ) { if ( ring ) { if ( line.size() < 4 ) { QString msg = QObject::tr( "ring %1 with less than four points" ).arg( i ); QgsDebugMsg( msg ); emit errorFound( QgsGeometry::Error( msg ) ); mErrorCount++; return; } if ( line[0] != line[ line.size()-1 ] ) { QString msg = QObject::tr( "ring %1 not closed" ).arg( i ); QgsDebugMsg( msg ); emit errorFound( QgsGeometry::Error( msg ) ); mErrorCount++; return; } } else if ( line.size() < 2 ) { QString msg = QObject::tr( "line %1 with less than two points" ).arg( i ); QgsDebugMsg( msg ); emit errorFound( QgsGeometry::Error( msg ) ); mErrorCount++; return; } int j = 0; while ( j < line.size() - 1 ) { int n = 0; while ( j < line.size() - 1 && line[j] == line[j+1] ) { line.remove( j ); n++; } if ( n > 0 ) { QString msg = QObject::tr( "line %1 contains %n duplicate node(s) at %2", "number of duplicate nodes", n ).arg( i ).arg( j ); QgsDebugMsg( msg ); emit errorFound( QgsGeometry::Error( msg, line[j] ) ); mErrorCount++; } j++; } for ( j = 0; !mStop && j < line.size() - 3; j++ ) { QgsVector v = line[j+1] - line[j]; double vl = v.length(); int n = ( j == 0 && ring ) ? line.size() - 2 : line.size() - 1; for ( int k = j + 2; !mStop && k < n; k++ ) { QgsVector w = line[k+1] - line[k]; QgsPoint s; if ( !intersectLines( line[j], v, line[k], w, s ) ) continue; double d = 0.0; try { d = -distLine2Point( line[j], v.perpVector(), s ); } catch ( QgsException & e ) { Q_UNUSED( e ); QgsDebugMsg( "Error validating: " + e.what() ); continue; } if ( d < 0 || d > vl ) continue; try { d = -distLine2Point( line[k], w.perpVector(), s ); } catch ( QgsException & e ) { Q_UNUSED( e ); QgsDebugMsg( "Error validating: " + e.what() ); continue; } if ( d <= 0 || d >= w.length() ) continue; QString msg = QObject::tr( "segments %1 and %2 of line %3 intersect at %4" ).arg( j ).arg( k ).arg( i ).arg( s.toString() ); QgsDebugMsg( msg ); emit errorFound( QgsGeometry::Error( msg, s ) ); mErrorCount++; } } }
void QgsRubberBand::addGeometry( const QgsGeometry& geom, QgsVectorLayer* layer ) { if ( geom.isEmpty() ) { return; } //maprender object of canvas const QgsMapSettings& ms = mMapCanvas->mapSettings(); int idx = mPoints.size(); switch ( geom.wkbType() ) { case QgsWkbTypes::Point: case QgsWkbTypes::Point25D: { QgsPoint pt; if ( layer ) { pt = ms.layerToMapCoordinates( layer, geom.asPoint() ); } else { pt = geom.asPoint(); } addPoint( pt, false, idx ); removeLastPoint( idx, false ); } break; case QgsWkbTypes::MultiPoint: case QgsWkbTypes::MultiPoint25D: { QgsMultiPoint mpt = geom.asMultiPoint(); for ( int i = 0; i < mpt.size(); ++i, ++idx ) { QgsPoint pt = mpt[i]; if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, pt ), false, idx ); removeLastPoint( idx, false ); } else { addPoint( pt, false, idx ); removeLastPoint( idx, false ); } } } break; case QgsWkbTypes::LineString: case QgsWkbTypes::LineString25D: { QgsPolyline line = geom.asPolyline(); for ( int i = 0; i < line.count(); i++ ) { if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, line[i] ), false, idx ); } else { addPoint( line[i], false, idx ); } } } break; case QgsWkbTypes::MultiLineString: case QgsWkbTypes::MultiLineString25D: { QgsMultiPolyline mline = geom.asMultiPolyline(); for ( int i = 0; i < mline.size(); ++i, ++idx ) { QgsPolyline line = mline[i]; if ( line.isEmpty() ) { --idx; } for ( int j = 0; j < line.size(); ++j ) { if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, line[j] ), false, idx ); } else { addPoint( line[j], false, idx ); } } } } break; case QgsWkbTypes::Polygon: case QgsWkbTypes::Polygon25D: { QgsPolygon poly = geom.asPolygon(); QgsPolyline line = poly[0]; for ( int i = 0; i < line.count(); i++ ) { if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, line[i] ), false, idx ); } else { addPoint( line[i], false, idx ); } } } break; case QgsWkbTypes::MultiPolygon: case QgsWkbTypes::MultiPolygon25D: { QgsMultiPolygon multipoly = geom.asMultiPolygon(); for ( int i = 0; i < multipoly.size(); ++i, ++idx ) { QgsPolygon poly = multipoly[i]; QgsPolyline line = poly[0]; for ( int j = 0; j < line.count(); ++j ) { if ( layer ) { addPoint( ms.layerToMapCoordinates( layer, line[j] ), false, idx ); } else { addPoint( line[j], false, idx ); } } } } break; case QgsWkbTypes::Unknown: default: return; } setVisible( true ); updateRect(); update(); }
void QgsRubberBand::addGeometry( QgsGeometry* geom, QgsVectorLayer* layer ) { if ( !geom ) { return; } //maprender object of canvas QgsMapRenderer* mr = mMapCanvas->mapRenderer(); if ( !mr ) { return; } int idx = mPoints.size(); switch ( geom->wkbType() ) { case QGis::WKBPoint: case QGis::WKBPoint25D: { QgsPoint pt; if ( layer ) { pt = mr->layerToMapCoordinates( layer, geom->asPoint() ); } else { pt = geom->asPoint(); } addPoint( pt, false, idx ); } break; case QGis::WKBMultiPoint: case QGis::WKBMultiPoint25D: { QgsMultiPoint mpt = geom->asMultiPoint(); for ( int i = 0; i < mpt.size(); ++i, ++idx ) { QgsPoint pt = mpt[i]; if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, pt ), false, idx ); } else { addPoint( pt, false, idx ); } } } break; case QGis::WKBLineString: case QGis::WKBLineString25D: { QgsPolyline line = geom->asPolyline(); for ( int i = 0; i < line.count(); i++ ) { if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx ); } else { addPoint( line[i], false, idx ); } } } break; case QGis::WKBMultiLineString: case QGis::WKBMultiLineString25D: { mPoints.clear(); QgsMultiPolyline mline = geom->asMultiPolyline(); for ( int i = 0; i < mline.size(); ++i, ++idx ) { QgsPolyline line = mline[i]; if ( line.size() == 0 ) { --idx; } for ( int j = 0; j < line.size(); ++j ) { if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx ); } else { addPoint( line[j], false, idx ); } } } } break; case QGis::WKBPolygon: case QGis::WKBPolygon25D: { QgsPolygon poly = geom->asPolygon(); QgsPolyline line = poly[0]; for ( int i = 0; i < line.count(); i++ ) { if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx ); } else { addPoint( line[i], false, idx ); } } } break; case QGis::WKBMultiPolygon: case QGis::WKBMultiPolygon25D: { mPoints.clear(); QgsMultiPolygon multipoly = geom->asMultiPolygon(); for ( int i = 0; i < multipoly.size(); ++i, ++idx ) { QgsPolygon poly = multipoly[i]; QgsPolyline line = poly[0]; for ( int j = 0; j < line.count(); ++j ) { if ( layer ) { addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx ); } else { addPoint( line[j], false, idx ); } } } } break; case QGis::WKBUnknown: default: return; } updateRect(); update(); }
ErrorList topolTest::checkSegmentLength( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ) { Q_UNUSED( layer1 ); Q_UNUSED( layer2 ); Q_UNUSED( isExtent ); int i = 0; ErrorList errorList; QgsFeature f; QList<FeatureLayer>::Iterator it; QList<FeatureLayer>::ConstIterator FeatureListEnd = mFeatureList1.end(); QgsPolygon pol; QgsMultiPolygon mpol; QgsPolyline segm; QgsPolyline ls; QgsMultiPolyline mls; QList<FeatureLayer> fls; TopolErrorShort* err; double distance; for ( it = mFeatureList1.begin(); it != FeatureListEnd; ++it ) { if ( !( ++i % 100 ) ) { emit progress( i ); } if ( testCancelled() ) { break; } QgsGeometry* g1 = it->feature.geometry(); // switching by type here, because layer can contain both single and multi version geometries switch ( g1->wkbType() ) { case QGis::WKBLineString: case QGis::WKBLineString25D: ls = g1->asPolyline(); for ( int i = 1; i < ls.size(); ++i ) { distance = sqrt( ls[i-1].sqrDist( ls[i] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << ls[i-1] << ls[i]; QgsGeometry* conflict = QgsGeometry::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); //err = new TopolErrorShort(g1->boundingBox(), QgsGeometry::fromPolyline(segm), fls); errorList << err; //break on getting the first error break; } } break; case QGis::WKBPolygon: case QGis::WKBPolygon25D: pol = g1->asPolygon(); for ( int i = 0; i < pol.size(); ++i ) { for ( int j = 1; j < pol[i].size(); ++j ) { distance = sqrt( pol[i][j-1].sqrDist( pol[i][j] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << pol[i][j-1] << pol[i][j]; QgsGeometry* conflict = QgsGeometry::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } break; case QGis::WKBMultiLineString: case QGis::WKBMultiLineString25D: mls = g1->asMultiPolyline(); for ( int k = 0; k < mls.size(); ++k ) { QgsPolyline& ls = mls[k]; for ( int i = 1; i < ls.size(); ++i ) { distance = sqrt( ls[i-1].sqrDist( ls[i] ) ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << ls[i-1] << ls[i]; QgsGeometry* conflict = QgsGeometry::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } break; case QGis::WKBMultiPolygon: case QGis::WKBMultiPolygon25D: mpol = g1->asMultiPolygon(); for ( int k = 0; k < mpol.size(); ++k ) { QgsPolygon& pol = mpol[k]; for ( int i = 0; i < pol.size(); ++i ) { for ( int j = 1; j < pol[i].size(); ++j ) { distance = pol[i][j-1].sqrDist( pol[i][j] ); if ( distance < tolerance ) { fls.clear(); fls << *it << *it; segm.clear(); segm << pol[i][j-1] << pol[i][j]; QgsGeometry* conflict = QgsGeometry::fromPolyline( segm ); err = new TopolErrorShort( g1->boundingBox(), conflict, fls ); errorList << err; //break on getting the first error break; } } } } break; default: continue; } } return errorList; }
ErrorList topolTest::checkPseudos( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent ) { Q_UNUSED( tolerance ); Q_UNUSED( layer2 ); int i = 0; ErrorList errorList; QgsFeature f; if ( layer1->geometryType() != QGis::Line ) { return errorList; } QList<FeatureLayer>::Iterator it; QList<FeatureLayer>::ConstIterator FeatureListEnd = mFeatureList1.end(); qDebug() << mFeatureList1.count(); QgsPoint startPoint; QgsPoint endPoint; std::multimap<QgsPoint, QgsFeatureId, PointComparer> endVerticesMap; for ( it = mFeatureList1.begin(); it != FeatureListEnd; ++it ) { if ( !( ++i % 100 ) ) emit progress( i ); if ( testCancelled() ) break; QgsGeometry* g1 = it->feature.geometry(); if ( !g1 ) { QgsMessageLog::logMessage( tr( "Skipping invalid first geometry in pseudo line test." ), tr( "Topology plugin" ) ); continue; } if ( !g1->asGeos() ) { QgsMessageLog::logMessage( tr( "Failed to import first geometry into GEOS in pseudo line test." ), tr( "Topology plugin" ) ); continue; } if ( g1->isMultipart() ) { QgsMultiPolyline lines = g1->asMultiPolyline(); for ( int m = 0; m < lines.count(); m++ ) { QgsPolyline line = lines[m]; startPoint = line[0]; endPoint = line[line.size() - 1]; endVerticesMap.insert( std::pair<QgsPoint, QgsFeatureId>( startPoint, it->feature.id() ) ); endVerticesMap.insert( std::pair<QgsPoint, QgsFeatureId>( endPoint, it->feature.id() ) ); } } else { QgsPolyline polyline = g1->asPolyline(); startPoint = polyline[0]; endPoint = polyline[polyline.size()-1]; endVerticesMap.insert( std::pair<QgsPoint, QgsFeatureId>( startPoint, it->feature.id() ) ); endVerticesMap.insert( std::pair<QgsPoint, QgsFeatureId>( endPoint, it->feature.id() ) ); } } QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() ); for ( std::multimap<QgsPoint, QgsFeatureId, PointComparer>::iterator pointIt = endVerticesMap.begin(), end = endVerticesMap.end(); pointIt != end; pointIt = endVerticesMap.upper_bound( pointIt->first ) ) { QgsPoint p = pointIt->first; QgsFeatureId k = pointIt->second; size_t repetitions = endVerticesMap.count( p ); if ( repetitions == 2 ) { QgsGeometry* conflictGeom = QgsGeometry::fromPoint( p ); if ( isExtent ) { if ( canvasExtentPoly->disjoint( conflictGeom ) ) { delete conflictGeom; continue; } } QgsRectangle bBox = conflictGeom->boundingBox(); QgsFeature feat; FeatureLayer ftrLayer1; //need to fetch attributes?? being safe side by fetching.. layer1->getFeatures( QgsFeatureRequest().setFilterFid( k ) ).nextFeature( feat ); ftrLayer1.feature = feat; ftrLayer1.layer = layer1; QList<FeatureLayer> errorFtrLayers; errorFtrLayers << ftrLayer1 << ftrLayer1; TopolErrorPseudos* err = new TopolErrorPseudos( bBox, conflictGeom, errorFtrLayers ); errorList << err; } } delete canvasExtentPoly; return errorList; }