void QgsPointSample::addSamplePoints( QgsFeature& inputFeature, QgsVectorFileWriter& writer, int nPoints, double minDistance ) { if ( !inputFeature.constGeometry() ) return; const QgsGeometry* geom = inputFeature.constGeometry(); QgsRectangle geomRect = geom->boundingBox(); if ( geomRect.isEmpty() ) { return; } QgsSpatialIndex sIndex; //to check minimum distance QMap< QgsFeatureId, QgsPoint > pointMapForFeature; int nIterations = 0; int maxIterations = nPoints * 200; int points = 0; double randX = 0; double randY = 0; while ( nIterations < maxIterations && points < nPoints ) { randX = (( double )mt_rand() / MD_RAND_MAX ) * geomRect.width() + geomRect.xMinimum(); randY = (( double )mt_rand() / MD_RAND_MAX ) * geomRect.height() + geomRect.yMinimum(); QgsPoint randPoint( randX, randY ); QgsGeometry* ptGeom = QgsGeometry::fromPoint( randPoint ); if ( ptGeom->within( geom ) && checkMinDistance( randPoint, sIndex, minDistance, pointMapForFeature ) ) { //add feature to writer QgsFeature f( mNCreatedPoints ); f.setAttribute( "id", mNCreatedPoints + 1 ); f.setAttribute( "station_id", points + 1 ); f.setAttribute( "stratum_id", inputFeature.id() ); f.setGeometry( ptGeom ); writer.addFeature( f ); sIndex.insertFeature( f ); pointMapForFeature.insert( mNCreatedPoints, randPoint ); ++points; ++mNCreatedPoints; } else { delete ptGeom; } ++nIterations; } }
void QgsRasterInterface::initStatistics( QgsRasterBandStats &statistics, int bandNo, int stats, const QgsRectangle &boundingBox, int sampleSize ) { QgsDebugMsgLevel( QString( "theBandNo = %1 sampleSize = %2" ).arg( bandNo ).arg( sampleSize ), 4 ); statistics.bandNumber = bandNo; statistics.statsGathered = stats; QgsRectangle finalExtent; if ( boundingBox.isEmpty() ) { finalExtent = extent(); } else { finalExtent = extent().intersect( boundingBox ); } statistics.extent = finalExtent; if ( sampleSize > 0 ) { // Calc resolution from theSampleSize double xRes, yRes; xRes = yRes = std::sqrt( ( finalExtent.width() * finalExtent.height() ) / sampleSize ); // But limit by physical resolution if ( capabilities() & Size ) { double srcXRes = extent().width() / xSize(); double srcYRes = extent().height() / ySize(); if ( xRes < srcXRes ) xRes = srcXRes; if ( yRes < srcYRes ) yRes = srcYRes; } QgsDebugMsgLevel( QString( "xRes = %1 yRes = %2" ).arg( xRes ).arg( yRes ), 4 ); statistics.width = static_cast <int>( finalExtent.width() / xRes ); statistics.height = static_cast <int>( finalExtent.height() / yRes ); } else { if ( capabilities() & Size ) { statistics.width = xSize(); statistics.height = ySize(); } else { statistics.width = 1000; statistics.height = 1000; } } QgsDebugMsgLevel( QString( "theStatistics.width = %1 statistics.height = %2" ).arg( statistics.width ).arg( statistics.height ), 4 ); }
void QgsRasterInterface::initStatistics( QgsRasterBandStats &theStatistics, int theBandNo, int theStats, const QgsRectangle & theExtent, int theSampleSize ) { QgsDebugMsg( QString( "theBandNo = %1 theSampleSize = %2" ).arg( theBandNo ).arg( theSampleSize ) ); theStatistics.bandNumber = theBandNo; theStatistics.statsGathered = theStats; QgsRectangle myExtent; if ( theExtent.isEmpty() ) { myExtent = extent(); } else { myExtent = extent().intersect( &theExtent ); } theStatistics.extent = myExtent; if ( theSampleSize > 0 ) { // Calc resolution from theSampleSize double xRes, yRes; xRes = yRes = sqrt(( myExtent.width() * myExtent.height() ) / theSampleSize ); // But limit by physical resolution if ( capabilities() & Size ) { double srcXRes = extent().width() / xSize(); double srcYRes = extent().height() / ySize(); if ( xRes < srcXRes ) xRes = srcXRes; if ( yRes < srcYRes ) yRes = srcYRes; } QgsDebugMsg( QString( "xRes = %1 yRes = %2" ).arg( xRes ).arg( yRes ) ); theStatistics.width = static_cast <int>( myExtent.width() / xRes ); theStatistics.height = static_cast <int>( myExtent.height() / yRes ); } else { if ( capabilities() & Size ) { theStatistics.width = xSize(); theStatistics.height = ySize(); } else { theStatistics.width = 1000; theStatistics.height = 1000; } } QgsDebugMsg( QString( "theStatistics.width = %1 theStatistics.height = %2" ).arg( theStatistics.width ).arg( theStatistics.height ) ); }
void QgsComposerLegend::doUpdateFilterByMap() { if ( mComposerMap ) mLegendModel->setLayerStyleOverrides( mComposerMap->layerStyleOverrides() ); else mLegendModel->setLayerStyleOverrides( QMap<QString, QString>() ); bool filterByExpression = QgsLayerTreeUtils::hasLegendFilterExpression( *( mCustomLayerTree ? mCustomLayerTree.get() : mComposition->project()->layerTreeRoot() ) ); if ( mComposerMap && ( mLegendFilterByMap || filterByExpression || mInAtlas ) ) { int dpi = mComposition->printResolution(); QgsRectangle requestRectangle; mComposerMap->requestedExtent( requestRectangle ); QSizeF size( requestRectangle.width(), requestRectangle.height() ); size *= mComposerMap->mapUnitsToMM() * dpi / 25.4; QgsMapSettings ms = mComposerMap->mapSettings( requestRectangle, size, dpi ); QgsGeometry filterPolygon; if ( mInAtlas ) { filterPolygon = composition()->atlasComposition().currentGeometry( mComposerMap->crs() ); } mLegendModel->setLegendFilter( &ms, /* useExtent */ mInAtlas || mLegendFilterByMap, filterPolygon, /* useExpressions */ true ); } else mLegendModel->setLegendFilterByMap( nullptr ); mForceResize = true; }
void QgsLayoutItemLegend::doUpdateFilterByMap() { if ( mMap ) mLegendModel->setLayerStyleOverrides( mMap->layerStyleOverrides() ); else mLegendModel->setLayerStyleOverrides( QMap<QString, QString>() ); bool filterByExpression = QgsLayerTreeUtils::hasLegendFilterExpression( *( mCustomLayerTree ? mCustomLayerTree.get() : mLayout->project()->layerTreeRoot() ) ); if ( mMap && ( mLegendFilterByMap || filterByExpression || mInAtlas ) ) { int dpi = mLayout->renderContext().dpi(); QgsRectangle requestRectangle = mMap->requestedExtent(); QSizeF size( requestRectangle.width(), requestRectangle.height() ); size *= mLayout->convertFromLayoutUnits( mMap->mapUnitsToLayoutUnits(), QgsUnitTypes::LayoutMillimeters ).length() * dpi / 25.4; QgsMapSettings ms = mMap->mapSettings( requestRectangle, size, dpi, true ); QgsGeometry filterPolygon; if ( mInAtlas ) { filterPolygon = mLayout->reportContext().currentGeometry( mMap->crs() ); } mLegendModel->setLegendFilter( &ms, /* useExtent */ mInAtlas || mLegendFilterByMap, filterPolygon, /* useExpressions */ true ); } else mLegendModel->setLegendFilterByMap( nullptr ); mForceResize = true; }
/* * Estimate a good default radius for the heatmap, based on the * bounding box size of the layer */ double HeatmapGui::estimateRadius() { QgsVectorLayer *inputLayer = inputVectorLayer(); // No input layer? Default to radius of 100 if ( !inputLayer ) return 100; // Find max dimension of layer bounding box QgsRectangle mExtent = inputLayer->extent(); double maxExtent = max( mExtent.width(), mExtent.height() ); // Return max dimension divided by 30. This is fairly arbitrary // but approximately corresponds to the default value chosen by ArcMap // TODO - a better solution is to let the data define the radius // choice by setting the radius equal to the average Nearest // Neighbour Index for the closest n points double estimate = maxExtent / 30; if ( mBufferUnitCombo->currentIndex() == HeatmapGui::LayerUnits ) { // layer units selected, so convert estimate from map units QgsCoordinateReferenceSystem layerCrs = inputLayer->crs(); estimate /= mapUnitsOf( 1, layerCrs ); } // Make estimate pretty by rounding off to first digit only (eg 356->300, 0.567->0.5) double tens = pow( 10, floor( log10( estimate ) ) ); return floor( estimate / tens + 0.5 ) * tens; }
void QgsMapOverviewCanvas::mouseReleaseEvent( QMouseEvent * e ) { // if (mPanningWidget->isHidden()) // return; if ( e->button() == Qt::LeftButton ) { // set new extent const QgsMapToPixel& cXf = mSettings.mapToPixel(); QRect rect = mPanningWidget->geometry(); QgsPoint center = cXf.toMapCoordinates( rect.center() ); QgsRectangle oldExtent = mMapCanvas->extent(); QgsRectangle ext; ext.setXMinimum( center.x() - oldExtent.width() / 2 ); ext.setXMaximum( center.x() + oldExtent.width() / 2 ); ext.setYMinimum( center.y() - oldExtent.height() / 2 ); ext.setYMaximum( center.y() + oldExtent.height() / 2 ); QgsDebugMsg( QString( "panning: new position: [%1,%2] [%3x%4]" ).arg( rect.left() ).arg( rect.top() ).arg( rect.width() ).arg( rect.height() ) ); mMapCanvas->setExtent( ext ); mMapCanvas->refresh(); } }
QgsDxfPalLabeling::QgsDxfPalLabeling( QgsDxfExport* dxf, const QgsRectangle& bbox, double scale, QGis::UnitType mapUnits ) : QgsPalLabeling() , mDxfExport( dxf ) , mImage( 0 ) , mPainter( 0 ) { mSettings = new QgsMapSettings; mSettings->setMapUnits( mapUnits ); mSettings->setExtent( bbox ); int dpi = 96; double factor = 1000 * dpi / scale / 25.4 * QGis::fromUnitToUnitFactor( mapUnits, QGis::Meters ); mSettings->setOutputSize( QSize( bbox.width() * factor, bbox.height() * factor ) ); mSettings->setOutputDpi( dpi ); mSettings->setCrsTransformEnabled( false ); init( *mSettings ); mImage = new QImage( 10, 10, QImage::Format_ARGB32_Premultiplied ); mImage->setDotsPerMeterX( 96 / 25.4 * 1000 ); mImage->setDotsPerMeterY( 96 / 25.4 * 1000 ); mPainter = new QPainter( mImage ); mRenderContext.setPainter( mPainter ); mRenderContext.setRendererScale( scale ); mRenderContext.setExtent( bbox ); mRenderContext.setScaleFactor( 96.0 / 25.4 ); mRenderContext.setMapToPixel( QgsMapToPixel( 1.0 / factor, bbox.xMinimum(), bbox.yMinimum(), bbox.height() * factor ) ); }
double QgsComposerScaleBar::mapDiagonal() const { if ( !mComposerMap ) { return 0.0; } QgsRectangle composerMapRect = mComposerMap->extent(); if ( mUnits == MapUnits ) { return sqrt( composerMapRect.width() * composerMapRect.width() + composerMapRect.height() * composerMapRect.height() ); } else { QgsDistanceArea da; da.setProjectionsEnabled( true ); da.setSourceCrs( mComposerMap->mapRenderer()->destinationCrs().srsid() ); QSettings s; da.setEllipsoid( s.value( "/qgis/measure/ellipsoid", "WGS84" ).toString() ); double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMaximum() ), QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) ); if ( mUnits == Feet ) { measure /= 0.3048; } return measure; } }
void QgsComposerLegend::updateFilterByMap() { if ( isRemoved() ) return; if ( mComposerMap ) mLegendModel2->setLayerStyleOverrides( mComposerMap->layerStyleOverrides() ); else mLegendModel2->setLayerStyleOverrides( QMap<QString, QString>() ); if ( mComposerMap && mLegendFilterByMap ) { int dpi = mComposition->printResolution(); QgsRectangle requestRectangle; mComposerMap->requestedExtent( requestRectangle ); QSizeF theSize( requestRectangle.width(), requestRectangle.height() ); theSize *= mComposerMap->mapUnitsToMM() * dpi / 25.4; QgsMapSettings ms = mComposerMap->mapSettings( requestRectangle, theSize, dpi ); mLegendModel2->setLegendFilterByMap( &ms ); } else mLegendModel2->setLegendFilterByMap( 0 ); adjustBoxSize(); update(); }
void QgsRasterFileWriter::globalOutputParameters( const QgsRectangle& extent, int nCols, int& nRows, double* geoTransform, double& pixelSize ) { pixelSize = extent.width() / nCols; //calculate nRows automatically for providers without exact resolution if ( nRows < 0 ) { nRows = ( double )nCols / extent.width() * extent.height() + 0.5; } geoTransform[0] = extent.xMinimum(); geoTransform[1] = pixelSize; geoTransform[2] = 0.0; geoTransform[3] = extent.yMaximum(); geoTransform[4] = 0.0; geoTransform[5] = -( extent.height() / nRows ); }
// Default implementation for values QMap<int, QVariant> QgsRasterDataProvider::identify( const QgsPoint & thePoint, IdentifyFormat theFormat, const QgsRectangle &theExtent, int theWidth, int theHeight ) { QgsDebugMsg( "Entered" ); QMap<int, QVariant> results; if ( theFormat != IdentifyFormatValue || !( capabilities() & IdentifyValue ) ) { QgsDebugMsg( "Format not supported" ); return results; } if ( !extent().contains( thePoint ) ) { // Outside the raster for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ ) { results.insert( bandNo, noDataValue( bandNo ) ); } return results; } QgsRectangle myExtent = theExtent; if ( myExtent.isEmpty() ) myExtent = extent(); if ( theWidth == 0 ) { theWidth = capabilities() & Size ? xSize() : 1000; } if ( theHeight == 0 ) { theHeight = capabilities() & Size ? ySize() : 1000; } // Calculate the row / column where the point falls double xres = ( myExtent.width() ) / theWidth; double yres = ( myExtent.height() ) / theHeight; int col = ( int ) floor(( thePoint.x() - myExtent.xMinimum() ) / xres ); int row = ( int ) floor(( myExtent.yMaximum() - thePoint.y() ) / yres ); double xMin = myExtent.xMinimum() + col * xres; double xMax = xMin + xres; double yMax = myExtent.yMaximum() - row * yres; double yMin = yMax - yres; QgsRectangle pixelExtent( xMin, yMin, xMax, yMax ); for ( int i = 1; i <= bandCount(); i++ ) { QgsRasterBlock * myBlock = block( i, pixelExtent, 1, 1 ); double value = noDataValue( i ); if ( myBlock ) value = myBlock->value( 0 ); results.insert( i, value ); } return results; }
QgsRectangle QgsMapSettings::fullExtent() const { // reset the map canvas extent since the extent may now be smaller // We can't use a constructor since QgsRectangle normalizes the rectangle upon construction QgsRectangle fullExtent; fullExtent.setMinimal(); // iterate through the map layers and test each layers extent // against the current min and max values QgsDebugMsgLevel( QStringLiteral( "Layer count: %1" ).arg( mLayers.count() ), 5 ); const auto constMLayers = mLayers; for ( const QgsWeakMapLayerPointer &layerPtr : constMLayers ) { if ( QgsMapLayer *lyr = layerPtr.data() ) { QgsDebugMsgLevel( "Updating extent using " + lyr->name(), 5 ); QgsDebugMsgLevel( "Input extent: " + lyr->extent().toString(), 5 ); if ( lyr->extent().isNull() ) continue; // Layer extents are stored in the coordinate system (CS) of the // layer. The extent must be projected to the canvas CS QgsRectangle extent = layerExtentToOutputExtent( lyr, lyr->extent() ); QgsDebugMsgLevel( "Output extent: " + extent.toString(), 5 ); fullExtent.combineExtentWith( extent ); } } if ( fullExtent.width() == 0.0 || fullExtent.height() == 0.0 ) { // If all of the features are at the one point, buffer the // rectangle a bit. If they are all at zero, do something a bit // more crude. if ( fullExtent.xMinimum() == 0.0 && fullExtent.xMaximum() == 0.0 && fullExtent.yMinimum() == 0.0 && fullExtent.yMaximum() == 0.0 ) { fullExtent.set( -1.0, -1.0, 1.0, 1.0 ); } else { const double padFactor = 1e-8; double widthPad = fullExtent.xMinimum() * padFactor; double heightPad = fullExtent.yMinimum() * padFactor; double xmin = fullExtent.xMinimum() - widthPad; double xmax = fullExtent.xMaximum() + widthPad; double ymin = fullExtent.yMinimum() - heightPad; double ymax = fullExtent.yMaximum() + heightPad; fullExtent.set( xmin, ymin, xmax, ymax ); } } QgsDebugMsgLevel( "Full extent: " + fullExtent.toString(), 5 ); return fullExtent; }
void QgsComposerMapWidget::on_mSetToMapCanvasExtentButton_clicked() { if ( mComposerMap ) { const QgsMapRenderer* renderer = mComposerMap->mapRenderer(); if ( renderer ) { QgsRectangle newExtent = renderer->extent(); //Make sure the width/height ratio is the same as in current composer map extent. //This is to keep the map item frame and the page layout fixed QgsRectangle currentMapExtent = *( mComposerMap->currentMapExtent() ); double currentWidthHeightRatio = currentMapExtent.width() / currentMapExtent.height(); double newWidthHeightRatio = newExtent.width() / newExtent.height(); if ( currentWidthHeightRatio < newWidthHeightRatio ) { //enlarge height of new extent, ensuring the map center stays the same double newHeight = newExtent.width() / currentWidthHeightRatio; double deltaHeight = newHeight - newExtent.height(); newExtent.setYMinimum( newExtent.yMinimum() - deltaHeight / 2 ); newExtent.setYMaximum( newExtent.yMaximum() + deltaHeight / 2 ); } else { //enlarge width of new extent, ensuring the map center stays the same double newWidth = currentWidthHeightRatio * newExtent.height(); double deltaWidth = newWidth - newExtent.width(); newExtent.setXMinimum( newExtent.xMinimum() - deltaWidth / 2 ); newExtent.setXMaximum( newExtent.xMaximum() + deltaWidth / 2 ); } //fill text into line edits mXMinLineEdit->setText( QString::number( newExtent.xMinimum() ) ); mXMaxLineEdit->setText( QString::number( newExtent.xMaximum() ) ); mYMinLineEdit->setText( QString::number( newExtent.yMinimum() ) ); mYMaxLineEdit->setText( QString::number( newExtent.yMaximum() ) ); mComposerMap->beginCommand( tr( "Map extent changed" ) ); mComposerMap->setNewExtent( newExtent ); mComposerMap->endCommand(); } } }
void QgsGrassRasterProvider::readBlock( int bandNo, int xBlock, int yBlock, void *block ) { Q_UNUSED( xBlock ); QgsDebugMsg( "Entered" ); clearLastError(); // TODO: optimize, see extent() QgsDebugMsg( "yBlock = " + QString::number( yBlock ) ); QStringList arguments; arguments.append( "map=" + mMapName + "@" + mMapset ); QgsRectangle ext = extent(); // TODO: cut the last block double cellHeight = ext.height() / mRows; double yMaximum = ext.yMaximum() - cellHeight * yBlock * mYBlockSize; double yMinimum = yMaximum - cellHeight * mYBlockSize; QgsDebugMsg( "mYBlockSize = " + QString::number( mYBlockSize ) ); arguments.append(( QString( "window=%1,%2,%3,%4,%5,%6" ) .arg( QgsRasterBlock::printValue( ext.xMinimum() ), QgsRasterBlock::printValue( yMinimum ), QgsRasterBlock::printValue( ext.xMaximum() ), QgsRasterBlock::printValue( yMaximum ) ) .arg( mCols ).arg( mYBlockSize ) ) ); arguments.append( "format=value" ); QString cmd = QgsApplication::libexecPath() + "grass/modules/qgis.d.rast"; QByteArray data; try { data = QgsGrass::runModule( mGisdbase, mLocation, mMapset, cmd, arguments ); } catch ( QgsGrass::Exception &e ) { QString error = tr( "Cannot read raster" ) + " : " + e.what(); QgsDebugMsg( error ); appendError( error ); // We don't set mValid to false, because the raster can be recreated and work next time } QgsDebugMsg( QString( "%1 bytes read from modules stdout" ).arg( data.size() ) ); // byteCount() in Qt >= 4.6 //int size = image->byteCount() < data.size() ? image->byteCount() : data.size(); int size = mCols * mYBlockSize * dataTypeSize( bandNo ); QgsDebugMsg( QString( "mCols = %1 mYBlockSize = %2 dataTypeSize = %3" ).arg( mCols ).arg( mYBlockSize ).arg( dataTypeSize( bandNo ) ) ); if ( size != data.size() ) { QString error = tr( "%1 bytes expected but %2 byte were read from qgis.d.rast" ).arg( size ).arg( data.size() ); QgsDebugMsg( error ); appendError( error ); size = size < data.size() ? size : data.size(); } memcpy( block, data.data(), size ); }
void QgsInterpolationDialog::setNewCellsizeYOnNRowschange() { QgsRectangle currentBBox = currentBoundingBox(); if ( !currentBBox.isEmpty() && mNumberOfRowsSpinBox->value() > 0 ) { mCellSizeYSpinBox->blockSignals( true ); mCellSizeYSpinBox->setValue( currentBBox.height() / mNumberOfRowsSpinBox->value() ); mCellSizeYSpinBox->blockSignals( false ); } }
bool QgsRasterProjector::extentSize( const QgsCoordinateTransform &ct, const QgsRectangle &srcExtent, int srcXSize, int srcYSize, QgsRectangle &destExtent, int &destXSize, int &destYSize ) { if ( srcExtent.isEmpty() || srcXSize <= 0 || srcYSize <= 0 ) { return false; } destExtent = ct.transformBoundingBox( srcExtent ); // We reproject pixel rectangle from 9 points matrix of source extent, of course, it gives // bigger xRes,yRes than reprojected edges (envelope) double srcXStep = srcExtent.width() / 3; double srcYStep = srcExtent.height() / 3; double srcXRes = srcExtent.width() / srcXSize; double srcYRes = srcExtent.height() / srcYSize; double destXRes = std::numeric_limits<double>::max(); double destYRes = std::numeric_limits<double>::max(); for ( int i = 0; i < 3; i++ ) { double x = srcExtent.xMinimum() + i * srcXStep; for ( int j = 0; j < 3; j++ ) { double y = srcExtent.yMinimum() + j * srcYStep; QgsRectangle srcRectangle( x - srcXRes / 2, y - srcYRes / 2, x + srcXRes / 2, y + srcYRes / 2 ); QgsRectangle destRectangle = ct.transformBoundingBox( srcRectangle ); if ( destRectangle.width() > 0 ) { destXRes = std::min( destXRes, destRectangle.width() ); } if ( destRectangle.height() > 0 ) { destYRes = std::min( destYRes, destRectangle.height() ); } } } destXSize = std::max( 1, static_cast< int >( destExtent.width() / destYRes ) ); destYSize = std::max( 1, static_cast< int >( destExtent.height() / destYRes ) ); return true; }
bool QgsMapRenderer::setExtent( const QgsRectangle& extent ) { //remember the previous extent mLastExtent = mExtent; // Don't allow zooms where the current extent is so small that it // can't be accurately represented using a double (which is what // currentExtent uses). Excluding 0 avoids a divide by zero and an // infinite loop when rendering to a new canvas. Excluding extents // greater than 1 avoids doing unnecessary calculations. // The scheme is to compare the width against the mean x coordinate // (and height against mean y coordinate) and only allow zooms where // the ratio indicates that there is more than about 12 significant // figures (there are about 16 significant figures in a double). if ( extent.width() > 0 && extent.height() > 0 && extent.width() < 1 && extent.height() < 1 ) { // Use abs() on the extent to avoid the case where the extent is // symmetrical about 0. double xMean = ( qAbs( extent.xMinimum() ) + qAbs( extent.xMaximum() ) ) * 0.5; double yMean = ( qAbs( extent.yMinimum() ) + qAbs( extent.yMaximum() ) ) * 0.5; double xRange = extent.width() / xMean; double yRange = extent.height() / yMean; static const double minProportion = 1e-12; if ( xRange < minProportion || yRange < minProportion ) return false; } mExtent = extent; if ( !extent.isEmpty() ) adjustExtentToSize(); emit extentsChanged(); return true; }
void QgsMapCanvas::setCenter( const QgsPoint& center ) { QgsRectangle r = mapSettings().extent(); double x = center.x(); double y = center.y(); setExtent( QgsRectangle( x - r.width() / 2.0, y - r.height() / 2.0, x + r.width() / 2.0, y + r.height() / 2.0 ) ); } // setCenter
void QgsInterpolationDialog::setNewCellsizeOnBoundingBoxChange() { QgsRectangle currentBbox = currentBoundingBox(); if ( currentBbox.isEmpty() ) { return; } if ( currentBbox.width() > 0 && mNumberOfColumnsSpinBox->value() > 0 ) { mCellsizeXSpinBox->blockSignals( true ); mCellsizeXSpinBox->setValue( currentBbox.width() / mNumberOfColumnsSpinBox->value() ); mCellsizeXSpinBox->blockSignals( false ); } if ( currentBbox.height() > 0 && mNumberOfRowsSpinBox->value() > 0 ) { mCellSizeYSpinBox->blockSignals( true ); mCellSizeYSpinBox->setValue( currentBbox.height() / mNumberOfRowsSpinBox->value() ); mCellSizeYSpinBox->blockSignals( false ); } }
bool QgsGeometrySliverPolygonCheck::checkThreshold( double layerToMapUnits, const QgsAbstractGeometry *geom, double &value ) const { double maxArea = mMaxAreaMapUnits / ( layerToMapUnits * layerToMapUnits ); QgsRectangle bb = geom->boundingBox(); double maxDim = std::max( bb.width(), bb.height() ); double area = geom->area(); value = ( maxDim * maxDim ) / area; if ( maxArea > 0. && area > maxArea ) { return false; } return value > mThresholdMapUnits; // the sliver threshold is actually a map unit independent number, just abusing QgsGeometryAreaCheck::mThresholdMapUnits to store it }
void QgsComposerMapOverview::overviewExtentChanged() { if ( !mComposerMap ) { return; } //if using overview centering, update the map's extent if ( mComposerMap->composition() && mCentered && mFrameMapId != -1 ) { QgsRectangle extent = *mComposerMap->currentMapExtent(); const QgsComposerMap* overviewFrameMap = mComposerMap->composition()->getComposerMapById( mFrameMapId ); if ( !overviewFrameMap ) { //redraw map so that overview gets updated mComposerMap->update(); return; } QgsRectangle otherExtent = *overviewFrameMap->currentMapExtent(); QgsPoint center = otherExtent.center(); QgsRectangle movedExtent( center.x() - extent.width() / 2, center.y() - extent.height() / 2, center.x() - extent.width() / 2 + extent.width(), center.y() - extent.height() / 2 + extent.height() ); *mComposerMap->currentMapExtent() = movedExtent; //trigger a recalculation of data defined extents, scale and rotation, since that //may override the map centering mComposerMap->refreshDataDefinedProperty( QgsComposerObject::MapScale ); //must invalidate cache so that map gets redrawn mComposerMap->cache(); } //repaint map so that overview gets updated mComposerMap->update(); }
void QgsInterpolationDialog::setNRowsOnCellsizeYChange() { QgsRectangle currentBBox = currentBoundingBox(); int newSize; if ( mCellSizeYSpinBox->value() <= 0 ) { return; } if ( currentBBox.height() <= 0 ) { newSize = 0; } else { newSize = ( int )( currentBBox.height() / mCellSizeYSpinBox->value() ); } mNumberOfRowsSpinBox->blockSignals( true ); mNumberOfRowsSpinBox->setValue( newSize ); mNumberOfRowsSpinBox->blockSignals( false ); }
void QgsMapToolPan::canvasReleaseEvent( QMouseEvent * e ) { if ( e->button() == Qt::LeftButton ) { if ( mExtentRubberBand ) { if ( e->modifiers() == Qt::ShiftModifier ) { // set center and zoom QSize zoomRectSize = mExtentRect.normalized().size(); QSize canvasSize = mCanvas->mapSettings().outputSize(); double sfx = ( double )zoomRectSize.width() / canvasSize.width(); double sfy = ( double )zoomRectSize.height() / canvasSize.height(); double scaleFactor = qMax( sfx, sfy ); QgsPoint c = mCanvas->getCoordinateTransform()->toMapCoordinates( mExtentRect.center() ); QgsRectangle oe = mCanvas->mapSettings().extent(); QgsRectangle e( c.x() - oe.width() / 2.0, c.y() - oe.height() / 2.0, c.x() + oe.width() / 2.0, c.y() + oe.height() / 2.0 ); e.scale( scaleFactor, &c ); mCanvas->setExtent( e, true ); mCanvas->refresh(); } else if ( e->modifiers() == Qt::ControlModifier ) { QgsMapToolDeleteItems( canvas() ).deleteItems( mExtentRubberBand->rect(), canvas()->mapSettings().destinationCrs() ); } delete mExtentRubberBand; mExtentRubberBand = 0; } else if ( mDragging ) { mCanvas->panActionEnd( e->pos() ); mDragging = false; mCanvas->setCursor( mCursor ); } else if ( mAllowItemInteraction && mPickClick ) { QgsFeaturePicker::PickResult result = QgsFeaturePicker::pick( mCanvas, e->pos(), toMapCoordinates( e->pos() ), QGis::AnyGeometry ); if ( !result.isEmpty() ) { emit itemPicked( result ); } } } }
QgsDxfPalLabeling::QgsDxfPalLabeling( QgsDxfExport* dxf, const QgsRectangle& bbox, double scale, QGis::UnitType mapUnits ): QgsPalLabeling(), mDxfExport( dxf ) { mMapRenderer.setExtent( bbox ); int dpi = 96; double factor = 1000 * dpi / scale / 25.4 * QGis::fromUnitToUnitFactor( mapUnits, QGis::Meters ); mMapRenderer.setOutputSize( QSizeF( bbox.width() * factor, bbox.height() * factor ), dpi ); mMapRenderer.setScale( scale ); mMapRenderer.setOutputUnits( QgsMapRenderer::Pixels ); init( &mMapRenderer ); mImage = new QImage( 10, 10, QImage::Format_ARGB32_Premultiplied ); mImage->setDotsPerMeterX( 96 / 25.4 * 1000 ); mImage->setDotsPerMeterY( 96 / 25.4 * 1000 ); mPainter = new QPainter( mImage ); mRenderContext.setPainter( mPainter ); mRenderContext.setRendererScale( scale ); mRenderContext.setExtent( bbox ); mRenderContext.setScaleFactor( 96.0 / 25.4 ); }
float QgsDemHeightMapGenerator::heightAt( double x, double y ) { // TODO: this is quite a primitive implementation: better to use heightmaps currently in use int res = 1024; QgsRectangle rect = mDtm->extent(); if ( mDtmCoarseData.isEmpty() ) { QgsRasterBlock *block = mDtm->dataProvider()->block( 1, rect, res, res ); block->convert( Qgis::Float32 ); mDtmCoarseData = block->data(); mDtmCoarseData.detach(); // make a deep copy delete block; } int cellX = ( int )( ( x - rect.xMinimum() ) / rect.width() * res + .5f ); int cellY = ( int )( ( rect.yMaximum() - y ) / rect.height() * res + .5f ); cellX = qBound( 0, cellX, res - 1 ); cellY = qBound( 0, cellY, res - 1 ); const float *data = ( const float * ) mDtmCoarseData.constData(); return data[cellX + cellY * res]; }
//! Returns a simplified version the specified geometry (Removing duplicated points) when is applied the specified map2pixel context QgsGeometry QgsMapToPixelSimplifier::simplify( const QgsGeometry& geometry ) const { if ( geometry.isEmpty() ) { return QgsGeometry(); } if ( mSimplifyFlags == QgsMapToPixelSimplifier::NoFlags ) { return geometry; } // Check whether the geometry can be simplified using the map2pixel context const QgsWkbTypes::Type singleType = QgsWkbTypes::singleType( geometry.wkbType() ); const QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( singleType ); if ( flatType == QgsWkbTypes::Point ) { return geometry; } const bool isaLinearRing = flatType == QgsWkbTypes::Polygon; const int numPoints = geometry.geometry()->nCoordinates(); if ( numPoints <= ( isaLinearRing ? 6 : 3 ) ) { // No simplify simple geometries return geometry; } const QgsRectangle envelope = geometry.boundingBox(); if ( qMax( envelope.width(), envelope.height() ) / numPoints > mTolerance * 2.0 ) { //points are in average too far apart to lead to any significant simplification return geometry; } return simplifyGeometry( mSimplifyFlags, mSimplifyAlgorithm, geometry.wkbType(), *geometry.geometry(), envelope, mTolerance, false ); }
QgsRasterBlock *QgsRasterDataProvider::block( int bandNo, QgsRectangle const &boundingBox, int width, int height, QgsRasterBlockFeedback *feedback ) { QgsDebugMsgLevel( QString( "bandNo = %1 width = %2 height = %3" ).arg( bandNo ).arg( width ).arg( height ), 4 ); QgsDebugMsgLevel( QString( "boundingBox = %1" ).arg( boundingBox.toString() ), 4 ); QgsRasterBlock *block = new QgsRasterBlock( dataType( bandNo ), width, height ); if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) ) { block->setNoDataValue( sourceNoDataValue( bandNo ) ); } if ( block->isEmpty() ) { QgsDebugMsg( "Couldn't create raster block" ); return block; } // Read necessary extent only QgsRectangle tmpExtent = extent().intersect( &boundingBox ); if ( tmpExtent.isEmpty() ) { QgsDebugMsg( "Extent outside provider extent" ); block->setIsNoData(); return block; } double xRes = boundingBox.width() / width; double yRes = boundingBox.height() / height; double tmpXRes, tmpYRes; double providerXRes = 0; double providerYRes = 0; if ( capabilities() & Size ) { providerXRes = extent().width() / xSize(); providerYRes = extent().height() / ySize(); tmpXRes = std::max( providerXRes, xRes ); tmpYRes = std::max( providerYRes, yRes ); if ( qgsDoubleNear( tmpXRes, xRes ) ) tmpXRes = xRes; if ( qgsDoubleNear( tmpYRes, yRes ) ) tmpYRes = yRes; } else { tmpXRes = xRes; tmpYRes = yRes; } if ( tmpExtent != boundingBox || tmpXRes > xRes || tmpYRes > yRes ) { // Read smaller extent or lower resolution if ( !extent().contains( boundingBox ) ) { QRect subRect = QgsRasterBlock::subRect( boundingBox, width, height, extent() ); block->setIsNoDataExcept( subRect ); } // Calculate row/col limits (before tmpExtent is aligned) int fromRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMaximum() ) / yRes ); int toRow = std::round( ( boundingBox.yMaximum() - tmpExtent.yMinimum() ) / yRes ) - 1; int fromCol = std::round( ( tmpExtent.xMinimum() - boundingBox.xMinimum() ) / xRes ); int toCol = std::round( ( tmpExtent.xMaximum() - boundingBox.xMinimum() ) / xRes ) - 1; QgsDebugMsgLevel( QString( "fromRow = %1 toRow = %2 fromCol = %3 toCol = %4" ).arg( fromRow ).arg( toRow ).arg( fromCol ).arg( toCol ), 4 ); if ( fromRow < 0 || fromRow >= height || toRow < 0 || toRow >= height || fromCol < 0 || fromCol >= width || toCol < 0 || toCol >= width ) { // Should not happen QgsDebugMsg( "Row or column limits out of range" ); return block; } // If lower source resolution is used, the extent must beS aligned to original // resolution to avoid possible shift due to resampling if ( tmpXRes > xRes ) { int col = std::floor( ( tmpExtent.xMinimum() - extent().xMinimum() ) / providerXRes ); tmpExtent.setXMinimum( extent().xMinimum() + col * providerXRes ); col = std::ceil( ( tmpExtent.xMaximum() - extent().xMinimum() ) / providerXRes ); tmpExtent.setXMaximum( extent().xMinimum() + col * providerXRes ); } if ( tmpYRes > yRes ) { int row = std::floor( ( extent().yMaximum() - tmpExtent.yMaximum() ) / providerYRes ); tmpExtent.setYMaximum( extent().yMaximum() - row * providerYRes ); row = std::ceil( ( extent().yMaximum() - tmpExtent.yMinimum() ) / providerYRes ); tmpExtent.setYMinimum( extent().yMaximum() - row * providerYRes ); } int tmpWidth = std::round( tmpExtent.width() / tmpXRes ); int tmpHeight = std::round( tmpExtent.height() / tmpYRes ); tmpXRes = tmpExtent.width() / tmpWidth; tmpYRes = tmpExtent.height() / tmpHeight; QgsDebugMsgLevel( QString( "Reading smaller block tmpWidth = %1 height = %2" ).arg( tmpWidth ).arg( tmpHeight ), 4 ); QgsDebugMsgLevel( QString( "tmpExtent = %1" ).arg( tmpExtent.toString() ), 4 ); QgsRasterBlock *tmpBlock = new QgsRasterBlock( dataType( bandNo ), tmpWidth, tmpHeight ); if ( sourceHasNoDataValue( bandNo ) && useSourceNoDataValue( bandNo ) ) { tmpBlock->setNoDataValue( sourceNoDataValue( bandNo ) ); } readBlock( bandNo, tmpExtent, tmpWidth, tmpHeight, tmpBlock->bits(), feedback ); int pixelSize = dataTypeSize( bandNo ); double xMin = boundingBox.xMinimum(); double yMax = boundingBox.yMaximum(); double tmpXMin = tmpExtent.xMinimum(); double tmpYMax = tmpExtent.yMaximum(); for ( int row = fromRow; row <= toRow; row++ ) { double y = yMax - ( row + 0.5 ) * yRes; int tmpRow = std::floor( ( tmpYMax - y ) / tmpYRes ); for ( int col = fromCol; col <= toCol; col++ ) { double x = xMin + ( col + 0.5 ) * xRes; int tmpCol = std::floor( ( x - tmpXMin ) / tmpXRes ); if ( tmpRow < 0 || tmpRow >= tmpHeight || tmpCol < 0 || tmpCol >= tmpWidth ) { QgsDebugMsg( "Source row or column limits out of range" ); block->setIsNoData(); // so that the problem becomes obvious and fixed delete tmpBlock; return block; } qgssize tmpIndex = static_cast< qgssize >( tmpRow ) * static_cast< qgssize >( tmpWidth ) + tmpCol; qgssize index = row * static_cast< qgssize >( width ) + col; char *tmpBits = tmpBlock->bits( tmpIndex ); char *bits = block->bits( index ); if ( !tmpBits ) { QgsDebugMsg( QString( "Cannot get input block data tmpRow = %1 tmpCol = %2 tmpIndex = %3." ).arg( tmpRow ).arg( tmpCol ).arg( tmpIndex ) ); continue; } if ( !bits ) { QgsDebugMsg( "Cannot set output block data." ); continue; } memcpy( bits, tmpBits, pixelSize ); } } delete tmpBlock; } else { readBlock( bandNo, boundingBox, width, height, block->bits(), feedback ); } // apply scale and offset block->applyScaleOffset( bandScale( bandNo ), bandOffset( bandNo ) ); // apply user no data values block->applyNoDataValues( userNoDataValues( bandNo ) ); return block; }
// Default implementation for values QgsRasterIdentifyResult QgsRasterDataProvider::identify( const QgsPointXY &point, QgsRaster::IdentifyFormat format, const QgsRectangle &boundingBox, int width, int height, int /*dpi*/ ) { QgsDebugMsgLevel( "Entered", 4 ); QMap<int, QVariant> results; if ( format != QgsRaster::IdentifyFormatValue || !( capabilities() & IdentifyValue ) ) { QgsDebugMsg( "Format not supported" ); return QgsRasterIdentifyResult( ERR( tr( "Format not supported" ) ) ); } if ( !extent().contains( point ) ) { // Outside the raster for ( int bandNo = 1; bandNo <= bandCount(); bandNo++ ) { results.insert( bandNo, QVariant() ); } return QgsRasterIdentifyResult( QgsRaster::IdentifyFormatValue, results ); } QgsRectangle finalExtent = boundingBox; if ( finalExtent.isEmpty() ) finalExtent = extent(); if ( width == 0 ) { width = capabilities() & Size ? xSize() : 1000; } if ( height == 0 ) { height = capabilities() & Size ? ySize() : 1000; } // Calculate the row / column where the point falls double xres = ( finalExtent.width() ) / width; double yres = ( finalExtent.height() ) / height; int col = static_cast< int >( std::floor( ( point.x() - finalExtent.xMinimum() ) / xres ) ); int row = static_cast< int >( std::floor( ( finalExtent.yMaximum() - point.y() ) / yres ) ); double xMin = finalExtent.xMinimum() + col * xres; double xMax = xMin + xres; double yMax = finalExtent.yMaximum() - row * yres; double yMin = yMax - yres; QgsRectangle pixelExtent( xMin, yMin, xMax, yMax ); for ( int i = 1; i <= bandCount(); i++ ) { QgsRasterBlock *myBlock = block( i, pixelExtent, 1, 1 ); if ( myBlock ) { double value = myBlock->value( 0 ); results.insert( i, value ); delete myBlock; } else { results.insert( i, QVariant() ); } } return QgsRasterIdentifyResult( QgsRaster::IdentifyFormatValue, results ); }
bool QgsMapToolIdentify::identifyRasterLayer( QList<IdentifyResult> *results, QgsRasterLayer *layer, QgsPoint point, const QgsRectangle& viewExtent, double mapUnitsPerPixel ) { QgsDebugMsg( "point = " + point.toString() ); if ( !layer ) return false; QgsRasterDataProvider *dprovider = layer->dataProvider(); if ( !dprovider ) return false; int capabilities = dprovider->capabilities(); if ( !( capabilities & QgsRasterDataProvider::Identify ) ) return false; QgsPoint pointInCanvasCrs = point; try { point = toLayerCoordinates( layer, point ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ); QgsDebugMsg( QString( "coordinate not reprojectable: %1" ).arg( cse.what() ) ); return false; } QgsDebugMsg( QString( "point = %1 %2" ).arg( point.x() ).arg( point.y() ) ); if ( !layer->extent().contains( point ) ) return false; QMap< QString, QString > attributes, derivedAttributes; QgsRaster::IdentifyFormat format = QgsRasterDataProvider::identifyFormatFromName( layer->customProperty( "identify/format" ).toString() ); // check if the format is really supported otherwise use first supported format if ( !( QgsRasterDataProvider::identifyFormatToCapability( format ) & capabilities ) ) { if ( capabilities & QgsRasterInterface::IdentifyFeature ) format = QgsRaster::IdentifyFormatFeature; else if ( capabilities & QgsRasterInterface::IdentifyValue ) format = QgsRaster::IdentifyFormatValue; else if ( capabilities & QgsRasterInterface::IdentifyHtml ) format = QgsRaster::IdentifyFormatHtml; else if ( capabilities & QgsRasterInterface::IdentifyText ) format = QgsRaster::IdentifyFormatText; else return false; } QgsRasterIdentifyResult identifyResult; // We can only use current map canvas context (extent, width, height) if layer is not reprojected, if ( mCanvas->hasCrsTransformEnabled() && dprovider->crs() != mCanvas->mapSettings().destinationCrs() ) { // To get some reasonable response for point/line WMS vector layers we must // use a context with approximately a resolution in layer CRS units // corresponding to current map canvas resolution (for examplei UMN Mapserver // in msWMSFeatureInfo() -> msQueryByRect() is using requested pixel // + TOLERANCE (layer param) for feature selection) // QgsRectangle r; r.setXMinimum( pointInCanvasCrs.x() - mapUnitsPerPixel / 2. ); r.setXMaximum( pointInCanvasCrs.x() + mapUnitsPerPixel / 2. ); r.setYMinimum( pointInCanvasCrs.y() - mapUnitsPerPixel / 2. ); r.setYMaximum( pointInCanvasCrs.y() + mapUnitsPerPixel / 2. ); r = toLayerCoordinates( layer, r ); // will be a bit larger // Mapserver (6.0.3, for example) does not work with 1x1 pixel box // but that is fixed (the rect is enlarged) in the WMS provider identifyResult = dprovider->identify( point, format, r, 1, 1 ); } else { // It would be nice to use the same extent and size which was used for drawing, // so that WCS can use cache from last draw, unfortunately QgsRasterLayer::draw() // is doing some tricks with extent and size to allign raster to output which // would be difficult to replicate here. // Note: cutting the extent may result in slightly different x and y resolutions // and thus shifted point calculated back in QGIS WMS (using average resolution) //viewExtent = dprovider->extent().intersect( &viewExtent ); // Width and height are calculated from not projected extent and we hope that // are similar to source width and height used to reproject layer for drawing. // TODO: may be very dangerous, because it may result in different resolutions // in source CRS, and WMS server (QGIS server) calcs wrong coor using average resolution. int width = qRound( viewExtent.width() / mapUnitsPerPixel ); int height = qRound( viewExtent.height() / mapUnitsPerPixel ); QgsDebugMsg( QString( "viewExtent.width = %1 viewExtent.height = %2" ).arg( viewExtent.width() ).arg( viewExtent.height() ) ); QgsDebugMsg( QString( "width = %1 height = %2" ).arg( width ).arg( height ) ); QgsDebugMsg( QString( "xRes = %1 yRes = %2 mapUnitsPerPixel = %3" ).arg( viewExtent.width() / width ).arg( viewExtent.height() / height ).arg( mapUnitsPerPixel ) ); identifyResult = dprovider->identify( point, format, viewExtent, width, height ); } derivedAttributes.insert( tr( "(clicked coordinate)" ), point.toString() ); if ( identifyResult.isValid() ) { QMap<int, QVariant> values = identifyResult.results(); QgsGeometry geometry; if ( format == QgsRaster::IdentifyFormatValue ) { Q_FOREACH ( int bandNo, values.keys() ) { QString valueString; if ( values.value( bandNo ).isNull() ) { valueString = tr( "no data" ); } else { double value = values.value( bandNo ).toDouble(); valueString = QgsRasterBlock::printValue( value ); } attributes.insert( dprovider->generateBandName( bandNo ), valueString ); } QString label = layer->name(); results->append( IdentifyResult( qobject_cast<QgsMapLayer *>( layer ), label, attributes, derivedAttributes ) ); }