More QgsDistanceArea API cleanups and simplification

- setEllipsoidalMode() was removed. Ellipsoidal calculations are
now enabled whenever a valid ellipsoid() has been set. Set the
ellipsoid to 'NONE' to disable ellipsoidal calculations.

- ellipsoidalEnabled() was removed. Ellipsoidal calculations
are now enabled whenever a valid ellipsoid() is set. Check
willUseEllipsoid() to determine whether ellipsoidal
calculations will be performed.

- sourceCrs() and setSourceCrs() now always take and return
QgsCoordinateReferenceSystem objects. All string/ID based CRS
methods were removed.

- geographic() was removed. This was only used internally
in one place, so was replaced with sourceCrs().isGeographic() instead.

- some largely overlapping measurement functions were consolidated
This commit is contained in:
Nyall Dawson 2017-04-18 08:11:51 +10:00
parent ca2b199c76
commit cc5b9bfe17
34 changed files with 172 additions and 317 deletions

View File

@ -951,7 +951,14 @@ QgsDial {#qgis_api_break_3_0_QgsDial}
QgsDistanceArea {#qgis_api_break_3_0_QgsDistanceArea}
---------------
- setEllipsoidalMode() was removed. Ellipsoidal calculations are now enabled whenever a valid ellipsoid() has been set. Set the
ellipsoid to 'NONE' to disable ellipsoidal calculations.
- ellipsoidalEnabled() was removed. Ellipsoidal calculations are now enabled whenever a valid ellipsoid() is set. Check
willUseEllipsoid() to determine whether ellipsoidal calculations will be performed.
- sourceCrs() now returns a QgsCoordinateReferenceSystem instead of the crs ID.
- setSourceCrs() now requires a QgsCoordinateReferenceSystem instead of crs ID.
- setSourceAuthId() was removed. Use setSourceCrs() instead.
- geographic() was removed. Check sourceCrs().isGeographic() instead.
- measure() has been removed. Use measureArea() or measureLength() instead.
- textUnit() was removed. Use formatDistance() or formatArea() instead.
- convertMeasurement was removed. Use QgsUnitTypes for conversion instead.

View File

@ -181,7 +181,7 @@ class QgsCoordinateReferenceSystem
* @param type One of the types described in CrsType
*/
// TODO QGIS 3: remove type and always use EPSG code
QgsCoordinateReferenceSystem( const long id, CrsType type = PostgisCrsId );
explicit QgsCoordinateReferenceSystem( const long id, CrsType type = PostgisCrsId );
operator QVariant() const;
static QList< long > validSrsIds();

View File

@ -12,14 +12,22 @@
class QgsDistanceArea
{
%Docstring
General purpose distance and area calculator.
- calculations are done on ellipsoid
- it's possible to pass points/features in any CRS, coordinates are transformed
- two options how to use it
+ use measure() takes QgsGeometry as a parameter and calculates distance or area
+ use directly measureLine(), measurePolygon() which take list of QgsPoints
(both cases transform the coordinates from source CRS to the ellipse coords)
- returned values are in meters resp. square meters
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
Measurements can either be performed on existing QgsGeometry objects, or using
lists of points.
If a valid ellipsoid() has been set for the QgsDistanceArea, all calculations will be
performed using ellipsoidal algorithms (e.g. using Vincenty's formulas). If no
ellipsoid has been set, all calculations will be performed using cartesian
formulas only. The behavior can be determined by calling willUseEllipsoid().
In order to perform accurate calculations, the source coordinate reference system
of all measured geometries must first be specified using setSourceCrs().
Usually, the measurements returned by QgsDistanceArea are in meters. If no valid
ellipsoid is set, then the units may not be meters. The units can be retrieved
by calling lengthUnits() and areaUnits().
%End
%TypeHeaderCode
@ -32,52 +40,22 @@ General purpose distance and area calculator.
Constructor
%End
void setEllipsoidalMode( bool flag );
%Docstring
Sets whether coordinates must be projected to ellipsoid before measuring
.. note::
for calculations to use the ellipsoid, both the ellipsoid mode must be true
and an ellipse must be set
\see setEllipsoid()
\see willUseEllipsoid()
%End
bool ellipsoidalEnabled() const;
%Docstring
Returns whether ellipsoidal calculations are enabled
\see willUseEllipsoid()
\see setEllipsoidalMode()
:rtype: bool
%End
bool willUseEllipsoid() const;
%Docstring
Returns whether calculations will use the ellipsoid. Calculations will only use the
ellipsoid if ellipsoidalEnabled() is true and an ellipsoid has been set.
ellipsoid if a valid ellipsoid() has been set.
.. versionadded:: 2.14
\see ellipsoidalEnabled()
\see ellipsoid()
:rtype: bool
%End
void setSourceCrs( long srsid );
%Docstring
Sets source spatial reference system (by QGIS CRS).
%End
void setSourceCrs( const QgsCoordinateReferenceSystem &srcCRS );
%Docstring
Sets source spatial reference system (by QGIS CRS).
Sets source spatial reference system.
.. versionadded:: 2.2
\see sourceCrs()
%End
void setSourceAuthId( const QString &authid );
%Docstring
Sets source spatial reference system by authid.
%End
QgsCoordinateReferenceSystem sourceCrs() const;
%Docstring
Returns the source spatial reference system.
@ -85,43 +63,31 @@ Constructor
:rtype: QgsCoordinateReferenceSystem
%End
long sourceCrsId() const;
%Docstring
Returns the QgsCoordinateReferenceSystem.srsid() for the CRS used during calculations.
\see setSourceCrs()
.. versionadded:: 2.14
:rtype: long
%End
bool geographic() const;
%Docstring
Returns true if a geographic (latitude/longitude based) source CRS is used.
:rtype: bool
%End
bool setEllipsoid( const QString &ellipsoid );
%Docstring
Sets ellipsoid by its acronym. Calculations will only use the ellipsoid if
both the ellipsoid has been set and ellipsoidalEnabled() is true.
Sets the ``ellipsoid`` by its acronym.
Calculations will only use the ellipsoid if a valid ellipsoid has been set.
:return: true if ellipsoid was successfully set
\see ellipsoid()
\see setEllipsoidalMode()
\see willUseEllipsoid()
:rtype: bool
%End
bool setEllipsoid( double semiMajor, double semiMinor );
%Docstring
Inverse flattening is calculated with invf = a/(a-b)
Sets ellipsoid by supplied radii. Calculations will only use the ellipsoid if
a valid ellipsoid been set.
:return: true if ellipsoid was successfully set
\see ellipsoid()
\see willUseEllipsoid()
:rtype: bool
%End
QString ellipsoid() const;
%Docstring
Returns ellipsoid's acronym. Calculations will only use the
ellipsoid if ellipsoidalEnabled() is true and an ellipsoid has been set.
ellipsoid if a valid ellipsoid has been set.
\see setEllipsoid()
\see ellipsoidalEnabled()
\see willUseEllipsoid()
:rtype: str
%End
@ -129,18 +95,28 @@ Inverse flattening is calculated with invf = a/(a-b)
double ellipsoidSemiMajor() const;
%Docstring
Returns the ellipsoid's semi major axis.
\see ellipsoid()
\see ellipsoidSemiMinor()
\see ellipsoidInverseFlattening()
:rtype: float
%End
double ellipsoidSemiMinor() const;
%Docstring
Returns ellipsoid's semi minor axis.
\see ellipsoid()
\see ellipsoidSemiMajor()
\see ellipsoidInverseFlattening()
:rtype: float
%End
double ellipsoidInverseFlattening() const;
%Docstring
Returns ellipsoid's inverse flattening.
The inverse flattening is calculated with invf = a/(a-b).
\see ellipsoid()
\see ellipsoidSemiMajor()
\see ellipsoidSemiMinor()
:rtype: float
%End
@ -194,7 +170,7 @@ Inverse flattening is calculated with invf = a/(a-b)
double measureLine( const QgsPoint &p1, const QgsPoint &p2 ) const;
%Docstring
Measures length of a line with one segment.
Measures the distance between two points.
\param p1 start of line
\param p2 end of line
:return: distance between points. The units for the returned distance can be retrieved by calling lengthUnits().
@ -202,10 +178,9 @@ Inverse flattening is calculated with invf = a/(a-b)
:rtype: float
%End
double measureLineProjected( const QgsPoint &p1, double distance = 1, double azimuth = M_PI / 2, QgsPoint *projectedPoint /Out/ = 0 ) const;
%Docstring
Calculates distance from one point with distance in meters and azimuth (direction)
Calculates the distance from one point with distance in meters and azimuth (direction)
When the sourceCrs() is geographic, computeSpheroidProject() will be called
otherwise QgsPoint.project() will be called after QgsUnitTypes.fromUnitToUnitFactor() has been applied to the distance
\note:
@ -245,7 +220,7 @@ Inverse flattening is calculated with invf = a/(a-b)
double bearing( const QgsPoint &p1, const QgsPoint &p2 ) const;
%Docstring
Compute the bearing (in radians) between two points.
Computes the bearing (in radians) between two points.
:rtype: float
%End

View File

@ -119,7 +119,6 @@ class FieldsCalculator(GeoAlgorithm):
da = QgsDistanceArea()
da.setSourceCrs(layer.crs())
da.setEllipsoidalMode(True)
da.setEllipsoid(QgsProject.instance().ellipsoid())
exp.setGeomCalculator(da)
exp.setDistanceUnits(QgsProject.instance().distanceUnits())

View File

@ -121,7 +121,6 @@ class FieldsMapper(GeoAlgorithm):
da = QgsDistanceArea()
da.setSourceCrs(layer.crs())
da.setEllipsoidalMode(True)
da.setEllipsoid(QgsProject.instance().ellipsoid())
exp_context = layer.createExpressionContext()

View File

@ -33,7 +33,8 @@ from qgis.core import (QgsField,
QgsFeature,
QgsFeatureRequest,
QgsWkbTypes,
QgsApplication)
QgsApplication,
QgsProject)
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
@ -117,7 +118,7 @@ class HubDistanceLines(GeoAlgorithm):
distance = QgsDistanceArea()
distance.setSourceCrs(layerPoints.crs())
distance.setEllipsoidalMode(True)
distance.setEllipsoid(QgsProject.instance().ellipsoid())
# Scan source points, find nearest hub, and write to output file
features = vector.features(layerPoints)

View File

@ -33,7 +33,8 @@ from qgis.core import (QgsField,
QgsFeature,
QgsFeatureRequest,
QgsWkbTypes,
QgsApplication)
QgsApplication,
QgsProject)
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.core.parameters import ParameterVector
@ -117,7 +118,7 @@ class HubDistancePoints(GeoAlgorithm):
distance = QgsDistanceArea()
distance.setSourceCrs(layerPoints.crs())
distance.setEllipsoidalMode(True)
distance.setEllipsoid(QgsProject.instance().ellipsoid())
# Scan source points, find nearest hub, and write to output file
features = vector.features(layerPoints)

View File

@ -343,7 +343,6 @@ def simpleMeasure(geom, method=0, ellips=None, crs=None):
if method == 2:
measure.setSourceCrs(crs)
measure.setEllipsoid(ellips)
measure.setEllipsoidalMode(True)
if geom.type() == QgsWkbTypes.PolygonGeometry:
attr1 = measure.measureArea(geom)

View File

@ -48,7 +48,6 @@ class ANALYSIS_EXPORT QgsGraphBuilderInterface
{
mDa.setSourceCrs( mCrs );
mDa.setEllipsoid( ellipsoidID );
mDa.setEllipsoidalMode( ctfEnabled );
}
virtual ~QgsGraphBuilderInterface()

View File

@ -19,6 +19,7 @@
#include "qgsspatialindex.h"
#include "qgsvectorfilewriter.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
#include <QProgressDialog>
#include <QFileInfo>
#ifndef _MSC_VER
@ -126,11 +127,11 @@ int QgsTransectSample::createSample( QProgressDialog *pd )
distanceArea.setSourceCrs( mStrataLayer->crs() );
if ( mMinDistanceUnits == Meters )
{
distanceArea.setEllipsoidalMode( true );
distanceArea.setEllipsoid( QgsProject::instance()->ellipsoid() );
}
else
{
distanceArea.setEllipsoidalMode( false );
distanceArea.setEllipsoid( GEO_NONE );
}
//possibility to transform output points to lat/long

View File

@ -7734,7 +7734,6 @@ void QgisApp::selectByForm()
QgsDistanceArea myDa;
myDa.setSourceCrs( vlayer->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
QgsAttributeEditorContext context;

View File

@ -705,7 +705,6 @@ QgsAttributeDialog *QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeat
QgsDistanceArea myDa;
myDa.setSourceCrs( l->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
QgsAttributeEditorContext context;

View File

@ -200,7 +200,6 @@ void QgsAttributeActionPropertiesDialog::init( const QSet<QString> &actionScopes
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mFieldExpression->setLayer( mLayer );

View File

@ -125,7 +125,6 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QWidget
myDa = new QgsDistanceArea();
myDa->setSourceCrs( mLayer->crs() );
myDa->setEllipsoidalMode( true );
myDa->setEllipsoid( QgsProject::instance()->ellipsoid() );
mEditorContext.setDistanceArea( *myDa );
@ -588,7 +587,6 @@ void QgsAttributeTableDialog::filterExpressionBuilder()
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
dlg.setGeomCalculator( myDa );
@ -949,7 +947,6 @@ void QgsAttributeTableDialog::setFilterExpression( const QString &filterString,
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
// parse search string and build parsed tree

View File

@ -174,7 +174,6 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
mSizeFieldExpressionWidget->setLayer( mLayer );
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mSizeFieldExpressionWidget->setGeomCalculator( myDa );
@ -866,7 +865,6 @@ QString QgsDiagramProperties::showExpressionBuilder( const QString &initialExpre
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
dlg.setGeomCalculator( myDa );

View File

@ -57,7 +57,6 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
context.setDistanceArea( myDa );

View File

@ -56,7 +56,6 @@ QgsFieldCalculator::QgsFieldCalculator( QgsVectorLayer *vl, QWidget *parent )
QgsDistanceArea myDa;
myDa.setSourceCrs( vl->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
builder->setGeomCalculator( myDa );
@ -156,7 +155,6 @@ void QgsFieldCalculator::accept()
QgsDistanceArea myDa;
myDa.setSourceCrs( mVectorLayer->crs() );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
QString calcString = builder->expressionText();

View File

@ -108,7 +108,6 @@ void QgsLabelingGui::setLayer( QgsMapLayer *mapLayer )
mFieldExpressionWidget->setLayer( mLayer );
QgsDistanceArea da;
da.setSourceCrs( mLayer->crs() );
da.setEllipsoidalMode( true );
da.setEllipsoid( QgsProject::instance()->ellipsoid() );
mFieldExpressionWidget->setGeomCalculator( da );

View File

@ -185,5 +185,4 @@ void QgsMapToolMeasureAngle::configureDistanceArea()
QString ellipsoidId = QgsProject::instance()->ellipsoid();
mDa.setSourceCrs( mCanvas->mapSettings().destinationCrs() );
mDa.setEllipsoid( ellipsoidId );
mDa.setEllipsoidalMode( true );
}

View File

@ -106,7 +106,6 @@ void QgsMeasureDialog::updateSettings()
mAreaUnits = QgsProject::instance()->areaUnits();
mDa.setSourceCrs( mTool->canvas()->mapSettings().destinationCrs() );
mDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mDa.setEllipsoidalMode( true );
mTable->clear();
mTotal = 0;

View File

@ -536,18 +536,17 @@ void QgsComposerHtml::setExpressionContext( const QgsFeature &feature, QgsVector
//setup distance area conversion
if ( layer )
{
mDistanceArea->setSourceCrs( layer->crs().srsid() );
mDistanceArea->setSourceCrs( layer->crs() );
}
else if ( mComposition )
{
//set to composition's mapsettings' crs
QgsComposerMap *referenceMap = mComposition->referenceMap();
if ( referenceMap )
mDistanceArea->setSourceCrs( referenceMap->crs().srsid() );
mDistanceArea->setSourceCrs( referenceMap->crs() );
}
if ( mComposition )
{
mDistanceArea->setEllipsoidalMode( true );
mDistanceArea->setEllipsoid( mComposition->project()->ellipsoid() );
}

View File

@ -260,16 +260,15 @@ void QgsComposerLabel::refreshExpressionContext()
//setup distance area conversion
if ( layer )
{
mDistanceArea->setSourceCrs( layer->crs().srsid() );
mDistanceArea->setSourceCrs( layer->crs() );
}
else
{
//set to composition's reference map's crs
QgsComposerMap *referenceMap = mComposition->referenceMap();
if ( referenceMap )
mDistanceArea->setSourceCrs( referenceMap->crs().srsid() );
mDistanceArea->setSourceCrs( referenceMap->crs() );
}
mDistanceArea->setEllipsoidalMode( true );
mDistanceArea->setEllipsoid( mComposition->project()->ellipsoid() );
contentChanged();

View File

@ -339,14 +339,12 @@ double QgsComposerScaleBar::mapWidth() const
else
{
QgsDistanceArea da;
da.setEllipsoidalMode( true );
da.setSourceCrs( mComposerMap->crs() );
da.setEllipsoid( mComposition->project()->ellipsoid() );
QgsUnitTypes::DistanceUnit units = QgsUnitTypes::DistanceMeters;
QgsUnitTypes::DistanceUnit units = da.lengthUnits();
double measure = da.measureLine( QgsPoint( composerMapRect.xMinimum(), composerMapRect.yMinimum() ),
QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ),
units );
QgsPoint( composerMapRect.xMaximum(), composerMapRect.yMinimum() ) );
switch ( mUnits )
{
case QgsComposerScaleBar::Feet:

View File

@ -228,7 +228,7 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
* \param type One of the types described in CrsType
*/
// TODO QGIS 3: remove type and always use EPSG code
QgsCoordinateReferenceSystem( const long id, CrsType type = PostgisCrsId );
explicit QgsCoordinateReferenceSystem( const long id, CrsType type = PostgisCrsId );
//! Copy constructor
QgsCoordinateReferenceSystem( const QgsCoordinateReferenceSystem &srs );

View File

@ -52,24 +52,13 @@ QHash< QString, QgsDistanceArea::EllipsoidParameters > QgsDistanceArea::sEllipso
QgsDistanceArea::QgsDistanceArea()
{
// init with default settings
setSourceCrs( GEOCRS_ID ); // WGS 84
setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( GEOCRS_ID ) ); // WGS 84
setEllipsoid( GEO_NONE );
}
void QgsDistanceArea::setEllipsoidalMode( bool flag )
{
mEllipsoidalMode = flag;
}
bool QgsDistanceArea::willUseEllipsoid() const
{
return mEllipsoidalMode && mEllipsoid != GEO_NONE;
}
void QgsDistanceArea::setSourceCrs( long srsid )
{
QgsCoordinateReferenceSystem srcCRS = QgsCoordinateReferenceSystem::fromSrsId( srsid );
mCoordTransform.setSourceCrs( srcCRS );
return mEllipsoid != GEO_NONE;
}
void QgsDistanceArea::setSourceCrs( const QgsCoordinateReferenceSystem &srcCRS )
@ -77,12 +66,6 @@ void QgsDistanceArea::setSourceCrs( const QgsCoordinateReferenceSystem &srcCRS )
mCoordTransform.setSourceCrs( srcCRS );
}
void QgsDistanceArea::setSourceAuthId( const QString &authId )
{
QgsCoordinateReferenceSystem srcCRS = QgsCoordinateReferenceSystem::fromOgcWmsCrs( authId );
mCoordTransform.setSourceCrs( srcCRS );
}
bool QgsDistanceArea::setEllipsoid( const QString &ellipsoid )
{
// Shortcut if ellipsoid is none.
@ -483,15 +466,8 @@ double QgsDistanceArea::measureLine( const QList<QgsPoint> &points ) const
}
double QgsDistanceArea::measureLine( const QgsPoint &p1, const QgsPoint &p2 ) const
{
QgsUnitTypes::DistanceUnit units;
return measureLine( p1, p2, units );
}
double QgsDistanceArea::measureLine( const QgsPoint &p1, const QgsPoint &p2, QgsUnitTypes::DistanceUnit &units ) const
{
double result;
units = mCoordTransform.sourceCrs().mapUnits();
try
{
@ -500,7 +476,6 @@ double QgsDistanceArea::measureLine( const QgsPoint &p1, const QgsPoint &p2, Qgs
QgsDebugMsgLevel( QString( "Measuring from %1 to %2" ).arg( p1.toString( 4 ), p2.toString( 4 ) ), 3 );
if ( willUseEllipsoid() )
{
units = QgsUnitTypes::DistanceMeters;
QgsDebugMsgLevel( QString( "Ellipsoidal calculations is enabled, using ellipsoid %1" ).arg( mEllipsoid ), 4 );
QgsDebugMsgLevel( QString( "From proj4 : %1" ).arg( mCoordTransform.sourceCrs().toProj4() ), 4 );
QgsDebugMsgLevel( QString( "To proj4 : %1" ).arg( mCoordTransform.destinationCrs().toProj4() ), 4 );
@ -529,7 +504,7 @@ double QgsDistanceArea::measureLineProjected( const QgsPoint &p1, double distanc
{
double result = 0.0;
QgsPoint p2;
if ( geographic() && willUseEllipsoid() )
if ( mCoordTransform.sourceCrs().isGeographic() && willUseEllipsoid() )
{
p2 = computeSpheroidProject( p1, distance, azimuth );
result = p1.distance( p2 );

View File

@ -26,15 +26,24 @@ class QgsGeometry;
class QgsAbstractGeometry;
class QgsCurve;
/** \ingroup core
General purpose distance and area calculator.
- calculations are done on ellipsoid
- it's possible to pass points/features in any CRS, coordinates are transformed
- two options how to use it
+ use measure() takes QgsGeometry as a parameter and calculates distance or area
+ use directly measureLine(), measurePolygon() which take list of QgsPoints
(both cases transform the coordinates from source CRS to the ellipse coords)
- returned values are in meters resp. square meters
/**
* \ingroup core
* A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
*
* Measurements can either be performed on existing QgsGeometry objects, or using
* lists of points.
*
* If a valid ellipsoid() has been set for the QgsDistanceArea, all calculations will be
* performed using ellipsoidal algorithms (e.g. using Vincenty's formulas). If no
* ellipsoid has been set, all calculations will be performed using cartesian
* formulas only. The behavior can be determined by calling willUseEllipsoid().
*
* In order to perform accurate calculations, the source coordinate reference system
* of all measured geometries must first be specified using setSourceCrs().
*
* Usually, the measurements returned by QgsDistanceArea are in meters. If no valid
* ellipsoid is set, then the units may not be meters. The units can be retrieved
* by calling lengthUnits() and areaUnits().
*/
class CORE_EXPORT QgsDistanceArea
{
@ -43,104 +52,79 @@ class CORE_EXPORT QgsDistanceArea
//! Constructor
QgsDistanceArea();
/** Sets whether coordinates must be projected to ellipsoid before measuring
* \note for calculations to use the ellipsoid, both the ellipsoid mode must be true
* and an ellipse must be set
* \see setEllipsoid()
* \see willUseEllipsoid()
*/
void setEllipsoidalMode( bool flag );
/** Returns whether ellipsoidal calculations are enabled
* \see willUseEllipsoid()
* \see setEllipsoidalMode()
*/
bool ellipsoidalEnabled() const { return mEllipsoidalMode; }
/** Returns whether calculations will use the ellipsoid. Calculations will only use the
* ellipsoid if ellipsoidalEnabled() is true and an ellipsoid has been set.
/**
* Returns whether calculations will use the ellipsoid. Calculations will only use the
* ellipsoid if a valid ellipsoid() has been set.
* \since QGIS 2.14
* \see ellipsoidalEnabled()
* \see ellipsoid()
*/
bool willUseEllipsoid() const;
/**
* Sets source spatial reference system (by QGIS CRS).
*/
void setSourceCrs( long srsid );
/**
* Sets source spatial reference system (by QGIS CRS).
* Sets source spatial reference system.
* \since QGIS 2.2
* \see sourceCrs()
*/
void setSourceCrs( const QgsCoordinateReferenceSystem &srcCRS );
/**
* Sets source spatial reference system by authid.
*/
void setSourceAuthId( const QString &authid );
/** Returns the source spatial reference system.
* Returns the source spatial reference system.
* \see setSourceCrs()
*/
QgsCoordinateReferenceSystem sourceCrs() const { return mCoordTransform.sourceCrs(); }
/** Returns the QgsCoordinateReferenceSystem::srsid() for the CRS used during calculations.
* \see setSourceCrs()
* \since QGIS 2.14
*/
long sourceCrsId() const { return mCoordTransform.sourceCrs().srsid(); }
/**
* Returns true if a geographic (latitude/longitude based) source CRS is used.
*/
bool geographic() const { return mCoordTransform.sourceCrs().isGeographic(); }
/** Sets ellipsoid by its acronym. Calculations will only use the ellipsoid if
* both the ellipsoid has been set and ellipsoidalEnabled() is true.
* Sets the \a ellipsoid by its acronym.
* Calculations will only use the ellipsoid if a valid ellipsoid has been set.
* \returns true if ellipsoid was successfully set
* \see ellipsoid()
* \see setEllipsoidalMode()
* \see willUseEllipsoid()
*/
bool setEllipsoid( const QString &ellipsoid );
/** Sets ellipsoid by supplied radii. Calculations will only use the ellipsoid if
* both the ellipsoid has been set and ellipsoidalEnabled() is true.
/**
* Sets ellipsoid by supplied radii. Calculations will only use the ellipsoid if
* a valid ellipsoid been set.
* \returns true if ellipsoid was successfully set
* \see ellipsoid()
* \see setEllipsoidalMode()
* \see willUseEllipsoid()
*/
// Inverse flattening is calculated with invf = a/(a-b)
bool setEllipsoid( double semiMajor, double semiMinor );
/** Returns ellipsoid's acronym. Calculations will only use the
* ellipsoid if ellipsoidalEnabled() is true and an ellipsoid has been set.
* ellipsoid if a valid ellipsoid has been set.
* \see setEllipsoid()
* \see ellipsoidalEnabled()
* \see willUseEllipsoid()
*/
QString ellipsoid() const { return mEllipsoid; }
/**
* Returns the ellipsoid's semi major axis.
* \see ellipsoid()
* \see ellipsoidSemiMinor()
* \see ellipsoidInverseFlattening()
*/
double ellipsoidSemiMajor() const { return mSemiMajor; }
/**
* Returns ellipsoid's semi minor axis.
* \see ellipsoid()
* \see ellipsoidSemiMajor()
* \see ellipsoidInverseFlattening()
*/
double ellipsoidSemiMinor() const { return mSemiMinor; }
/**
* Returns ellipsoid's inverse flattening.
* The inverse flattening is calculated with invf = a/(a-b).
* \see ellipsoid()
* \see ellipsoidSemiMajor()
* \see ellipsoidSemiMinor()
*/
double ellipsoidInverseFlattening() const { return mInvFlattening; }
/** Measures the area of a geometry.
/**
* Measures the area of a geometry.
* \param geometry geometry to measure
* \returns area of geometry. For geometry collections, non surface geometries will be ignored. The units for the
* returned area can be retrieved by calling areaUnits().
@ -151,7 +135,8 @@ class CORE_EXPORT QgsDistanceArea
*/
double measureArea( const QgsGeometry &geometry ) const;
/** Measures the length of a geometry.
/**
* Measures the length of a geometry.
* \param geometry geometry to measure
* \returns length of geometry. For geometry collections, non curve geometries will be ignored. The units for the
* returned distance can be retrieved by calling lengthUnits().
@ -162,7 +147,8 @@ class CORE_EXPORT QgsDistanceArea
*/
double measureLength( const QgsGeometry &geometry ) const;
/** Measures the perimeter of a polygon geometry.
/**
* Measures the perimeter of a polygon geometry.
* \param geometry geometry to measure
* \returns perimeter of geometry. For geometry collections, any non-polygon geometries will be ignored. The units for the
* returned perimeter can be retrieved by calling lengthUnits().
@ -173,14 +159,16 @@ class CORE_EXPORT QgsDistanceArea
*/
double measurePerimeter( const QgsGeometry &geometry ) const;
/** Measures the length of a line with multiple segments.
/**
* Measures the length of a line with multiple segments.
* \param points list of points in line
* \returns length of line. The units for the returned length can be retrieved by calling lengthUnits().
* \see lengthUnits()
*/
double measureLine( const QList<QgsPoint> &points ) const;
/** Measures length of a line with one segment.
/**
* Measures the distance between two points.
* \param p1 start of line
* \param p2 end of line
* \returns distance between points. The units for the returned distance can be retrieved by calling lengthUnits().
@ -188,18 +176,8 @@ class CORE_EXPORT QgsDistanceArea
*/
double measureLine( const QgsPoint &p1, const QgsPoint &p2 ) const;
/** Measures length of line with one segment and returns units of distance.
* \param p1 start of line
* \param p2 end of line
* \param units will be set to units of measure
* \returns calculated distance between points. Distance units are stored in units parameter.
* \note Not available in Python bindings.
* \since QGIS 2.12
*/
SIP_SKIP double measureLine( const QgsPoint &p1, const QgsPoint &p2, QgsUnitTypes::DistanceUnit &units ) const;
/**
* Calculates distance from one point with distance in meters and azimuth (direction)
* Calculates the distance from one point with distance in meters and azimuth (direction)
* When the sourceCrs() is geographic, computeSpheroidProject() will be called
* otherwise QgsPoint.project() will be called after QgsUnitTypes::fromUnitToUnitFactor() has been applied to the distance
* \note:
@ -215,13 +193,15 @@ class CORE_EXPORT QgsDistanceArea
*/
double measureLineProjected( const QgsPoint &p1, double distance = 1, double azimuth = M_PI / 2, QgsPoint *projectedPoint SIP_OUT = nullptr ) const;
/** Returns the units of distance for length calculations made by this object.
/**
* Returns the units of distance for length calculations made by this object.
* \since QGIS 2.14
* \see areaUnits()
*/
QgsUnitTypes::DistanceUnit lengthUnits() const;
/** Returns the units of area for areal calculations made by this object.
/**
* Returns the units of area for areal calculations made by this object.
* \since QGIS 2.14
* \see lengthUnits()
*/
@ -233,11 +213,12 @@ class CORE_EXPORT QgsDistanceArea
double measurePolygon( const QList<QgsPoint> &points ) const;
/**
* Compute the bearing (in radians) between two points.
* Computes the bearing (in radians) between two points.
*/
double bearing( const QgsPoint &p1, const QgsPoint &p2 ) const;
/** Returns an distance formatted as a friendly string.
/**
* Returns an distance formatted as a friendly string.
* \param distance distance to format
* \param decimals number of decimal places to show
* \param unit unit of distance
@ -249,7 +230,8 @@ class CORE_EXPORT QgsDistanceArea
*/
static QString formatDistance( double distance, int decimals, QgsUnitTypes::DistanceUnit unit, bool keepBaseUnit = false );
/** Returns an area formatted as a friendly string.
/**
* Returns an area formatted as a friendly string.
* \param area area to format
* \param decimals number of decimal places to show
* \param unit unit of area
@ -261,7 +243,8 @@ class CORE_EXPORT QgsDistanceArea
*/
static QString formatArea( double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit = false );
/** Takes a length measurement calculated by this QgsDistanceArea object and converts it to a
/**
* Takes a length measurement calculated by this QgsDistanceArea object and converts it to a
* different distance unit.
* \param length length value calculated by this class to convert. It is assumed that the length
* was calculated by this class, ie that its unit of length is equal to lengthUnits().
@ -272,7 +255,8 @@ class CORE_EXPORT QgsDistanceArea
*/
double convertLengthMeasurement( double length, QgsUnitTypes::DistanceUnit toUnits ) const;
/** Takes an area measurement calculated by this QgsDistanceArea object and converts it to a
/**
* Takes an area measurement calculated by this QgsDistanceArea object and converts it to a
* different areal unit.
* \param area area value calculated by this class to convert. It is assumed that the area
* was calculated by this class, ie that its unit of area is equal to areaUnits().
@ -363,9 +347,6 @@ class CORE_EXPORT QgsDistanceArea
//! used for transforming coordinates from source CRS to ellipsoid's coordinates
QgsCoordinateTransform mCoordTransform;
//! indicates whether we will transform coordinates
bool mEllipsoidalMode = false;
//! ellipsoid acronym (from table tbl_ellipsoids)
QString mEllipsoid;

View File

@ -4402,7 +4402,6 @@ void QgsExpression::initGeomCalculator()
// Use planimetric as default
d->mCalc = std::shared_ptr<QgsDistanceArea>( new QgsDistanceArea() );
d->mCalc->setEllipsoidalMode( false );
}
void QgsExpression::detach()

View File

@ -26,7 +26,6 @@
#include "qgsproject.h"
QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( const QgsVectorLayer *layer )
: mCrsId( 0 )
{
QMutexLocker locker( &layer->mFeatureSourceConstructorMutex );
mProviderFeatureSource = layer->dataProvider()->featureSource();
@ -39,7 +38,7 @@ QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( const QgsVectorLayer *
mJoinBuffer = layer->mJoinBuffer->clone();
mExpressionFieldBuffer = new QgsExpressionFieldBuffer( *layer->mExpressionFieldBuffer );
mCrsId = layer->crs().srsid();
mCrs = layer->crs();
mHasEditBuffer = layer->editBuffer();
if ( mHasEditBuffer )
@ -543,8 +542,7 @@ void QgsVectorLayerFeatureIterator::prepareExpression( int fieldIdx )
QgsExpression *exp = new QgsExpression( exps[oi].cachedExpression );
QgsDistanceArea da;
da.setSourceCrs( mSource->mCrsId );
da.setEllipsoidalMode( true );
da.setSourceCrs( mSource->mCrs );
da.setEllipsoid( QgsProject::instance()->ellipsoid() );
exp->setGeomCalculator( &da );
exp->setDistanceUnits( QgsProject::instance()->distanceUnits() );

View File

@ -18,6 +18,7 @@
#include "qgis_core.h"
#include "qgsfeatureiterator.h"
#include "qgsfields.h"
#include "qgscoordinatereferencesystem.h"
#include <QSet>
#include <memory>
@ -74,7 +75,7 @@ class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource
QgsChangedAttributesMap mChangedAttributeValues;
QgsAttributeList mDeletedAttributeIds;
long mCrsId;
QgsCoordinateReferenceSystem mCrs;
};
/** \ingroup core

View File

@ -353,7 +353,6 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeatur
// init distance/area calculator
QString ellipsoid = QgsProject::instance()->ellipsoid();
QgsDistanceArea calc;
calc.setEllipsoidalMode( true );
calc.setEllipsoid( ellipsoid );
calc.setSourceCrs( layer->crs() );

View File

@ -76,9 +76,8 @@ void TestQgsDistanceArea::basic()
QCOMPARE( resultA, 5.0 );
// Now, on an ellipsoid. Always less?
daA.setSourceCrs( 3006 );
daA.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3006 ) );
daA.setEllipsoid( QStringLiteral( "WGS84" ) );
daA.setEllipsoidalMode( true );
resultA = daA.measureLine( p1, p2 );
QVERIFY( resultA < 5.0 );
@ -107,7 +106,6 @@ void TestQgsDistanceArea::basic()
void TestQgsDistanceArea::noEllipsoid()
{
QgsDistanceArea da;
da.setEllipsoidalMode( true );
da.setEllipsoid( GEO_NONE );
QVERIFY( !da.willUseEllipsoid() );
QCOMPARE( da.ellipsoid(), GEO_NONE );
@ -117,7 +115,6 @@ void TestQgsDistanceArea::cache()
{
// test that ellipsoid can be retrieved correctly from cache
QgsDistanceArea da;
da.setEllipsoidalMode( true );
// warm cache
QVERIFY( da.setEllipsoid( QStringLiteral( "Ganymede2000" ) ) );
@ -129,7 +126,6 @@ void TestQgsDistanceArea::cache()
// a second time, so ellipsoid is fetched from cache
QgsDistanceArea da2;
da2.setEllipsoidalMode( true );
QVERIFY( da2.setEllipsoid( QStringLiteral( "Ganymede2000" ) ) );
QVERIFY( da2.willUseEllipsoid() );
QCOMPARE( da2.ellipsoidSemiMajor(), 2632400.0 );
@ -139,7 +135,6 @@ void TestQgsDistanceArea::cache()
// using parameters
QgsDistanceArea da3;
da3.setEllipsoidalMode( true );
QVERIFY( da3.setEllipsoid( QStringLiteral( "PARAMETER:2631400:2341350" ) ) );
QVERIFY( da3.willUseEllipsoid() );
QCOMPARE( da3.ellipsoidSemiMajor(), 2631400.0 );
@ -149,7 +144,6 @@ void TestQgsDistanceArea::cache()
// again, to check parameters with cache
QgsDistanceArea da4;
da4.setEllipsoidalMode( true );
QVERIFY( da4.setEllipsoid( QStringLiteral( "PARAMETER:2631400:2341350" ) ) );
QVERIFY( da4.willUseEllipsoid() );
QCOMPARE( da4.ellipsoidSemiMajor(), 2631400.0 );
@ -159,14 +153,12 @@ void TestQgsDistanceArea::cache()
// invalid
QgsDistanceArea da5;
da5.setEllipsoidalMode( true );
QVERIFY( !da5.setEllipsoid( QStringLiteral( "MyFirstEllipsoid" ) ) );
QVERIFY( !da5.willUseEllipsoid() );
QCOMPARE( da5.ellipsoid(), GEO_NONE );
// invalid again, should be cached
QgsDistanceArea da6;
da6.setEllipsoidalMode( true );
QVERIFY( !da6.setEllipsoid( QStringLiteral( "MyFirstEllipsoid" ) ) );
QVERIFY( !da6.willUseEllipsoid() );
QCOMPARE( da6.ellipsoid(), GEO_NONE );
@ -185,8 +177,7 @@ void TestQgsDistanceArea::test_distances()
// Set up DA
QgsDistanceArea myDa;
myDa.setSourceAuthId( QStringLiteral( "EPSG:4030" ) );
myDa.setEllipsoidalMode( true );
myDa.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:4030" ) ) );
myDa.setEllipsoid( QStringLiteral( "WGS84" ) );
QString myFileName = QStringLiteral( TEST_DATA_DIR ) + "/GeodTest-nano.dat";
@ -224,9 +215,8 @@ void TestQgsDistanceArea::regression13601()
{
//test regression #13601
QgsDistanceArea calc;
calc.setEllipsoidalMode( true );
calc.setEllipsoid( QStringLiteral( "NONE" ) );
calc.setSourceCrs( 1108L );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 1108L ) );
QgsGeometry geom( QgsGeometryFactory::geomFromWkt( QStringLiteral( "Polygon ((252000 1389000, 265000 1389000, 265000 1385000, 252000 1385000, 252000 1389000))" ) ) );
QGSCOMPARENEAR( calc.measureArea( geom ), 52000000, 0.0001 );
}
@ -235,8 +225,7 @@ void TestQgsDistanceArea::collections()
{
//test measuring for collections
QgsDistanceArea myDa;
myDa.setSourceAuthId( QStringLiteral( "EPSG:4030" ) );
myDa.setEllipsoidalMode( true );
myDa.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:4030" ) ) );
myDa.setEllipsoid( QStringLiteral( "WGS84" ) );
//collection of lines, should be sum of line length
@ -267,21 +256,21 @@ void TestQgsDistanceArea::measureUnits()
{
//test regression #13610
QgsDistanceArea calc;
calc.setEllipsoidalMode( false );
calc.setEllipsoid( QStringLiteral( "NONE" ) );
calc.setSourceCrs( 254L );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 254L ) );
QgsUnitTypes::DistanceUnit units;
QgsPoint p1( 1341683.9854275715, 408256.9562717728 );
QgsPoint p2( 1349321.7807031618, 408256.9562717728 );
double result = calc.measureLine( p1, p2, units );
double result = calc.measureLine( p1, p2 );
units = calc.lengthUnits();
//no OTF, result will be in CRS unit (feet)
QCOMPARE( units, QgsUnitTypes::DistanceFeet );
QGSCOMPARENEAR( result, 7637.7952755903825, 0.001 );
calc.setEllipsoidalMode( true );
calc.setEllipsoid( QStringLiteral( "WGS84" ) );
result = calc.measureLine( p1, p2, units );
units = calc.lengthUnits();
result = calc.measureLine( p1, p2 );
//OTF, result will be in meters
QCOMPARE( units, QgsUnitTypes::DistanceMeters );
QGSCOMPARENEAR( result, 2328.0988253106957, 0.001 );
@ -290,11 +279,10 @@ void TestQgsDistanceArea::measureUnits()
void TestQgsDistanceArea::measureAreaAndUnits()
{
QgsDistanceArea da;
da.setSourceCrs( 3452 );
da.setEllipsoidalMode( false );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3452 ) );
da.setEllipsoid( QStringLiteral( "NONE" ) );
QgsCoordinateReferenceSystem daCRS;
daCRS.createFromSrsId( da.sourceCrsId() );
daCRS.createFromSrsId( da.sourceCrs().srsid() );
QgsPolyline ring;
ring << QgsPoint( 0, 0 )
<< QgsPoint( 1, 0 )
@ -321,15 +309,6 @@ void TestQgsDistanceArea::measureAreaAndUnits()
da.setEllipsoid( QStringLiteral( "WGS84" ) );
area = da.measureArea( polygon );
units = da.areaUnits();
QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) );
QVERIFY( ( qgsDoubleNear( area, 3.0, 0.00000001 ) && units == QgsUnitTypes::AreaSquareDegrees )
|| ( qgsDoubleNear( area, 37176087091.5, 0.1 ) && units == QgsUnitTypes::AreaSquareMeters ) );
da.setEllipsoidalMode( true );
area = da.measureArea( polygon );
units = da.areaUnits();
QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) );
// should always be in Meters Squared
QGSCOMPARENEAR( area, 37416879192.9, 0.1 );
@ -352,8 +331,8 @@ void TestQgsDistanceArea::measureAreaAndUnits()
poly << ring;
polygon = QgsGeometry::fromPolygon( poly );
da.setSourceCrs( 27469 );
da.setEllipsoidalMode( false );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 27469 ) );
da.setEllipsoid( QStringLiteral( "NONE" ) );
// measurement should be in square feet
area = da.measureArea( polygon );
units = da.areaUnits();
@ -365,7 +344,7 @@ void TestQgsDistanceArea::measureAreaAndUnits()
area = da.convertAreaMeasurement( area, QgsUnitTypes::AreaSquareYards );
QGSCOMPARENEAR( area, 222222.2222, 0.001 );
da.setEllipsoidalMode( true );
da.setEllipsoid( QStringLiteral( "WGS84" ) );
// now should be in Square Meters again
area = da.measureArea( polygon );
units = da.areaUnits();
@ -382,8 +361,7 @@ void TestQgsDistanceArea::measureAreaAndUnits()
void TestQgsDistanceArea::emptyPolygon()
{
QgsDistanceArea da;
da.setSourceCrs( 3452 );
da.setEllipsoidalMode( true );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3452 ) );
da.setEllipsoid( QStringLiteral( "WGS84" ) );
//test that measuring an empty polygon doesn't crash
@ -394,9 +372,8 @@ void TestQgsDistanceArea::regression14675()
{
//test regression #14675
QgsDistanceArea calc;
calc.setEllipsoidalMode( true );
calc.setEllipsoid( QStringLiteral( "GRS80" ) );
calc.setSourceCrs( 145L );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 145L ) );
QgsGeometry geom( QgsGeometryFactory::geomFromWkt( QStringLiteral( "Polygon ((917593.5791854317067191 6833700.00807378999888897, 917596.43389983859378844 6833700.67099479306489229, 917599.53056440979707986 6833700.78673478215932846, 917593.5791854317067191 6833700.00807378999888897))" ) ) );
//lots of tolerance here - the formulas get quite unstable with small areas due to division by very small floats
QGSCOMPARENEAR( calc.measureArea( geom ), 0.83301, 0.02 );

View File

@ -1878,9 +1878,8 @@ class TestQgsExpression: public QObject
{
//test calculations with and without geometry calculator set
QgsDistanceArea da;
da.setSourceAuthId( QStringLiteral( "EPSG:3111" ) );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:3111" ) ) );
da.setEllipsoid( QStringLiteral( "WGS84" ) );
da.setEllipsoidalMode( true );
QgsFeature feat;
QgsPolyline polygonRing3111;

View File

@ -250,13 +250,13 @@ class TestQgsPointLocator : public QObject
void testExtent()
{
QgsRectangle bbox1( 10, 10, 11, 11 ); // out of layer's bounds
QgsPointLocator loc1( mVL, 0, &bbox1 );
QgsPointLocator loc1( mVL, QgsCoordinateReferenceSystem(), &bbox1 );
QgsPointLocator::Match m1 = loc1.nearestVertex( QgsPoint( 2, 2 ), 999 );
QVERIFY( !m1.isValid() );
QgsRectangle bbox2( 0, 0, 1, 1 ); // in layer's bounds
QgsPointLocator loc2( mVL, 0, &bbox2 );
QgsPointLocator loc2( mVL, QgsCoordinateReferenceSystem(), &bbox2 );
QgsPointLocator::Match m2 = loc2.nearestVertex( QgsPoint( 2, 2 ), 999 );
QVERIFY( m2.isValid() );
@ -272,7 +272,7 @@ class TestQgsPointLocator : public QObject
flist << ff;
vlNullGeom->dataProvider()->addFeatures( flist );
QgsPointLocator loc( vlNullGeom, 0, nullptr );
QgsPointLocator loc( vlNullGeom, QgsCoordinateReferenceSystem(), nullptr );
QgsPointLocator::Match m1 = loc.nearestVertex( QgsPoint( 2, 2 ), std::numeric_limits<double>::max() );
QVERIFY( !m1.isValid() );
@ -294,7 +294,7 @@ class TestQgsPointLocator : public QObject
flist << ff;
vlEmptyGeom->dataProvider()->addFeatures( flist );
QgsPointLocator loc( vlEmptyGeom, 0, nullptr );
QgsPointLocator loc( vlEmptyGeom, QgsCoordinateReferenceSystem(), nullptr );
QgsPointLocator::Match m1 = loc.nearestVertex( QgsPoint( 2, 2 ), std::numeric_limits<double>::max() );
QVERIFY( !m1.isValid() );

View File

@ -38,14 +38,10 @@ class TestQgsDistanceArea(unittest.TestCase):
# test setting/getting the source CRS
da = QgsDistanceArea()
# try setting using a crs id
da.setSourceCrs(3452)
self.assertEqual(da.sourceCrsId(), 3452)
# try setting using a CRS object
crs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId)
da.setSourceCrs(crs)
self.assertEqual(da.sourceCrsId(), crs.srsid())
self.assertEqual(da.sourceCrs().srsid(), crs.srsid())
def testMeasureLine(self):
# +-+
@ -68,16 +64,14 @@ class TestQgsDistanceArea(unittest.TestCase):
da_3068 = QgsDistanceArea()
da_wsg84 = QgsDistanceArea()
da_3068.setSourceAuthId('EPSG:3068')
da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'))
if (da_3068.sourceCrs().isGeographic()):
da_3068.setEllipsoid(da_3068.sourceCrs().ellipsoidAcronym())
da_3068.setEllipsoidalMode(True)
print(("setting [{}] srid [{}] description [{}]".format(u'Soldner Berlin', da_3068.sourceCrs().authid(), da_3068.sourceCrs().description())))
self.assertEqual(da_3068.sourceCrs().authid(), 'EPSG:3068')
da_wsg84.setSourceAuthId('EPSG:4326')
da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'))
if (da_wsg84.sourceCrs().isGeographic()):
da_wsg84.setEllipsoid(da_wsg84.sourceCrs().ellipsoidAcronym())
da_wsg84.setEllipsoidalMode(True)
self.assertEqual(da_wsg84.sourceCrs().authid(), 'EPSG:4326')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}]".format(u'Wsg84', da_wsg84.sourceCrs().authid(), da_wsg84.sourceCrs().description(), da_wsg84.sourceCrs().isGeographic())))
# print(("-- projectionAcronym[{}] ellipsoidAcronym[{}] toWkt[{}] mapUnits[{}] toProj4[{}]".format(da_wsg84.sourceCrs().projectionAcronym(),da_wsg84.sourceCrs().ellipsoidAcronym(), da_wsg84.sourceCrs().toWkt(),da_wsg84.sourceCrs().mapUnits(),da_wsg84.sourceCrs().toProj4())))
@ -138,45 +132,39 @@ class TestQgsDistanceArea(unittest.TestCase):
# +-+ +
# checking returned length_mapunits/projected_points of diffferent world points with results from spatialite ST_Project
da_3068 = QgsDistanceArea()
da_3068.setSourceAuthId('EPSG:3068')
da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'))
if (da_3068.sourceCrs().isGeographic()):
da_3068.setEllipsoid(da_3068.sourceCrs().ellipsoidAcronym())
da_3068.setEllipsoidalMode(True)
self.assertEqual(da_3068.sourceCrs().authid(), 'EPSG:3068')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:3068', da_3068.sourceCrs().authid(), da_3068.sourceCrs().description(), da_3068.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_3068.lengthUnits()), da_3068.sourceCrs().projectionAcronym(), da_3068.sourceCrs().ellipsoidAcronym())))
da_wsg84 = QgsDistanceArea()
da_wsg84.setSourceAuthId('EPSG:4326')
da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'))
if (da_wsg84.sourceCrs().isGeographic()):
da_wsg84.setEllipsoid(da_wsg84.sourceCrs().ellipsoidAcronym())
da_wsg84.setEllipsoidalMode(True)
self.assertEqual(da_wsg84.sourceCrs().authid(), 'EPSG:4326')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}] ellipsoid[{}]".format(u'EPSG:4326', da_wsg84.sourceCrs().authid(), da_wsg84.sourceCrs().description(), da_wsg84.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_wsg84.lengthUnits()), da_wsg84.sourceCrs().projectionAcronym(), da_wsg84.sourceCrs().ellipsoidAcronym(), da_wsg84.ellipsoid())))
da_4314 = QgsDistanceArea()
da_4314.setSourceAuthId('EPSG:4314')
da_4314.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4314'))
if (da_4314.sourceCrs().isGeographic()):
da_4314.setEllipsoid(da_4314.sourceCrs().ellipsoidAcronym())
da_4314.setEllipsoidalMode(True)
self.assertEqual(da_4314.sourceCrs().authid(), 'EPSG:4314')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:4314', da_4314.sourceCrs().authid(), da_4314.sourceCrs().description(), da_4314.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_4314.lengthUnits()), da_4314.sourceCrs().projectionAcronym(), da_4314.sourceCrs().ellipsoidAcronym())))
da_4805 = QgsDistanceArea()
da_4805.setSourceAuthId('EPSG:4805')
da_4805.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4805'))
if (da_4805.sourceCrs().isGeographic()):
da_4805.setEllipsoid(da_4805.sourceCrs().ellipsoidAcronym())
da_4805.setEllipsoidalMode(True)
self.assertEqual(da_4805.sourceCrs().authid(), 'EPSG:4805')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:4805', da_4805.sourceCrs().authid(), da_4805.sourceCrs().description(), da_4805.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_4805.lengthUnits()), da_4805.sourceCrs().projectionAcronym(), da_4805.sourceCrs().ellipsoidAcronym())))
da_5665 = QgsDistanceArea()
da_5665.setSourceAuthId('EPSG:5665')
da_5665.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:5665'))
if (da_5665.sourceCrs().isGeographic()):
da_5665.setEllipsoid(da_5665.sourceCrs().ellipsoidAcronym())
da_5665.setEllipsoidalMode(True)
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:5665', da_5665.sourceCrs().authid(), da_5665.sourceCrs().description(), da_5665.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_5665.lengthUnits()), da_5665.sourceCrs().projectionAcronym(), da_5665.sourceCrs().ellipsoidAcronym())))
self.assertEqual(da_5665.sourceCrs().authid(), 'EPSG:5665')
da_25833 = QgsDistanceArea()
da_25833.setSourceAuthId('EPSG:25833')
da_25833.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:25833'))
if (da_25833.sourceCrs().isGeographic()):
da_25833.setEllipsoid(da_25833.sourceCrs().ellipsoidAcronym())
da_25833.setEllipsoidalMode(True)
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:25833', da_25833.sourceCrs().authid(), da_25833.sourceCrs().description(), da_25833.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_25833.lengthUnits()), da_25833.sourceCrs().projectionAcronym(), da_25833.sourceCrs().ellipsoidAcronym())))
self.assertEqual(da_25833.sourceCrs().authid(), 'EPSG:25833')
@ -463,18 +451,11 @@ class TestQgsDistanceArea(unittest.TestCase):
"""test QgsDistanceArea::willUseEllipsoid """
da = QgsDistanceArea()
da.setEllipsoidalMode(False)
da.setEllipsoid("NONE")
self.assertFalse(da.willUseEllipsoid())
da.setEllipsoidalMode(True)
self.assertFalse(da.willUseEllipsoid())
da.setEllipsoid("WGS84")
assert da.willUseEllipsoid()
da.setEllipsoidalMode(False)
self.assertFalse(da.willUseEllipsoid())
self.assertTrue(da.willUseEllipsoid())
def testLengthMeasureAndUnits(self):
"""Test a variety of length measurements in different CRS and ellipsoid modes, to check that the
@ -482,8 +463,7 @@ class TestQgsDistanceArea(unittest.TestCase):
"""
da = QgsDistanceArea()
da.setSourceCrs(3452)
da.setEllipsoidalMode(False)
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452))
da.setEllipsoid("NONE")
# We check both the measured length AND the units, in case the logic regarding
@ -499,14 +479,6 @@ class TestQgsDistanceArea(unittest.TestCase):
distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
units = da.lengthUnits()
print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units))))
assert ((abs(distance - 2.23606797) < 0.00000001 and units == QgsUnitTypes.DistanceDegrees) or
(abs(distance - 248.52) < 0.01 and units == QgsUnitTypes.DistanceMeters))
da.setEllipsoidalMode(True)
distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
units = da.lengthUnits()
print(("measured {} in {}".format(distance, QgsUnitTypes.toString(units))))
# should always be in Meters
self.assertAlmostEqual(distance, 247555.57, delta=0.01)
@ -517,8 +489,8 @@ class TestQgsDistanceArea(unittest.TestCase):
self.assertAlmostEqual(distance, 133.669, delta=0.01)
# now try with a source CRS which is in feet
da.setSourceCrs(27469)
da.setEllipsoidalMode(False)
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469))
da.setEllipsoid("NONE")
# measurement should be in feet
distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
units = da.lengthUnits()
@ -530,7 +502,7 @@ class TestQgsDistanceArea(unittest.TestCase):
distance = da.convertLengthMeasurement(distance, QgsUnitTypes.DistanceMeters)
self.assertAlmostEqual(distance, 0.6815, delta=0.001)
da.setEllipsoidalMode(True)
da.setEllipsoid("WGS84")
# now should be in Meters again
distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
units = da.lengthUnits()
@ -548,8 +520,7 @@ class TestQgsDistanceArea(unittest.TestCase):
"""
da = QgsDistanceArea()
da.setSourceCrs(3452)
da.setEllipsoidalMode(False)
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452))
da.setEllipsoid("NONE")
polygon = QgsGeometry.fromPolygon(
@ -571,14 +542,6 @@ class TestQgsDistanceArea(unittest.TestCase):
area = da.measureArea(polygon)
units = da.areaUnits()
print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
assert ((abs(area - 3.0) < 0.00000001 and units == QgsUnitTypes.AreaSquareDegrees) or
(abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.AreaSquareMeters))
da.setEllipsoidalMode(True)
area = da.measureArea(polygon)
units = da.areaUnits()
print(("measured {} in {}".format(area, QgsUnitTypes.toString(units))))
# should always be in Meters Squared
self.assertAlmostEqual(area, 37416879192.9, delta=0.1)
@ -594,8 +557,8 @@ class TestQgsDistanceArea(unittest.TestCase):
QgsPoint(1850000, 4423000), QgsPoint(1851000, 4423000), QgsPoint(1851000, 4424000), QgsPoint(1852000, 4424000), QgsPoint(1852000, 4425000), QgsPoint(1851000, 4425000), QgsPoint(1850000, 4423000)
]]
)
da.setSourceCrs(27469)
da.setEllipsoidalMode(False)
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469))
da.setEllipsoid("NONE")
# measurement should be in square feet
area = da.measureArea(polygon)
units = da.areaUnits()
@ -607,7 +570,7 @@ class TestQgsDistanceArea(unittest.TestCase):
area = da.convertAreaMeasurement(area, QgsUnitTypes.AreaSquareYards)
self.assertAlmostEqual(area, 222222.2222, delta=0.001)
da.setEllipsoidalMode(True)
da.setEllipsoid("WGS84")
# now should be in Square Meters again
area = da.measureArea(polygon)
units = da.areaUnits()