Merge pull request #54726 from troopa81/make_avoidintersection_return_enum

Make avoidIntersections return an enum
This commit is contained in:
Julien Cabieces 2023-09-28 09:09:48 +02:00 committed by GitHub
commit 4676af859f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 96 additions and 27 deletions

View File

@ -1464,7 +1464,10 @@ QgsGeometry.AddRingNotInExistingFeature.__doc__ = "The input ring doesn't have a
QgsGeometry.SplitCannotSplitPoint = Qgis.GeometryOperationResult.SplitCannotSplitPoint
QgsGeometry.SplitCannotSplitPoint.is_monkey_patched = True
QgsGeometry.SplitCannotSplitPoint.__doc__ = "Cannot split points"
Qgis.GeometryOperationResult.__doc__ = "Success or failure of a geometry operation.\n\nThis enum gives details about cause of failure.\n\n.. versionadded:: 3.22\n\n" + '* ``Success``: ' + Qgis.GeometryOperationResult.Success.__doc__ + '\n' + '* ``NothingHappened``: ' + Qgis.GeometryOperationResult.NothingHappened.__doc__ + '\n' + '* ``InvalidBaseGeometry``: ' + Qgis.GeometryOperationResult.InvalidBaseGeometry.__doc__ + '\n' + '* ``InvalidInputGeometryType``: ' + Qgis.GeometryOperationResult.InvalidInputGeometryType.__doc__ + '\n' + '* ``SelectionIsEmpty``: ' + Qgis.GeometryOperationResult.SelectionIsEmpty.__doc__ + '\n' + '* ``SelectionIsGreaterThanOne``: ' + Qgis.GeometryOperationResult.SelectionIsGreaterThanOne.__doc__ + '\n' + '* ``GeometryEngineError``: ' + Qgis.GeometryOperationResult.GeometryEngineError.__doc__ + '\n' + '* ``LayerNotEditable``: ' + Qgis.GeometryOperationResult.LayerNotEditable.__doc__ + '\n' + '* ``AddPartSelectedGeometryNotFound``: ' + Qgis.GeometryOperationResult.AddPartSelectedGeometryNotFound.__doc__ + '\n' + '* ``AddPartNotMultiGeometry``: ' + Qgis.GeometryOperationResult.AddPartNotMultiGeometry.__doc__ + '\n' + '* ``AddRingNotClosed``: ' + Qgis.GeometryOperationResult.AddRingNotClosed.__doc__ + '\n' + '* ``AddRingNotValid``: ' + Qgis.GeometryOperationResult.AddRingNotValid.__doc__ + '\n' + '* ``AddRingCrossesExistingRings``: ' + Qgis.GeometryOperationResult.AddRingCrossesExistingRings.__doc__ + '\n' + '* ``AddRingNotInExistingFeature``: ' + Qgis.GeometryOperationResult.AddRingNotInExistingFeature.__doc__ + '\n' + '* ``SplitCannotSplitPoint``: ' + Qgis.GeometryOperationResult.SplitCannotSplitPoint.__doc__
QgsGeometry.GeometryTypeHasChanged = Qgis.GeometryOperationResult.GeometryTypeHasChanged
QgsGeometry.GeometryTypeHasChanged.is_monkey_patched = True
QgsGeometry.GeometryTypeHasChanged.__doc__ = "Operation has changed geometry type"
Qgis.GeometryOperationResult.__doc__ = "Success or failure of a geometry operation.\n\nThis enum gives details about cause of failure.\n\n.. versionadded:: 3.22\n\n" + '* ``Success``: ' + Qgis.GeometryOperationResult.Success.__doc__ + '\n' + '* ``NothingHappened``: ' + Qgis.GeometryOperationResult.NothingHappened.__doc__ + '\n' + '* ``InvalidBaseGeometry``: ' + Qgis.GeometryOperationResult.InvalidBaseGeometry.__doc__ + '\n' + '* ``InvalidInputGeometryType``: ' + Qgis.GeometryOperationResult.InvalidInputGeometryType.__doc__ + '\n' + '* ``SelectionIsEmpty``: ' + Qgis.GeometryOperationResult.SelectionIsEmpty.__doc__ + '\n' + '* ``SelectionIsGreaterThanOne``: ' + Qgis.GeometryOperationResult.SelectionIsGreaterThanOne.__doc__ + '\n' + '* ``GeometryEngineError``: ' + Qgis.GeometryOperationResult.GeometryEngineError.__doc__ + '\n' + '* ``LayerNotEditable``: ' + Qgis.GeometryOperationResult.LayerNotEditable.__doc__ + '\n' + '* ``AddPartSelectedGeometryNotFound``: ' + Qgis.GeometryOperationResult.AddPartSelectedGeometryNotFound.__doc__ + '\n' + '* ``AddPartNotMultiGeometry``: ' + Qgis.GeometryOperationResult.AddPartNotMultiGeometry.__doc__ + '\n' + '* ``AddRingNotClosed``: ' + Qgis.GeometryOperationResult.AddRingNotClosed.__doc__ + '\n' + '* ``AddRingNotValid``: ' + Qgis.GeometryOperationResult.AddRingNotValid.__doc__ + '\n' + '* ``AddRingCrossesExistingRings``: ' + Qgis.GeometryOperationResult.AddRingCrossesExistingRings.__doc__ + '\n' + '* ``AddRingNotInExistingFeature``: ' + Qgis.GeometryOperationResult.AddRingNotInExistingFeature.__doc__ + '\n' + '* ``SplitCannotSplitPoint``: ' + Qgis.GeometryOperationResult.SplitCannotSplitPoint.__doc__ + '\n' + '* ``GeometryTypeHasChanged``: ' + Qgis.GeometryOperationResult.GeometryTypeHasChanged.__doc__
# --
Qgis.GeometryOperationResult.baseClass = Qgis
QgsGeometry.ValidityFlag = Qgis.GeometryValidityFlag

