Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't identify 3d layers when clicking the terrain #59790

Merged
merged 5 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions python/PyQt6/gui/auto_additions/qgsmaptoolidentify.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ def _force_int(v): return int(v.value) if isinstance(v, Enum) else v
QgsMapToolIdentify.Type.__eq__ = lambda flag1, flag2: _force_int(flag1) == _force_int(flag2)
QgsMapToolIdentify.Type.__and__ = lambda flag1, flag2: _force_int(flag1) & _force_int(flag2)
QgsMapToolIdentify.Type.__or__ = lambda flag1, flag2: QgsMapToolIdentify.Type(_force_int(flag1) | _force_int(flag2))
try:
QgsMapToolIdentify.IdentifyProperties.__attribute_docs__ = {'searchRadiusMapUnits': 'Identify search radius is map units. Use negative value to ignore', 'skip3DLayers': 'Skip identify results from layers that have a 3d renderer set'}
QgsMapToolIdentify.IdentifyProperties.__group__ = ['maptools']
except (NameError, AttributeError):
pass
try:
QgsMapToolIdentify.__attribute_docs__ = {'identifyProgress': 'Emitted when the identify action progresses.\n\n:param processed: number of objects processed so far\n:param total: total number of objects to process\n', 'identifyMessage': 'Emitted when the identify operation needs to show a user-facing message\n\n:param message: Message to show to the user\n', 'changedRasterResults': 'Emitted when the format of raster ``results`` is changed and need to be updated in user-facing displays.\n'}
QgsMapToolIdentify.__signal_arguments__ = {'identifyProgress': ['processed: int', 'total: int'], 'identifyMessage': ['message: str'], 'changedRasterResults': ['results: List[QgsMapToolIdentify.IdentifyResult]']}
Expand Down
47 changes: 43 additions & 4 deletions python/PyQt6/gui/auto_generated/maptools/qgsmaptoolidentify.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ after selecting a point, performs the identification:
QMap< QString, QVariant > mParams;
};

struct IdentifyProperties
{
double searchRadiusMapUnits;
bool skip3DLayers;
};

QgsMapToolIdentify( QgsMapCanvas *canvas );
%Docstring
constructor
Expand Down Expand Up @@ -215,29 +221,62 @@ Works only if layer was already rendered (triangular mesh is created)
Returns derived attributes map for a clicked point in map coordinates. May be 2D or 3D point.
%End

void setCanvasPropertiesOverrides( double searchRadiusMapUnits );
void setCanvasPropertiesOverrides( double searchRadiusMapUnits ) /Deprecated/;
%Docstring
Overrides some map canvas properties inside the map tool for the upcoming identify requests.

This is useful when the identification is triggered by some other piece of GUI like a 3D map view
and some properties like search radius need to be adjusted so that identification returns correct
results. Currently only search radius may be overridden.

results.
When the custom identification has finished, :py:func:`~QgsMapToolIdentify.restoreCanvasPropertiesOverrides` should
be called to erase any overrides.

:param searchRadiusMapUnits: The overridden search radius in map units

.. seealso:: :py:func:`restoreCanvasPropertiesOverrides`

.. versionadded:: 3.4

.. deprecated:: 3.42

Use :py:func:`~QgsMapToolIdentify.setPropertiesOverrides` instead.
%End

void restoreCanvasPropertiesOverrides();
void restoreCanvasPropertiesOverrides() /Deprecated/;
%Docstring
Clears canvas properties overrides previously set with :py:func:`~QgsMapToolIdentify.setCanvasPropertiesOverrides`

.. seealso:: :py:func:`setCanvasPropertiesOverrides`

.. versionadded:: 3.4

.. deprecated:: 3.42

Use :py:func:`~QgsMapToolIdentify.restorePropertiesOverrides` instead.
%End

void setPropertiesOverrides( IdentifyProperties overrides );
%Docstring
Overrides some map canvas properties inside the map tool for the upcoming identify requests.

This is useful when the identification is triggered by some other piece of GUI like a 3D map view
and some properties like search radius need to be adjusted so that identification returns correct
results.
When the custom identification has finished, :py:func:`~QgsMapToolIdentify.restorePropertiesOverrides` should
be called to erase any overrides.

:param overrides: The identify tool properties that will be overridden

.. versionadded:: 3.42
%End

