Skip to content

Commit

Permalink
Merge pull request #222 from homann/test_DA
Browse files Browse the repository at this point in the history
Test of QgsDistanceArea + functionality addition
  • Loading branch information
timlinux committed Sep 3, 2012
2 parents ff7b21d + bb3d86b commit 56c15dc
Show file tree
Hide file tree
Showing 7 changed files with 354 additions and 0 deletions.
10 changes: 10 additions & 0 deletions python/core/qgsdistancearea.sip
Expand Up @@ -13,6 +13,12 @@ class QgsDistanceArea
//! Destructor
~QgsDistanceArea();

//! Copy constructor
QgsDistanceArea(const QgsDistanceArea & origDA );

//! Assignment operator
operator=(const QgsDistanceArea & origDA );

//! sets whether coordinates must be projected to ellipsoid before measuring
void setEllipsoidalMode(bool flag);
void setProjectionsEnabled(bool flag) /Deprecated/;
Expand All @@ -39,6 +45,10 @@ class QgsDistanceArea
//! sets ellipsoid by its acronym
bool setEllipsoid(const QString& ellipsoid);

//! Sets ellipsoid by supplied radii
// Inverse flattening is calculated with invf = a/(a-b)
bool setEllipsoid( double semiMajor, double semiMinor );

//! returns ellipsoid's acronym
const QString& ellipsoid();

Expand Down
49 changes: 49 additions & 0 deletions src/core/qgsdistancearea.cpp
Expand Up @@ -48,11 +48,44 @@ QgsDistanceArea::QgsDistanceArea()
}


//! Copy constructor
QgsDistanceArea::QgsDistanceArea( const QgsDistanceArea & origDA )
{
_copy( origDA );
}

QgsDistanceArea::~QgsDistanceArea()
{
delete mCoordTransform;
}

//! Assignment operator
QgsDistanceArea & QgsDistanceArea::operator=( const QgsDistanceArea & origDA )
{
if ( this == & origDA )
{
// Do not copy unto self
return *this;
}
_copy( origDA );
return *this;
}

//! Copy helper. Avoid Sqlite3 accesses.
void QgsDistanceArea::_copy( const QgsDistanceArea & origDA )
{
mEllipsoidalMode = origDA.mEllipsoidalMode;
mEllipsoid = origDA.mEllipsoid;
mSemiMajor = origDA.mSemiMajor;
mSemiMinor = origDA.mSemiMinor;
mInvFlattening = origDA.mInvFlattening;
// Some calculations and trig. Should not be TOO time consuming.
// Alternatively we could copy the temp vars?
computeAreaInit();
mSourceRefSys = origDA.mSourceRefSys;
mCoordTransform = new QgsCoordinateTransform( origDA.mCoordTransform->sourceCrs(), origDA.mCoordTransform->destCRS() );
}

void QgsDistanceArea::setEllipsoidalMode( bool flag )
{
mEllipsoidalMode = flag;
Expand Down Expand Up @@ -175,6 +208,22 @@ bool QgsDistanceArea::setEllipsoid( const QString& ellipsoid )
return true;
}

//! Sets ellipsoid by supplied radii
// Inverse flattening is calculated with invf = a/(a-b)
// Also, b = a-(a/invf)
bool QgsDistanceArea::setEllipsoid( double semiMajor, double semiMinor )
{
mEllipsoid = "PARAMETER";
mSemiMajor = semiMajor;
mSemiMinor = semiMinor;
mInvFlattening = mSemiMajor / ( mSemiMajor - mSemiMinor );

computeAreaInit();

return true;
}



