QgsGeometry QgsTransectAlgorithm::calcTransect( const QgsPoint &point, const double angleAtVertex, const double length, const QgsTransectAlgorithm::Side orientation, const double angle ) { QgsPoint pLeft; // left point of the line QgsPoint pRight; // right point of the line QgsPolyline line; if ( ( orientation == QgsTransectAlgorithm::Right ) || ( orientation == QgsTransectAlgorithm::Both ) ) { pLeft = point.project( length, angle + 180.0 / M_PI * angleAtVertex ); if ( orientation != QgsTransectAlgorithm::Both ) pRight = point; } if ( ( orientation == QgsTransectAlgorithm::Left ) || ( orientation == QgsTransectAlgorithm::Both ) ) { pRight = point.project( -length, angle + 180.0 / M_PI * angleAtVertex ); if ( orientation != QgsTransectAlgorithm::Both ) pLeft = point; } line.append( pLeft ); line.append( pRight ); return QgsGeometry::fromPolyline( line ); }
void RgShortestPathWidget::exportPath() { RgExportDlg dlg( this ); if ( !dlg.exec() ) return; QgsVectorLayer *vl = dlg.mapLayer(); if ( vl == NULL ) return; QgsPoint p1, p2; QgsGraph *path = getPath( p1, p2 ); if ( path == NULL ) return; QgsCoordinateTransform ct( mPlugin->iface()->mapCanvas()->mapSettings().destinationCrs(), vl->crs() ); int startVertexIdx = path->findVertex( p1 ); int stopVertexIdx = path->findVertex( p2 ); double time = 0.0; double cost = 0.0; Unit timeUnit = Unit::byName( mPlugin->timeUnitName() ); Unit distanceUnit = Unit::byName( mPlugin->distanceUnitName() ); QgsPolyline p; while ( startVertexIdx != stopVertexIdx ) { if ( stopVertexIdx < 0 ) break; QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc(); if ( l.empty() ) break; const QgsGraphArc& e = path->arc( l.front() ); cost += e.property( 0 ).toDouble(); time += e.property( 1 ).toDouble(); p.push_front( ct.transform( path->vertex( e.inVertex() ).point() ) ); stopVertexIdx = e.outVertex(); } p.push_front( ct.transform( p1 ) ); QgsFeature f; f.initAttributes( vl->pendingFields().count() ); f.setGeometry( QgsGeometry::fromPolyline( p ) ); f.setAttribute( 0, cost / distanceUnit.multipler() ); f.setAttribute( 1, time / timeUnit.multipler() ); QgsFeatureList features; features << f; vl->dataProvider()->addFeatures( features ); vl->updateExtents(); mPlugin->iface()->mapCanvas()->update(); delete path; }
QgsPolyline QgsRubberBand::getPolyline( const QList<QgsPoint> & points ) { QgsPolyline polyline; QList<QgsPoint>::const_iterator iter = points.constBegin(); for ( ; iter != points.constEnd(); ++iter ) { polyline.append( *iter ); } return polyline; }
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 ); }
QgsAbstractGeometryV2* QgsGeometryImport::fromRect( const QgsRectangle& rect ) { QgsPolyline ring; ring.append( QgsPoint( rect.xMinimum(), rect.yMinimum() ) ); ring.append( QgsPoint( rect.xMaximum(), rect.yMinimum() ) ); ring.append( QgsPoint( rect.xMaximum(), rect.yMaximum() ) ); ring.append( QgsPoint( rect.xMinimum(), rect.yMaximum() ) ); ring.append( QgsPoint( rect.xMinimum(), rect.yMinimum() ) ); QgsPolygon polygon; polygon.append( ring ); return fromPolygon( polygon ); }
static QVariant pointAt( const QVariantList& values, QgsFeature* f, QgsExpression* parent ) // helper function { int idx = getIntValue( values.at( 0 ), parent ); ENSURE_GEOM_TYPE( f, g, QGis::Line ); QgsPolyline polyline = g->asPolyline(); if ( idx < 0 ) idx += polyline.count(); if ( idx < 0 || idx >= polyline.count() ) { parent->setEvalErrorString( QObject::tr( "Index is out of range" ) ); return QVariant(); } return QVariant( QPointF( polyline[idx].x(), polyline[idx].y() ) ); }
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 ); }
double QgsGrassGisLib::G_area_of_polygon( const double *x, const double *y, int n ) { QgsPolyline polyline; for ( int i = 0; i < n; i++ ) { polyline.append( QgsPoint( x[i], y[i] ) ); } QgsPolygon polygon; polygon.append( polyline ); QgsGeometry* geo = QgsGeometry::fromPolygon( polygon ); double area = mDistanceArea.measure( geo ); delete geo; if ( !mCrs.geographicFlag() ) { area *= qPow( G_database_units_to_meters_factor(), 2 ); } return area; }
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; }
QgsPolyline QgsOSMDatabase::wayPoints( QgsOSMId id ) const { QgsPolyline points; // bind the way identifier sqlite3_bind_int64( mStmtWayNodePoints, 1, id ); while ( sqlite3_step( mStmtWayNodePoints ) == SQLITE_ROW ) { if ( sqlite3_column_type( mStmtWayNodePoints, 0 ) == SQLITE_NULL ) return QgsPolyline(); // missing some nodes double lon = sqlite3_column_double( mStmtWayNodePoints, 0 ); double lat = sqlite3_column_double( mStmtWayNodePoints, 1 ); points.append( QgsPoint( lon, lat ) ); } sqlite3_reset( mStmtWayNodePoints ); return points; }
void RgShortestPathWidget::exportPath() { RgExportDlg dlg( this ); if ( !dlg.exec() ) return; QgsVectorLayer *vl = dlg.mapLayer(); if ( vl == NULL ) return; QgsPoint p1, p2; QgsGraph *path = getPath( p1, p2 ); if ( path == NULL ) return; QgsCoordinateTransform ct( mPlugin->iface()->mapCanvas()->mapRenderer()->destinationCrs(), vl->crs() ); int startVertexIdx = path->findVertex( p1 ); int stopVertexIdx = path->findVertex( p2 ); QgsPolyline p; while ( startVertexIdx != stopVertexIdx ) { QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc(); if ( l.empty() ) break; const QgsGraphArc& e = path->arc( l.front() ); p.push_front( ct.transform( path->vertex( e.inVertex() ).point() ) ); stopVertexIdx = e.outVertex(); } p.push_front( ct.transform( p1 ) ); vl->startEditing(); QgsFeature f; f.setGeometry( QgsGeometry::fromPolyline( p ) ); vl->addFeature( f ); vl->updateExtents(); mPlugin->iface()->mapCanvas()->update(); delete path; }
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; }
// TODO: move to geometry utils double closestSegment( const QgsPolyline& pl, const QgsPoint& pt, int& vertexAfter, double epsilon ) { double sqrDist = std::numeric_limits<double>::max(); const QgsPoint* pldata = pl.constData(); int plcount = pl.count(); double prevX = pldata[0].x(), prevY = pldata[0].y(); double segmentPtX, segmentPtY; for ( int i = 1; i < plcount; ++i ) { double currentX = pldata[i].x(); double currentY = pldata[i].y(); double testDist = QgsGeometryUtils::sqrDistToLine( pt.x(), pt.y(), prevX, prevY, currentX, currentY, segmentPtX, segmentPtY, epsilon ); if ( testDist < sqrDist ) { sqrDist = testDist; vertexAfter = i; } prevX = currentX; prevY = currentY; } return sqrDist; }
bool TopolError::fixSnap() { bool ok; QgsFeature f1, f2; FeatureLayer fl = mFeaturePairs[1]; ok = fl.layer->getFeatures(( QgsFeatureRequest().setFilterFid( fl.feature.id() ) ) ).nextFeature( f2 ); fl = mFeaturePairs.first(); ok = ok && fl.layer->getFeatures( QgsFeatureRequest().setFilterFid( fl.feature.id() ) ).nextFeature( f1 ); if ( !ok ) return false; const QgsGeometry* ge = f1.constGeometry(); QgsPolyline line = ge->asPolyline(); line.last() = mConflict->asPolyline().last(); QgsGeometry* newG = QgsGeometry::fromPolyline( line ); bool ret = fl.layer->changeGeometry( f1.id(), newG ); delete newG; return ret; }
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 QgsDxfExport::writePolyline( const QgsPolyline& line, const QString& layer, const QString& lineStyleName, int color, double width, bool polygon ) { writeGroup( 0, "POLYLINE" ); writeGroup( 8, layer ); writeGroup( 6, lineStyleName ); writeGroup( 62, color ); writeGroup( 66, 1 ); int type = polygon ? 1 : 0; writeGroup( 70, type ); if ( width > 0 ) //width -1: use default width { writeGroup( 40, width ); writeGroup( 41, width ); } QgsPolyline::const_iterator lineIt = line.constBegin(); for ( ; lineIt != line.constEnd(); ++lineIt ) { writeVertex( *lineIt, layer ); } writeGroup( 0, "SEQEND" ); }
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; }
// TODO: move to geometry utils double distance2D( const QgsPolyline& coords ) { int np = coords.count(); if ( np == 0 ) return 0; double x0 = coords[0].x(), y0 = coords[0].y(); double x1, y1; double dist = 0; for ( int i = 1; i < np; ++i ) { x1 = coords[i].x(); y1 = coords[i].y(); dist += sqrt(( x1 - x0 ) * ( x1 - x0 ) + ( y1 - y0 ) * ( y1 - y0 ) ); x0 = x1; y0 = y1; } return dist; }
void QgsOSMDatabase::exportSpatiaLiteWays( bool closed, const QString& tableName, const QStringList& tagKeys, const QStringList& notNullTagKeys ) { Q_UNUSED( tagKeys ); QString sqlInsertLine = QString( "INSERT INTO %1 VALUES (?" ).arg( quotedIdentifier( tableName ) ); for ( int i = 0; i < tagKeys.count(); ++i ) sqlInsertLine += QString( ",?" ); sqlInsertLine += ", GeomFromWKB(?, 4326))"; sqlite3_stmt* stmtInsert; if ( sqlite3_prepare_v2( mDatabase, sqlInsertLine.toUtf8().constData(), -1, &stmtInsert, nullptr ) != SQLITE_OK ) { mError = "Prepare SELECT FROM ways failed."; return; } QgsOSMWayIterator ways = listWays(); QgsOSMWay w; while (( w = ways.next() ).isValid() ) { QgsOSMTags t = tags( true, w.id() ); QgsPolyline polyline = wayPoints( w.id() ); if ( polyline.count() < 2 ) continue; // invalid way bool isArea = ( polyline.first() == polyline.last() ); // closed way? // filter out closed way that are not areas through tags if ( isArea && ( t.contains( "highway" ) || t.contains( "barrier" ) ) ) { // make sure tags that indicate areas are taken into consideration when deciding on a closed way is or isn't an area // and allow for a closed way to be exported both as a polygon and a line in case both area and non-area tags are present if (( t.value( "area" ) != "yes" && !t.contains( "amenity" ) && !t.contains( "landuse" ) && !t.contains( "building" ) && !t.contains( "natural" ) && !t.contains( "leisure" ) && !t.contains( "aeroway" ) ) || !closed ) isArea = false; } if ( closed != isArea ) continue; // skip if it's not what we're looking for //check not null tags bool skipNull = false; for ( int i = 0; i < notNullTagKeys.count() && !skipNull; ++i ) if ( !t.contains( notNullTagKeys[i] ) ) skipNull = true; if ( skipNull ) continue; QgsGeometry geom = closed ? QgsGeometry::fromPolygon( QgsPolygon() << polyline ) : QgsGeometry::fromPolyline( polyline ); int col = 0; sqlite3_bind_int64( stmtInsert, ++col, w.id() ); // tags for ( int i = 0; i < tagKeys.count(); ++i ) { if ( t.contains( tagKeys[i] ) ) sqlite3_bind_text( stmtInsert, ++col, t.value( tagKeys[i] ).toUtf8().constData(), -1, SQLITE_TRANSIENT ); else sqlite3_bind_null( stmtInsert, ++col ); } if ( !geom.isEmpty() ) sqlite3_bind_blob( stmtInsert, ++col, geom.asWkb(), ( int ) geom.wkbSize(), SQLITE_STATIC ); else sqlite3_bind_null( stmtInsert, ++col ); int insertRes = sqlite3_step( stmtInsert ); if ( insertRes != SQLITE_DONE ) { mError = QString( "Error inserting way %1 [%2]" ).arg( w.id() ).arg( insertRes ); break; } sqlite3_reset( stmtInsert ); sqlite3_clear_bindings( stmtInsert ); } sqlite3_finalize( stmtInsert ); }
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; }
void CDTMapToolSelectTrainingSamples::canvasReleaseEvent(QgsMapMouseEvent *e) { if ( e->button() == Qt::LeftButton ) { if ( mDragging ) { mCanvas->panActionEnd( e->pos() ); mDragging = false; } else // add pan to mouse cursor { // transform the mouse pos to map coordinates QgsPoint center = mCanvas->getCoordinateTransform()->toMapPoint( e->x(), e->y() ); mCanvas->setExtent( QgsRectangle( center, center ) ); mCanvas->refresh(); } } else if (e->button()==Qt::RightButton) { QgsVectorLayer* vlayer = NULL; if ( !mapCanvas->currentLayer() || ( vlayer = qobject_cast<QgsVectorLayer *>( mapCanvas->currentLayer() ) ) == NULL ) return; QRect selectRect( 0, 0, 0, 0 ); int boxSize = 1; selectRect.setLeft ( e->pos().x() - boxSize ); selectRect.setRight ( e->pos().x() + boxSize ); selectRect.setTop ( e->pos().y() - boxSize ); selectRect.setBottom( e->pos().y() + boxSize ); const QgsMapToPixel* transform = mapCanvas->getCoordinateTransform(); QgsPoint ll = transform->toMapCoordinates( selectRect.left(), selectRect.bottom() ); QgsPoint ur = transform->toMapCoordinates( selectRect.right(), selectRect.top() ); QgsPolyline points; points.push_back(ll); points.push_back(QgsPoint( ur.x(), ll.y() )); points.push_back(ur); points.push_back(QgsPoint( ll.x(), ur.y() )); QgsPolygon polygon; polygon.push_back(points); QgsGeometry selectGeom = *(QgsGeometry::fromPolygon(polygon) ); if ( mapCanvas->mapSettings().hasCrsTransformEnabled() ) { QgsCoordinateTransform ct( mapCanvas->mapSettings().destinationCrs(), vlayer->crs() ); selectGeom.transform( ct ); } QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectGeom.boundingBox() ).setFlags( QgsFeatureRequest::ExactIntersect ) ); QgsFeature f; qint64 closestFeatureId = 0; bool foundSingleFeature = false; double closestFeatureDist = std::numeric_limits<double>::max(); while ( fit.nextFeature( f ) ) { QgsGeometry* g = f.geometry(); if ( !selectGeom.intersects( g ) ) continue; foundSingleFeature = true; double distance = g->distance( selectGeom ); if ( distance <= closestFeatureDist ) { closestFeatureDist = distance; closestFeatureId = f.attribute("GridCode").toInt(); } } if ( foundSingleFeature ) addSingleSample( closestFeatureId ); } }
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 QgsDxfPalLabeling::drawLabel( pal::LabelPosition* label, QgsRenderContext& context, QgsPalLayerSettings& tmpLyr, DrawLabelType drawType, double dpiRatio ) { Q_UNUSED( context ); Q_UNUSED( drawType ); Q_UNUSED( dpiRatio ); if ( drawType == QgsPalLabeling::LabelBuffer ) { return; } //debug: print label infos if ( mDxfExport ) { QgsPalGeometry *g = dynamic_cast< QgsPalGeometry* >( label->getFeaturePart()->getUserGeometry() ); if ( !g ) return; //label text QString txt = g->text( label->getPartId() ); //angle double angle = label->getAlpha() * 180 / M_PI; //debug: show label rectangle #if 0 QgsPolyline line; for ( int i = 0; i < 4; ++i ) { line.append( QgsPoint( label->getX( i ), label->getY( i ) ) ); } mDxfExport->writePolyline( line, g->dxfLayer(), "CONTINUOUS", 1, 0.01, true ); #endif QString wrapchr = tmpLyr.wrapChar.isEmpty() ? "\n" : tmpLyr.wrapChar; //add the direction symbol if needed if ( !txt.isEmpty() && tmpLyr.placement == QgsPalLayerSettings::Line && tmpLyr.addDirectionSymbol ) { bool prependSymb = false; QString symb = tmpLyr.rightDirectionSymbol; if ( label->getReversed() ) { prependSymb = true; symb = tmpLyr.leftDirectionSymbol; } if ( tmpLyr.reverseDirectionSymbol ) { if ( symb == tmpLyr.rightDirectionSymbol ) { prependSymb = true; symb = tmpLyr.leftDirectionSymbol; } else { prependSymb = false; symb = tmpLyr.rightDirectionSymbol; } } if ( tmpLyr.placeDirectionSymbol == QgsPalLayerSettings::SymbolAbove ) { prependSymb = true; symb = symb + wrapchr; } else if ( tmpLyr.placeDirectionSymbol == QgsPalLayerSettings::SymbolBelow ) { prependSymb = false; symb = wrapchr + symb; } if ( prependSymb ) { txt.prepend( symb ); } else { txt.append( symb ); } } txt = txt.replace( wrapchr, "\\P" ); if ( tmpLyr.textFont.underline() ) { txt.prepend( "\\L" ).append( "\\l" ); } if ( tmpLyr.textFont.overline() ) { txt.prepend( "\\O" ).append( "\\o" ); } if ( tmpLyr.textFont.strikeOut() ) { txt.prepend( "\\K" ).append( "\\k" ); } txt.prepend( QString( "\\f%1|i%2|b%3;\\H%4;\\W0.75;" ) .arg( tmpLyr.textFont.family() ) .arg( tmpLyr.textFont.italic() ? 1 : 0 ) .arg( tmpLyr.textFont.bold() ? 1 : 0 ) .arg( label->getHeight() / ( 1 + txt.count( "\\P" ) ) * 0.75 ) ); mDxfExport->writeMText( g->dxfLayer(), txt, QgsPoint( label->getX(), label->getY() ), label->getWidth() * 1.1, angle, tmpLyr.textColor ); } }
int QgsVectorLayerEditUtils::addTopologicalPoints( QgsGeometry* geom ) { if ( !L->hasGeometryType() ) return 1; if ( !geom ) { return 1; } int returnVal = 0; QGis::WkbType wkbType = geom->wkbType(); switch ( wkbType ) { //line case QGis::WKBLineString25D: case QGis::WKBLineString: { QgsPolyline theLine = geom->asPolyline(); QgsPolyline::const_iterator line_it = theLine.constBegin(); for ( ; line_it != theLine.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } break; } //multiline case QGis::WKBMultiLineString25D: case QGis::WKBMultiLineString: { QgsMultiPolyline theMultiLine = geom->asMultiPolyline(); QgsPolyline currentPolyline; for ( int i = 0; i < theMultiLine.size(); ++i ) { QgsPolyline::const_iterator line_it = currentPolyline.constBegin(); for ( ; line_it != currentPolyline.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } break; } //polygon case QGis::WKBPolygon25D: case QGis::WKBPolygon: { QgsPolygon thePolygon = geom->asPolygon(); QgsPolyline currentRing; for ( int i = 0; i < thePolygon.size(); ++i ) { currentRing = thePolygon.at( i ); QgsPolyline::const_iterator line_it = currentRing.constBegin(); for ( ; line_it != currentRing.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } break; } //multipolygon case QGis::WKBMultiPolygon25D: case QGis::WKBMultiPolygon: { QgsMultiPolygon theMultiPolygon = geom->asMultiPolygon(); QgsPolygon currentPolygon; QgsPolyline currentRing; for ( int i = 0; i < theMultiPolygon.size(); ++i ) { currentPolygon = theMultiPolygon.at( i ); for ( int j = 0; j < currentPolygon.size(); ++j ) { currentRing = currentPolygon.at( j ); QgsPolyline::const_iterator line_it = currentRing.constBegin(); for ( ; line_it != currentRing.constEnd(); ++line_it ) { if ( addTopologicalPoints( *line_it ) != 0 ) { returnVal = 2; } } } } break; } default: break; } return returnVal; }
void TestQgsDistanceArea::measureAreaAndUnits() { QgsDistanceArea da; da.setSourceCrs( 3452 ); da.setEllipsoidalMode( false ); da.setEllipsoid( "NONE" ); QgsCoordinateReferenceSystem daCRS; daCRS.createFromSrsId( da.sourceCrsId() ); QgsPolyline ring; ring << QgsPoint( 0, 0 ) << QgsPoint( 1, 0 ) << QgsPoint( 1, 1 ) << QgsPoint( 2, 1 ) << QgsPoint( 2, 2 ) << QgsPoint( 0, 2 ) << QgsPoint( 0, 0 ); QgsPolygon poly; poly << ring; QgsGeometry polygon( QgsGeometry::fromPolygon( poly ) ); // We check both the measured area AND the units, in case the logic regarding // ellipsoids and units changes in future double area = da.measureArea( &polygon ); QgsUnitTypes::AreaUnit units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); QVERIFY(( qgsDoubleNear( area, 3.0, 0.00000001 ) && units == QgsUnitTypes::AreaSquareDegrees ) || ( qgsDoubleNear( area, 37176087091.5, 0.1 ) && units == QgsUnitTypes::AreaSquareMeters ) ); da.setEllipsoid( "WGS84" ); area = da.measureArea( &polygon ); units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); QVERIFY(( qgsDoubleNear( area, 3.0, 0.00000001 ) && units == QgsUnitTypes::AreaSquareDegrees ) || ( qgsDoubleNear( area, 37176087091.5, 0.1 ) && units == QgsUnitTypes::AreaSquareMeters ) ); da.setEllipsoidalMode( true ); area = da.measureArea( &polygon ); units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); // should always be in Meters Squared QGSCOMPARENEAR( area, 37416879192.9, 0.1 ); QCOMPARE( units, QgsUnitTypes::AreaSquareMeters ); // test converting the resultant area area = da.convertAreaMeasurement( area, QgsUnitTypes::AreaSquareMiles ); QGSCOMPARENEAR( area, 14446.7378, 0.001 ); // now try with a source CRS which is in feet ring.clear(); ring << QgsPoint( 1850000, 4423000 ) << QgsPoint( 1851000, 4423000 ) << QgsPoint( 1851000, 4424000 ) << QgsPoint( 1852000, 4424000 ) << QgsPoint( 1852000, 4425000 ) << QgsPoint( 1851000, 4425000 ) << QgsPoint( 1850000, 4423000 ); poly.clear(); poly << ring; polygon = QgsGeometry::fromPolygon( poly ); da.setSourceCrs( 27469 ); da.setEllipsoidalMode( false ); // measurement should be in square feet area = da.measureArea( &polygon ); units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); QGSCOMPARENEAR( area, 2000000, 0.001 ); QCOMPARE( units, QgsUnitTypes::AreaSquareFeet ); // test converting the resultant area area = da.convertAreaMeasurement( area, QgsUnitTypes::AreaSquareYards ); QGSCOMPARENEAR( area, 222222.2222, 0.001 ); da.setEllipsoidalMode( true ); // now should be in Square Meters again area = da.measureArea( &polygon ); units = da.areaUnits(); QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); QGSCOMPARENEAR( area, 184149.37, 1.0 ); QCOMPARE( units, QgsUnitTypes::AreaSquareMeters ); // test converting the resultant area area = da.convertAreaMeasurement( area, QgsUnitTypes::AreaSquareYards ); QgsDebugMsg( QString( "measured %1 in sq yrds" ).arg( area ) ); QGSCOMPARENEAR( area, 220240.8172549, 0.00001 ); }
bool QgsEllipseSymbolLayerV2::writeDxf( QgsDxfExport& e, double mmMapUnitScaleFactor, const QString& layerName, QgsSymbolV2RenderContext *context, const QgsFeature*, const QPointF& shift ) const { //width double symbolWidth = mSymbolWidth; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH ) ) //1. priority: data defined setting on symbol layer le { context->setOriginalValueVariable( mSymbolWidth ); symbolWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_WIDTH, *context, mSymbolWidth ).toDouble(); } else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level { symbolWidth = mSize; } if ( mSymbolWidthUnit == QgsSymbolV2::MM ) { symbolWidth *= mmMapUnitScaleFactor; } //height double symbolHeight = mSymbolHeight; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT ) ) //1. priority: data defined setting on symbol layer level { context->setOriginalValueVariable( mSymbolHeight ); symbolHeight = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_HEIGHT, *context, mSymbolHeight ).toDouble(); } else if ( context->renderHints() & QgsSymbolV2::DataDefinedSizeScale ) //2. priority: is data defined size on symbol level { symbolHeight = mSize; } if ( mSymbolHeightUnit == QgsSymbolV2::MM ) { symbolHeight *= mmMapUnitScaleFactor; } //outline width double outlineWidth = mOutlineWidth; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH ) ) { context->setOriginalValueVariable( mOutlineWidth ); outlineWidth = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_WIDTH, *context, mOutlineWidth ).toDouble(); } if ( mOutlineWidthUnit == QgsSymbolV2::MM ) { outlineWidth *= outlineWidth; } //fill color bool ok; QColor fc = mFillColor; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR ) ) { context->setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mFillColor ) ); QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_FILL_COLOR, *context, QVariant(), &ok ).toString(); if ( ok ) fc = QgsSymbolLayerV2Utils::decodeColor( colorString ); } //outline color QColor oc = mOutlineColor; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR ) ) { context->setOriginalValueVariable( QgsSymbolLayerV2Utils::encodeColor( mOutlineColor ) ); QString colorString = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_OUTLINE_COLOR, *context, QVariant(), &ok ).toString(); if ( ok ) oc = QgsSymbolLayerV2Utils::decodeColor( colorString ); } //symbol name QString symbolName = mSymbolName; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME ) ) { context->setOriginalValueVariable( mSymbolName ); symbolName = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_SYMBOL_NAME, *context, mSymbolName ).toString(); } //offset double offsetX = 0; double offsetY = 0; markerOffset( *context, offsetX, offsetY ); QPointF off( offsetX, offsetY ); //priority for rotation: 1. data defined symbol level, 2. symbol layer rotation (mAngle) double rotation = 0.0; if ( hasDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION ) ) { context->setOriginalValueVariable( mAngle ); rotation = evaluateDataDefinedProperty( QgsSymbolLayerV2::EXPR_ROTATION, *context, mAngle ).toDouble() + mLineAngle; } else if ( !qgsDoubleNear( mAngle + mLineAngle, 0.0 ) ) { rotation = mAngle + mLineAngle; } rotation = -rotation; //rotation in Qt is counterclockwise if ( rotation ) off = _rotatedOffset( off, rotation ); QTransform t; t.translate( shift.x() + offsetX, shift.y() + offsetY ); if ( rotation != 0 ) t.rotate( rotation ); double halfWidth = symbolWidth / 2.0; double halfHeight = symbolHeight / 2.0; if ( symbolName == "circle" ) { if ( qgsDoubleNear( halfWidth, halfHeight ) ) { QPointF pt( t.map( QPointF( 0, 0 ) ) ); e.writeFilledCircle( layerName, oc, pt, halfWidth ); } else { QgsPolyline line; double stepsize = 2 * M_PI / 40; for ( int i = 0; i < 39; ++i ) { double angle = stepsize * i; double x = halfWidth * cos( angle ); double y = halfHeight * sin( angle ); QPointF pt( t.map( QPointF( x, y ) ) ); line.push_back( pt ); } //close ellipse with first point line.push_back( line.at( 0 ) ); if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( QgsPolygon() << line, layerName, "SOLID", fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth ); } } else if ( symbolName == "rectangle" ) { QgsPolygon p( 1 ); p[0].resize( 5 ); p[0][0] = t.map( QPointF( -halfWidth, -halfHeight ) ); p[0][1] = t.map( QPointF( halfWidth, -halfHeight ) ); p[0][2] = t.map( QPointF( halfWidth, halfHeight ) ); p[0][3] = t.map( QPointF( -halfWidth, halfHeight ) ); p[0][4] = p[0][0]; if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( p, layerName, "SOLID", fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( p[0], layerName, "CONTINUOUS", oc, outlineWidth ); return true; } else if ( symbolName == "cross" && mPen.style() != Qt::NoPen ) { QgsPolyline line( 2 ); line[0] = t.map( QPointF( -halfWidth, 0 ) ); line[1] = t.map( QPointF( halfWidth, 0 ) ); e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth ); line[0] = t.map( QPointF( 0, halfHeight ) ); line[1] = t.map( QPointF( 0, -halfHeight ) ); e.writePolyline( line, layerName, "CONTINUOUS", oc, outlineWidth ); return true; } else if ( symbolName == "triangle" ) { QgsPolygon p( 1 ); p[0].resize( 4 ); p[0][0] = QPointF( t.map( QPointF( -halfWidth, -halfHeight ) ) ); p[0][1] = QPointF( t.map( QPointF( halfWidth, -halfHeight ) ) ); p[0][2] = QPointF( t.map( QPointF( 0, halfHeight ) ) ); p[0][3] = p[0][0]; if ( mBrush.style() != Qt::NoBrush ) e.writePolygon( p, layerName, "SOLID", fc ); if ( mPen.style() != Qt::NoPen ) e.writePolyline( p[0], layerName, "CONTINUOUS", oc, outlineWidth ); return true; } return false; //soon... }
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(); }