const QgsGraphDirector* RoadGraphPlugin::director() const { QList< QgsMapLayer* > mapLayers = QgsMapLayerRegistry::instance()->mapLayersByName( mSettings->mLayerName ); if ( mapLayers.isEmpty() ) return nullptr; QgsVectorLayer *layer = dynamic_cast< QgsVectorLayer* >( mapLayers.at( 0 ) ); if ( !layer ) return nullptr; if ( layer->wkbType() == QgsWkbTypes::LineString || layer->wkbType() == QgsWkbTypes::MultiLineString ) { SpeedUnit speedUnit = SpeedUnit::byName( mSettings->mSpeedUnitName ); QgsLineVectorLayerDirector * director = new QgsLineVectorLayerDirector( layer, layer->fields().lookupField( mSettings->mDirection ), mSettings->mFirstPointToLastPointDirectionVal, mSettings->mLastPointToFirstPointDirectionVal, mSettings->mBothDirectionVal, mSettings->mDefaultDirection ); director->addProperter( new QgsDistanceArcProperter() ); director->addProperter( new RgSpeedProperter( layer->fields().lookupField( mSettings->mSpeed ), mSettings->mDefaultSpeed, speedUnit.multipler() ) ); return director; } return nullptr; }
int QgsMapToolCapture::nextPoint( const QgsPoint &mapPoint, QgsPoint &layerPoint ) { QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); if ( !vlayer ) { QgsDebugMsg( QStringLiteral( "no vector layer" ) ); return 1; } try { QgsPointXY mapP( mapPoint.x(), mapPoint.y() ); //#spellok layerPoint = QgsPoint( toLayerCoordinates( vlayer, mapP ) ); //transform snapped point back to layer crs //#spellok if ( QgsWkbTypes::hasZ( vlayer->wkbType() ) ) layerPoint.addZValue( defaultZValue() ); if ( QgsWkbTypes::hasM( vlayer->wkbType() ) ) layerPoint.addMValue( 0.0 ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ) QgsDebugMsg( QStringLiteral( "transformation to layer coordinate failed" ) ); return 2; } return 0; }
QgsPoint QgsMapToolCapture::mapPoint( const QgsPointXY &point ) const { QgsPoint newPoint( QgsWkbTypes::Point, point.x(), point.y() ); // get current layer QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); if ( !vlayer ) { return newPoint; } // convert to the corresponding type for a full ZM support const QgsWkbTypes::Type type = vlayer->wkbType(); if ( QgsWkbTypes::hasZ( type ) && !QgsWkbTypes::hasM( type ) ) { newPoint.convertTo( QgsWkbTypes::PointZ ); } else if ( !QgsWkbTypes::hasZ( type ) && QgsWkbTypes::hasM( type ) ) { newPoint.convertTo( QgsWkbTypes::PointM ); } else if ( QgsWkbTypes::hasZ( type ) && QgsWkbTypes::hasM( type ) ) { newPoint.convertTo( QgsWkbTypes::PointZM ); } // set z value if necessary if ( QgsWkbTypes::hasZ( newPoint.wkbType() ) ) { newPoint.setZ( defaultZValue() ); } return newPoint; }
void QgsServerProjectParser::addLayerProjectSettings( QDomElement& layerElem, QDomDocument& doc, QgsMapLayer* currentLayer ) const { if ( !currentLayer ) { return; } // Layer tree name QDomElement treeNameElem = doc.createElement( "TreeName" ); QDomText treeNameText = doc.createTextNode( currentLayer->name() ); treeNameElem.appendChild( treeNameText ); layerElem.appendChild( treeNameElem ); if ( currentLayer->type() == QgsMapLayer::VectorLayer ) { QgsVectorLayer* vLayer = static_cast<QgsVectorLayer*>( currentLayer ); const QSet<QString>& excludedAttributes = vLayer->excludeAttributesWMS(); int displayFieldIdx = vLayer->fieldNameIndex( vLayer->displayField() ); QString displayField = displayFieldIdx < 0 ? "maptip" : vLayer->displayField(); //attributes QDomElement attributesElem = doc.createElement( "Attributes" ); const QgsFields& layerFields = vLayer->pendingFields(); for ( int idx = 0; idx < layerFields.count(); ++idx ) { const QgsField& field = layerFields[idx]; if ( excludedAttributes.contains( field.name() ) ) { continue; } // field alias in case of displayField if ( idx == displayFieldIdx ) { displayField = vLayer->attributeDisplayName( idx ); } QDomElement attributeElem = doc.createElement( "Attribute" ); attributeElem.setAttribute( "name", field.name() ); attributeElem.setAttribute( "type", QVariant::typeToName( field.type() ) ); attributeElem.setAttribute( "typeName", field.typeName() ); QString alias = vLayer->attributeAlias( idx ); if ( !alias.isEmpty() ) { attributeElem.setAttribute( "alias", alias ); } //edit type to text attributeElem.setAttribute( "editType", vLayer->editFormConfig()->widgetType( idx ) ); attributeElem.setAttribute( "comment", field.comment() ); attributeElem.setAttribute( "length", field.length() ); attributeElem.setAttribute( "precision", field.precision() ); attributesElem.appendChild( attributeElem ); } //displayfield layerElem.setAttribute( "displayField", displayField ); //geometry type layerElem.setAttribute( "geometryType", QGis::featureType( vLayer->wkbType() ) ); layerElem.appendChild( attributesElem ); } }
int QgsMapToolCapture::fetchLayerPoint( const QgsPointLocator::Match &match, QgsPoint &layerPoint ) { QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); QgsVectorLayer *sourceLayer = match.layer(); if ( match.isValid() && match.hasVertex() && sourceLayer && ( sourceLayer->crs() == vlayer->crs() ) ) { QgsFeature f; QgsFeatureRequest request; request.setFilterFid( match.featureId() ); bool fetched = match.layer()->getFeatures( request ).nextFeature( f ); if ( fetched ) { QgsVertexId vId; if ( !f.geometry().vertexIdFromVertexNr( match.vertexIndex(), vId ) ) return 2; layerPoint = f.geometry().constGet()->vertexAt( vId ); // ZM support depends on the target layer if ( !QgsWkbTypes::hasZ( vlayer->wkbType() ) ) { layerPoint.dropZValue(); } if ( !QgsWkbTypes::hasM( vlayer->wkbType() ) ) { layerPoint.dropMValue(); } return 0; } else { return 2; } } else { return 1; } }
const QgsGraphDirector* RoadGraphPlugin::director() const { QgsVectorLayer *layer = nullptr; QMap< QString, QgsMapLayer* > mapLayers = QgsMapLayerRegistry::instance()->mapLayers(); QMap< QString, QgsMapLayer* >::const_iterator it; for ( it = mapLayers.begin(); it != mapLayers.end(); ++it ) { if ( it.value()->name() != mSettings->mLayer ) continue; layer = dynamic_cast< QgsVectorLayer* >( it.value() ); break; } if ( !layer ) return nullptr; if ( layer->wkbType() == QGis::WKBLineString || layer->wkbType() == QGis::WKBMultiLineString ) { QgsVectorDataProvider *provider = layer->dataProvider(); if ( !provider ) return nullptr; SpeedUnit speedUnit = SpeedUnit::byName( mSettings->mSpeedUnitName ); QgsLineVectorLayerDirector * director = new QgsLineVectorLayerDirector( layer, provider->fieldNameIndex( mSettings->mDirection ), mSettings->mFirstPointToLastPointDirectionVal, mSettings->mLastPointToFirstPointDirectionVal, mSettings->mBothDirectionVal, mSettings->mDefaultDirection ); director->addProperter( new QgsDistanceArcProperter() ); director->addProperter( new RgSpeedProperter( provider->fieldNameIndex( mSettings->mSpeed ), mSettings->mDefaultSpeed, speedUnit.multipler() ) ); return director; } return nullptr; }
void LayerSelectorDialog::populateLayers() { QgsVectorLayer* layer; QMap<QString, QgsMapLayer*> mapLayers = QgsMapLayerRegistry::instance()->mapLayers(); QMap<QString, QgsMapLayer*>::iterator layer_it = mapLayers.begin(); for ( ; layer_it != mapLayers.end(); ++layer_it ) { if ( layer_it.value()->type() == QgsMapLayer::VectorLayer ) { layer = qobject_cast<QgsVectorLayer *> ( layer_it.value() ); QTreeWidgetItem *item = new QTreeWidgetItem( treeLayers ); item->setText( 0, layer_it.value()->name() ); switch ( layer->wkbType() ) { // polygon case QGis::WKBPolygon: case QGis::WKBPolygon25D: { item->setText( 1, "Polygon" ); break; } // point case QGis::WKBPoint: case QGis::WKBPoint25D: { item->setText( 1, "Point" ); break; } // line case QGis::WKBLineString: case QGis::WKBLineString25D: { item->setText( 1, "Line" ); break; } default: break; } // switch } } }
void QgsMapToolAddPart::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { //check if we operate on a vector layer QgsVectorLayer *vlayer = currentVectorLayer(); if ( !vlayer ) { notifyNotVectorLayer(); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } bool isGeometryEmpty = false; QgsFeatureList selectedFeatures = vlayer->selectedFeatures(); if ( !selectedFeatures.isEmpty() && selectedFeatures.at( 0 ).geometry().isNull() ) isGeometryEmpty = true; if ( !checkSelection() ) { stopCapturing(); return; } int errorCode = 0; switch ( mode() ) { case CapturePoint: { QgsPoint layerPoint; QgsPointXY mapPoint = e->mapPoint(); if ( nextPoint( QgsPoint( mapPoint ), layerPoint ) != 0 ) { QgsDebugMsg( "nextPoint failed" ); return; } vlayer->beginEditCommand( tr( "Part added" ) ); errorCode = vlayer->addPart( QgsPointSequence() << layerPoint ); } break; case CaptureLine: case CapturePolygon: { //add point to list and to rubber band if ( e->button() == Qt::LeftButton ) { int error = addVertex( e->mapPoint(), e->mapPointMatch() ); if ( error == 1 ) { QgsDebugMsg( "current layer is not a vector layer" ); return; } else if ( error == 2 ) { //problem with coordinate transformation emit messageEmitted( tr( "Coordinate transform error. Cannot transform the point to the layers coordinate system" ), Qgis::Warning ); return; } startCapturing(); return; } else if ( e->button() != Qt::RightButton ) { deleteTempRubberBand(); return; } if ( !isCapturing() ) return; if ( mode() == CapturePolygon ) { closePolygon(); } //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(); } vlayer->beginEditCommand( tr( "Part added" ) ); if ( mode() == CapturePolygon ) { //avoid intersections QgsCurvePolygon *cp = new QgsCurvePolygon(); cp->setExteriorRing( curveToAdd ); QgsGeometry *geom = new QgsGeometry( cp ); geom->avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() ); const QgsCurvePolygon *cpGeom = qgsgeometry_cast<const QgsCurvePolygon *>( geom->constGet() ); if ( !cpGeom ) { stopCapturing(); delete geom; vlayer->destroyEditCommand(); return; } errorCode = vlayer->addPart( cpGeom->exteriorRing()->clone() ); delete geom; } else { errorCode = vlayer->addPart( curveToAdd ); } stopCapturing(); } break; default: Q_ASSERT( !"invalid capture mode" ); errorCode = 6; break; } QString errorMessage; switch ( errorCode ) { case 0: { // remove previous message emit messageDiscarded(); //add points to other features to keep topology up-to-date bool topologicalEditing = QgsProject::instance()->topologicalEditing(); if ( topologicalEditing ) { addTopologicalPoints( points() ); } vlayer->endEditCommand(); vlayer->triggerRepaint(); if ( ( !isGeometryEmpty ) && QgsWkbTypes::isSingleType( vlayer->wkbType() ) ) { emit messageEmitted( tr( "Add part: Feature geom is single part and you've added more than one" ), Qgis::Warning ); } return; } case 1: errorMessage = tr( "Selected feature is not multi part." ); break; case 2: errorMessage = tr( "New part's geometry is not valid." ); break; case 3: errorMessage = tr( "New polygon ring not disjoint with existing polygons." ); break; case 4: errorMessage = tr( "No feature selected. Please select a feature with the selection tool or in the attribute table" ); break; case 5: errorMessage = tr( "Several features are selected. Please select only one feature to which an island should be added." ); break; case 6: errorMessage = tr( "Selected geometry could not be found" ); break; } emit messageEmitted( errorMessage, Qgis::Warning ); vlayer->destroyEditCommand(); }
void QgsMapToolDigitizeFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mLayer ); if ( !vlayer ) //if no given layer take the current from canvas 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." ), Qgis::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" ), Qgis::Warning ); return; } QgsPointXY savePoint; //point in layer coordinates try { QgsPoint fetchPoint; int res; res = fetchLayerPoint( e->mapPointMatch(), fetchPoint ); if ( res == 0 ) { savePoint = QgsPointXY( 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" ), Qgis::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::fromPointXY( savePoint ); } else if ( !QgsWkbTypes::isMultiType( layerWKBType ) && QgsWkbTypes::hasZ( layerWKBType ) ) { g = QgsGeometry( new QgsPoint( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), defaultZValue() ) ); } else if ( QgsWkbTypes::isMultiType( layerWKBType ) && !QgsWkbTypes::hasZ( layerWKBType ) ) { g = QgsGeometry::fromMultiPointXY( QgsMultiPointXY() << savePoint ); } else if ( QgsWkbTypes::isMultiType( layerWKBType ) && QgsWkbTypes::hasZ( layerWKBType ) ) { QgsMultiPoint *mp = new QgsMultiPoint(); mp->addGeometry( new QgsPoint( QgsWkbTypes::PointZ, savePoint.x(), savePoint.y(), defaultZValue() ) ); g = QgsGeometry( mp ); } else { // if layer supports more types (mCheckGeometryType is false) g = QgsGeometry::fromPointXY( savePoint ); } if ( QgsWkbTypes::hasM( layerWKBType ) ) { g.get()->addMValue(); } f.setGeometry( g ); f.setValid( true ); digitized( f ); // we are done with digitizing for now so instruct advanced digitizing dock to reset its CAD points cadDockWidget()->clearPoints(); } } // 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" ), Qgis::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" ), Qgis::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" ), Qgis::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 std::unique_ptr< 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; QList<QgsPointLocator::Match> snappingMatchesList; QgsCurve *curveToAdd = nullptr; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { curveToAdd = captureCurve()->clone(); } else { curveToAdd = captureCurve()->curveToLine(); snappingMatchesList = snappingMatches(); } if ( mode() == CaptureLine ) { QgsGeometry g( curveToAdd ); f->setGeometry( g ); } else { QgsCurvePolygon *poly = nullptr; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { poly = new QgsCurvePolygon(); } else { poly = new QgsPolygon(); } poly->setExteriorRing( curveToAdd ); QgsGeometry g( poly ); f->setGeometry( g ); QgsGeometry featGeom = f->geometry(); int avoidIntersectionsReturn = featGeom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() ); f->setGeometry( featGeom ); if ( avoidIntersectionsReturn == 1 ) { //not a polygon type. Impossible to get there } if ( f->geometry().isEmpty() ) //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" ), Qgis::Critical ); stopCapturing(); return; } } f->setValid( true ); digitized( *f ); stopCapturing(); } } }
void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e ) { QgsDebugMsg( "entered." ); QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ); if ( !vlayer ) { notifyNotVectorLayer(); return; } QGis::WkbType layerWKBType = vlayer->wkbType(); QgsVectorDataProvider* provider = vlayer->dataProvider(); if ( !( provider->capabilities() & QgsVectorDataProvider::AddFeatures ) ) { QMessageBox::information( 0, tr( "Layer cannot be added to" ), tr( "The data provider for this layer does not support the addition of features." ) ); return; } if ( !vlayer->isEditable() ) { notifyNotEditableLayer(); return; } // POINT CAPTURING if ( mode() == CapturePoint ) { //check we only use this tool for point/multipoint layers if ( vlayer->geometryType() != QGis::Point ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture point' tool on this vector layer" ) ); return; } QgsPoint idPoint; //point in map coordinates QList<QgsSnappingResult> snapResults; QgsPoint savePoint; //point in layer coordinates if ( mSnapper.snapToBackgroundLayers( e->pos(), snapResults ) == 0 ) { idPoint = snapPointFromResults( snapResults, e->pos() ); try { savePoint = toLayerCoordinates( vlayer, idPoint ); QgsDebugMsg( "savePoint = " + savePoint.toString() ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); QMessageBox::information( 0, tr( "Coordinate transform error" ), tr( "Cannot transform the point to the layers coordinate system" ) ); 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 = new QgsFeature( 0, "WKBPoint" ); QgsGeometry *g = 0; if ( layerWKBType == QGis::WKBPoint || layerWKBType == QGis::WKBPoint25D ) { g = QgsGeometry::fromPoint( savePoint ); } else if ( layerWKBType == QGis::WKBMultiPoint || layerWKBType == QGis::WKBMultiPoint25D ) { g = QgsGeometry::fromMultiPoint( QgsMultiPoint() << savePoint ); } f->setGeometry( g ); vlayer->beginEditCommand( tr( "Feature added" ) ); if ( addFeature( vlayer, f ) ) { vlayer->endEditCommand(); } else { delete f; vlayer->destroyEditCommand(); } mCanvas->refresh(); } } else if ( mode() == CaptureLine || mode() == CapturePolygon ) { //check we only use the line tool for line/multiline layers if ( mode() == CaptureLine && vlayer->geometryType() != QGis::Line ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture line' tool on this vector layer" ) ); return; } //check we only use the polygon tool for polygon/multipolygon layers if ( mode() == CapturePolygon && vlayer->geometryType() != QGis::Polygon ) { QMessageBox::information( 0, tr( "Wrong editing tool" ), tr( "Cannot apply the 'capture polygon' tool on this vector layer" ) ); return; } //add point to list and to rubber band int error = addVertex( e->pos() ); if ( error == 1 ) { //current layer is not a vector layer return; } else if ( error == 2 ) { //problem with coordinate transformation QMessageBox::information( 0, tr( "Coordinate transform error" ), tr( "Cannot transform the point to the layers coordinate system" ) ); return; } if ( e->button() == Qt::LeftButton ) { startCapturing(); } else if ( e->button() == Qt::RightButton ) { // End of string //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; } //create QgsFeature with wkb representation QgsFeature* f = new QgsFeature( 0, "WKBLineString" ); QgsGeometry *g; if ( mode() == CaptureLine ) { if ( layerWKBType == QGis::WKBLineString || layerWKBType == QGis::WKBLineString25D ) { g = QgsGeometry::fromPolyline( points().toVector() ); } else if ( layerWKBType == QGis::WKBMultiLineString || layerWKBType == QGis::WKBMultiLineString25D ) { g = QgsGeometry::fromMultiPolyline( QgsMultiPolyline() << points().toVector() ); } else { QMessageBox::critical( 0, tr( "Error" ), tr( "Cannot add feature. Unknown WKB type" ) ); stopCapturing(); return; //unknown wkbtype } f->setGeometry( g ); } else // polygon { if ( layerWKBType == QGis::WKBPolygon || layerWKBType == QGis::WKBPolygon25D ) { g = QgsGeometry::fromPolygon( QgsPolygon() << points().toVector() ); } else if ( layerWKBType == QGis::WKBMultiPolygon || layerWKBType == QGis::WKBMultiPolygon25D ) { g = QgsGeometry::fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << points().toVector() ) ); } else { QMessageBox::critical( 0, tr( "Error" ), tr( "Cannot add feature. Unknown WKB type" ) ); stopCapturing(); return; //unknown wkbtype } if ( !g ) { stopCapturing(); delete f; return; // invalid geometry; one possibility is from duplicate points } f->setGeometry( g ); int avoidIntersectionsReturn = f->geometry()->avoidIntersections(); if ( avoidIntersectionsReturn == 1 ) { //not a polygon type. Impossible to get there } #if 0 else if ( avoidIntersectionsReturn == 2 ) //MH120131: disable this error message until there is a better way to cope with the single type / multi type problem { //bail out... QMessageBox::critical( 0, tr( "Error" ), tr( "The feature could not be added because removing the polygon intersections would change the geometry type" ) ); delete f; stopCapturing(); return; } #endif else if ( avoidIntersectionsReturn == 3 ) { QMessageBox::critical( 0, tr( "Error" ), tr( "An error was reported during intersection removal" ) ); } } vlayer->beginEditCommand( tr( "Feature added" ) ); if ( addFeature( vlayer, f ) ) { //add points to other features to keep topology up-to-date int topologicalEditing = QgsProject::instance()->readNumEntry( "Digitizing", "/TopologicalEditing", 0 ); if ( topologicalEditing ) { vlayer->addTopologicalPoints( f->geometry() ); } vlayer->endEditCommand(); } else { delete f; vlayer->destroyEditCommand(); } stopCapturing(); } } }
void QgsMapToolAddFeature::cadCanvasReleaseEvent( QgsMapMouseEvent* e ) { QgsVectorLayer* vlayer = currentVectorLayer(); if ( !vlayer ) { notifyNotVectorLayer(); return; } QGis::WkbType 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() != QGis::Point && 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 { 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 = 0; if ( layerWKBType == QGis::WKBPoint || layerWKBType == QGis::WKBPoint25D ) { g = QgsGeometry::fromPoint( savePoint ); } else if ( layerWKBType == QGis::WKBMultiPoint || layerWKBType == QGis::WKBMultiPoint25D ) { g = QgsGeometry::fromMultiPoint( QgsMultiPoint() << savePoint ); } else { // if layer supports more types (mCheckGeometryType is false) g = QgsGeometry::fromPoint( savePoint ); } f.setGeometry( g ); f.setValid( true ); addFeature( vlayer, &f, false ); mCanvas->refresh(); } } // 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() != QGis::Line && 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() != QGis::Polygon && 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() ); 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; QgsCurveV2* curveToAdd = 0; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { curveToAdd = captureCurve()->clone(); } else { curveToAdd = captureCurve()->curveToLine(); } if ( mode() == CaptureLine ) { f->setGeometry( new QgsGeometry( curveToAdd ) ); } else { QgsCurvePolygonV2* poly = 0; if ( hasCurvedSegments && providerSupportsCurvedSegments ) { poly = new QgsCurvePolygonV2(); } else { poly = new QgsPolygonV2(); } poly->setExteriorRing( curveToAdd ); f->setGeometry( new QgsGeometry( poly ) ); int avoidIntersectionsReturn = f->geometry()->avoidIntersections(); if ( avoidIntersectionsReturn == 1 ) { //not a polygon type. Impossible to get there } #if 0 else if ( avoidIntersectionsReturn == 2 ) //MH120131: disable this error message until there is a better way to cope with the single type / multi type problem { //bail out... emit messageEmitted( tr( "The feature could not be added because removing the polygon intersections would change the geometry type" ), QgsMessageBar::CRITICAL ); stopCapturing(); return; } #endif else if ( avoidIntersectionsReturn == 3 ) { emit messageEmitted( tr( "An error was reported during intersection removal" ), QgsMessageBar::CRITICAL ); } if ( !f->constGeometry()->asWkb() ) //avoid intersection might have removed the whole geometry { QString reason; if ( avoidIntersectionsReturn != 2 ) { reason = tr( "The feature cannot be added because it's geometry is empty" ); } else { reason = tr( "The feature cannot be added because it's geometry collapsed due to intersection avoidance" ); } emit messageEmitted( reason, QgsMessageBar::CRITICAL ); stopCapturing(); return; } } 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() == QGis::Polygon && vl->isEditable() ) { vl->addTopologicalPoints( f->constGeometry() ); } } } else if ( topologicalEditing ) { vlayer->addTopologicalPoints( f->constGeometry() ); } } stopCapturing(); } } }
// Slot called when the menu item is triggered // If you created more menu items / toolbar buttons in initiGui, you should // create a separate handler for each action - this single run() method will // not be enough void Heatmap::run() { HeatmapGui d( mQGisIface->mainWindow(), QgisGui::ModalDialogFlags, &mSessionSettings ); //check that dialog found a suitable vector layer if ( !d.inputVectorLayer() ) { mQGisIface->messageBar()->pushMessage( tr( "Layer not found" ), tr( "The heatmap plugin requires at least one point vector layer" ), QgsMessageBar::INFO, mQGisIface->messageTimeout() ); return; } if ( d.exec() != QDialog::Accepted ) { return; } QgsVectorLayer* inputLayer = d.inputVectorLayer(); // Get the required data from the dialog QgsRectangle myBBox = d.bbox(); int columns = d.columns(); int rows = d.rows(); double cellsize = d.cellSizeX(); // or d.cellSizeY(); both have the same value mDecay = d.decayRatio(); KernelShape kernelShape = d.kernelShape(); OutputValues valueType = d.outputValues(); //is input layer multipoint? bool isMultiPoint = inputLayer->wkbType() == QGis::WKBMultiPoint || inputLayer->wkbType() == QGis::WKBMultiPoint25D; // Getting the rasterdataset in place GDALAllRegister(); GDALDataset *emptyDataset; GDALDriver *myDriver; myDriver = GetGDALDriverManager()->GetDriverByName( d.outputFormat().toUtf8() ); if ( myDriver == NULL ) { mQGisIface->messageBar()->pushMessage( tr( "GDAL driver error" ), tr( "Cannot open the driver for the specified format" ), QgsMessageBar::WARNING, mQGisIface->messageTimeout() ); return; } double geoTransform[6] = { myBBox.xMinimum(), cellsize, 0, myBBox.yMinimum(), 0, cellsize }; emptyDataset = myDriver->Create( d.outputFilename().toUtf8(), columns, rows, 1, GDT_Float32, NULL ); emptyDataset->SetGeoTransform( geoTransform ); // Set the projection on the raster destination to match the input layer emptyDataset->SetProjection( inputLayer->crs().toWkt().toLocal8Bit().data() ); GDALRasterBand *poBand; poBand = emptyDataset->GetRasterBand( 1 ); poBand->SetNoDataValue( NO_DATA ); float* line = ( float * ) CPLMalloc( sizeof( float ) * columns ); for ( int i = 0; i < columns ; i++ ) { line[i] = NO_DATA; } // Write the empty raster for ( int i = 0; i < rows ; i++ ) { poBand->RasterIO( GF_Write, 0, i, columns, 1, line, columns, 1, GDT_Float32, 0, 0 ); } CPLFree( line ); //close the dataset GDALClose(( GDALDatasetH ) emptyDataset ); // open the raster in GA_Update mode GDALDataset *heatmapDS; heatmapDS = ( GDALDataset * ) GDALOpen( TO8F( d.outputFilename() ), GA_Update ); if ( !heatmapDS ) { mQGisIface->messageBar()->pushMessage( tr( "Raster update error" ), tr( "Could not open the created raster for updating. The heatmap was not generated." ), QgsMessageBar::WARNING ); return; } poBand = heatmapDS->GetRasterBand( 1 ); QgsAttributeList myAttrList; int rField = 0; int wField = 0; // Handle different radius options double radius; double radiusToMapUnits = 1; int myBuffer = 0; if ( d.variableRadius() ) { rField = d.radiusField(); myAttrList.append( rField ); QgsDebugMsg( QString( "Radius Field index received: %1" ).arg( rField ) ); // If not using map units, then calculate a conversion factor to convert the radii to map units if ( d.radiusUnit() == HeatmapGui::Meters ) { radiusToMapUnits = mapUnitsOf( 1, inputLayer->crs() ); } } else { radius = d.radius(); // radius returned by d.radius() is already in map units myBuffer = bufferSize( radius, cellsize ); } if ( d.weighted() ) { wField = d.weightField(); myAttrList.append( wField ); } // This might have attributes or mightnot have attibutes at all // based on the variableRadius() and weighted() QgsFeatureIterator fit = inputLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( myAttrList ) ); int totalFeatures = inputLayer->featureCount(); int counter = 0; QProgressDialog p( tr( "Creating heatmap" ), tr( "Abort" ), 0, totalFeatures, mQGisIface->mainWindow() ); p.setWindowModality( Qt::ApplicationModal ); p.show(); QgsFeature myFeature; while ( fit.nextFeature( myFeature ) ) { counter++; p.setValue( counter ); QApplication::processEvents(); if ( p.wasCanceled() ) { mQGisIface->messageBar()->pushMessage( tr( "Heatmap generation aborted" ), tr( "QGIS will now load the partially-computed raster" ), QgsMessageBar::INFO, mQGisIface->messageTimeout() ); break; } QgsGeometry* featureGeometry = myFeature.geometry(); if ( !featureGeometry ) { continue; } // convert the geometry to multipoint QgsMultiPoint multiPoints; if ( !isMultiPoint ) { QgsPoint myPoint = featureGeometry->asPoint(); // avoiding any empty points or out of extent points if (( myPoint.x() < myBBox.xMinimum() ) || ( myPoint.y() < myBBox.yMinimum() ) || ( myPoint.x() > myBBox.xMaximum() ) || ( myPoint.y() > myBBox.yMaximum() ) ) { continue; } multiPoints << myPoint; } else { multiPoints = featureGeometry->asMultiPoint(); } // If radius is variable then fetch it and calculate new pixel buffer size if ( d.variableRadius() ) { radius = myFeature.attribute( rField ).toDouble() * radiusToMapUnits; myBuffer = bufferSize( radius, cellsize ); } int blockSize = 2 * myBuffer + 1; //Block SIDE would be more appropriate double weight = 1.0; if ( d.weighted() ) { weight = myFeature.attribute( wField ).toDouble(); } //loop through all points in multipoint for ( QgsMultiPoint::const_iterator pointIt = multiPoints.constBegin(); pointIt != multiPoints.constEnd(); ++pointIt ) { // avoiding any empty points or out of extent points if ((( *pointIt ).x() < myBBox.xMinimum() ) || (( *pointIt ).y() < myBBox.yMinimum() ) || (( *pointIt ).x() > myBBox.xMaximum() ) || (( *pointIt ).y() > myBBox.yMaximum() ) ) { continue; } // calculate the pixel position unsigned int xPosition, yPosition; xPosition = ((( *pointIt ).x() - myBBox.xMinimum() ) / cellsize ) - myBuffer; yPosition = ((( *pointIt ).y() - myBBox.yMinimum() ) / cellsize ) - myBuffer; // get the data float *dataBuffer = ( float * ) CPLMalloc( sizeof( float ) * blockSize * blockSize ); poBand->RasterIO( GF_Read, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ); for ( int xp = 0; xp <= myBuffer; xp++ ) { for ( int yp = 0; yp <= myBuffer; yp++ ) { double distance = sqrt( pow( xp, 2.0 ) + pow( yp, 2.0 ) ); // is pixel outside search bandwidth of feature? if ( distance > myBuffer ) { continue; } double pixelValue = weight * calculateKernelValue( distance, myBuffer, kernelShape, valueType ); // clearing anamolies along the axes if ( xp == 0 && yp == 0 ) { pixelValue /= 4; } else if ( xp == 0 || yp == 0 ) { pixelValue /= 2; } int pos[4]; pos[0] = ( myBuffer + xp ) * blockSize + ( myBuffer + yp ); pos[1] = ( myBuffer + xp ) * blockSize + ( myBuffer - yp ); pos[2] = ( myBuffer - xp ) * blockSize + ( myBuffer + yp ); pos[3] = ( myBuffer - xp ) * blockSize + ( myBuffer - yp ); for ( int p = 0; p < 4; p++ ) { if ( dataBuffer[ pos[p] ] == NO_DATA ) { dataBuffer[ pos[p] ] = 0; } dataBuffer[ pos[p] ] += pixelValue; } } } poBand->RasterIO( GF_Write, xPosition, yPosition, blockSize, blockSize, dataBuffer, blockSize, blockSize, GDT_Float32, 0, 0 ); CPLFree( dataBuffer ); } } // Finally close the dataset GDALClose(( GDALDatasetH ) heatmapDS ); // Open the file in QGIS window if requested if ( d.addToCanvas() ) { mQGisIface->addRasterLayer( d.outputFilename(), QFileInfo( d.outputFilename() ).baseName() ); } }
RgLineVectorLayerSettingsWidget::RgLineVectorLayerSettingsWidget( RgLineVectorLayerSettings *s, QWidget* parent ) : QWidget( parent ) { // create base widgets; QTabWidget *tab = new QTabWidget( this ); QVBoxLayout *v = new QVBoxLayout( this ); v->addWidget( tab ); // transportation layer QFrame *frame = new QFrame( this ); tab->addTab( frame, tr( "Transportation layer" ) ); v = new QVBoxLayout( frame ); QLabel *l = new QLabel( tr( "Layer" ), frame ); mcbLayers = new QComboBox( frame ); QHBoxLayout *h = new QHBoxLayout(); h->addWidget( l ); h->addWidget( mcbLayers ); v->addLayout( h ); h = new QHBoxLayout(); l = new QLabel( tr( "Direction field" ), frame ); mcbDirection = new QComboBox( frame ); h->addWidget( l ); h->addWidget( mcbDirection ); v->addLayout( h ); h = new QHBoxLayout(); h->addWidget( new QLabel( tr( "Value for forward direction" ), frame ) ); mleFirstPointToLastPointDirection = new QLineEdit( s->mFirstPointToLastPointDirectionVal, frame ); h->addWidget( mleFirstPointToLastPointDirection ); v->addLayout( h ); h = new QHBoxLayout(); h->addWidget( new QLabel( tr( "Value for reverse direction" ), frame ) ); mleLastPointToFirstPointDirection = new QLineEdit( s->mLastPointToFirstPointDirectionVal, frame ); h->addWidget( mleLastPointToFirstPointDirection ); v->addLayout( h ); h = new QHBoxLayout(); h->addWidget( new QLabel( tr( "Value two-way direction" ), frame ) ); mleBothDirection = new QLineEdit( s->mBothDirectionVal, frame ); h->addWidget( mleBothDirection ); v->addLayout( h ); h = new QHBoxLayout(); l = new QLabel( tr( "Speed field" ), frame ); mcbSpeed = new QComboBox( frame ); h->addWidget( l ); h->addWidget( mcbSpeed ); mcbUnitOfSpeed = new QComboBox( this ); h->addWidget( mcbUnitOfSpeed ); mcbUnitOfSpeed->insertItem( 0, tr( "km/h" ) ); mcbUnitOfSpeed->insertItem( 0, tr( "m/s" ) ); v->addLayout( h ); frame = new QFrame( tab ); tab->addTab( frame, tr( "Default settings" ) ); v = new QVBoxLayout( frame ); h = new QHBoxLayout(); l = new QLabel( tr( "Direction" ), frame ); mcbDirectionDefault = new QComboBox( frame ); mcbDirectionDefault->insertItem( 0, tr( "Two-way direction" ) ); mcbDirectionDefault->insertItem( 1, tr( "Forward direction" ) ); mcbDirectionDefault->insertItem( 2, tr( "Reverse direction" ) ); connect( mcbLayers, SIGNAL( currentIndexChanged( int ) ), this, SLOT( on_mcbLayers_selectItem() ) ); h->addWidget( l ); h->addWidget( mcbDirectionDefault ); v->addLayout( h ); h = new QHBoxLayout(); l = new QLabel( tr( "Cost" ), frame ); h->addWidget( l ); l = new QLabel( tr( "Line lengths" ), frame ); h->addWidget( l ); v->addLayout( h ); h = new QHBoxLayout(); l = new QLabel( tr( "Speed" ), frame ); msbSpeedDefault = new QSpinBox( frame ); msbSpeedDefault->setMinimum( 1 ); msbSpeedDefault->setMaximum( 10000000 ); h->addWidget( l ); h->addWidget( msbSpeedDefault ); v->addLayout( h ); // fill list of layers QMap<QString, QgsMapLayer*> mapLayers = QgsMapLayerRegistry::instance()->mapLayers(); QMap<QString, QgsMapLayer*>::iterator layer_it = mapLayers.begin(); for ( ; layer_it != mapLayers.end(); ++layer_it ) { QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer_it.value() ); if ( !vl ) continue; if ( vl->wkbType() == QGis::WKBLineString || vl->wkbType() == QGis::WKBMultiLineString ) mcbLayers->insertItem( 0, vl->name() ); } //sets current settings msbSpeedDefault->setValue( static_cast<int>( s->mDefaultSpeed ) ); int idx = mcbLayers->findText( s->mLayer ); if ( idx != -1 ) { mcbLayers->setCurrentIndex( idx ); } idx = mcbDirection->findText( s->mDirection ); if ( idx != -1 ) mcbDirection->setCurrentIndex( idx ); idx = mcbSpeed->findText( s->mSpeed ); if ( idx != -1 ) mcbSpeed->setCurrentIndex( idx ); switch ( s->mDefaultDirection ) { case RgLineVectorLayerSettings::Both: mcbDirectionDefault->setCurrentIndex( 0 ); break; case RgLineVectorLayerSettings::FirstPointToLastPoint: mcbDirectionDefault->setCurrentIndex( 1 ); break; case RgLineVectorLayerSettings::LastPointToFirstPoint: mcbDirectionDefault->setCurrentIndex( 2 ); break; } if ( s->mSpeedUnitName == "km/h" ) mcbUnitOfSpeed->setCurrentIndex( 1 ); else if ( s->mSpeedUnitName == "m/s" ) mcbUnitOfSpeed->setCurrentIndex( 0 ); } // RgLineVectorLayerSettingsWidget::RgLineVectorLayerSettingsWidget()