mirror of
https://github.com/qgis/QGIS.git
synced 2025-11-22 00:14:55 -05:00
Add rotate and transform(QTransform) methods to QgsGeometry
Reimplement translate in terms of transform(QTransform). Includes new unit test for rotate() and translate() methods. Includes sip bindings update.
This commit is contained in:
parent
85619dae12
commit
e2e47d71c6
@ -251,6 +251,18 @@ class QgsGeometry
|
||||
@return 0 in case of success*/
|
||||
int transform( const QgsCoordinateTransform& ct );
|
||||
|
||||
/**Transform this geometry as described by QTransform ct
|
||||
@note added in 2.8
|
||||
@return 0 in case of success*/
|
||||
int transform( const QTransform& ct );
|
||||
|
||||
/**Rotate this geometry around the Z axis
|
||||
@note added in 2.8
|
||||
@param rotation clockwise rotation in degrees
|
||||
@param center rotation center
|
||||
@return 0 in case of success*/
|
||||
int rotate( double rotation, const QgsPoint& center );
|
||||
|
||||
/**Splits this geometry according to a given line. Note that the geometry is only split once. If there are several intersections
|
||||
between geometry and splitLine, only the first one is considered.
|
||||
@param splitLine the line that splits the geometry
|
||||
|
||||
@ -2706,7 +2706,7 @@ int QgsGeometry::addPart( GEOSGeometry *newPart )
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QgsGeometry::translate( double dx, double dy )
|
||||
int QgsGeometry::transform( const QTransform& t )
|
||||
{
|
||||
if ( mDirtyWkb )
|
||||
exportGeosToWkb();
|
||||
@ -2717,17 +2717,17 @@ int QgsGeometry::translate( double dx, double dy )
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool hasZValue = false;
|
||||
QgsWkbPtr wkbPtr( mGeometry + 1 );
|
||||
QGis::WkbType wkbType;
|
||||
wkbPtr >> wkbType;
|
||||
|
||||
bool hasZValue = false;
|
||||
switch ( wkbType )
|
||||
{
|
||||
case QGis::WKBPoint25D:
|
||||
case QGis::WKBPoint:
|
||||
{
|
||||
translateVertex( wkbPtr, dx, dy, hasZValue );
|
||||
transformVertex( wkbPtr, t, hasZValue );
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2738,7 +2738,7 @@ int QgsGeometry::translate( double dx, double dy )
|
||||
int nPoints;
|
||||
wkbPtr >> nPoints;
|
||||
for ( int index = 0; index < nPoints; ++index )
|
||||
translateVertex( wkbPtr, dx, dy, hasZValue );
|
||||
transformVertex( wkbPtr, t, hasZValue );
|
||||
|
||||
break;
|
||||
}
|
||||
@ -2754,7 +2754,7 @@ int QgsGeometry::translate( double dx, double dy )
|
||||
int nPoints;
|
||||
wkbPtr >> nPoints;
|
||||
for ( int index2 = 0; index2 < nPoints; ++index2 )
|
||||
translateVertex( wkbPtr, dx, dy, hasZValue );
|
||||
transformVertex( wkbPtr, t, hasZValue );
|
||||
|
||||
}
|
||||
break;
|
||||
@ -2766,11 +2766,10 @@ int QgsGeometry::translate( double dx, double dy )
|
||||
{
|
||||
int nPoints;
|
||||
wkbPtr >> nPoints;
|
||||
|
||||
for ( int index = 0; index < nPoints; ++index )
|
||||
{
|
||||
wkbPtr += 1 + sizeof( int );
|
||||
translateVertex( wkbPtr, dx, dy, hasZValue );
|
||||
transformVertex( wkbPtr, t, hasZValue );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2787,7 +2786,8 @@ int QgsGeometry::translate( double dx, double dy )
|
||||
int nPoints;
|
||||
wkbPtr >> nPoints;
|
||||
for ( int index2 = 0; index2 < nPoints; ++index2 )
|
||||
translateVertex( wkbPtr, dx, dy, hasZValue );
|
||||
transformVertex( wkbPtr, t, hasZValue );
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2801,19 +2801,17 @@ int QgsGeometry::translate( double dx, double dy )
|
||||
for ( int index = 0; index < nPolys; ++index )
|
||||
{
|
||||
wkbPtr += 1 + sizeof( int ); //skip endian and polygon type
|
||||
|
||||
int nRings;
|
||||
wkbPtr >> nRings;
|
||||
|
||||
for ( int index2 = 0; index2 < nRings; ++index2 )
|
||||
{
|
||||
int nPoints;
|
||||
wkbPtr >> nPoints;
|
||||
for ( int index3 = 0; index3 < nPoints; ++index3 )
|
||||
translateVertex( wkbPtr, dx, dy, hasZValue );
|
||||
transformVertex( wkbPtr, t, hasZValue );
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
@ -2823,6 +2821,19 @@ int QgsGeometry::translate( double dx, double dy )
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QgsGeometry::translate( double dx, double dy )
|
||||
{
|
||||
return transform( QTransform::fromTranslate( dx, dy ) );
|
||||
}
|
||||
|
||||
int QgsGeometry::rotate( double rotation, const QgsPoint& center )
|
||||
{
|
||||
QTransform t = QTransform::fromTranslate( center.x(), center.y() );
|
||||
t.rotate( -rotation );
|
||||
t.translate( -center.x(), -center.y() );
|
||||
return transform( t );
|
||||
}
|
||||
|
||||
int QgsGeometry::transform( const QgsCoordinateTransform& ct )
|
||||
{
|
||||
if ( mDirtyWkb )
|
||||
@ -4612,20 +4623,25 @@ bool QgsGeometry::convertToMultiType()
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsGeometry::translateVertex( QgsWkbPtr &wkbPtr, double dx, double dy, bool hasZValue )
|
||||
void QgsGeometry::transformVertex( QgsWkbPtr &wkbPtr, const QTransform& trans, bool hasZValue )
|
||||
{
|
||||
double x, y, translated_x, translated_y;
|
||||
double x, y, rotated_x, rotated_y;
|
||||
|
||||
QgsWkbPtr tmp = wkbPtr;
|
||||
|
||||
memcpy( &x, tmp, sizeof( double ) );
|
||||
tmp += sizeof( double );
|
||||
memcpy( &y, tmp, sizeof( double ) );
|
||||
tmp += sizeof( double );
|
||||
|
||||
trans.map( x, y, &rotated_x, &rotated_y );
|
||||
|
||||
//x-coordinate
|
||||
memcpy( &x, wkbPtr, sizeof( double ) );
|
||||
translated_x = x + dx;
|
||||
memcpy( wkbPtr, &translated_x, sizeof( double ) );
|
||||
memcpy( wkbPtr, &rotated_x, sizeof( double ) );
|
||||
wkbPtr += sizeof( double );
|
||||
|
||||
//y-coordinate
|
||||
memcpy( &y, wkbPtr, sizeof( double ) );
|
||||
translated_y = y + dy;
|
||||
memcpy( wkbPtr, &translated_y, sizeof( double ) );
|
||||
memcpy( wkbPtr, &rotated_y, sizeof( double ) );
|
||||
wkbPtr += sizeof( double );
|
||||
|
||||
if ( hasZValue )
|
||||
|
||||
@ -293,6 +293,18 @@ class CORE_EXPORT QgsGeometry
|
||||
@return 0 in case of success*/
|
||||
int transform( const QgsCoordinateTransform& ct );
|
||||
|
||||
/**Transform this geometry as described by QTransform ct
|
||||
@note added in 2.8
|
||||
@return 0 in case of success*/
|
||||
int transform( const QTransform& ct );
|
||||
|
||||
/**Rotate this geometry around the Z axis
|
||||
@note added in 2.8
|
||||
@param rotation clockwise rotation in degrees
|
||||
@param center rotation center
|
||||
@return 0 in case of success*/
|
||||
int rotate( double rotation, const QgsPoint& center );
|
||||
|
||||
/**Splits this geometry according to a given line. Note that the geometry is only split once. If there are several intersections
|
||||
between geometry and splitLine, only the first one is considered.
|
||||
@param splitLine the line that splits the geometry
|
||||
@ -565,12 +577,11 @@ class CORE_EXPORT QgsGeometry
|
||||
const GEOSCoordSequence* old_sequence,
|
||||
GEOSCoordSequence** new_sequence );
|
||||
|
||||
/**Translates a single vertex by dx and dy.
|
||||
/**Transform a single vertex by QTransform
|
||||
@param wkbPtr pointer to current position in wkb array. Is increased automatically by the function
|
||||
@param dx translation of x coordinate
|
||||
@param dy translation of y coordinate
|
||||
@param trans transform matrix
|
||||
@param hasZValue 25D type?*/
|
||||
void translateVertex( QgsWkbPtr &wkbPtr, double dx, double dy, bool hasZValue );
|
||||
void transformVertex( QgsWkbPtr &wkbPtr, const QTransform& trans, bool hasZValue );
|
||||
|
||||
/**Transforms a single vertex by ct.
|
||||
@param wkbPtr pointer to current position in wkb. Is increased automatically by the function
|
||||
|
||||
@ -60,6 +60,8 @@ class TestQgsGeometry : public QObject
|
||||
#endif
|
||||
void intersectionCheck1();
|
||||
void intersectionCheck2();
|
||||
void translateCheck1();
|
||||
void rotateCheck1();
|
||||
void unionCheck1();
|
||||
void unionCheck2();
|
||||
void differenceCheck1();
|
||||
@ -359,6 +361,81 @@ void TestQgsGeometry::intersectionCheck2()
|
||||
QVERIFY( !mpPolygonGeometryA->intersects( mpPolygonGeometryC ) );
|
||||
}
|
||||
|
||||
void TestQgsGeometry::translateCheck1()
|
||||
{
|
||||
QString wkt = "LINESTRING(0 0, 10 0, 10 10)";
|
||||
QScopedPointer<QgsGeometry> geom( QgsGeometry::fromWkt( wkt ) );
|
||||
geom->translate( 10, -5 );
|
||||
QString obtained = geom->exportToWkt();
|
||||
QString expected = "LINESTRING(10 -5, 20 -5, 20 5)";
|
||||
QCOMPARE( obtained, expected );
|
||||
geom->translate( -10, 5 );
|
||||
obtained = geom->exportToWkt();
|
||||
QCOMPARE( obtained, wkt );
|
||||
|
||||
wkt = "POLYGON((-2 4,-2 -10,2 3,-2 4),(1 1,-1 1,-1 -1,1 1))";
|
||||
geom.reset( QgsGeometry::fromWkt( wkt ) );
|
||||
geom->translate( -2, 10 );
|
||||
obtained = geom->exportToWkt();
|
||||
expected = "POLYGON((-4 14,-4 0,0 13,-4 14),(-1 11,-3 11,-3 9,-1 11))";
|
||||
QCOMPARE( obtained, expected );
|
||||
geom->translate( 2, -10 );
|
||||
obtained = geom->exportToWkt();
|
||||
QCOMPARE( obtained, wkt );
|
||||
|
||||
wkt = "POINT(40 50)";
|
||||
geom.reset( QgsGeometry::fromWkt( wkt ) );
|
||||
geom->translate( -2, 10 );
|
||||
obtained = geom->exportToWkt();
|
||||
expected = "POINT(38 60)";
|
||||
QCOMPARE( obtained, expected );
|
||||
geom->translate( 2, -10 );
|
||||
obtained = geom->exportToWkt();
|
||||
QCOMPARE( obtained, wkt );
|
||||
|
||||
}
|
||||
|
||||
void TestQgsGeometry::rotateCheck1()
|
||||
{
|
||||
QString wkt = "LINESTRING(0 0, 10 0, 10 10)";
|
||||
QScopedPointer<QgsGeometry> geom( QgsGeometry::fromWkt( wkt ) );
|
||||
geom->rotate( 90, QgsPoint( 0, 0 ) );
|
||||
QString obtained = geom->exportToWkt();
|
||||
QString expected = "LINESTRING(0 0, 0 -10, 10 -10)";
|
||||
QCOMPARE( obtained, expected );
|
||||
geom->rotate( -90, QgsPoint( 0, 0 ) );
|
||||
obtained = geom->exportToWkt();
|
||||
QCOMPARE( obtained, wkt );
|
||||
|
||||
wkt = "POLYGON((-2 4,-2 -10,2 3,-2 4),(1 1,-1 1,-1 -1,1 1))";
|
||||
geom.reset( QgsGeometry::fromWkt( wkt ) );
|
||||
geom->rotate( 90, QgsPoint( 0, 0 ) );
|
||||
obtained = geom->exportToWkt();
|
||||
expected = "POLYGON((4 2,-10 2,3 -2,4 2),(1 -1,1 1,-1 1,1 -1))";
|
||||
QCOMPARE( obtained, expected );
|
||||
geom->rotate( -90, QgsPoint( 0, 0 ) );
|
||||
obtained = geom->exportToWkt();
|
||||
QCOMPARE( obtained, wkt );
|
||||
|
||||
wkt = "POINT(40 50)";
|
||||
geom.reset( QgsGeometry::fromWkt( wkt ) );
|
||||
geom->rotate( 90, QgsPoint( 0, 0 ) );
|
||||
obtained = geom->exportToWkt();
|
||||
expected = "POINT(50 -40)";
|
||||
QCOMPARE( obtained, expected );
|
||||
geom->rotate( -90, QgsPoint( 0, 0 ) );
|
||||
obtained = geom->exportToWkt();
|
||||
QCOMPARE( obtained, wkt );
|
||||
geom->rotate( 180, QgsPoint( 40, 0 ) );
|
||||
expected = "POINT(40 -50)";
|
||||
obtained = geom->exportToWkt();
|
||||
QCOMPARE( obtained, expected );
|
||||
geom->rotate( 180, QgsPoint( 40, 0 ) ); // round-trip
|
||||
obtained = geom->exportToWkt();
|
||||
QCOMPARE( obtained, wkt );
|
||||
|
||||
}
|
||||
|
||||
void TestQgsGeometry::unionCheck1()
|
||||
{
|
||||
// should be a multipolygon with 2 parts as A does not intersect C
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user