View File

@ -2430,7 +2430,7 @@ empty if none of the child geometries match the desired type.
.. versionadded:: 3.2
%End
int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers );
int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers ) /Deprecated/;
%Docstring
Modifies geometry to avoid intersections with the layers specified in project properties
@ -2444,6 +2444,25 @@ Modifies geometry to avoid intersections with the layers specified in project pr
4 if the geometry is not intersected by one of the geometries present in the provided layers.
.. versionadded:: 1.5
.. deprecated::
QGIS 3.34
%End
Qgis::GeometryOperationResult avoidIntersectionsV2( const QList<QgsVectorLayer *> &avoidIntersectionsLayers );
%Docstring
Modifies geometry to avoid intersections with the layers specified in project properties
:param avoidIntersectionsLayers: list of layers to check for intersections
:return: Success in case of success
InvalidInputGeometryType if geometry is not of polygon type
GeometryTypeHasChanged if avoid intersection has changed the geometry type
InvalidBaseGeometry at least one geometry intersected is invalid. The algorithm may not work and return the same geometry as the input. You must fix your intersecting geometries.
NothingHappened if the geometry is not intersected by one of the geometries present in the provided layers.
.. versionadded:: 3.34
%End
QgsGeometry makeValid( Qgis::MakeValidMethod method = Qgis::MakeValidMethod::Linework, bool keepCollapsed = false ) const throw( QgsNotSupportedException );

View File

@ -891,6 +891,7 @@ The development version
AddRingNotInExistingFeature,
// Split features
SplitCannotSplitPoint,
GeometryTypeHasChanged,
};
enum class GeometryValidityFlag

View File

