[quick] Fix identify: give priority to points (and lines)

Without priority for points (and lines) it is otherwise very difficult
to identify them on top of polygons or difficult to identify a point
on top of a line.

Also lowered the default radius from 8mm (which seemed excessively large) to 5mm.
This commit is contained in:
Martin Dobias 2019-02-09 12:01:28 +01:00
parent f95d3235f3
commit 673d494941
2 changed files with 39 additions and 15 deletions

View File

@ -93,13 +93,13 @@ QgsQuickFeatureLayerPairs QgsQuickIdentifyKit::identify( const QPointF &point, Q
return results;
}
static QgsQuickFeatureLayerPair _closestFeature( const QgsQuickFeatureLayerPairs &results, const QgsMapSettings &mapSettings, const QPointF &point )
static QgsQuickFeatureLayerPair _closestFeature( const QgsQuickFeatureLayerPairs &results, const QgsMapSettings &mapSettings, const QPointF &point, double searchRadius )
{
QgsPointXY mapPoint = mapSettings.mapToPixel().toMapCoordinates( point.toPoint() );
QgsGeometry mapPointGeom( QgsGeometry::fromPointXY( mapPoint ) );
double distMin = 1e10;
int iMin = -1;
double distMinPoint = 1e10, distMinLine = 1e10, distMinPolygon = 1e10;
int iMinPoint = -1, iMinLine = -1, iMinPolygon = -1;
for ( int i = 0; i < results.count(); ++i )
{
const QgsQuickFeatureLayerPair &res = results.at( i );
@ -116,27 +116,51 @@ static QgsQuickFeatureLayerPair _closestFeature( const QgsQuickFeatureLayerPairs
}
double dist = geom.distance( mapPointGeom );
if ( dist < distMin )
QgsWkbTypes::GeometryType type = QgsWkbTypes::geometryType( geom.wkbType() );
if ( type == QgsWkbTypes::PointGeometry )
{
iMin = i;
distMin = dist;
if ( dist < distMinPoint )
{
iMinPoint = i;
distMinPoint = dist;
}
}
else if ( type == QgsWkbTypes::LineGeometry )
{
if ( dist < distMinLine )
{
iMinLine = i;
distMinLine = dist;
}
}
else // polygons
{
if ( dist < distMinPolygon )
{
iMinPolygon = i;
distMinPolygon = dist;
}
}
}
if ( results.empty() )
{
return QgsQuickFeatureLayerPair();
}
// we give priority to points, then lines, then polygons
// the rationale is that points in polygon (or on a line) would have nearly
// always non-zero distance while polygon surrounding it has zero distance,
// so it would be difficult to identify it
if ( iMinPoint != -1 && distMinPoint <= searchRadius )
return results.at( iMinPoint );
else if ( iMinLine != -1 && distMinLine <= searchRadius )
return results.at( iMinLine );
else if ( iMinPolygon != -1 )
return results.at( iMinPolygon );
else
{
return results.at( iMin );
}
return QgsQuickFeatureLayerPair();
}
QgsQuickFeatureLayerPair QgsQuickIdentifyKit::identifyOne( const QPointF &point, QgsVectorLayer *layer )
{
QgsQuickFeatureLayerPairs results = identify( point, layer );
return _closestFeature( results, mMapSettings->mapSettings(), point );
return _closestFeature( results, mMapSettings->mapSettings(), point, searchRadiusMU() );
}
QgsFeatureList QgsQuickIdentifyKit::identifyVectorLayer( QgsVectorLayer *layer, const QgsPointXY &point ) const

View File

@ -166,7 +166,7 @@ class QUICK_EXPORT QgsQuickIdentifyKit : public QObject
QgsRectangle toLayerCoordinates( QgsMapLayer *layer, const QgsRectangle &rect ) const;
QgsFeatureList identifyVectorLayer( QgsVectorLayer *layer, const QgsPointXY &point ) const;
double mSearchRadiusMm = 8;
double mSearchRadiusMm = 5;
int mFeaturesLimit = 100;
IdentifyMode mIdentifyMode = IdentifyMode::TopDownAll;
};