Merge pull request #5719 from nyalldawson/translate_z

geometries: translate Z/M
This commit is contained in:
Nyall Dawson 2017-11-24 22:12:11 +11:00 committed by GitHub
commit 14531964a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 610 additions and 192 deletions

View File

@ -234,10 +234,13 @@ class QgsAbstractGeometry
transform.
%End
virtual void transform( const QTransform &t ) = 0;
virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0,
double mTranslate = 0.0, double mScale = 1.0 ) = 0;
%Docstring
Transforms the geometry using a QTransform object
\param t QTransform transformation
Transforms the x and y components of the geometry using a QTransform object ``t``.
Optionally, the geometry's z values can be scaled via ``zScale`` and translated via ``zTranslate``.
Similarly, m-values can be scaled via ``mScale`` and translated via ``mTranslate``.
%End
virtual void draw( QPainter &p ) const = 0;

View File

@ -87,7 +87,7 @@ class QgsCircularString: QgsCurve
virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false );
virtual void transform( const QTransform &t );
virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
virtual void addToPainterPath( QPainterPath &path ) const;

View File

@ -112,7 +112,7 @@ class QgsCompoundCurve: QgsCurve
virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false );
virtual void transform( const QTransform &t );
virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
virtual void addToPainterPath( QPainterPath &path ) const;

View File

@ -131,7 +131,7 @@ Adds an interior ring to the geometry (takes ownership)
virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false );
virtual void transform( const QTransform &t );
virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
virtual bool insertVertex( QgsVertexId position, const QgsPoint &vertex );

View File

@ -566,9 +566,9 @@ Returns true if WKB of the geometry is of WKBMulti* type
:rtype: QgsGeometry
%End
OperationResult translate( double dx, double dy );
OperationResult translate( double dx, double dy, double dz = 0.0, double dm = 0.0 );
%Docstring
Translates this geometry by dx, dy
Translates this geometry by dx, dy, dz and dm.
:return: OperationResult a result code: success or reason of failure
:rtype: OperationResult
%End
@ -580,9 +580,13 @@ Returns true if WKB of the geometry is of WKBMulti* type
:rtype: OperationResult
%End
OperationResult transform( const QTransform &ct );
OperationResult transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
%Docstring
Transforms this geometry as described by QTransform ct
Transforms the x and y components of the geometry using a QTransform object ``t``.
Optionally, the geometry's z values can be scaled via ``zScale`` and translated via ``zTranslate``.
Similarly, m-values can be scaled via ``mScale`` and translated via ``mTranslate``.
:return: OperationResult a result code: success or reason of failure
:rtype: OperationResult
%End

View File

@ -83,7 +83,7 @@ Adds a geometry and takes ownership. Returns true in case of success.
virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false );
virtual void transform( const QTransform &t );
virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
virtual void draw( QPainter &p ) const;

View File

@ -225,7 +225,7 @@ Closes the line string by appending the first point to the end of the line, if i
virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false );
virtual void transform( const QTransform &t );
virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
virtual void addToPainterPath( QPainterPath &path ) const;

View File

@ -359,7 +359,7 @@ class QgsPoint: QgsAbstractGeometry
virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false );
virtual void transform( const QTransform &t );
virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
virtual QgsCoordinateSequence coordinateSequence() const;

View File

@ -143,7 +143,6 @@ from .SymmetricalDifference import SymmetricalDifference
from .TextToFloat import TextToFloat
from .TinInterpolation import TinInterpolation
from .TopoColors import TopoColor
from .Translate import Translate
from .TruncateTable import TruncateTable
from .Union import Union
from .UniqueValues import UniqueValues
@ -268,7 +267,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
TextToFloat(),
TinInterpolation(),
TopoColor(),
Translate(),
TruncateTable(),
Union(),
UniqueValues(),

View File

