Skip to content

Commit

Permalink
Min inscribed circle radius (unfinished)
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso authored and nyalldawson committed Nov 29, 2021
1 parent c6577db commit 114fc7c
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
39 changes: 34 additions & 5 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgsexpressionnodeimpl.h"
#include "qgsexiftools.h"
#include "qgsfeaturerequest.h"
#include "qgsgeos.h"
#include "qgsstringutils.h"
#include "qgsmultipoint.h"
#include "qgsgeometryutils.h"
Expand Down Expand Up @@ -6612,15 +6613,22 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
bool cacheEnabled = cacheValue.toBool();

// Sixth parameter (for intersects only) is the min area
// Seventh parameter (for intersects only) is the min inscribed circle radius
double minArea { -1 };
double minInscribedCircleRadius { -1 };
if ( isIntersectsFunc )
{
// Fourth parameter is the limit

node = QgsExpressionUtils::getNode( values.at( 5 ), parent ); //in expressions overlay functions throw the exception: Eval Error: Cannot convert '' to int
ENSURE_NO_EVAL_ERROR
const QVariant minAreaValue = node->eval( parent, context );
ENSURE_NO_EVAL_ERROR
minArea = QgsExpressionUtils::getDoubleValue( minAreaValue, parent );
node = QgsExpressionUtils::getNode( values.at( 6 ), parent ); //in expressions overlay functions throw the exception: Eval Error: Cannot convert '' to int
ENSURE_NO_EVAL_ERROR
const QVariant minInscribedCircleRadiusValue = node->eval( parent, context );
ENSURE_NO_EVAL_ERROR
minInscribedCircleRadius = QgsExpressionUtils::getDoubleValue( minInscribedCircleRadiusValue, parent );
}


Expand Down Expand Up @@ -6745,10 +6753,30 @@ static QVariant executeGeomOverlay( const QVariantList &values, const QgsExpress
if ( ! relationFunction || ( geometry.*relationFunction )( feat2.geometry() ) ) // Calls the method provided as template argument for the function (e.g. QgsGeometry::intersects)
{

// Check min area for intersection (if set)
if ( isIntersectsFunc && minArea != -1 && geometry.intersection( feat2.geometry() ).area() <= minArea )
if ( isIntersectsFunc && ( minArea != -1 || minInscribedCircleRadius != -1 ) )
{
continue;
const QgsGeometry intersection { geometry.intersection( feat2.geometry() ) };
// Check min area for intersection (if set)
// qDebug() << feat2.id() << intersection.area();
if ( minArea != -1 && intersection.area() <= minArea )
{
continue;
}

// Check min inscribed circle radius for intersection (if set)
if ( minInscribedCircleRadius != -1 )
{
const QgsAbstractGeometry *geom { intersection.constGet() };
const QgsRectangle bbox = geom->boundingBox();
const double width = bbox.width();
const double height = bbox.height();
const double size = width > height ? width : height;
const double tolerance = size / 1000.0;
if ( QgsGeos( geom ).maximumInscribedCircle( tolerance )->length() / 2 < minInscribedCircleRadius )
{
continue;
}
}
}

found = true;
Expand Down Expand Up @@ -7250,7 +7278,8 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< QgsExpressionFunction::Parameter( QStringLiteral( "filter" ), true, QVariant(), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "limit" ), true, QVariant( -1 ), true )
<< QgsExpressionFunction::Parameter( QStringLiteral( "cache" ), true, QVariant( false ), false )
<< QgsExpressionFunction::Parameter( QStringLiteral( "min_intersection_area" ), true, QVariant( -1 ), false ),
<< QgsExpressionFunction::Parameter( QStringLiteral( "min_area" ), true, QVariant( -1 ), false )
<< QgsExpressionFunction::Parameter( QStringLiteral( "min_inscribed_circle_radius" ), true, QVariant( -1 ), false ),
i.value(), QStringLiteral( "GeometryGroup" ), QString(), true, QSet<QString>() << QgsFeatureRequest::ALL_ATTRIBUTES, true );

// The current feature is accessed for the geometry, so this should not be cached
Expand Down
12 changes: 10 additions & 2 deletions tests/src/core/testqgsoverlayexpression.cpp
Expand Up @@ -43,6 +43,8 @@ class TestQgsOverlayExpression: public QObject
public:

TestQgsOverlayExpression() = default;
void testOverlayExpression();
void testOverlayExpression_data();

private:
QgsVectorLayer *mRectanglesLayer = nullptr;
Expand All @@ -57,8 +59,6 @@ class TestQgsOverlayExpression: public QObject
void testOverlay();
void testOverlay_data();

void testOverlayExpression();
void testOverlayExpression_data();

void testOverlaySelf();
};
Expand Down Expand Up @@ -116,6 +116,7 @@ void TestQgsOverlayExpression::testOverlay_data()
QTest::addColumn<QString>( "geometry" );
QTest::addColumn<bool>( "expectedResult" );

/*
QTest::newRow( "intersects" ) << "overlay_intersects('rectangles')" << "POLYGON((-120 30, -105 30, -105 20, -120 20, -120 30))" << true;
QTest::newRow( "intersects [cached]" ) << "overlay_intersects('rectangles',cache:=true)" << "POLYGON((-120 30, -105 30, -105 20, -120 20, -120 30))" << true;
Expand Down Expand Up @@ -154,6 +155,13 @@ void TestQgsOverlayExpression::testOverlay_data()
QTest::newRow( "disjoint no match" ) << "overlay_disjoint('rectangles')" << "LINESTRING(-155 15, -122 32, -84 4)" << false;
QTest::newRow( "disjoint no match [cached]" ) << "overlay_disjoint('rectangles',cache:=true)" << "LINESTRING(-155 15, -122 32, -84 4)" << false;
*/

QTest::newRow( "intersects min_area no match" ) << "overlay_intersects('polys', min_area:=1.3)" << "POLYGON((-107.37 33.75, -102.76 33.75, -102.76 36.97, -107.37 36.97, -107.37 33.75))" << false;
QTest::newRow( "intersects min_area match" ) << "overlay_intersects('polys', min_area:=1.28)" << "POLYGON((-107.37 33.75, -102.76 33.75, -102.76 36.97, -107.37 36.97, -107.37 33.75))" << true;

QTest::newRow( "intersects min_inscribed_circle_radius no match" ) << "overlay_intersects('polys', min_inscribed_circle_radius:=1.0)" << "POLYGON((-107.37 33.75, -102.76 33.75, -102.76 36.97, -107.37 36.97, -107.37 33.75))" << false;
QTest::newRow( "intersects min_inscribed_circle_radius match" ) << "overlay_intersects('polys', min_area:=0.457)" << "POLYGON((-107.37 33.75, -102.76 33.75, -102.76 36.97, -107.37 36.97, -107.37 33.75))" << true;
}

void TestQgsOverlayExpression::testOverlayExpression()
Expand Down

0 comments on commit 114fc7c

Please sign in to comment.