@ -277,18 +277,18 @@ void QgsAppGpsDigitizing::createFeature()
if ( geometryLayerCrs.type() == Qgis::GeometryType::Polygon )
{
const int avoidIntersectionsReturn = geometryLayerCrs.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers() );
if ( avoidIntersectionsReturn == 1 )
const Qgis::GeometryOperationResult avoidIntersectionsReturn = geometryLayerCrs.avoidIntersectionsV2( QgsProject::instance()->avoidIntersectionsLayers() );
if ( avoidIntersectionsReturn == Qgis::GeometryOperationResult::InvalidInputGeometryType )
{
//not a polygon type. Impossible to get there
}
else if ( avoidIntersectionsReturn == 2 )
else if ( avoidIntersectionsReturn == Qgis::GeometryOperationResult::GeometryTypeHasChanged )
{
//bail out...
QgisApp::instance()->messageBar()->pushWarning( tr( "Add Feature" ), tr( "The feature could not be added because removing the polygon intersections would change the geometry type." ) );
return;
}
else if ( avoidIntersectionsReturn == 3 )
else if ( avoidIntersectionsReturn == Qgis::GeometryOperationResult::InvalidBaseGeometry )
{
QgisApp::instance()->messageBar()->pushCritical( tr( "Add Feature" ), tr( "The feature has been added, but at least one geometry intersected is invalid. These geometries must be manually repaired." ) );
return;
@ -488,4 +488,3 @@ QVariant QgsAppGpsDigitizing::timestamp( QgsVectorLayer *vlayer, int idx ) const
}
return value;
}

View File

@ -10227,7 +10227,7 @@ void QgisApp::pasteFromClipboard( QgsMapLayer *destinationLayer )
}
if ( avoidIntersectionsLayers.size() > 0 )
{
geom.avoidIntersections( avoidIntersectionsLayers );
geom.avoidIntersectionsV2( avoidIntersectionsLayers );
}
// count collapsed geometries

View File

@ -162,6 +162,7 @@ void QgsMapToolAddPart::finalizeEditCommand( QgsVectorLayer *layer, Qgis::Geomet
case Qgis::GeometryOperationResult::LayerNotEditable:
case Qgis::GeometryOperationResult::NothingHappened:
case Qgis::GeometryOperationResult::SplitCannotSplitPoint:
case Qgis::GeometryOperationResult::GeometryTypeHasChanged:
// Should not reach here
// Other OperationResults should not be returned by addPart
errorMessage = tr( "Unexpected OperationResult: %1" ).arg( qgsEnumValueToKey( errorCode ) );
@ -228,4 +229,3 @@ QgsVectorLayer *QgsMapToolAddPart::getLayerAndCheckSelection()
else
return nullptr;
}

View File

@ -100,6 +100,7 @@ void QgsMapToolAddRing::polygonCaptured( const QgsCurvePolygon *polygon )
case Qgis::GeometryOperationResult::LayerNotEditable:
case Qgis::GeometryOperationResult::AddPartSelectedGeometryNotFound:
case Qgis::GeometryOperationResult::AddPartNotMultiGeometry:
case Qgis::GeometryOperationResult::GeometryTypeHasChanged:
errorMessage = tr( "an unknown error occurred (%1)" ).arg( qgsEnumValueToKey( addRingReturnCode ) );
break;
}

View File

