void QgsPointDistanceRenderer::drawGroup( const ClusteredGroup& group, QgsRenderContext& context ) { //calculate centroid of all points, this will be center of group QgsMultiPointV2* groupMultiPoint = new QgsMultiPointV2(); Q_FOREACH ( const GroupedFeature& f, group ) { groupMultiPoint->addGeometry( f.feature.geometry().geometry()->clone() ); }
QgsAbstractGeometryV2* QgsGeometryImport::fromMultiPoint( const QgsMultiPoint& multipoint ) { QgsMultiPointV2* mp = new QgsMultiPointV2(); QgsMultiPoint::const_iterator ptIt = multipoint.constBegin(); for ( ; ptIt != multipoint.constEnd(); ++ptIt ) { QgsPointV2* pt = new QgsPointV2( ptIt->x(), ptIt->y() ); mp->addGeometry( pt ); } return mp; }
QgsAbstractGeometry* QgsCurve::boundary() const { if ( isEmpty() ) return nullptr; if ( isClosed() ) return nullptr; QgsMultiPointV2* multiPoint = new QgsMultiPointV2(); multiPoint->addGeometry( new QgsPointV2( startPoint() ) ); multiPoint->addGeometry( new QgsPointV2( endPoint() ) ); return multiPoint; }
QgsAbstractGeometryV2* QgsMultiCurveV2::boundary() const { QgsMultiPointV2* multiPoint = new QgsMultiPointV2(); for ( int i = 0; i < mGeometries.size(); ++i ) { if ( QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( mGeometries.at( i ) ) ) { if ( !curve->isClosed() ) { multiPoint->addGeometry( new QgsPointV2( curve->startPoint() ) ); multiPoint->addGeometry( new QgsPointV2( curve->endPoint() ) ); } } } if ( multiPoint->numGeometries() == 0 ) { delete multiPoint; return nullptr; } return multiPoint; }
void QgsPointDisplacementRenderer::drawGroup( const DisplacementGroup& group, QgsRenderContext& context ) { const QgsFeature& feature = group.begin().value().first; bool selected = mSelectedFeatures.contains( feature.id() ); // maybe we should highlight individual features instead of the whole group? //get list of labels and symbols QStringList labelAttributeList; QList<QgsMarkerSymbolV2*> symbolList; QgsMultiPointV2* groupMultiPoint = new QgsMultiPointV2(); for ( DisplacementGroup::const_iterator attIt = group.constBegin(); attIt != group.constEnd(); ++attIt ) { labelAttributeList << ( mDrawLabels ? getLabel( attIt.value().first ) : QString() ); symbolList << dynamic_cast<QgsMarkerSymbolV2*>( attIt.value().second ); groupMultiPoint->addGeometry( attIt.value().first.constGeometry()->geometry()->clone() ); } //calculate centroid of all points, this will be center of group QgsGeometry groupGeom( groupMultiPoint ); QgsGeometry* centroid = groupGeom.centroid(); QPointF pt; _getPoint( pt, context, centroid->asWkb() ); delete centroid; //calculate max diagonal size from all symbols in group double diagonal = 0; Q_FOREACH ( QgsMarkerSymbolV2* symbol, symbolList ) { if ( symbol ) { diagonal = qMax( diagonal, QgsSymbolLayerV2Utils::convertToPainterUnits( context, M_SQRT2 * symbol->size(), symbol->outputUnit(), symbol->mapUnitScale() ) ); } } QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM, 1.0, selected ); QList<QPointF> symbolPositions; QList<QPointF> labelPositions; double circleRadius = -1.0; calculateSymbolAndLabelPositions( symbolContext, pt, symbolList.size(), diagonal, symbolPositions, labelPositions, circleRadius ); //draw Circle if ( circleRadius > 0 ) drawCircle( circleRadius, symbolContext, pt, symbolList.size() ); //draw mid point if ( labelAttributeList.size() > 1 ) { if ( mCenterSymbol ) { mCenterSymbol->renderPoint( pt, &feature, context, -1, selected ); } else { context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) ); } } //draw symbols on the circle drawSymbols( feature, context, symbolList, symbolPositions, selected ); //and also the labels drawLabels( pt, symbolContext, labelPositions, labelAttributeList ); }
void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent* e ) { QgsVectorLayer* vlayer = currentVectorLayer(); if ( !vlayer ) { notifyNotVectorLayer(); return; } QgsWkbTypes::Type layerWKBType = vlayer->wkbType(); QgsVectorDataProvider* provider = vlayer->dataProvider(); if ( !( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) ) { emit messageEmitted( tr( "The data provider for this layer does not support the addition of features." ), QgsMessageBar::WARNING ); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } // POINT CAPTURING if ( mode() == CapturePoint ) { if ( e->button() != Qt::LeftButton ) return; //check we only use this tool for point/multipoint layers if ( vlayer->geometryType() != QgsWkbTypes::PointGeometry && mCheckGeometryType ) { emit messageEmitted( tr( "Wrong editing tool, cannot apply the 'capture point' tool on this vector layer" ), QgsMessageBar::WARNING ); return; } QgsPoint savePoint; //point in layer coordinates try { QgsPointV2 fetchPoint; int res; res = fetchLayerPoint( e->mapPointMatch(), fetchPoint ); if ( res == 0 ) { savePoint = QgsPoint( fetchPoint.x(), fetchPoint.y() ); } else { savePoint = toLayerCoordinates( vlayer, e->mapPoint() ); } QgsDebugMsg( "savePoint = " + savePoint.toString() ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); emit messageEmitted( tr( "Cannot transform the point to the layers coordinate system" ), QgsMessageBar::WARNING ); return; } //only do the rest for provider with feature addition support //note that for the grass provider, this will return false since //grass provider has its own mechanism of feature addition if ( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) { QgsFeature f( vlayer->fields(), 0 ); QgsGeometry g; if ( layerWKBType == QgsWkbTypes::Point ) { g = QgsGeometry::fromPoint( savePoint ); } else if ( layerWKBType == QgsWkbTypes::Point25D ) { g = QgsGeometry( new QgsPointV2( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), 0.0 ) ); } else if ( layerWKBType == QgsWkbTypes::MultiPoint ) { g = QgsGeometry::fromMultiPoint( QgsMultiPoint() << savePoint ); } else if ( layerWKBType == QgsWkbTypes::MultiPoint25D ) { QgsMultiPointV2* mp = new QgsMultiPointV2(); mp->addGeometry( new QgsPointV2( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), 0.0 ) ); g = QgsGeometry( mp ); } else { // if layer supports more types (mCheckGeometryType is false) g = QgsGeometry::fromPoint( savePoint ); } f.setGeometry( g ); f.setValid( true ); addFeature( vlayer, &f, false ); vlayer->triggerRepaint(); } } // LINE AND POLYGON CAPTURING else if ( mode() == CaptureLine || mode() == CapturePolygon ) { //check we only use the line tool for line/multiline layers if ( mode() == CaptureLine && vlayer->geometryType() != QgsWkbTypes::LineGeometry && mCheckGeometryType ) { emit messageEmitted( tr( "Wrong editing tool, cannot apply the 'capture line' tool on this vector layer" ), QgsMessageBar::WARNING ); return; } //check we only use the polygon tool for polygon/multipolygon layers if ( mode() == CapturePolygon && vlayer->geometryType() != QgsWkbTypes::PolygonGeometry && mCheckGeometryType ) { emit messageEmitted( tr( "Wrong editing tool, cannot apply the 'capture polygon' tool on this vector layer" ), QgsMessageBar::WARNING ); return; } //add point to list and to rubber band if ( e->button() == Qt::LeftButton ) { int error = addVertex( e->mapPoint(), e->mapPointMatch() ); if ( error == 1 ) { //current layer is not a vector layer return; } else if ( error == 2 ) { //problem with coordinate transformation emit messageEmitted( tr( "Cannot transform the point to the layers coordinate system" ), QgsMessageBar::WARNING ); return; } startCapturing(); } else if ( e->button() == Qt::RightButton ) { // End of string deleteTempRubberBand(); //lines: bail out if there are not at least two vertices if ( mode() == CaptureLine && size() < 2 ) { stopCapturing(); return; } //polygons: bail out if there are not at least two vertices if ( mode() == CapturePolygon && size() < 3 ) { stopCapturing(); return; } if ( mode() == CapturePolygon ) { closePolygon(); } //create QgsFeature with wkb representation QScopedPointer< QgsFeature > f( new QgsFeature( vlayer->fields(), 0 ) ); //does compoundcurve contain circular strings? //does provider support circular strings? bool hasCurvedSegments = captureCurve()->hasCurvedSegments(); bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries; QgsCurve* curveToAdd = nullptr; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { curveToAdd = captureCurve()->clone(); } else { curveToAdd = captureCurve()->curveToLine(); } if ( mode() == CaptureLine ) { QgsGeometry* g = new QgsGeometry( curveToAdd ); f->setGeometry( *g ); delete g; } else { QgsCurvePolygon* poly = nullptr; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { poly = new QgsCurvePolygon(); } else { poly = new QgsPolygonV2(); } poly->setExteriorRing( curveToAdd ); QgsGeometry* g = new QgsGeometry( poly ); f->setGeometry( *g ); delete g; QgsGeometry featGeom = f->geometry(); int avoidIntersectionsReturn = featGeom.avoidIntersections(); f->setGeometry( featGeom ); if ( avoidIntersectionsReturn == 1 ) { //not a polygon type. Impossible to get there } if ( f->geometry().isGeosEmpty() ) //avoid intersection might have removed the whole geometry { emit messageEmitted( tr( "The feature cannot be added because it's geometry collapsed due to intersection avoidance" ), QgsMessageBar::CRITICAL ); stopCapturing(); return; } } f->setValid( true ); if ( addFeature( vlayer, f.data(), false ) ) { //add points to other features to keep topology up-to-date int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); //use always topological editing for avoidIntersection. //Otherwise, no way to guarantee the geometries don't have a small gap in between. QStringList intersectionLayers = QgsProject::instance()->readListEntry( "Digitizing", "/AvoidIntersectionsList" ); bool avoidIntersection = !intersectionLayers.isEmpty(); if ( avoidIntersection ) //try to add topological points also to background layers { QStringList::const_iterator lIt = intersectionLayers.constBegin(); for ( ; lIt != intersectionLayers.constEnd(); ++lIt ) { QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( *lIt ); QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( ml ); //can only add topological points if background layer is editable... if ( vl && vl->geometryType() == QgsWkbTypes::PolygonGeometry && vl->isEditable() ) { vl->addTopologicalPoints( f->geometry() ); } } } else if ( topologicalEditing ) { vlayer->addTopologicalPoints( f->geometry() ); } } stopCapturing(); } } }