Skip to content
Permalink
Browse files

Merge pull request #8330 from 3nids/fix9160

Properly zoom to feature for single point selected
  • Loading branch information
3nids committed Oct 25, 2018
2 parents 1118f4a + daca55a commit 8eb193020a1cb2477cf1fa7897ad9923bc415dc9
@@ -183,6 +183,13 @@ Scale the rectangle around its center point.
void scale( double scaleFactor, double centerX, double centerY );
%Docstring
Scale the rectangle around its center point.
%End

QgsRectangle scaled( double scaleFactor, const QgsPointXY *center = 0 ) const;
%Docstring
Scale the rectangle around its ``center`` point.

.. versionadded:: 3.4
%End

void grow( double delta );
@@ -58,6 +58,13 @@ QgsRectangle QgsRectangle::fromCenterAndSize( QgsPointXY center, double width, d
return QgsRectangle( xMin, yMin, xMax, yMax );
}

QgsRectangle QgsRectangle::scaled( double scaleFactor, const QgsPointXY *center ) const
{
QgsRectangle scaledRect = QgsRectangle( *this );
scaledRect.scale( scaleFactor, center );
return scaledRect;
}

QgsRectangle QgsRectangle::operator-( const QgsVector v ) const
{
double xmin = mXmin - v.x();
@@ -261,6 +261,12 @@ class CORE_EXPORT QgsRectangle
mYmax = centerY + newHeight / 2.0;
}

/**
* Scale the rectangle around its \a center point.
* \since QGIS 3.4
*/
QgsRectangle scaled( double scaleFactor, const QgsPointXY *center = nullptr ) const;

/**
* Grows the rectangle in place by the specified amount.
* \see buffered()
@@ -996,8 +996,40 @@ void QgsMapCanvas::zoomToSelected( QgsVectorLayer *layer )
}

rect = mapSettings().layerExtentToOutputExtent( layer, rect );

// zoom in if point cannot be distinguished from others
// also check that rect is empty, as it might not in case of multi points
if ( layer->geometryType() == QgsWkbTypes::PointGeometry && rect.isEmpty() )
{
int scaleFactor = 5;
QgsPointXY center = mSettings.mapToLayerCoordinates( layer, rect.center() );
QgsRectangle extentRect = mSettings.mapToLayerCoordinates( layer, extent() ).scaled( 1.0 / scaleFactor, &center );
QgsFeatureRequest req = QgsFeatureRequest().setFilterRect( extentRect ).setLimit( 1000 ).setNoAttributes();
QgsFeatureIterator fit = layer->getFeatures( req );
QgsFeature f;
QgsPointXY closestPoint;
double closestSquaredDistance = extentRect.width() + extentRect.height();
bool pointFound = false;
while ( fit.nextFeature( f ) )
{
QgsPointXY point = f.geometry().asPoint();
double sqrDist = point.sqrDist( center );
if ( sqrDist > closestSquaredDistance || sqrDist < 4 * std::numeric_limits<double>::epsilon() )
continue;
pointFound = true;
closestPoint = point;
closestSquaredDistance = sqrDist;
}
if ( pointFound )
{
// combine selected point with closest point and scale this rect
rect.combineExtentWith( mSettings.layerToMapCoordinates( layer, closestPoint ) );
rect.scale( scaleFactor, &center );
}
}

zoomToFeatureExtent( rect );
} // zoomToSelected
}

void QgsMapCanvas::zoomToFeatureExtent( QgsRectangle &rect )
{
@@ -40,6 +40,7 @@ class TestQgsRectangle: public QObject
void isFinite();
void combine();
void dataStream();
void scale();
};

void TestQgsRectangle::isEmpty()
@@ -348,5 +349,22 @@ void TestQgsRectangle::dataStream()
QCOMPARE( result, original );
}

void TestQgsRectangle::scale()
{
QgsRectangle rect( 10, 20, 30, 60 );
rect.scale( 2 );
QCOMPARE( rect, QgsRectangle( 0, 0, 40, 80 ) );
rect.scale( .5 );
QCOMPARE( rect, QgsRectangle( 10, 20, 30, 60 ) );
QgsPointXY center( 10, 20 );

// with center
rect.scale( 2, &center );
QCOMPARE( rect, QgsRectangle( -10, -20, 30, 60 ) );

// scaled
QCOMPARE( rect, QgsRectangle( 10, 20, 30, 60 ).scaled( 2, &center ) );
}

QGSTEST_MAIN( TestQgsRectangle )
#include "testqgsrectangle.moc"

0 comments on commit 8eb1930

Please sign in to comment.
You can’t perform that action at this time.