void restorePropertiesOverrides();
%Docstring
Clears canvas properties overrides previously set with :py:func:`~QgsMapToolIdentify.setPropertiesOverrides`

.. seealso:: :py:func:`setPropertiesOverrides`

.. versionadded:: 3.42
%End

};
Expand Down
5 changes: 5 additions & 0 deletions python/gui/auto_additions/qgsmaptoolidentify.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
QgsMapToolIdentify.IdentifyMode.baseClass = QgsMapToolIdentify
QgsMapToolIdentify.LayerType.baseClass = QgsMapToolIdentify
LayerType = QgsMapToolIdentify # dirty hack since SIP seems to introduce the flags in module
try:
QgsMapToolIdentify.IdentifyProperties.__attribute_docs__ = {'searchRadiusMapUnits': 'Identify search radius is map units. Use negative value to ignore', 'skip3DLayers': 'Skip identify results from layers that have a 3d renderer set'}
QgsMapToolIdentify.IdentifyProperties.__group__ = ['maptools']
except (NameError, AttributeError):
pass
try:
QgsMapToolIdentify.__attribute_docs__ = {'identifyProgress': 'Emitted when the identify action progresses.\n\n:param processed: number of objects processed so far\n:param total: total number of objects to process\n', 'identifyMessage': 'Emitted when the identify operation needs to show a user-facing message\n\n:param message: Message to show to the user\n', 'changedRasterResults': 'Emitted when the format of raster ``results`` is changed and need to be updated in user-facing displays.\n'}
QgsMapToolIdentify.__signal_arguments__ = {'identifyProgress': ['processed: int', 'total: int'], 'identifyMessage': ['message: str'], 'changedRasterResults': ['results: List[QgsMapToolIdentify.IdentifyResult]']}
Expand Down
47 changes: 43 additions & 4 deletions python/gui/auto_generated/maptools/qgsmaptoolidentify.sip.in
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ after selecting a point, performs the identification:
QMap< QString, QVariant > mParams;
};

struct IdentifyProperties
{
double searchRadiusMapUnits;
bool skip3DLayers;
};

QgsMapToolIdentify( QgsMapCanvas *canvas );
%Docstring
constructor
Expand Down Expand Up @@ -215,29 +221,62 @@ Works only if layer was already rendered (triangular mesh is created)
Returns derived attributes map for a clicked point in map coordinates. May be 2D or 3D point.
%End

void setCanvasPropertiesOverrides( double searchRadiusMapUnits );
void setCanvasPropertiesOverrides( double searchRadiusMapUnits ) /Deprecated/;
%Docstring
Overrides some map canvas properties inside the map tool for the upcoming identify requests.

This is useful when the identification is triggered by some other piece of GUI like a 3D map view
and some properties like search radius need to be adjusted so that identification returns correct
results. Currently only search radius may be overridden.

results.
When the custom identification has finished, :py:func:`~QgsMapToolIdentify.restoreCanvasPropertiesOverrides` should
be called to erase any overrides.

:param searchRadiusMapUnits: The overridden search radius in map units

.. seealso:: :py:func:`restoreCanvasPropertiesOverrides`

.. versionadded:: 3.4

.. deprecated:: 3.42

Use :py:func:`~QgsMapToolIdentify.setPropertiesOverrides` instead.
%End

void restoreCanvasPropertiesOverrides();
void restoreCanvasPropertiesOverrides() /Deprecated/;
%Docstring
Clears canvas properties overrides previously set with :py:func:`~QgsMapToolIdentify.setCanvasPropertiesOverrides`

.. seealso:: :py:func:`setCanvasPropertiesOverrides`

.. versionadded:: 3.4

.. deprecated:: 3.42

Use :py:func:`~QgsMapToolIdentify.restorePropertiesOverrides` instead.
%End

void setPropertiesOverrides( IdentifyProperties overrides );
%Docstring
Overrides some map canvas properties inside the map tool for the upcoming identify requests.

This is useful when the identification is triggered by some other piece of GUI like a 3D map view
and some properties like search radius need to be adjusted so that identification returns correct
results.
When the custom identification has finished, :py:func:`~QgsMapToolIdentify.restorePropertiesOverrides` should
be called to erase any overrides.

:param overrides: The identify tool properties that will be overridden

.. versionadded:: 3.42
%End

void restorePropertiesOverrides();
%Docstring
Clears canvas properties overrides previously set with :py:func:`~QgsMapToolIdentify.setPropertiesOverrides`