double QgsDistanceArea::measure( QgsGeometry* geometry )
{
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgsdistancearea.h
Expand Up @@ -40,6 +40,12 @@ class CORE_EXPORT QgsDistanceArea
//! Destructor
~QgsDistanceArea();

//! Copy constructor
QgsDistanceArea( const QgsDistanceArea & origDA );

//! Assignment operator
QgsDistanceArea & operator=( const QgsDistanceArea & origDA );

//! sets whether coordinates must be projected to ellipsoid before measuring
void setEllipsoidalMode( bool flag );
Q_DECL_DEPRECATED void setProjectionsEnabled( bool flag ) { setEllipsoidalMode( flag ); };
Expand All @@ -65,6 +71,10 @@ class CORE_EXPORT QgsDistanceArea
//! sets ellipsoid by its acronym
bool setEllipsoid( const QString& ellipsoid );

//! Sets ellipsoid by supplied radii
// Inverse flattening is calculated with invf = a/(a-b)
bool setEllipsoid( double semiMajor, double semiMinor );

//! returns ellipsoid's acronym
const QString& ellipsoid() { return mEllipsoid; }

Expand Down Expand Up @@ -134,6 +144,8 @@ class CORE_EXPORT QgsDistanceArea
void computeAreaInit();

private:
//! Copy helper
void _copy( const QgsDistanceArea & origDA );

//! used for transforming coordinates from source CRS to ellipsoid's coordinates
QgsCoordinateTransform* mCoordTransform;
Expand Down
1 change: 1 addition & 0 deletions tests/src/core/CMakeLists.txt
Expand Up @@ -78,6 +78,7 @@ ENDMACRO (ADD_QGIS_TEST)
#############################################################
# Tests:

ADD_QGIS_TEST(distanceareatest testqgsdistancearea.cpp)
ADD_QGIS_TEST(applicationtest testqgsapplication.cpp)
ADD_QGIS_TEST(expressiontest testqgsexpression.cpp)
ADD_QGIS_TEST(filewritertest testqgsvectorfilewriter.cpp)
Expand Down
169 changes: 169 additions & 0 deletions tests/src/core/testqgsdistancearea.cpp
@@ -0,0 +1,169 @@
/***************************************************************************
testqgsdistancearea.cpp
--------------------------------------
Date : Tue 14 Aug 2012
Copyright : (C) 2012 by Magnus Homann
Email : magnus at homann dot se
***************************************************************************
* *
* 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 <QtTest>
#include <QFile>
#include <QTextStream>
#include <QObject>
#include <QString>
#include <QStringList>
#include <qgsapplication.h>
//header for class being tested
#include <qgsdistancearea.h>
#include <qgspoint.h>
#include "qgslogger.h"

class TestQgsDistanceArea: public QObject
{

Q_OBJECT;
private slots:
void initTestCase();
void basic();
void test_distances();
void unit_conversions();
};

void TestQgsDistanceArea::initTestCase()
{
//
// Runs once before any tests are run
//
// init QGIS's paths - true means that all path will be inited from prefix
QgsApplication::init();
QgsApplication::initQgis();
QgsApplication::showSettings();
}

void TestQgsDistanceArea::basic()
{
QgsPoint p1( 1.0, 3.0 ), p2( -2.0, -1.0 );
QgsDistanceArea daA;
double resultA, resultB, resultC;

daA.setEllipsoid( "NONE" );
resultA = daA.measureLine( p1, p2 );
QCOMPARE( resultA, 5.0 );

// Now, on an ellipsoid. Always less?
daA.setSourceCrs( 3006 );
daA.setEllipsoid( "WGS84" );
daA.setEllipsoidalMode( true );
resultA = daA.measureLine( p1, p2 );
QVERIFY( resultA < 5.0 );

// Test copy constructor
QgsDistanceArea daB( daA );
resultB = daB.measureLine( p1, p2 );
QCOMPARE( resultA, resultB );

// Different Ellipsoid
daB.setEllipsoid( "WGS72" );
resultB = daB.measureLine( p1, p2 );
QVERIFY( ! qFuzzyCompare( resultA, resultB ) );

// Test assignment
QgsDistanceArea * daC;
daC = new QgsDistanceArea;
*daC = daB;
resultC = daC->measureLine( p1, p2 );
QCOMPARE( resultB, resultC );
delete daC;

// Use parameter setting of ellipsoid radii (from WGS72 )
daA.setEllipsoid( 6378135.0, 6378135.0 - ( 6378135.0 / 298.26 ) );
resultA = daA.measureLine( p1, p2 );
QCOMPARE( resultA, resultB );
};

void TestQgsDistanceArea::test_distances()
{
// Read the file of Geod data
// Column 0 (first) is latitude point 1
// Column 1 is longitude point 1
// Column 3 is latitude point 2
// Column 4 is longitude point 3
// Column 6 is the resulting distance in meters on the WGS84 ellipsoid
// Note: lat is north/south, so the QgsPoint should be ( long, lat )
// See http://geographiclib.sourceforge.net/html/geodesic.html#testgeod

// Set up DA
QgsDistanceArea myDa;
myDa.setSourceAuthId( "EPSG:4030" );
myDa.setEllipsoidalMode( true );
myDa.setEllipsoid( "WGS84" );

QString myFileName = QString( TEST_DATA_DIR ) + QDir::separator() + "GeodTest-nano.dat";

QFile myFile( myFileName );
if ( ! myFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
{
QFAIL( "Couldn't open file" );
return;
}
QTextStream in( & myFile );
while ( !in.atEnd() )
{
QString line = in.readLine();
// Some test points (antipodal) does not converge with the chosen algorithm!
// See calcaulator at http://www.movable-type.co.uk/scripts/latlong-vincenty.html
// These are commented out.
if ( line[0] != '#' )
{
QStringList myLineList = line.split( ' ' ); // Split fields on space.
// Create points
QgsPoint p1( myLineList[1].toDouble(), myLineList[0].toDouble() );
QgsPoint p2( myLineList[4].toDouble(), myLineList[3].toDouble() );
double result = myDa.measureLine( p1, p2 );
// QgsDebugMsg( QString( "Distance from %1 to %2 is %3" ).arg( p1.toString( 15 ) ).arg( p2.toString( 15 ) ).arg( result, 0, 'g', 15 ) );
// QgsDebugMsg( QString( "Distance should be %1" ).arg( myLineList[6] ) );
// Check result is less than 0.5mm from expected.
QVERIFY( qAbs( result - myLineList[6].toDouble() ) < 0.0005 );
}
}

};

void TestQgsDistanceArea::unit_conversions()
{
// Do some very simple test of conversion and units
QgsDistanceArea myDa;
myDa.setEllipsoidalMode( "NONE" );

double inputValue;
QGis::UnitType inputUnit;
QGis::UnitType outputUnit;

inputValue = 10000.0;
inputUnit = QGis::Meters;
outputUnit = QGis::Feet;
//outputUnit = QGis::Meters;

// First, convert from sq.meter to sq.feet
myDa.convertMeasurement( inputValue, inputUnit, outputUnit, true );
QVERIFY( qAbs( inputValue - 107639.1041671 ) <= 0.0000001 );

// The print a text unit. This is i18n, so we should ignore the unit
// and use the locale settings for separation of digits.
QString myTxt = QgsDistanceArea::textUnit( inputValue, 7, inputUnit, true, false );
QString expectedTxt = QLocale::system().toString( 2.4710538146717, 'g', 1 + 7 );
QVERIFY( myTxt.startsWith( expectedTxt ) ); // Ignore units for now.
};

QTEST_MAIN( TestQgsDistanceArea )
#include "moc_testqgsdistancearea.cxx"




0 comments on commit 56c15dc

Please sign in to comment.