bool QgsMapToolIdentify::identifyRasterLayer( QgsRasterLayer *layer, int x, int y ) { bool res = true; if ( !layer ) return false; QgsRasterDataProvider *dprovider = layer->dataProvider(); if ( dprovider && ( dprovider->capabilities() & QgsRasterDataProvider::Identify ) == 0 ) return false; QMap< QString, QString > attributes, derivedAttributes; QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates( x, y ); idPoint = toLayerCoordinates( layer, idPoint ); QString type; if ( layer->providerType() == "wms" ) { type = tr( "WMS layer" ); //if WMS layer does not cover the view origin, //we need to map the view pixel coordinates //to WMS layer pixel coordinates QgsRectangle viewExtent = mCanvas->extent(); QgsRectangle layerExtent = layer->extent(); double mapUnitsPerPixel = mCanvas->mapUnitsPerPixel(); if ( mapUnitsPerPixel > 0 && viewExtent.intersects( layerExtent ) ) { double xMinView = viewExtent.xMinimum(); double yMaxView = viewExtent.yMaximum(); double xMinLayer = layerExtent.xMinimum(); double yMaxLayer = layerExtent.yMaximum(); idPoint.set( xMinView < xMinLayer ? floor( x - ( xMinLayer - xMinView ) / mapUnitsPerPixel ) : x, yMaxView > yMaxLayer ? floor( y - ( yMaxView - yMaxLayer ) / mapUnitsPerPixel ) : y ); attributes.insert( tr( "Feature info" ), layer->identifyAsHtml( idPoint ) ); } else { res = false; } } else { type = tr( "Raster" ); res = layer->extent().contains( idPoint ) && layer->identify( idPoint, attributes ); } if ( res ) { derivedAttributes.insert( tr( "(clicked coordinate)" ), idPoint.toString() ); results()->addFeature( layer, type, attributes, derivedAttributes ); } return res; }
QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTextFeatureSource* source, bool ownSource, const QgsFeatureRequest& request ) : QgsAbstractFeatureIteratorFromSource<QgsDelimitedTextFeatureSource>( source, ownSource, request ) , mTestGeometryExact( false ) { // Determine mode to use based on request... QgsDebugMsg( "Setting up QgsDelimitedTextIterator" ); // Does the layer have geometry - will revise later to determine if we actually need to // load it. bool hasGeometry = mSource->mGeomRep != QgsDelimitedTextProvider::GeomNone; // Does the layer have an explicit or implicit subset (implicit subset is if we have geometry which can // be invalid) mTestSubset = mSource->mSubsetExpression; mTestGeometry = false; mMode = FileScan; if ( request.filterType() == QgsFeatureRequest::FilterFid ) { QgsDebugMsg( "Configuring for returning single id" ); mFeatureIds.append( request.filterFid() ); mMode = FeatureIds; mTestSubset = false; } // If have geometry and testing geometry then evaluate options... // If we don't have geometry then all records pass geometry filter. // CC: 2013-05-09 // Not sure about intended relationship between filtering on geometry and // requesting no geometry? Have preserved current logic of ignoring spatial filter // if not requesting geometry. else if ( request.filterType() == QgsFeatureRequest::FilterRect && hasGeometry ) { QgsDebugMsg( "Configuring for rectangle select" ); mTestGeometry = true; // Exact intersection test only applies for WKT geometries mTestGeometryExact = mRequest.flags() & QgsFeatureRequest::ExactIntersect && mSource->mGeomRep == QgsDelimitedTextProvider::GeomAsWkt; QgsRectangle rect = request.filterRect(); // If request doesn't overlap extents, then nothing to return if ( ! rect.intersects( mSource->mExtent ) ) { QgsDebugMsg( "Rectangle outside layer extents - no features to return" ); mMode = FeatureIds; } // If the request extents include the entire layer, then revert to // a file scan else if ( rect.contains( mSource->mExtent ) ) { QgsDebugMsg( "Rectangle contains layer extents - bypass spatial filter" ); mTestGeometry = false; } // If we have a spatial index then use it. The spatial index already accounts // for the subset. Also means we don't have to test geometries unless doing exact // intersection else if ( mSource->mUseSpatialIndex ) { mFeatureIds = mSource->mSpatialIndex->intersects( rect ); // Sort for efficient sequential retrieval qSort( mFeatureIds.begin(), mFeatureIds.end() ); QgsDebugMsg( QString( "Layer has spatial index - selected %1 features from index" ).arg( mFeatureIds.size() ) ); mMode = FeatureIds; mTestSubset = false; mTestGeometry = mTestGeometryExact; } } // If we have a subset index then use it.. if ( mMode == FileScan && mSource->mUseSubsetIndex ) { QgsDebugMsg( QString( "Layer has subset index - use %1 items from subset index" ).arg( mSource->mSubsetIndex.size() ) ); mTestSubset = false; mMode = SubsetIndex; } // Otherwise just have to scan the file if ( mMode == FileScan ) { QgsDebugMsg( "File will be scanned for desired features" ); } // If the layer has geometry, do we really need to load it? // We need it if it is asked for explicitly in the request, // if we are testing geometry (ie spatial filter), or // if testing the subset expression. if ( hasGeometry && ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) || mTestGeometry || ( mTestSubset && mSource->mSubsetExpression->needsGeometry() ) ) ) { mLoadGeometry = true; } else { QgsDebugMsgLevel( "Feature geometries not required", 4 ); mLoadGeometry = false; } QgsDebugMsg( QString( "Iterator is scanning file: " ) + ( mMode == FileScan ? "Yes" : "No" ) ); QgsDebugMsg( QString( "Iterator is loading geometries: " ) + ( mLoadGeometry ? "Yes" : "No" ) ); QgsDebugMsg( QString( "Iterator is testing geometries: " ) + ( mTestGeometry ? "Yes" : "No" ) ); QgsDebugMsg( QString( "Iterator is testing subset: " ) + ( mTestSubset ? "Yes" : "No" ) ); rewind(); }
osg::Image* QgsOsgEarthTileSource::createImage( const TileKey& key, ProgressCallback* progress ) { QString kname = key.str().c_str(); kname.replace( '/', '_' ); Q_UNUSED( progress ); //Get the extents of the tile int tileSize = getPixelsPerTile(); if ( tileSize <= 0 ) { QgsDebugMsg( "Tile size too small." ); return ImageUtils::createEmptyImage(); } QgsRectangle viewExtent = mQGisIface->mapCanvas()->fullExtent(); if ( mCoordTransform ) { QgsDebugMsg( QString( "vext0:%1" ).arg( viewExtent.toString( 5 ) ) ); viewExtent = mCoordTransform->transformBoundingBox( viewExtent ); } QgsDebugMsg( QString( "vext1:%1" ).arg( viewExtent.toString( 5 ) ) ); double xmin, ymin, xmax, ymax; key.getExtent().getBounds( xmin, ymin, xmax, ymax ); QgsRectangle tileExtent( xmin, ymin, xmax, ymax ); QgsDebugMsg( QString( "text0:%1" ).arg( tileExtent.toString( 5 ) ) ); if ( !viewExtent.intersects( tileExtent ) ) { QgsDebugMsg( QString( "earth tile key:%1 ext:%2: NO INTERSECT" ).arg( kname ).arg( tileExtent.toString( 5 ) ) ); return ImageUtils::createEmptyImage(); } #ifdef USE_RENDERER QImage *qImage = createQImage( tileSize, tileSize ); if ( !qImage ) { QgsDebugMsg( QString( "earth tile key:%1 ext:%2: EMPTY IMAGE" ).arg( kname ).arg( tileExtent.toString( 5 ) ) ); return ImageUtils::createEmptyImage(); } mMapRenderer->setLayerSet( mQGisIface->mapCanvas()->mapRenderer()->layerSet() ); mMapRenderer->setOutputSize( QSize( tileSize, tileSize ), qImage->logicalDpiX() ); mMapRenderer->setExtent( tileExtent ); QPainter thePainter( qImage ); mMapRenderer->render( &thePainter ); #else mMapSettings.setLayers( mQGisIface->mapCanvas()->mapSettings().layers() ); mMapSettings.setOutputSize( QSize( tileSize, tileSize ) ); mMapSettings.setOutputDpi( QgsApplication::desktop()->logicalDpiX() ); mMapSettings.setExtent( tileExtent ); mMapSettings.setBackgroundColor( QColor( 0, 0, 0, 0 ) ); QgsMapRendererSequentialJob job( mMapSettings ); job.start(); job.waitForFinished(); QImage *qImage = new QImage( job.renderedImage() ); if ( !qImage ) { QgsDebugMsg( QString( "earth tile key:%1 ext:%2: EMPTY IMAGE" ).arg( kname ).arg( tileExtent.toString( 5 ) ) ); return ImageUtils::createEmptyImage(); } Q_ASSERT( qImage->logicalDpiX() == QgsApplication::desktop()->logicalDpiX() ); Q_ASSERT( qImage->format() == QImage::Format_ARGB32_Premultiplied ); #endif QgsDebugMsg( QString( "earth tile key:%1 ext:%2" ).arg( kname ).arg( tileExtent.toString( 5 ) ) ); #if 0 qImage->save( QString( "/tmp/tile-%1.png" ).arg( kname ) ); #endif osg::ref_ptr<osg::Image> image = new osg::Image; //The pixel format is always RGBA to support transparency image->setImage( tileSize, tileSize, 1, 4, // width, height, depth, pixelFormat? GL_BGRA, GL_UNSIGNED_BYTE, //Why not GL_RGBA - Qt bug? qImage->bits(), osg::Image::NO_DELETE, 1 ); image->flipVertical(); //Create a transparent image if we don't have an image if ( !image.valid() ) { QgsDebugMsg( "image is invalid" ); return ImageUtils::createEmptyImage(); } QgsDebugMsg( "returning image" ); return image.release(); }
void QgsMapToolMoveFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e ) { QgsVectorLayer *vlayer = currentVectorLayer(); if ( !vlayer || !vlayer->isEditable() ) { delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); cadDockWidget()->clear(); notifyNotEditableLayer(); return; } if ( !mRubberBand ) { //find first geometry under mouse cursor and store iterator to it QgsPointXY layerCoords = toLayerCoordinates( vlayer, e->mapPoint() ); double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() ); QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius, layerCoords.x() + searchRadius, layerCoords.y() + searchRadius ); if ( vlayer->selectedFeatureCount() == 0 ) { QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ).setNoAttributes() ); //find the closest feature QgsGeometry pointGeometry = QgsGeometry::fromPointXY( layerCoords ); if ( pointGeometry.isNull() ) { cadDockWidget()->clear(); return; } double minDistance = std::numeric_limits<double>::max(); QgsFeature cf; QgsFeature f; while ( fit.nextFeature( f ) ) { if ( f.hasGeometry() ) { double currentDistance = pointGeometry.distance( f.geometry() ); if ( currentDistance < minDistance ) { minDistance = currentDistance; cf = f; } } } if ( minDistance == std::numeric_limits<double>::max() ) { cadDockWidget()->clear(); return; } mMovedFeatures.clear(); mMovedFeatures << cf.id(); //todo: take the closest feature, not the first one... mRubberBand = createRubberBand( vlayer->geometryType() ); mRubberBand->setToGeometry( cf.geometry(), vlayer ); } else { mMovedFeatures = vlayer->selectedFeatureIds(); mRubberBand = createRubberBand( vlayer->geometryType() ); QgsFeature feat; QgsFeatureIterator it = vlayer->getSelectedFeatures( QgsFeatureRequest().setNoAttributes() ); bool allFeaturesInView = true; QgsRectangle viewRect = mCanvas->mapSettings().mapToLayerCoordinates( vlayer, mCanvas->extent() ); while ( it.nextFeature( feat ) ) { mRubberBand->addGeometry( feat.geometry(), vlayer ); if ( allFeaturesInView && !viewRect.intersects( feat.geometry().boundingBox() ) ) allFeaturesInView = false; } if ( !allFeaturesInView ) { // for extra safety to make sure we are not modifying geometries by accident int res = QMessageBox::warning( mCanvas, tr( "Move features" ), tr( "Some of the selected features are outside of the current map view. Would you still like to continue?" ), QMessageBox::Yes | QMessageBox::No ); if ( res != QMessageBox::Yes ) { mMovedFeatures.clear(); delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); return; } } } mStartPointMapCoords = e->mapPoint(); mRubberBand->show(); } else { // copy and move mode if ( e->button() != Qt::LeftButton ) { cadDockWidget()->clear(); delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); return; } QgsPointXY startPointLayerCoords = toLayerCoordinates( ( QgsMapLayer * )vlayer, mStartPointMapCoords ); QgsPointXY stopPointLayerCoords = toLayerCoordinates( ( QgsMapLayer * )vlayer, e->mapPoint() ); double dx = stopPointLayerCoords.x() - startPointLayerCoords.x(); double dy = stopPointLayerCoords.y() - startPointLayerCoords.y(); vlayer->beginEditCommand( mMode == Move ? tr( "Feature moved" ) : tr( "Feature copied and moved" ) ); switch ( mMode ) { case Move: Q_FOREACH ( QgsFeatureId id, mMovedFeatures ) { vlayer->translateFeature( id, dx, dy ); } delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); cadDockWidget()->clear(); break; case CopyMove: QgsFeatureRequest request; request.setFilterFids( mMovedFeatures ); QString *errorMsg = new QString(); if ( !QgisApp::instance()->vectorLayerTools()->copyMoveFeatures( vlayer, request, dx, dy, errorMsg ) ) { emit messageEmitted( *errorMsg, Qgis::Critical ); delete mRubberBand; mRubberBand = nullptr; mSnapIndicator->setMatch( QgsPointLocator::Match() ); } break; } vlayer->endEditCommand(); vlayer->triggerRepaint(); }