.. seealso:: :py:func:`setPropertiesOverrides`

.. versionadded:: 3.42
%End

};
Expand Down
10 changes: 5 additions & 5 deletions src/app/3d/qgs3dmaptoolidentify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,7 @@ void Qgs3DMapToolIdentify::mouseReleaseEvent( QMouseEvent *event )
}
}

// We only handle terrain results if there were no vector layer results because:
// a. terrain results will overwrite other existing results.
// b. terrain results use 2d identify logic and may contain results from vector layers that
// are not actually rendered on the terrain as they have a 3d renderer set.
// We only handle terrain results if there were no vector layer results so they don't get overwritten
if ( showTerrainResults && allHits.contains( nullptr ) )
{
const QgsRayCastingUtils::RayHit hit = allHits.value( nullptr ).first();
Expand Down Expand Up @@ -172,7 +169,10 @@ void Qgs3DMapToolIdentify::mouseReleaseEvent( QMouseEvent *event )
QgsDebugError( QStringLiteral( "Could not transform identified coordinates to project crs: %1" ).arg( e.what() ) );
}

identifyTool2D->identifyAndShowResults( QgsGeometry::fromPointXY( mapPointCanvas2D ), searchRadiusCanvas2D );
QgsMapToolIdentify::IdentifyProperties props;
props.searchRadiusMapUnits = searchRadiusCanvas2D;
props.skip3DLayers = true;
identifyTool2D->identifyAndShowResults( QgsGeometry::fromPointXY( mapPointCanvas2D ), props );
}

// We need to show other layer type results AFTER terrain results so they don't get overwritten
Expand Down
6 changes: 3 additions & 3 deletions src/app/qgsmaptoolidentifyaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,11 @@ void QgsMapToolIdentifyAction::deactivate()
QgsMapToolIdentify::deactivate();
}

void QgsMapToolIdentifyAction::identifyAndShowResults( const QgsGeometry &geom, double searchRadiusMapUnits )
void QgsMapToolIdentifyAction::identifyAndShowResults( const QgsGeometry &geom, IdentifyProperties properties )
{
setCanvasPropertiesOverrides( searchRadiusMapUnits );
setPropertiesOverrides( properties );
mSelectionHandler->setSelectedGeometry( geom );
restoreCanvasPropertiesOverrides();
restorePropertiesOverrides();
}

void QgsMapToolIdentifyAction::clearResults()
Expand Down
8 changes: 6 additions & 2 deletions src/app/qgsmaptoolidentifyaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,12 @@ class APP_EXPORT QgsMapToolIdentifyAction : public QgsMapToolIdentify

void deactivate() override;

