mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-17 00:09:36 -04:00
[feature][expressions] Add new "scale" function for scaling a geometry
Just like the 'rotate' function, 'scale' accepts an optional point to apply the scaling from. If not specified, scaling is done from the centre of the geometry's bounding box.
This commit is contained in:
parent
7c03c9ec4a
commit
deba02b162
13
resources/function_help/json/scale
Normal file
13
resources/function_help/json/scale
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "scale",
|
||||
"type": "function",
|
||||
"groups": ["GeometryGroup"],
|
||||
"description": "Returns a scaled version of a geometry. Calculations are in the Spatial Reference System of this geometry.",
|
||||
"arguments": [ {"arg":"geometry","description":"a geometry"},
|
||||
{"arg":"x_scale","description":"x-axis scaling factor"},
|
||||
{"arg":"y_scale","description":"y-axis scaling factor"},
|
||||
{"arg":"center", "optional":true,"description":"scaling center point. If not specified, the center of the geometry's bounding box is used."}
|
||||
],
|
||||
"examples": [ { "expression":"scale($geometry, 2, 0.5, make_point(4, 5))", "returns":"geometry scaled twice horizontally and halved vertically, around the (4, 5) point"},
|
||||
{ "expression":"scale($geometry, 2, 0.5)", "returns":"geometry twice horizontally and halved vertically, around the center of its bounding box"}]
|
||||
}
|
@ -4134,6 +4134,37 @@ static QVariant fcnRotate( const QVariantList &values, const QgsExpressionContex
|
||||
return QVariant::fromValue( fGeom );
|
||||
}
|
||||
|
||||
static QVariant fcnScale( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
const double xScale = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
|
||||
const double yScale = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
|
||||
const QgsGeometry center = values.at( 3 ).isValid() ? QgsExpressionUtils::getGeometry( values.at( 3 ), parent )
|
||||
: QgsGeometry();
|
||||
|
||||
QgsPointXY pt;
|
||||
if ( center.isNull() )
|
||||
{
|
||||
// if center wasn't specified, use bounding box centroid
|
||||
pt = fGeom.boundingBox().center();
|
||||
}
|
||||
else if ( QgsWkbTypes::flatType( center.constGet()->simplifiedTypeRef()->wkbType() ) != QgsWkbTypes::Point )
|
||||
{
|
||||
parent->setEvalErrorString( QObject::tr( "Function 'scale' requires a point value for the center" ) );
|
||||
return QVariant();
|
||||
}
|
||||
else
|
||||
{
|
||||
pt = center.asPoint();
|
||||
}
|
||||
|
||||
QTransform t = QTransform::fromTranslate( pt.x(), pt.y() );
|
||||
t.scale( xScale, yScale );
|
||||
t.translate( -pt.x(), -pt.y() );
|
||||
fGeom.transform( t );
|
||||
return QVariant::fromValue( fGeom );
|
||||
}
|
||||
|
||||
static QVariant fcnAffineTransform( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
@ -7140,6 +7171,11 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "rotation" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "center" ), true ),
|
||||
fcnRotate, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "scale" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "x_scale" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "y_scale" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "center" ), true ),
|
||||
fcnScale, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "affine_transform" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "delta_x" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "delta_y" ) )
|
||||
|
@ -1322,6 +1322,16 @@ class TestQgsExpression: public QObject
|
||||
QTest::newRow( "rotate line fixed multi point" ) << "geom_to_wkt(rotate(geom_from_wkt('LineString(0 0, 10 0, 10 10)'),90, geom_from_wkt('MULTIPOINT((-5 -3))')))" << false << QVariant( "LineString (-2 -8, -2 -18, 8 -18)" );
|
||||
QTest::newRow( "rotate line fixed multi point multiple" ) << "geom_to_wkt(rotate(geom_from_wkt('LineString(0 0, 10 0, 10 10)'),90, geom_from_wkt('MULTIPOINT(-5 -3,1 2)')))" << true << QVariant();
|
||||
QTest::newRow( "rotate polygon centroid" ) << "geom_to_wkt(rotate(geom_from_wkt('Polygon((0 0, 10 0, 10 10, 0 0))'),-90))" << false << QVariant( "Polygon ((10 0, 10 10, 0 10, 10 0))" );
|
||||
QTest::newRow( "scale not geom" ) << "scale('g', 1.2, 0.8)" << true << QVariant();
|
||||
QTest::newRow( "scale null" ) << "scale(NULL, 1.2, 0.8)" << false << QVariant();
|
||||
QTest::newRow( "scale point" ) << "geom_to_wkt(scale(geom_from_wkt('POINT( 20 10)'), 1.2, 0.8, geom_from_wkt('POINT( 30 15)')))" << false << QVariant( "Point (18 11)" );
|
||||
QTest::newRow( "scale line centroid" ) << "geom_to_wkt(scale(geom_from_wkt('LineString(0 0, 10 0, 10 10)'),1.2, 0.8))" << false << QVariant( "LineString (-1 1, 11 1, 11 9)" );
|
||||
QTest::newRow( "scale line fixed point" ) << "geom_to_wkt(scale(geom_from_wkt('LineString(0 0, 10 0, 10 10)'),1.2, 0.8, make_point(5, 2)))" << false << QVariant( "LineString (-1 0.4, 11 0.4, 11 8.4)" );
|
||||
QTest::newRow( "scale line fixed point not geom" ) << "geom_to_wkt(scale(geom_from_wkt('LineString(0 0, 10 0, 10 10)'),1.2, 0.8, 'a'))" << true << QVariant();
|
||||
QTest::newRow( "scale line fixed point not point" ) << "geom_to_wkt(scale(geom_from_wkt('LineString(0 0, 10 0, 10 10)'),1.2, 0.8, geom_from_wkt('LineString(0 0, 10 0, 10 10)')))" << true << QVariant();
|
||||
QTest::newRow( "scale line fixed multi point" ) << "geom_to_wkt(scale(geom_from_wkt('LineString(0 0, 10 0, 10 10)'),1.2, 0.8, geom_from_wkt('MULTIPOINT((-5 -3))')))" << false << QVariant( "LineString (1 -0.6, 13 -0.6, 13 7.4)" );
|
||||
QTest::newRow( "scale line fixed multi point multiple" ) << "geom_to_wkt(scale(geom_from_wkt('LineString(0 0, 10 0, 10 10)'),1.2, 0.8, geom_from_wkt('MULTIPOINT(-5 -3,1 2)')))" << true << QVariant();
|
||||
QTest::newRow( "scale polygon centroid" ) << "geom_to_wkt(scale(geom_from_wkt('Polygon((0 0, 10 0, 10 10, 0 0))'), 1.2, 0.8))" << false << QVariant( "Polygon ((-1 1, 11 1, 11 9, -1 1))" );
|
||||
QTest::newRow( "affine_transform not geom" ) << "affine_transform('g', 0, 0, 0, 0, 0, 0)" << true << QVariant();
|
||||
QTest::newRow( "affine_transform null" ) << "affine_transform(NULL, 0, 0, 0, 0, 0, 0)" << false << QVariant();
|
||||
QTest::newRow( "affine_transform point XYZM" ) << "geom_to_wkt(affine_transform(geom_from_wkt('POINT(2 2 2 2)'), 2, 2, 180, 0, 1, 1, 1, 2, 2))" << false << QVariant( "PointZM (2 0 5 5)" );
|
||||
|
Loading…
x
Reference in New Issue
Block a user