Skip to content
Permalink
Browse files

[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.
  • Loading branch information
wonder-sk committed Feb 12, 2019
1 parent f95d323 commit 673d4949417db430e3ce4e18661c75d428a2d650
Showing with 39 additions and 15 deletions.
  1. +38 −14 src/quickgui/qgsquickidentifykit.cpp
  2. +1 −1 src/quickgui/qgsquickidentifykit.h
@@ -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
@@ -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;
};

0 comments on commit 673d494

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