//! Triggers map identification of at the given location and outputs results in GUI
void identifyAndShowResults( const QgsGeometry &geom, double searchRadiusMapUnits );
/**
* Triggers map identification at the given location and outputs results in GUI
* \param geom The geometry to use for identification
* \param properties Sets overridden properties for this identification, like search radius
*/
void identifyAndShowResults( const QgsGeometry &geom, IdentifyProperties properties );
//! Clears any previous results from the GUI
void clearResults();
//! Looks up feature by its ID and outputs the result in GUI
Expand Down
33 changes: 27 additions & 6 deletions src/gui/maptools/qgsmaptoolidentify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,24 @@ QList<QgsMapToolIdentify::IdentifyResult> QgsMapToolIdentify::identify( const Qg

void QgsMapToolIdentify::setCanvasPropertiesOverrides( double searchRadiusMapUnits )
{
mOverrideCanvasSearchRadius = searchRadiusMapUnits;
mPropertiesOverrides.searchRadiusMapUnits = searchRadiusMapUnits;
}

void QgsMapToolIdentify::restoreCanvasPropertiesOverrides()
{
mOverrideCanvasSearchRadius = -1;
mPropertiesOverrides.searchRadiusMapUnits = -1;
mPropertiesOverrides.skip3DLayers = false;
}

void QgsMapToolIdentify::setPropertiesOverrides( IdentifyProperties overrides )
{
mPropertiesOverrides = overrides;
}

void QgsMapToolIdentify::restorePropertiesOverrides()
{
mPropertiesOverrides.searchRadiusMapUnits = -1;
mPropertiesOverrides.skip3DLayers = false;
}

void QgsMapToolIdentify::activate()
Expand Down Expand Up @@ -280,13 +292,16 @@ bool QgsMapToolIdentify::identifyMeshLayer( QList<QgsMapToolIdentify::IdentifyRe
if ( !layer )
return false;

if ( mPropertiesOverrides.skip3DLayers && layer->renderer3D() )
return false;

if ( !identifyContext.zRange().isInfinite() )
{
if ( !layer->elevationProperties()->isVisibleInZRange( identifyContext.zRange() ) )
return false;
}

double searchRadius = mOverrideCanvasSearchRadius < 0 ? searchRadiusMU( mCanvas ) : mOverrideCanvasSearchRadius;
double searchRadius = mPropertiesOverrides.searchRadiusMapUnits < 0 ? searchRadiusMU( mCanvas ) : mPropertiesOverrides.searchRadiusMapUnits;
bool isTemporal = identifyContext.isTemporal() && layer->temporalProperties()->isActive();

QList<QgsMeshDatasetIndex> datasetIndexList;
Expand Down Expand Up @@ -455,7 +470,7 @@ bool QgsMapToolIdentify::identifyVectorTileLayer( QList<QgsMapToolIdentify::Iden
QgsRectangle r;
if ( isSingleClick )
{
double sr = mOverrideCanvasSearchRadius < 0 ? searchRadiusMU( mCanvas ) : mOverrideCanvasSearchRadius;
double sr = mPropertiesOverrides.searchRadiusMapUnits < 0 ? searchRadiusMU( mCanvas ) : mPropertiesOverrides.searchRadiusMapUnits;
r = toLayerCoordinates( layer, QgsRectangle( point.x() - sr, point.y() - sr, point.x() + sr, point.y() + sr ) );
}
else
Expand Down Expand Up @@ -540,6 +555,9 @@ bool QgsMapToolIdentify::identifyVectorTileLayer( QList<QgsMapToolIdentify::Iden

bool QgsMapToolIdentify::identifyPointCloudLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsPointCloudLayer *layer, const QgsGeometry &geometry, const QgsIdentifyContext &identifyContext )
{
if ( mPropertiesOverrides.skip3DLayers && layer->renderer3D() )
return false;

if ( !identifyContext.zRange().isInfinite() )
{
if ( !layer->elevationProperties()->isVisibleInZRange( identifyContext.zRange(), layer ) )
Expand All @@ -553,7 +571,7 @@ bool QgsMapToolIdentify::identifyPointCloudLayer( QList<QgsMapToolIdentify::Iden
if ( !identifyContext.zRange().isInfinite() )
context.setZRange( identifyContext.zRange() );

const double searchRadiusMapUnits = mOverrideCanvasSearchRadius < 0 ? searchRadiusMU( mCanvas ) : mOverrideCanvasSearchRadius;
const double searchRadiusMapUnits = mPropertiesOverrides.searchRadiusMapUnits < 0 ? searchRadiusMU( mCanvas ) : mPropertiesOverrides.searchRadiusMapUnits;

const QVector<QVariantMap> points = renderer->identify( layer, context, geometry, searchRadiusMapUnits );

Expand Down Expand Up @@ -582,6 +600,9 @@ bool QgsMapToolIdentify::identifyVectorLayer( QList<QgsMapToolIdentify::Identify
if ( !layer || !layer->isSpatial() || !layer->dataProvider() )
return false;

if ( mPropertiesOverrides.skip3DLayers && layer->renderer3D() )
return false;

if ( !layer->isInScaleRange( mCanvas->mapSettings().scale() ) )
{
QgsDebugMsgLevel( QStringLiteral( "Out of scale limits" ), 2 );
Expand Down Expand Up @@ -633,7 +654,7 @@ bool QgsMapToolIdentify::identifyVectorLayer( QList<QgsMapToolIdentify::Identify
QgsRectangle r;
if ( isSingleClick )
{
double sr = mOverrideCanvasSearchRadius < 0 ? searchRadiusMU( mCanvas ) : mOverrideCanvasSearchRadius;
double sr = mPropertiesOverrides.searchRadiusMapUnits < 0 ? searchRadiusMU( mCanvas ) : mPropertiesOverrides.searchRadiusMapUnits;
r = toLayerCoordinates( layer, QgsRectangle( point.x() - sr, point.y() - sr, point.x() + sr, point.y() + sr ) );
}
else
Expand Down
Loading
Loading