mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Add extrude function to QgsGeometry
This commit is contained in:
parent
e290c985f7
commit
542541007c
@ -433,9 +433,12 @@ class QgsGeometry
|
||||
/** Returns a geometry representing the points making up this geometry that do not make up other. */
|
||||
QgsGeometry* difference( const QgsGeometry* geometry ) const /Factory/;
|
||||
|
||||
/** Returns a Geometry representing the points making up this Geometry that do not make up other. */
|
||||
/** Returns a Geometry representing the points making up this geometry that do not make up other. */
|
||||
QgsGeometry* symDifference( const QgsGeometry* geometry ) const /Factory/;
|
||||
|
||||
/** Returns an extruded version of this geometry. */
|
||||
QgsGeometry extrude( double x, double y );
|
||||
|
||||
/** Exports the geometry to WKT
|
||||
* @note precision parameter added in 2.4
|
||||
* @return true in case of success and false else
|
||||
|
20
resources/function_help/json/extrude
Normal file
20
resources/function_help/json/extrude
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "extrude",
|
||||
"type": "function",
|
||||
"description": "Returns an extruded version of the input (Multi-)Curve or (Multi-)Linestring geometry with an extension specified by x and y.",
|
||||
"arguments": [
|
||||
{"arg":"geom","description":"a polygon geometry"},
|
||||
{"arg":"x","description":"x extension, numeric value"},
|
||||
{"arg":"y","description":"y extension, numeric value"}
|
||||
],
|
||||
"examples": [
|
||||
{
|
||||
"expression":"extrude(geom_from_wkt('LineString(1 2, 3 2, 4 3)'), 1, 2)",
|
||||
"returns":"Polygon ((1 2, 3 2, 4 3, 5 5, 4 4, 2 4, 1 2))"
|
||||
},
|
||||
{
|
||||
"expression":"extrude(geom_from_wkt('MultiLineString((1 2, 3 2), (4 3, 8 3)'), 1, 2)",
|
||||
"returns":"MultiPolygon (((1 2, 3 2, 4 4, 2 4, 1 2)),((4 3, 8 3, 9 5, 5 5, 4 3)))"
|
||||
}
|
||||
]
|
||||
}
|
@ -320,6 +320,7 @@ SET(QGIS_CORE_SRCS
|
||||
geometry/qgsgeometry.cpp
|
||||
geometry/qgsgeometrycollectionv2.cpp
|
||||
geometry/qgsgeometryeditutils.cpp
|
||||
geometry/qgsinternalgeometryengine.cpp
|
||||
geometry/qgsgeometryfactory.cpp
|
||||
geometry/qgsgeometryutils.cpp
|
||||
geometry/qgsgeos.cpp
|
||||
@ -788,6 +789,7 @@ SET(QGIS_CORE_HDRS
|
||||
layertree/qgslayertreeutils.h
|
||||
|
||||
geometry/qgsgeometry.h
|
||||
geometry/qgsinternalgeometryengine.h
|
||||
geometry/qgsabstractgeometryv2.h
|
||||
geometry/qgswkbtypes.h
|
||||
geometry/qgspointv2.h
|
||||
|
@ -23,6 +23,7 @@ email : morb at ozemail dot com dot au
|
||||
#include "qgsgeometryeditutils.h"
|
||||
#include "qgsgeometryfactory.h"
|
||||
#include "qgsgeometryutils.h"
|
||||
#include "qgsinternalgeometryengine.h"
|
||||
#include "qgsgeos.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgslogger.h"
|
||||
@ -1404,6 +1405,13 @@ QgsGeometry* QgsGeometry::symDifference( const QgsGeometry* geometry ) const
|
||||
return new QgsGeometry( resultGeom );
|
||||
}
|
||||
|
||||
QgsGeometry QgsGeometry::extrude( double x, double y )
|
||||
{
|
||||
QgsInternalGeometryEngine engine( *this );
|
||||
|
||||
return engine.extrude( x, y );
|
||||
}
|
||||
|
||||
QList<QgsGeometry*> QgsGeometry::asGeometryCollection() const
|
||||
{
|
||||
QList<QgsGeometry*> geometryList;
|
||||
|
@ -480,9 +480,12 @@ class CORE_EXPORT QgsGeometry
|
||||
/** Returns a geometry representing the points making up this geometry that do not make up other. */
|
||||
QgsGeometry* difference( const QgsGeometry* geometry ) const;
|
||||
|
||||
/** Returns a Geometry representing the points making up this Geometry that do not make up other. */
|
||||
/** Returns a geometry representing the points making up this geometry that do not make up other. */
|
||||
QgsGeometry* symDifference( const QgsGeometry* geometry ) const;
|
||||
|
||||
/** Returns an extruded version of this geometry. */
|
||||
QgsGeometry extrude( double x, double y );
|
||||
|
||||
/** Exports the geometry to WKT
|
||||
* @note precision parameter added in 2.4
|
||||
* @return true in case of success and false else
|
||||
|
@ -13,8 +13,8 @@ email : marco.hugentobler at sourcepole dot com
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSVECTORTOPOLOGY_H
|
||||
#define QGSVECTORTOPOLOGY_H
|
||||
#ifndef QGSGEOMETRYENGINE_H
|
||||
#define QGSGEOMETRYENGINE_H
|
||||
|
||||
#include "qgspointv2.h"
|
||||
#include "qgslinestringv2.h"
|
||||
@ -106,4 +106,4 @@ class CORE_EXPORT QgsGeometryEngine
|
||||
QgsGeometryEngine();
|
||||
};
|
||||
|
||||
#endif // QGSVECTORTOPOLOGY_H
|
||||
#endif // QGSGEOMETRYENGINE_H
|
||||
|
88
src/core/geometry/qgsinternalgeometryengine.cpp
Normal file
88
src/core/geometry/qgsinternalgeometryengine.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/***************************************************************************
|
||||
qgsinternalgeometryengine.cpp - QgsInternalGeometryEngine
|
||||
|
||||
---------------------
|
||||
begin : 13.1.2016
|
||||
copyright : (C) 2016 by Matthias Kuhn
|
||||
email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsinternalgeometryengine.h"
|
||||
|
||||
#include "qgslinestringv2.h"
|
||||
#include "qgsmultipolygonv2.h"
|
||||
#include "qgspolygonv2.h"
|
||||
#include "qgsmulticurvev2.h"
|
||||
|
||||
#include <QTransform>
|
||||
|
||||
QgsInternalGeometryEngine::QgsInternalGeometryEngine( const QgsGeometry& geometry )
|
||||
: mGeometry( geometry.geometry() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* This class is considered CRITICAL and any change MUST be accompanied with
|
||||
* full unit tests.
|
||||
* See details in QEP #17
|
||||
****************************************************************************/
|
||||
|
||||
QgsGeometry QgsInternalGeometryEngine::extrude( double x, double y )
|
||||
{
|
||||
QList<QgsLineStringV2*> linesToProcess;
|
||||
|
||||
const QgsMultiCurveV2* multiCurve = dynamic_cast< const QgsMultiCurveV2* >( mGeometry );
|
||||
if ( multiCurve )
|
||||
{
|
||||
for ( int i = 0; i < multiCurve->partCount(); ++i )
|
||||
{
|
||||
linesToProcess << static_cast<QgsLineStringV2*>( multiCurve->geometryN( i )->clone() );
|
||||
}
|
||||
}
|
||||
|
||||
const QgsCurveV2* curve = dynamic_cast< const QgsCurveV2* >( mGeometry );
|
||||
if ( curve )
|
||||
{
|
||||
linesToProcess << static_cast<QgsLineStringV2*>( curve->segmentize() );
|
||||
}
|
||||
|
||||
QgsMultiPolygonV2* multipolygon = linesToProcess.size() > 1 ? new QgsMultiPolygonV2() : nullptr;
|
||||
QgsPolygonV2* polygon;
|
||||
|
||||
if ( !linesToProcess.empty() )
|
||||
{
|
||||
Q_FOREACH ( QgsLineStringV2* line, linesToProcess )
|
||||
{
|
||||
QTransform transform = QTransform::fromTranslate( x, y );
|
||||
|
||||
QgsLineStringV2* secondline = line->reversed();
|
||||
secondline->transform( transform );
|
||||
|
||||
line->append( secondline );
|
||||
line->addVertex( line->pointN( 0 ) );
|
||||
|
||||
polygon = new QgsPolygonV2();
|
||||
polygon->setExteriorRing( line );
|
||||
|
||||
if ( multipolygon )
|
||||
multipolygon->addGeometry( polygon );
|
||||
|
||||
delete secondline;
|
||||
}
|
||||
|
||||
if ( multipolygon )
|
||||
return QgsGeometry( multipolygon );
|
||||
else
|
||||
return QgsGeometry( polygon );
|
||||
}
|
||||
|
||||
return QgsGeometry();
|
||||
}
|
54
src/core/geometry/qgsinternalgeometryengine.h
Normal file
54
src/core/geometry/qgsinternalgeometryengine.h
Normal file
@ -0,0 +1,54 @@
|
||||
/***************************************************************************
|
||||
qgsinternalgeometryengine.h - QgsInternalGeometryEngine
|
||||
|
||||
---------------------
|
||||
begin : 13.1.2016
|
||||
copyright : (C) 2016 by Matthias Kuhn
|
||||
email : matthias@opengis.ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
#ifndef QGSINTERNALGEOMETRYENGINE_H
|
||||
#define QGSINTERNALGEOMETRYENGINE_H
|
||||
|
||||
#include "qgsgeometry.h"
|
||||
|
||||
/**
|
||||
* This class offers geometry processing methods.
|
||||
*
|
||||
* The methods are available via QgsGeometry::[geometryfunction]
|
||||
* and therefore this does not need to be accessed directly.
|
||||
*
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
|
||||
class QgsInternalGeometryEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The caller is responsible that the geometry is available and unchanged
|
||||
* for the whole lifetime of this object.
|
||||
* @param geometry
|
||||
*/
|
||||
QgsInternalGeometryEngine( const QgsGeometry& geometry );
|
||||
|
||||
/**
|
||||
* Will extrude a line or (segmentized) curve by a given offset and return a polygon
|
||||
* representation of it.
|
||||
*
|
||||
* @param x offset in x direction
|
||||
* @param y offset in y direction
|
||||
* @return an extruded polygon
|
||||
*/
|
||||
QgsGeometry extrude( double x, double y );
|
||||
|
||||
private:
|
||||
const QgsAbstractGeometryV2* mGeometry;
|
||||
};
|
||||
|
||||
#endif // QGSINTERNALGEOMETRYENGINE_H
|
@ -2153,6 +2153,21 @@ static QVariant fcnAzimuth( const QVariantList& values, const QgsExpressionConte
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
static QVariant fcnExtrude( const QVariantList& values, const QgsExpressionContext*, QgsExpression* parent )
|
||||
{
|
||||
if ( values.length() != 3 )
|
||||
return QVariant();
|
||||
|
||||
QgsGeometry fGeom = getGeometry( values.at( 0 ), parent );
|
||||
double x = getDoubleValue( values.at( 1 ), parent );
|
||||
double y = getDoubleValue( values.at( 2 ), parent );
|
||||
|
||||
QgsGeometry geom = fGeom.extrude( x, y );
|
||||
|
||||
QVariant result = geom.geometry() ? QVariant::fromValue( geom ) : QVariant();
|
||||
return result;
|
||||
}
|
||||
|
||||
static QVariant fcnRound( const QVariantList& values, const QgsExpressionContext *, QgsExpression* parent )
|
||||
{
|
||||
if ( values.length() == 2 )
|
||||
@ -2915,6 +2930,7 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
|
||||
<< new StaticFunction( "geom_to_wkt", -1, fcnGeomToWKT, "GeometryGroup", QString(), false, QStringList(), false, QStringList() << "geomToWKT" )
|
||||
<< new StaticFunction( "geometry", 1, fcnGetGeometry, "GeometryGroup", QString(), true )
|
||||
<< new StaticFunction( "transform", 3, fcnTransformGeometry, "GeometryGroup" )
|
||||
<< new StaticFunction( "extrude", 3, fcnExtrude, "GeometryGroup", QString() )
|
||||
<< new StaticFunction( "$rownum", 0, fcnRowNumber, "deprecated" )
|
||||
<< new StaticFunction( "$id", 0, fcnFeatureId, "Record" )
|
||||
<< new StaticFunction( "$currentfeature", 0, fcnFeature, "Record" )
|
||||
|
@ -280,7 +280,7 @@ class CORE_EXPORT QgsExpression
|
||||
QgsDistanceArea* geomCalculator();
|
||||
|
||||
//! Sets the geometry calculator used in evaluation of expressions,
|
||||
// instead of the default.
|
||||
//! instead of the default.
|
||||
void setGeomCalculator( const QgsDistanceArea &calc );
|
||||
|
||||
/** This function currently replaces each expression between [% and %]
|
||||
|
@ -345,7 +345,7 @@ class TestQgsGeometry(TestCase):
|
||||
'simplify_error.wkt'), 'rt')
|
||||
myWKT = myWKTFile.readline()
|
||||
myWKTFile.close()
|
||||
print myWKT
|
||||
# print myWKT
|
||||
myGeometry = QgsGeometry().fromWkt(myWKT)
|
||||
assert myGeometry is not None
|
||||
myStartLength = len(myWKT)
|
||||
@ -1191,6 +1191,17 @@ class TestQgsGeometry(TestCase):
|
||||
expwkt = "MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)),((4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0)))"
|
||||
wkt = polygon.exportToWkt()
|
||||
|
||||
def testExtrude(self):
|
||||
points = [QgsPoint(1, 2), QgsPoint(3, 2), QgsPoint(4, 3)]
|
||||
line = QgsGeometry.fromPolyline(points)
|
||||
expected = QgsGeometry.fromWkt('Polygon ((1 2, 3 2, 4 3, 5 5, 4 4, 2 4, 1 2))')
|
||||
self.assertEqual(line.extrude(1, 2).exportToWkt(), expected.exportToWkt())
|
||||
|
||||
points2 = [[QgsPoint(1, 2), QgsPoint(3, 2)], [QgsPoint(4, 3), QgsPoint(8, 3)]]
|
||||
multiline = QgsGeometry.fromMultiPolyline(points2)
|
||||
expected = QgsGeometry.fromWkt('MultiPolygon (((1 2, 3 2, 4 4, 2 4, 1 2)),((4 3, 8 3, 9 5, 5 5, 4 3)))')
|
||||
self.assertEqual(multiline.extrude(1, 2).exportToWkt(), expected.exportToWkt())
|
||||
|
||||
def testBoundingBox(self):
|
||||
# 2-+-+-+-+-3
|
||||
# | |
|
||||
|
Loading…
x
Reference in New Issue
Block a user