@ -1,76 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
Translate.py
--------------
Date : August 2016
Copyright : (C) 2016 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* 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. *
* *
***************************************************************************
"""
__author__ = 'Nyall Dawson'
__date__ = 'August 2016'
__copyright__ = '(C) 2016, Nyall Dawson'
# This will get replaced with a git SHA1 when you do a git archive323
__revision__ = '$Format:%H$'
from qgis.core import (QgsProcessingException,
QgsProcessingParameterNumber)
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
class Translate(QgisFeatureBasedAlgorithm):
DELTA_X = 'DELTA_X'
DELTA_Y = 'DELTA_Y'
def group(self):
return self.tr('Vector geometry')
def __init__(self):
super().__init__()
self.delta_x = 0
self.delta_y = 0
def initParameters(self, config=None):
self.addParameter(QgsProcessingParameterNumber(self.DELTA_X,
self.tr('Offset distance (x-axis)'), QgsProcessingParameterNumber.Double, defaultValue=0.0))
self.addParameter(QgsProcessingParameterNumber(self.DELTA_Y,
self.tr('Offset distance (y-axis)'), QgsProcessingParameterNumber.Double, defaultValue=0.0))
def name(self):
return 'translategeometry'
def displayName(self):
return self.tr('Translate geometry')
def outputName(self):
return self.tr('Translated')
def prepareAlgorithm(self, parameters, context, feedback):
self.delta_x = self.parameterAsDouble(parameters, self.DELTA_X, context)
self.delta_y = self.parameterAsDouble(parameters, self.DELTA_Y, context)
return True
def processFeature(self, feature, feedback):
input_geometry = feature.geometry()
if input_geometry:
output_geometry = input_geometry
output_geometry.translate(self.delta_x, self.delta_y)
if not output_geometry:
raise QgsProcessingException(
self.tr('Error translating geometry'))
feature.setGeometry(output_geometry)
return feature

View File

@ -0,0 +1,32 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>buffer_polys</Name>
<ElementPath>buffer_polys</ElementPath>
<!--POLYGON-->
<GeometryType>3</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>6</FeatureCount>
<ExtentXMin>-1.50000</ExtentXMin>
<ExtentXMax>10.50000</ExtentXMax>
<ExtentYMin>-3.50000</ExtentYMin>
<ExtentYMax>6.50000</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>name</Name>
<ElementPath>name</ElementPath>
<Type>String</Type>
<Width>5</Width>
</PropertyDefn>
<PropertyDefn>
<Name>intval</Name>
<ElementPath>intval</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>floatval</Name>
<ElementPath>floatval</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>gridify_lines</Name>
<ElementPath>gridify_lines</ElementPath>
<!--LINESTRING-->
<GeometryType>2</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>7</FeatureCount>
<ExtentXMin>-2.00000</ExtentXMin>
<ExtentXMax>12.00000</ExtentXMax>
<ExtentYMin>-4.00000</ExtentYMin>
<ExtentYMax>6.00000</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,32 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>gridify_polys</Name>
<ElementPath>gridify_polys</ElementPath>
<!--POLYGON-->
<GeometryType>3</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>6</FeatureCount>
<ExtentXMin>-2.00000</ExtentXMin>
<ExtentXMax>10.00000</ExtentXMax>
<ExtentYMin>-4.00000</ExtentYMin>
<ExtentYMax>6.00000</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>name</Name>
<ElementPath>name</ElementPath>
<Type>String</Type>
<Width>5</Width>
</PropertyDefn>
<PropertyDefn>
<Name>intval</Name>
<ElementPath>intval</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>floatval</Name>
<ElementPath>floatval</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>lines_bounds</Name>
<ElementPath>lines_bounds</ElementPath>
<!--POLYGON-->
<GeometryType>3</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>7</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>11.00000</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
<ExtentYMax>5.00000</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>multiline_offset</Name>
<ElementPath>multiline_offset</ElementPath>
<!--MULTILINESTRING-->
<GeometryType>5</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>4</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>6.02404</ExtentXMax>
<ExtentYMin>0.00000</ExtentYMin>
<ExtentYMax>5.11935</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>

Binary file not shown.

View File

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ translate_z_m.xsd"
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y><gml:Z>8</gml:Z></gml:coord>
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y><gml:Z>8</gml:Z></gml:coord>
</gml:Box>
</gml:boundedBy>
<gml:featureMember>
<ogr:translate_z_m fid="points.0">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>1</ogr:id>
<ogr:id2>2</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
<gml:featureMember>
<ogr:translate_z_m fid="points.1">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>2</ogr:id>
<ogr:id2>1</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
<gml:featureMember>
<ogr:translate_z_m fid="points.2">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>3</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
<gml:featureMember>
<ogr:translate_z_m fid="points.3">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>5,2,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>4</ogr:id>
<ogr:id2>2</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
<gml:featureMember>
<ogr:translate_z_m fid="points.4">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>4,1,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>5</ogr:id>
<ogr:id2>1</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
<gml:featureMember>
<ogr:translate_z_m fid="points.5">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-5,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>6</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
<gml:featureMember>
<ogr:translate_z_m fid="points.6">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>8,-1,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>7</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
<gml:featureMember>
<ogr:translate_z_m fid="points.7">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>7,-1,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>8</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
<gml:featureMember>
<ogr:translate_z_m fid="points.8">
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>0,-1,8</gml:coordinates></gml:Point></ogr:geometryProperty>
<ogr:id>9</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:translate_z_m>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]

View File

@ -0,0 +1 @@
GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="translate_z_m" type="ogr:translate_z_m_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="translate_z_m_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="id" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:long">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="id2" nillable="true" minOccurs="0" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:long">
<xs:totalDigits value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>

View File

@ -0,0 +1,31 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>variable_buffer_points</Name>
<ElementPath>variable_buffer_points</ElementPath>
<!--POLYGON-->
<GeometryType>3</GeometryType>
<SRSName>EPSG:3857</SRSName>
<DatasetSpecificInfo>
<FeatureCount>9</FeatureCount>
<ExtentXMin>-50000.00000</ExtentXMin>
<ExtentXMax>990555.92635</ExtentXMax>
<ExtentYMin>-607305.25727</ExtentYMin>
<ExtentYMax>384111.17140</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>id</Name>
<ElementPath>id</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>id2</Name>
<ElementPath>id2</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>buffer</Name>
<ElementPath>buffer</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -1087,7 +1087,7 @@ tests:
geometry:
precision: 7
- algorithm: qgis:translategeometry
- algorithm: native:translategeometry
name: Lines translated
params:
DELTA_X: 0.1
@ -1100,6 +1100,21 @@ tests:
name: expected/lines_translated.gml
type: vector
- algorithm: native:translategeometry
name: Translate Z/M
params:
DELTA_M: 4.0
DELTA_X: 0.0
DELTA_Y: 0.0
DELTA_Z: 3.0
INPUT:
name: custom/pointszm.shp
type: vector
results:
OUTPUT:
name: expected/translate_z_m.shp
type: vector
- algorithm: qgis:singlesidedbuffer
name: Single sided buffer lines (left, round)
params:

View File

@ -59,6 +59,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmsubdivide.cpp
processing/qgsalgorithmtransect.cpp
processing/qgsalgorithmtransform.cpp
processing/qgsalgorithmtranslate.cpp
processing/qgsnativealgorithms.cpp

View File

@ -0,0 +1,114 @@
/***************************************************************************
qgsalgorithmtranslate.cpp
---------------------
begin : November 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* 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 "qgsalgorithmtranslate.h"
///@cond PRIVATE
QString QgsTranslateAlgorithm::name() const
{
return QStringLiteral( "translategeometry" );
}
QString QgsTranslateAlgorithm::displayName() const
{
return QObject::tr( "Translate geometry" );
}
QStringList QgsTranslateAlgorithm::tags() const
{
return QObject::tr( "move,shift,transform,z,m,values,add" ).split( ',' );
}
QString QgsTranslateAlgorithm::group() const
{
return QObject::tr( "Vector geometry" );
}
QString QgsTranslateAlgorithm::outputName() const
{
return QObject::tr( "Translated" );
}
QString QgsTranslateAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm moves the geometries within a layer, by offsetting them with a specified x and y displacement." )
+ QStringLiteral( "\n\n" )
+ QObject::tr( "Z and M values present in the geometry can also be translated." );
}
QgsTranslateAlgorithm *QgsTranslateAlgorithm::createInstance() const
{
return new QgsTranslateAlgorithm();
}
void QgsTranslateAlgorithm::initParameters( const QVariantMap & )
{
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "DELTA_X" ),
QObject::tr( "Offset distance (x-axis)" ), QgsProcessingParameterNumber::Double,
0.0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "DELTA_Y" ),
QObject::tr( "Offset distance (y-axis)" ), QgsProcessingParameterNumber::Double,
0.0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "DELTA_Z" ),
QObject::tr( "Offset distance (z-axis)" ), QgsProcessingParameterNumber::Double,
0.0 ) );
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "DELTA_M" ),
QObject::tr( "Offset distance (m values)" ), QgsProcessingParameterNumber::Double,
0.0 ) );
}
bool QgsTranslateAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
mDeltaX = parameterAsDouble( parameters, QStringLiteral( "DELTA_X" ), context );
mDeltaY = parameterAsDouble( parameters, QStringLiteral( "DELTA_Y" ), context );
mDeltaZ = parameterAsDouble( parameters, QStringLiteral( "DELTA_Z" ), context );
mDeltaM = parameterAsDouble( parameters, QStringLiteral( "DELTA_M" ), context );
return true;
}
QgsFeature QgsTranslateAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback * )
{
QgsFeature f = feature;
if ( f.hasGeometry() )
{
QgsGeometry geometry = f.geometry();
if ( mDeltaZ != 0 && !geometry.constGet()->is3D() )
geometry.get()->addZValue( 0 );
if ( mDeltaM != 0 && !geometry.constGet()->isMeasure() )
geometry.get()->addMValue( 0 );
geometry.translate( mDeltaX, mDeltaY, mDeltaZ, mDeltaM );
f.setGeometry( geometry );
}
return f;
}
QgsWkbTypes::Type QgsTranslateAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
{
QgsWkbTypes::Type wkb = inputWkbType;
if ( mDeltaZ != 0 )
wkb = QgsWkbTypes::addZ( wkb );
if ( mDeltaM != 0 )
wkb = QgsWkbTypes::addM( wkb );
return wkb;
}
///@endcond

View File

@ -0,0 +1,65 @@
/***************************************************************************
qgsalgorithmtranslate.h
---------------------
begin : November 2017
copyright : (C) 2017 by Nyall Dawson
email : nyall dot dawson at gmail dot com
***************************************************************************/
/***************************************************************************
* *
* 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 QGSALGORITHMTRANSLATE_H
#define QGSALGORITHMTRANSLATE_H
#define SIP_NO_FILE
#include "qgis.h"
#include "qgsprocessingalgorithm.h"
///@cond PRIVATE
/**
* Native translate algorithm.
*/
class QgsTranslateAlgorithm : public QgsProcessingFeatureBasedAlgorithm
{
public:
QgsTranslateAlgorithm() = default;
QString name() const override;
QString displayName() const override;
virtual QStringList tags() const override;
QString group() const override;
QString shortHelpString() const override;
QgsTranslateAlgorithm *createInstance() const override SIP_FACTORY;
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
protected:
QString outputName() const override;
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
QgsFeature processFeature( const QgsFeature &feature, QgsProcessingFeedback *feedback ) override;
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override;
private:
double mDeltaX = 0.0;
double mDeltaY = 0.0;
double mDeltaZ = 0.0;
double mDeltaM = 0.0;
};
///@endcond PRIVATE
#endif // QGSALGORITHMTRANSLATE_H

View File

@ -56,6 +56,7 @@
#include "qgsalgorithmsubdivide.h"
#include "qgsalgorithmtransect.h"
#include "qgsalgorithmtransform.h"
#include "qgsalgorithmtranslate.h"
///@cond PRIVATE
@ -133,7 +134,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsSubdivideAlgorithm() );
addAlgorithm( new QgsTransectAlgorithm() );
addAlgorithm( new QgsTransformAlgorithm() );
addAlgorithm( new QgsTranslateAlgorithm() );
}

View File

@ -262,10 +262,13 @@ class CORE_EXPORT QgsAbstractGeometry
bool transformZ = false ) = 0;
/**
* Transforms the geometry using a QTransform object
* \param t QTransform transformation
* Transforms the x and y components of the geometry using a QTransform object \a t.
*
* Optionally, the geometry's z values can be scaled via \a zScale and translated via \a zTranslate.
* Similarly, m-values can be scaled via \a mScale and translated via \a mTranslate.
*/
virtual void transform( const QTransform &t ) = 0;
virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0,
double mTranslate = 0.0, double mScale = 1.0 ) = 0;
/**
* Draws the geometry using the specified QPainter.

View File

@ -559,17 +559,27 @@ void QgsCircularString::transform( const QgsCoordinateTransform &ct, QgsCoordina
}
}
void QgsCircularString::transform( const QTransform &t )
void QgsCircularString::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
{
clearCache();
int nPoints = numPoints();
bool hasZ = is3D();
bool hasM = isMeasure();
for ( int i = 0; i < nPoints; ++i )
{
qreal x, y;
t.map( mX.at( i ), mY.at( i ), &x, &y );
mX[i] = x;
mY[i] = y;
if ( hasZ )
{
mZ[i] = mZ.at( i ) * zScale + zTranslate;
}
if ( hasM )
{
mM[i] = mM.at( i ) * mScale + mTranslate;
}
}
}

View File

@ -76,7 +76,7 @@ class CORE_EXPORT QgsCircularString: public QgsCurve
void draw( QPainter &p ) const override;
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false ) override;
void transform( const QTransform &t ) override;
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
void addToPainterPath( QPainterPath &path ) const override;
void drawAsPolygon( QPainter &p ) const override;
bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;

View File

@ -509,11 +509,11 @@ void QgsCompoundCurve::transform( const QgsCoordinateTransform &ct, QgsCoordinat
clearCache();
}
void QgsCompoundCurve::transform( const QTransform &t )
void QgsCompoundCurve::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
{
for ( QgsCurve *curve : qgis::as_const( mCurves ) )
{
curve->transform( t );
curve->transform( t, zTranslate, zScale, mTranslate, mScale );
}
clearCache();
}

View File

@ -99,7 +99,7 @@ class CORE_EXPORT QgsCompoundCurve: public QgsCurve
void draw( QPainter &p ) const override;
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false ) override;
void transform( const QTransform &t ) override;
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
void addToPainterPath( QPainterPath &path ) const override;
void drawAsPolygon( QPainter &p ) const override;
bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;

View File

@ -704,16 +704,16 @@ void QgsCurvePolygon::transform( const QgsCoordinateTransform &ct, QgsCoordinate
clearCache();
}
void QgsCurvePolygon::transform( const QTransform &t )
void QgsCurvePolygon::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
{
if ( mExteriorRing )
{
mExteriorRing->transform( t );
mExteriorRing->transform( t, zTranslate, zScale, mTranslate, mScale );
}
for ( QgsCurve *curve : qgis::as_const( mInteriorRings ) )
{
curve->transform( t );
curve->transform( t, zTranslate, zScale, mTranslate, mScale );
}
clearCache();
}

View File

@ -111,7 +111,7 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
void draw( QPainter &p ) const override;
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false ) override;
void transform( const QTransform &t ) override;
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;

View File

@ -752,7 +752,7 @@ QgsGeometry::OperationResult QgsGeometry::addPart( GEOSGeometry *newPart )
return QgsGeometryEditUtils::addPart( d->geometry.get(), std::move( geom ) );
}
QgsGeometry::OperationResult QgsGeometry::translate( double dx, double dy )
QgsGeometry::OperationResult QgsGeometry::translate( double dx, double dy, double dz, double dm )
{
if ( !d->geometry )
{
@ -761,7 +761,7 @@ QgsGeometry::OperationResult QgsGeometry::translate( double dx, double dy )
detach();
d->geometry->transform( QTransform::fromTranslate( dx, dy ) );
d->geometry->transform( QTransform::fromTranslate( dx, dy ), dz, 1.0, dm );
return QgsGeometry::Success;
}
@ -2308,7 +2308,7 @@ QgsGeometry::OperationResult QgsGeometry::transform( const QgsCoordinateTransfor
return QgsGeometry::Success;
}
QgsGeometry::OperationResult QgsGeometry::transform( const QTransform &ct )
QgsGeometry::OperationResult QgsGeometry::transform( const QTransform &ct, double zTranslate, double zScale, double mTranslate, double mScale )
{
if ( !d->geometry )
{
@ -2316,7 +2316,7 @@ QgsGeometry::OperationResult QgsGeometry::transform( const QTransform &ct )
}
detach();
d->geometry->transform( ct );
d->geometry->transform( ct, zTranslate, zScale, mTranslate, mScale );
return QgsGeometry::Success;
}

View File

@ -624,10 +624,10 @@ class CORE_EXPORT QgsGeometry
QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
/**
* Translates this geometry by dx, dy
* Translates this geometry by dx, dy, dz and dm.
* \returns OperationResult a result code: success or reason of failure
*/
OperationResult translate( double dx, double dy );
OperationResult translate( double dx, double dy, double dz = 0.0, double dm = 0.0 );
/**
* Transforms this geometry as described by CoordinateTransform ct
@ -636,10 +636,14 @@ class CORE_EXPORT QgsGeometry
OperationResult transform( const QgsCoordinateTransform &ct );
/**
* Transforms this geometry as described by QTransform ct
* Transforms the x and y components of the geometry using a QTransform object \a t.
*
* Optionally, the geometry's z values can be scaled via \a zScale and translated via \a zTranslate.
* Similarly, m-values can be scaled via \a mScale and translated via \a mTranslate.
*
* \returns OperationResult a result code: success or reason of failure
*/
OperationResult transform( const QTransform &ct );
OperationResult transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
/**
* Rotate this geometry around the Z axis

View File

@ -241,11 +241,11 @@ void QgsGeometryCollection::transform( const QgsCoordinateTransform &ct, QgsCoor
clearCache(); //set bounding box invalid
}
void QgsGeometryCollection::transform( const QTransform &t )
void QgsGeometryCollection::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
{
for ( QgsAbstractGeometry *g : qgis::as_const( mGeometries ) )
{
g->transform( t );
g->transform( t, zTranslate, zScale, mTranslate, mScale );
}
clearCache(); //set bounding box invalid
}

View File

@ -88,7 +88,7 @@ class CORE_EXPORT QgsGeometryCollection: public QgsAbstractGeometry
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false ) override;
void transform( const QTransform &t ) override;
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
void draw( QPainter &p ) const override;

View File

@ -772,15 +772,25 @@ void QgsLineString::transform( const QgsCoordinateTransform &ct, QgsCoordinateTr
clearCache();
}
void QgsLineString::transform( const QTransform &t )
void QgsLineString::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
{
int nPoints = numPoints();
bool hasZ = is3D();
bool hasM = isMeasure();
for ( int i = 0; i < nPoints; ++i )
{
qreal x, y;
t.map( mX.at( i ), mY.at( i ), &x, &y );
mX[i] = x;
mY[i] = y;
if ( hasZ )
{
mZ[i] = mZ.at( i ) * zScale + zTranslate;
}
if ( hasM )
{
mM[i] = mM.at( i ) * mScale + mTranslate;
}
}
clearCache();
}

View File

@ -210,7 +210,7 @@ class CORE_EXPORT QgsLineString: public QgsCurve
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false ) override;
void transform( const QTransform &t ) override;
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
void addToPainterPath( QPainterPath &path ) const override;
void drawAsPolygon( QPainter &p ) const override;

View File

@ -494,13 +494,22 @@ bool QgsPoint::addMValue( double mValue )
return true;
}
void QgsPoint::transform( const QTransform &t )
void QgsPoint::transform( const QTransform &t, double zTranslate, double zScale, double mTranslate, double mScale )
{
clearCache();
qreal x, y;
t.map( mX, mY, &x, &y );
mX = x;
mY = y;
if ( is3D() )
{
mZ = mZ * zScale + zTranslate;
}
if ( isMeasure() )
{
mM = mM * mScale + mTranslate;
}
}

View File

@ -403,7 +403,7 @@ class CORE_EXPORT QgsPoint: public QgsAbstractGeometry
void draw( QPainter &p ) const override;
void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform,
bool transformZ = false ) override;
void transform( const QTransform &t ) override;
void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
QgsCoordinateSequence coordinateSequence() const override;
int nCoordinates() const override;
int vertexNumberFromVertexId( QgsVertexId id ) const override;

View File

@ -326,18 +326,6 @@ void QgsMapToolIdentify::closestVertexAttributes( const QgsAbstractGeometry &geo
}
}
void QgsMapToolIdentify::closestPointAttributes( const QgsAbstractGeometry &geometry, QgsMapLayer *layer, const QgsPointXY &layerPoint, QMap< QString, QString > &derivedAttributes )
{
Q_UNUSED( layer );
// measure
if ( QgsWkbTypes::hasM( geometry.wkbType() ) )
{
QgsPoint closestPoint = QgsGeometryUtils::closestPoint( geometry, QgsPoint( layerPoint.x(), layerPoint.y() ) );
QString str = QLocale::system().toString( closestPoint.m(), 'g', 10 );
derivedAttributes.insert( QStringLiteral( "Closest point M" ), str );
}
}
QString QgsMapToolIdentify::formatCoordinate( const QgsPointXY &canvasPoint ) const
{
return QgsCoordinateUtils::formatCoordinateForProject( canvasPoint, mCanvas->mapSettings().destinationCrs(),
@ -396,27 +384,28 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeatur
QString str = formatDistance( dist );
derivedAttributes.insert( tr( "Length" ), str );
const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( feature->geometry().constGet() );
if ( curve )
const QgsAbstractGeometry *geom = feature->geometry().constGet();
if ( geom )
{
str = QLocale::system().toString( curve->nCoordinates() );
str = QLocale::system().toString( geom->nCoordinates() );
derivedAttributes.insert( tr( "Vertices" ), str );
//add details of closest vertex to identify point
closestVertexAttributes( *curve, vId, layer, derivedAttributes );
closestPointAttributes( *curve, layer, layerPoint, derivedAttributes );
closestVertexAttributes( *geom, vId, layer, derivedAttributes );
// Add the start and end points in as derived attributes
QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->startPoint().x(), curve->startPoint().y() ) );
str = formatXCoordinate( pnt );
derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str );
str = formatYCoordinate( pnt );
derivedAttributes.insert( tr( "firstY" ), str );
pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->endPoint().x(), curve->endPoint().y() ) );
str = formatXCoordinate( pnt );
derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str );
str = formatYCoordinate( pnt );
derivedAttributes.insert( tr( "lastY" ), str );
if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( geom ) )
{
// Add the start and end points in as derived attributes
QgsPointXY pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->startPoint().x(), curve->startPoint().y() ) );
str = formatXCoordinate( pnt );
derivedAttributes.insert( tr( "firstX", "attributes get sorted; translation for lastX should be lexically larger than this one" ), str );
str = formatYCoordinate( pnt );
derivedAttributes.insert( tr( "firstY" ), str );
pnt = mCanvas->mapSettings().layerToMapCoordinates( layer, QgsPointXY( curve->endPoint().x(), curve->endPoint().y() ) );
str = formatXCoordinate( pnt );
derivedAttributes.insert( tr( "lastX", "attributes get sorted; translation for firstX should be lexically smaller than this one" ), str );
str = formatYCoordinate( pnt );
derivedAttributes.insert( tr( "lastY" ), str );
}
}
}
else if ( geometryType == QgsWkbTypes::PolygonGeometry )

View File

@ -195,11 +195,6 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
*/
void closestVertexAttributes( const QgsAbstractGeometry &geometry, QgsVertexId vId, QgsMapLayer *layer, QMap< QString, QString > &derivedAttributes );
/**
* Adds details of the closest point to derived attributes
*/
void closestPointAttributes( const QgsAbstractGeometry &geometry, QgsMapLayer *layer, const QgsPointXY &layerPoint, QMap< QString, QString > &derivedAttributes );
QString formatCoordinate( const QgsPointXY &canvasPoint ) const;
QString formatXCoordinate( const QgsPointXY &canvasPoint ) const;
QString formatYCoordinate( const QgsPointXY &canvasPoint ) const;

View File

@ -738,6 +738,8 @@ void TestQgsGeometry::point()
QgsPoint p17( QgsWkbTypes::PointZM, 10, 20, 30, 40 );
p17.transform( qtr );
QVERIFY( p17 == QgsPoint( QgsWkbTypes::PointZM, 20, 60, 30, 40 ) );
p17.transform( QTransform::fromScale( 1, 1 ), 11, 2, 3, 4 );
QVERIFY( p17 == QgsPoint( QgsWkbTypes::PointZM, 20, 60, 71, 163 ) );
//coordinateSequence
QgsPoint p18( QgsWkbTypes::PointZM, 1.0, 2.0, 3.0, 4.0 );
@ -1644,6 +1646,12 @@ void TestQgsGeometry::circularString()
QCOMPARE( l23.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 22, 36, 13, 14 ) );
QCOMPARE( l23.boundingBox(), QgsRectangle( 2, 6, 22, 36 ) );
l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
<< QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
l23.transform( QTransform::fromScale( 1, 1 ), 3, 2, 4, 3 );
QCOMPARE( l23.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 9, 16 ) );
QCOMPARE( l23.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 29, 46 ) );
//insert vertex
//cannot insert vertex in empty line
QgsCircularString l24;
@ -3318,6 +3326,12 @@ void TestQgsGeometry::lineString()
QCOMPARE( l23.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 22, 36, 13, 14 ) );
QCOMPARE( l23.boundingBox(), QgsRectangle( 2, 6, 22, 36 ) );
l23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 1, 2, 3, 4 )
<< QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) );
l23.transform( QTransform::fromScale( 1, 1 ), 3, 2, 4, 3 );
QCOMPARE( l23.pointN( 0 ), QgsPoint( QgsWkbTypes::PointZM, 1, 2, 9, 16 ) );
QCOMPARE( l23.pointN( 1 ), QgsPoint( QgsWkbTypes::PointZM, 11, 12, 29, 46 ) );
//insert vertex
//insert vertex in empty line
@ -5175,25 +5189,25 @@ void TestQgsGeometry::polygon()
QgsPolygon pTransform2;
pTransform2.setExteriorRing( l23.clone() );
pTransform2.addInteriorRing( l23.clone() );
pTransform2.transform( qtr );
pTransform2.transform( qtr, 2, 3, 4, 5 );
extR = static_cast< const QgsLineString * >( pTransform2.exteriorRing() );
QGSCOMPARENEAR( extR->pointN( 0 ).x(), 2, 100 );
QGSCOMPARENEAR( extR->pointN( 0 ).y(), 6, 100 );
QGSCOMPARENEAR( extR->pointN( 0 ).z(), 3.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 0 ).m(), 4.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 0 ).z(), 11.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 0 ).m(), 24.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 1 ).x(), 22, 100 );
QGSCOMPARENEAR( extR->pointN( 1 ).y(), 36, 100 );
QGSCOMPARENEAR( extR->pointN( 1 ).z(), 13.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 1 ).m(), 14.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 1 ).z(), 41.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 1 ).m(), 74.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 2 ).x(), 2, 100 );
QGSCOMPARENEAR( extR->pointN( 2 ).y(), 36, 100 );
QGSCOMPARENEAR( extR->pointN( 2 ).z(), 23.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 2 ).m(), 24.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 2 ).z(), 71.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 2 ).m(), 124.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 3 ).x(), 2, 100 );
QGSCOMPARENEAR( extR->pointN( 3 ).y(), 6, 100 );
QGSCOMPARENEAR( extR->pointN( 3 ).z(), 3.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 3 ).m(), 4.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 3 ).z(), 11.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 3 ).m(), 24.0, 0.001 );
QGSCOMPARENEAR( pTransform2.exteriorRing()->boundingBox().xMinimum(), 2, 0.001 );
QGSCOMPARENEAR( pTransform2.exteriorRing()->boundingBox().yMinimum(), 6, 0.001 );
QGSCOMPARENEAR( pTransform2.exteriorRing()->boundingBox().xMaximum(), 22, 0.001 );
@ -5201,20 +5215,20 @@ void TestQgsGeometry::polygon()
intR = static_cast< const QgsLineString * >( pTransform2.interiorRing( 0 ) );
QGSCOMPARENEAR( intR->pointN( 0 ).x(), 2, 100 );
QGSCOMPARENEAR( intR->pointN( 0 ).y(), 6, 100 );
QGSCOMPARENEAR( intR->pointN( 0 ).z(), 3.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 0 ).m(), 4.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 0 ).z(), 11.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 0 ).m(), 24.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 1 ).x(), 22, 100 );
QGSCOMPARENEAR( intR->pointN( 1 ).y(), 36, 100 );
QGSCOMPARENEAR( intR->pointN( 1 ).z(), 13.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 1 ).m(), 14.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 1 ).z(), 41.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 1 ).m(), 74.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 2 ).x(), 2, 100 );
QGSCOMPARENEAR( intR->pointN( 2 ).y(), 36, 100 );
QGSCOMPARENEAR( intR->pointN( 2 ).z(), 23.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 2 ).m(), 24.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 2 ).z(), 71.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 2 ).m(), 124.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 3 ).x(), 2, 100 );
QGSCOMPARENEAR( intR->pointN( 3 ).y(), 6, 100 );
QGSCOMPARENEAR( intR->pointN( 3 ).z(), 3.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 3 ).m(), 4.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 3 ).z(), 11.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 3 ).m(), 24.0, 0.001 );
QGSCOMPARENEAR( intR->boundingBox().xMinimum(), 2, 0.001 );
QGSCOMPARENEAR( intR->boundingBox().yMinimum(), 6, 0.001 );
QGSCOMPARENEAR( intR->boundingBox().xMaximum(), 22, 0.001 );
@ -9309,13 +9323,13 @@ void TestQgsGeometry::compoundCurve()
QgsLineString ls23;
ls23.setPoints( QgsPointSequence() << QgsPoint( QgsWkbTypes::PointZM, 11, 12, 13, 14 ) << QgsPoint( QgsWkbTypes::PointZM, 21, 13, 13, 14 ) );
c23.addCurve( ls23.clone() );
c23.transform( qtr );
c23.transform( qtr, 5, 2, 4, 3 );
c23.pointAt( 0, pt, v );
QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 2, 6, 3, 4 ) );
QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 2, 6, 11, 16 ) );
c23.pointAt( 1, pt, v );
QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 22, 36, 13, 14 ) );
QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 22, 36, 31, 46 ) );
c23.pointAt( 2, pt, v );
QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 42, 39, 13, 14 ) );
QCOMPARE( pt, QgsPoint( QgsWkbTypes::PointZM, 42, 39, 31, 46 ) );
QCOMPARE( c23.boundingBox(), QgsRectangle( 2, 6, 42, 39 ) );
//insert vertex
@ -14144,25 +14158,25 @@ void TestQgsGeometry::geometryCollection()
QgsGeometryCollection pTransform2;
pTransform2.addGeometry( l23.clone() );
pTransform2.addGeometry( l23.clone() );
pTransform2.transform( qtr );
pTransform2.transform( qtr, 3, 2, 6, 3 );
extR = static_cast< const QgsLineString * >( pTransform2.geometryN( 0 ) );
QGSCOMPARENEAR( extR->pointN( 0 ).x(), 2, 100 );
QGSCOMPARENEAR( extR->pointN( 0 ).y(), 6, 100 );
QGSCOMPARENEAR( extR->pointN( 0 ).z(), 3.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 0 ).m(), 4.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 0 ).z(), 9.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 0 ).m(), 18.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 1 ).x(), 22, 100 );
QGSCOMPARENEAR( extR->pointN( 1 ).y(), 36, 100 );
QGSCOMPARENEAR( extR->pointN( 1 ).z(), 13.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 1 ).m(), 14.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 1 ).z(), 29.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 1 ).m(), 48.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 2 ).x(), 2, 100 );
QGSCOMPARENEAR( extR->pointN( 2 ).y(), 36, 100 );
QGSCOMPARENEAR( extR->pointN( 2 ).z(), 23.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 2 ).m(), 24.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 2 ).z(), 49.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 2 ).m(), 78.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 3 ).x(), 2, 100 );
QGSCOMPARENEAR( extR->pointN( 3 ).y(), 6, 100 );
QGSCOMPARENEAR( extR->pointN( 3 ).z(), 3.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 3 ).m(), 4.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 3 ).z(), 9.0, 0.001 );
QGSCOMPARENEAR( extR->pointN( 3 ).m(), 18.0, 0.001 );
QGSCOMPARENEAR( extR->boundingBox().xMinimum(), 2, 0.001 );
QGSCOMPARENEAR( extR->boundingBox().yMinimum(), 6, 0.001 );
QGSCOMPARENEAR( extR->boundingBox().xMaximum(), 22, 0.001 );
@ -14170,20 +14184,20 @@ void TestQgsGeometry::geometryCollection()
intR = static_cast< const QgsLineString * >( pTransform2.geometryN( 1 ) );
QGSCOMPARENEAR( intR->pointN( 0 ).x(), 2, 100 );
QGSCOMPARENEAR( intR->pointN( 0 ).y(), 6, 100 );
QGSCOMPARENEAR( intR->pointN( 0 ).z(), 3.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 0 ).m(), 4.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 0 ).z(), 9.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 0 ).m(), 18.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 1 ).x(), 22, 100 );
QGSCOMPARENEAR( intR->pointN( 1 ).y(), 36, 100 );
QGSCOMPARENEAR( intR->pointN( 1 ).z(), 13.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 1 ).m(), 14.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 1 ).z(), 29.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 1 ).m(), 48.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 2 ).x(), 2, 100 );
QGSCOMPARENEAR( intR->pointN( 2 ).y(), 36, 100 );
QGSCOMPARENEAR( intR->pointN( 2 ).z(), 23.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 2 ).m(), 24.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 2 ).z(), 49.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 2 ).m(), 78.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 3 ).x(), 2, 100 );
QGSCOMPARENEAR( intR->pointN( 3 ).y(), 6, 100 );
QGSCOMPARENEAR( intR->pointN( 3 ).z(), 3.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 3 ).m(), 4.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 3 ).z(), 9.0, 0.001 );
QGSCOMPARENEAR( intR->pointN( 3 ).m(), 18.0, 0.001 );
QGSCOMPARENEAR( intR->boundingBox().xMinimum(), 2, 0.001 );
QGSCOMPARENEAR( intR->boundingBox().yMinimum(), 6, 0.001 );
QGSCOMPARENEAR( intR->boundingBox().xMaximum(), 22, 0.001 );