@ -194,11 +194,11 @@ void QgsMapToolReshape::reshape( QgsVectorLayer *vlayer )
case Qgis::AvoidIntersectionsMode::AllowIntersections:
break;
}
int res = -1;
Qgis::GeometryOperationResult res = Qgis::GeometryOperationResult::NothingHappened;
if ( avoidIntersectionsLayers.size() > 0 )
{
res = geom.avoidIntersections( QgsProject::instance()->avoidIntersectionsLayers(), ignoreFeatures );
if ( res == 1 )
res = geom.avoidIntersectionsV2( QgsProject::instance()->avoidIntersectionsLayers(), ignoreFeatures );
if ( res == Qgis::GeometryOperationResult::InvalidInputGeometryType )
{
emit messageEmitted( tr( "An error was reported during intersection removal" ), Qgis::MessageLevel::Critical );
vlayer->destroyEditCommand();
@ -213,7 +213,7 @@ void QgsMapToolReshape::reshape( QgsVectorLayer *vlayer )
vlayer->destroyEditCommand();
return;
}
if ( res == 3 )
if ( res == Qgis::GeometryOperationResult::InvalidBaseGeometry )
{
emit messageEmitted( tr( "At least one geometry intersected is invalid. These geometries must be manually repaired." ), Qgis::MessageLevel::Warning );
}

View File

@ -2425,11 +2425,11 @@ void QgsVertexTool::applyEditsToLayers( QgsVertexTool::VertexEdits &edits )
QgsGeometry featGeom = itFeatEdit.value().geom;
if ( avoidIntersectionsLayers.size() > 0 )
{
int avoidIntersectionsReturn = featGeom.avoidIntersections( avoidIntersectionsLayers, ignoreFeatures );
Qgis::GeometryOperationResult avoidIntersectionsReturn = featGeom.avoidIntersectionsV2( avoidIntersectionsLayers, ignoreFeatures );
switch ( avoidIntersectionsReturn )
{
case 2: // Geometry type was changed, let's try our best to make it compatible with the target layer
case Qgis::GeometryOperationResult::GeometryTypeHasChanged: // Geometry type was changed, let's try our best to make it compatible with the target layer
{
const QVector<QgsGeometry> newGeoms = featGeom.coerceToType( layer->wkbType() );
if ( newGeoms.count() == 1 )
@ -2476,7 +2476,7 @@ void QgsVertexTool::applyEditsToLayers( QgsVertexTool::VertexEdits &edits )
break;
}
case 3:
case Qgis::GeometryOperationResult::InvalidBaseGeometry:
emit messageEmitted( tr( "At least one geometry intersected is invalid. These geometries must be manually repaired." ), Qgis::MessageLevel::Warning );
break;
@ -2485,7 +2485,7 @@ void QgsVertexTool::applyEditsToLayers( QgsVertexTool::VertexEdits &edits )
}
// if the geometry has been changed
if ( avoidIntersectionsReturn != 1 && avoidIntersectionsReturn != 4 )
if ( avoidIntersectionsReturn != Qgis::GeometryOperationResult::InvalidInputGeometryType && avoidIntersectionsReturn != Qgis::GeometryOperationResult::NothingHappened )
{
// then add the new points generated by avoidIntersections
QgsGeometry oldGeom = layer->getGeometry( itFeatEdit.key() ).convertToType( Qgis::GeometryType::Point, true );

View File

@ -3039,11 +3039,11 @@ bool QgsGeometry::deletePart( int partNum )
return ok;
}
int QgsGeometry::avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers, const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures )
Qgis::GeometryOperationResult QgsGeometry::avoidIntersectionsV2( const QList<QgsVectorLayer *> &avoidIntersectionsLayers, const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures )
{
if ( !d->geometry )
{
return 1;
return Qgis::GeometryOperationResult::InvalidInputGeometryType;
}
Qgis::WkbType geomTypeBeforeModification = wkbType();
@ -3059,15 +3059,45 @@ int QgsGeometry::avoidIntersections( const QList<QgsVectorLayer *> &avoidInterse
}
if ( geomTypeBeforeModification != wkbType() )
return 2;
return Qgis::GeometryOperationResult::GeometryTypeHasChanged;
if ( haveInvalidGeometry )
return 3;
return Qgis::GeometryOperationResult::InvalidBaseGeometry;
if ( !geomModified )
return 4;
return Qgis::GeometryOperationResult::NothingHappened;
return 0;
return Qgis::GeometryOperationResult::Success;
}
int QgsGeometry::avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers, const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures )
{
const Qgis::GeometryOperationResult result = avoidIntersectionsV2( avoidIntersectionsLayers, ignoreFeatures );
switch ( result )
{
case Qgis::GeometryOperationResult::Success:
return 0;
case Qgis::GeometryOperationResult::InvalidInputGeometryType:
return 1;
case Qgis::GeometryOperationResult::GeometryTypeHasChanged:
return 2;
case Qgis::GeometryOperationResult::InvalidBaseGeometry:
return 3;
case Qgis::GeometryOperationResult::NothingHappened:
// these should never happen
case Qgis::GeometryOperationResult::SelectionIsEmpty:
case Qgis::GeometryOperationResult::SelectionIsGreaterThanOne:
case Qgis::GeometryOperationResult::GeometryEngineError:
case Qgis::GeometryOperationResult::LayerNotEditable:
case Qgis::GeometryOperationResult::AddPartSelectedGeometryNotFound:
case Qgis::GeometryOperationResult::AddPartNotMultiGeometry:
case Qgis::GeometryOperationResult::AddRingNotClosed:
case Qgis::GeometryOperationResult::AddRingNotValid:
case Qgis::GeometryOperationResult::AddRingCrossesExistingRings:
case Qgis::GeometryOperationResult::AddRingNotInExistingFeature:
case Qgis::GeometryOperationResult::SplitCannotSplitPoint:
return 4;
}
}
QgsGeometry QgsGeometry::makeValid( Qgis::MakeValidMethod method, bool keepCollapsed ) const
{

View File

@ -2550,9 +2550,24 @@ class CORE_EXPORT QgsGeometry
* 3 at least one geometry intersected is invalid. The algorithm may not work and return the same geometry as the input. You must fix your intersecting geometries.
* 4 if the geometry is not intersected by one of the geometries present in the provided layers.
* \since QGIS 1.5
* \deprecated QGIS 3.34
*/
int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures SIP_PYARGREMOVE = ( QHash<QgsVectorLayer *, QSet<QgsFeatureId> >() ) );
Q_DECL_DEPRECATED int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures SIP_PYARGREMOVE = ( QHash<QgsVectorLayer *, QSet<QgsFeatureId> >() ) ) SIP_DEPRECATED;
/**
* Modifies geometry to avoid intersections with the layers specified in project properties
* \param avoidIntersectionsLayers list of layers to check for intersections
* \param ignoreFeatures possibility to give a list of features where intersections should be ignored (not available in Python bindings)
* \returns Success in case of success
* InvalidInputGeometryType if geometry is not of polygon type
* GeometryTypeHasChanged if avoid intersection has changed the geometry type
* InvalidBaseGeometry at least one geometry intersected is invalid. The algorithm may not work and return the same geometry as the input. You must fix your intersecting geometries.
* NothingHappened if the geometry is not intersected by one of the geometries present in the provided layers.
* \since QGIS 3.34
*/
Qgis::GeometryOperationResult avoidIntersectionsV2( const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures SIP_PYARGREMOVE = ( QHash<QgsVectorLayer *, QSet<QgsFeatureId> >() ) );
/**
* Attempts to make an invalid geometry valid without losing vertices.

View File

@ -1483,6 +1483,7 @@ class CORE_EXPORT Qgis
AddRingNotInExistingFeature, //!< The input ring doesn't have any existing ring to fit into
// Split features
SplitCannotSplitPoint, //!< Cannot split points
GeometryTypeHasChanged, //!< Operation has changed geometry type
};
Q_ENUM( GeometryOperationResult )

View File

@ -58,8 +58,8 @@ void QgsMapToolCaptureLayerGeometry::geometryCaptured( const QgsGeometry &geomet
}
if ( avoidIntersectionsLayers.size() > 0 )
{
const int avoidIntersectionsReturn = g.avoidIntersections( avoidIntersectionsLayers );
if ( avoidIntersectionsReturn == 3 )
const Qgis::GeometryOperationResult avoidIntersectionsReturn = g.avoidIntersectionsV2( avoidIntersectionsLayers );
if ( avoidIntersectionsReturn == Qgis::GeometryOperationResult::InvalidBaseGeometry )
{
emit messageEmitted( tr( "The feature has been added, but at least one geometry intersected is invalid. These geometries must be manually repaired." ), Qgis::MessageLevel::Warning );
}