mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-07 00:15:48 -04:00
Add affine transform expression (#44771)
This commit is contained in:
parent
2c24e8841c
commit
9e38e43876
23
resources/function_help/json/affine_transform
Normal file
23
resources/function_help/json/affine_transform
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "affine_transform",
|
||||
"type": "function",
|
||||
"groups": ["GeometryGroup"],
|
||||
"description": "Returns the geometry after an affine transformation. Calculations are in the Spatial Reference System of this geometry. The operations are performed in a scale, rotation, translation order. If there is a Z or M offset but the coordinate is not present in the geometry, it will be added.",
|
||||
"arguments": [
|
||||
{"arg":"geometry","description":"a geometry"},
|
||||
{"arg":"deltaX","description":"x-axis translation"},
|
||||
{"arg":"deltaY","description":"y-axis translation"},
|
||||
{"arg":"rotationZ","description":"rotation around z-axis in degrees counter-clockwise"},
|
||||
{"arg":"scaleX","description":"x-axis scale factor"},
|
||||
{"arg":"scaleY","description":"y-axis scale factor"},
|
||||
{"arg":"deltaZ","optional":true,"default":"0","description":"z-axis translation"},
|
||||
{"arg":"deltaM","optional":true,"default":"0","description":"m-axis translation"},
|
||||
{"arg":"scaleZ","optional":true,"default":"1","description":"z-axis scale factor"},
|
||||
{"arg":"scaleM","optional":true,"default":"1","description":"m-axis scale factor"}
|
||||
],
|
||||
"examples": [
|
||||
{ "expression":"geom_to_wkt(affine_transform(geom_from_wkt('LINESTRING(1 1, 2 2)'), 2, 2, 0, 1, 1))", "returns":"'LineString (3 3, 4 4)'"},
|
||||
{ "expression":"geom_to_wkt(affine_transform(geom_from_wkt('POLYGON((0 0, 0 3, 2 2, 0 0))'), 0, 0, -90, 1, 2))", "returns":"'Polygon ((0 0, 6 0, 4 -2, 0 0))'"},
|
||||
{ "expression":"geom_to_wkt(affine_transform(geom_from_wkt('POINT(3 1)'), 0, 0, 0, 1, 1, 5, 0))", "returns":"'PointZ (3 1 5)'"}
|
||||
]
|
||||
}
|
@ -4006,6 +4006,46 @@ static QVariant fcnRotate( const QVariantList &values, const QgsExpressionContex
|
||||
return QVariant::fromValue( fGeom );
|
||||
}
|
||||
|
||||
static QVariant fcnAffineTransform( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
if ( fGeom.isNull() )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
const double deltaX = QgsExpressionUtils::getDoubleValue( values.at( 1 ), parent );
|
||||
const double deltaY = QgsExpressionUtils::getDoubleValue( values.at( 2 ), parent );
|
||||
|
||||
const double rotationZ = QgsExpressionUtils::getDoubleValue( values.at( 3 ), parent );
|
||||
|
||||
const double scaleX = QgsExpressionUtils::getDoubleValue( values.at( 4 ), parent );
|
||||
const double scaleY = QgsExpressionUtils::getDoubleValue( values.at( 5 ), parent );
|
||||
|
||||
const double deltaZ = QgsExpressionUtils::getDoubleValue( values.at( 6 ), parent );
|
||||
const double deltaM = QgsExpressionUtils::getDoubleValue( values.at( 7 ), parent );
|
||||
const double scaleZ = QgsExpressionUtils::getDoubleValue( values.at( 8 ), parent );
|
||||
const double scaleM = QgsExpressionUtils::getDoubleValue( values.at( 9 ), parent );
|
||||
|
||||
if ( deltaZ != 0.0 && !fGeom.constGet()->is3D() )
|
||||
{
|
||||
fGeom.get()->addZValue( 0 );
|
||||
}
|
||||
if ( deltaM != 0.0 && !fGeom.constGet()->isMeasure() )
|
||||
{
|
||||
fGeom.get()->addMValue( 0 );
|
||||
}
|
||||
|
||||
QTransform transform;
|
||||
transform.translate( deltaX, deltaY );
|
||||
transform.rotate( rotationZ );
|
||||
transform.scale( scaleX, scaleY );
|
||||
fGeom.transform( transform, deltaZ, scaleZ, deltaM, scaleM );
|
||||
|
||||
return QVariant::fromValue( fGeom );
|
||||
}
|
||||
|
||||
|
||||
static QVariant fcnCentroid( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
|
||||
{
|
||||
QgsGeometry fGeom = QgsExpressionUtils::getGeometry( values.at( 0 ), parent );
|
||||
@ -6972,6 +7012,17 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "rotation" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "center" ), true ),
|
||||
fcnRotate, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "affine_transform" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "deltaX" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "deltaY" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "rotationZ" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "scaleX" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "scaleY" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "deltaZ" ), true, 0 )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "deltaM" ), true, 0 )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "scaleZ" ), true, 1 )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "scaleM" ), true, 1 ),
|
||||
fcnAffineTransform, QStringLiteral( "GeometryGroup" ) )
|
||||
<< new QgsStaticExpressionFunction( QStringLiteral( "buffer" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "geometry" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "distance" ) )
|
||||
<< QgsExpressionFunction::Parameter( QStringLiteral( "segments" ), true, 8 ),
|
||||
|
@ -1305,6 +1305,13 @@ 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( "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)" );
|
||||
QTest::newRow( "affine_transform point with negative scale" ) << "geom_to_wkt(affine_transform(geom_from_wkt('POINT(1 1)'), 0, 0, 90, -2, -2))" << false << QVariant( "Point (2 -2)" );
|
||||
QTest::newRow( "affine_transform line XY" ) << "geom_to_wkt(affine_transform(geom_from_wkt('LINESTRING(1 0, 2 0)'), 0, 0, 90, 2, 1))" << false << QVariant( "LineString (0 2, 0 4)" );
|
||||
QTest::newRow( "affine_transform polygon XYZ" ) << "geom_to_wkt(affine_transform(geom_from_wkt('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'), 0, 0, -90, 0.5, 0.5))" << false << QVariant( "Polygon ((0 0, 0.5 0, 0.5 -0.5, 0 -0.5, 0 0))" );
|
||||
QTest::newRow( "affine_transform point XY with translation on ZM" ) << "geom_to_wkt(affine_transform(geom_from_wkt('POINT(1 1)'), 0, 0, 0, 1, 1, 3, 4))" << false << QVariant( "PointZM (1 1 3 4)" );
|
||||
QTest::newRow( "is_multipart true" ) << "is_multipart(geom_from_wkt('MULTIPOINT ((0 0),(1 1),(2 2))'))" << false << QVariant( true );
|
||||
QTest::newRow( "is_multipart false" ) << "is_multipart(geom_from_wkt('POINT (0 0)'))" << false << QVariant( false );
|
||||
QTest::newRow( "is_multipart false empty geometry" ) << "is_multipart(geom_from_wkt('POINT EMPTY'))" << false << QVariant( false );
|
||||
|
Loading…
x
Reference in New Issue
Block a user