[composer] Improvements to grid annotation string formatting (sponsored

by NIWA, New Zealand):
- Don't show directional suffix for 0 or 180 latitudes or 180 longitudes
- Add padded coordinate modes
- Fix precision errors causing minutes/seconds > 60
- Wraparound longitudes to restrict them to the -180 to 180 degree range
This commit is contained in:
Nyall Dawson 2014-09-03 20:40:24 +10:00
parent 8c091bbda5
commit f68b2586b9
7 changed files with 693 additions and 45 deletions

View File

@ -57,16 +57,26 @@ class QgsPoint
/** Return a string representation as degrees minutes seconds. /** Return a string representation as degrees minutes seconds.
* Its up to the calling function to ensure that this point can * Its up to the calling function to ensure that this point can
* be meaningfully represented in this form. * be meaningfully represented in this form.
* @param thePrecision number of decimal points to use for seconds
* @param useSuffix set to true to include a direction suffix (eg 'N'),
* set to false to use a "-" prefix for west and south coordinates
* @param padded set to true to force minutes and seconds to use two decimals,
* eg, '05' instead of '5'.
* @note added in QGIS 1.4 * @note added in QGIS 1.4
*/ */
QString toDegreesMinutesSeconds( int thePrecision ) const; QString toDegreesMinutesSeconds( int thePrecision, const bool useSuffix = true, const bool padded = false ) const;
/** Return a string representation as degrees minutes. /** Return a string representation as degrees minutes.
* Its up to the calling function to ensure that this point can * Its up to the calling function to ensure that this point can
* be meaningfully represented in this form. * be meaningfully represented in this form.
* @param thePrecision number of decimal points to use for minutes
* @param useSuffix set to true to include a direction suffix (eg 'N'),
* set to false to use a "-" prefix for west and south coordinates
* @param padded set to true to force minutes to use two decimals,
* eg, '05' instead of '5'.
* @note added in QGIS 1.9 * @note added in QGIS 1.9
*/ */
QString toDegreesMinutes( int thePrecision ) const; QString toDegreesMinutes( int thePrecision, const bool useSuffix = true, const bool padded = false ) const;
/*! Return the well known text representation for the point. /*! Return the well known text representation for the point.

View File

@ -66,8 +66,14 @@ QgsComposerMapWidget::QgsComposerMapWidget( QgsComposerMap* composerMap ): QgsCo
mGridTypeComboBox->insertItem( 3, tr( "Frame and annotations only" ) ); mGridTypeComboBox->insertItem( 3, tr( "Frame and annotations only" ) );
mAnnotationFormatComboBox->insertItem( 0, tr( "Decimal" ) ); mAnnotationFormatComboBox->insertItem( 0, tr( "Decimal" ) );
mAnnotationFormatComboBox->insertItem( 1, tr( "DegreeMinute" ) ); mAnnotationFormatComboBox->insertItem( 1, tr( "Decimal with suffix" ) );
mAnnotationFormatComboBox->insertItem( 2, tr( "DegreeMinuteSecond" ) ); mAnnotationFormatComboBox->insertItem( 2, tr( "Degree, minute" ) );
mAnnotationFormatComboBox->insertItem( 3, tr( "Degree, minute with suffix" ) );
mAnnotationFormatComboBox->insertItem( 4, tr( "Degree, minute aligned" ) );
mAnnotationFormatComboBox->insertItem( 5, tr( "Degree, minute, second" ) );
mAnnotationFormatComboBox->insertItem( 6, tr( "Degree, minute, second with suffix" ) );
mAnnotationFormatComboBox->insertItem( 7, tr( "Degree, minute, second aligned" ) );
mAnnotationFontColorButton->setColorDialogTitle( tr( "Select font color" ) ); mAnnotationFontColorButton->setColorDialogTitle( tr( "Select font color" ) );
mAnnotationFontColorButton->setColorDialogOptions( QColorDialog::ShowAlphaChannel ); mAnnotationFontColorButton->setColorDialogOptions( QColorDialog::ShowAlphaChannel );
@ -1265,8 +1271,33 @@ void QgsComposerMapWidget::setGridItems( const QgsComposerMapGrid* grid )
mAnnotationFontColorButton->setColor( grid->gridAnnotationFontColor() ); mAnnotationFontColorButton->setColor( grid->gridAnnotationFontColor() );
//mAnnotationFormatComboBox //mAnnotationFormatComboBox
QgsComposerMap::GridAnnotationFormat gf = grid->gridAnnotationFormat(); switch ( grid->gridAnnotationFormat() )
mAnnotationFormatComboBox->setCurrentIndex(( int )gf ); {
case QgsComposerMap::Decimal:
mAnnotationFormatComboBox->setCurrentIndex( 0 );
break;
case QgsComposerMap::DegreeMinute:
mAnnotationFormatComboBox->setCurrentIndex( 3 );
break;
case QgsComposerMap::DegreeMinuteSecond:
mAnnotationFormatComboBox->setCurrentIndex( 6 );
break;
case QgsComposerMap::DecimalWithSuffix:
mAnnotationFormatComboBox->setCurrentIndex( 1 );
break;
case QgsComposerMap::DegreeMinuteNoSuffix:
mAnnotationFormatComboBox->setCurrentIndex( 2 );
break;
case QgsComposerMap::DegreeMinutePadded:
mAnnotationFormatComboBox->setCurrentIndex( 4 );
break;
case QgsComposerMap::DegreeMinuteSecondNoSuffix:
mAnnotationFormatComboBox->setCurrentIndex( 5 );
break;
case QgsComposerMap::DegreeMinuteSecondPadded:
mAnnotationFormatComboBox->setCurrentIndex( 7 );
break;
}
mDistanceToMapFrameSpinBox->setValue( grid->annotationFrameDistance() ); mDistanceToMapFrameSpinBox->setValue( grid->annotationFrameDistance() );
mCoordinatePrecisionSpinBox->setValue( grid->gridAnnotationPrecision() ); mCoordinatePrecisionSpinBox->setValue( grid->gridAnnotationPrecision() );
@ -1851,7 +1882,35 @@ void QgsComposerMapWidget::on_mAnnotationFormatComboBox_currentIndexChanged( int
} }
mComposerMap->beginCommand( tr( "Annotation format changed" ) ); mComposerMap->beginCommand( tr( "Annotation format changed" ) );
grid->setGridAnnotationFormat(( QgsComposerMap::GridAnnotationFormat )index );
switch ( index )
{
case 0:
grid->setGridAnnotationFormat( QgsComposerMap::Decimal );
break;
case 3:
grid->setGridAnnotationFormat( QgsComposerMap::DegreeMinute );
break;
case 6:
grid->setGridAnnotationFormat( QgsComposerMap::DegreeMinuteSecond );
break;
case 1:
grid->setGridAnnotationFormat( QgsComposerMap::DecimalWithSuffix );
break;
case 2:
grid->setGridAnnotationFormat( QgsComposerMap::DegreeMinuteNoSuffix );
break;
case 4:
grid->setGridAnnotationFormat( QgsComposerMap::DegreeMinutePadded );
break;
case 5:
grid->setGridAnnotationFormat( QgsComposerMap::DegreeMinuteSecondNoSuffix );
break;
case 7:
grid->setGridAnnotationFormat( QgsComposerMap::DegreeMinuteSecondPadded );
break;
}
mComposerMap->updateBoundingRect(); mComposerMap->updateBoundingRect();
mComposerMap->update(); mComposerMap->update();
mComposerMap->endCommand(); mComposerMap->endCommand();

View File

@ -90,7 +90,12 @@ class CORE_EXPORT QgsComposerMap : public QgsComposerItem
{ {
Decimal = 0, Decimal = 0,
DegreeMinute, DegreeMinute,
DegreeMinuteSecond DegreeMinuteSecond,
DecimalWithSuffix,
DegreeMinuteNoSuffix,
DegreeMinutePadded,
DegreeMinuteSecondNoSuffix,
DegreeMinuteSecondPadded
}; };
enum GridFrameStyle enum GridFrameStyle

View File

@ -1029,6 +1029,19 @@ QString QgsComposerMapGrid::gridAnnotationString( double value, QgsComposerMap::
{ {
return QString::number( value, 'f', mGridAnnotationPrecision ); return QString::number( value, 'f', mGridAnnotationPrecision );
} }
else if ( mGridAnnotationFormat == QgsComposerMap::DecimalWithSuffix )
{
QString hemisphere;
if ( coord == QgsComposerMap::Longitude )
{
hemisphere = value < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
}
else
{
hemisphere = value < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
}
return QString::number( qAbs( value ), 'f', mGridAnnotationPrecision ) + hemisphere;
}
QgsPoint p; QgsPoint p;
p.setX( coord == QgsComposerMap::Longitude ? value : 0 ); p.setX( coord == QgsComposerMap::Longitude ? value : 0 );
@ -1039,10 +1052,26 @@ QString QgsComposerMapGrid::gridAnnotationString( double value, QgsComposerMap::
{ {
annotationString = p.toDegreesMinutes( mGridAnnotationPrecision ); annotationString = p.toDegreesMinutes( mGridAnnotationPrecision );
} }
else //DegreeMinuteSecond else if ( mGridAnnotationFormat == QgsComposerMap::DegreeMinuteNoSuffix )
{
annotationString = p.toDegreesMinutes( mGridAnnotationPrecision, false );
}
else if ( mGridAnnotationFormat == QgsComposerMap::DegreeMinutePadded )
{
annotationString = p.toDegreesMinutes( mGridAnnotationPrecision, true, true );
}
else if ( mGridAnnotationFormat == QgsComposerMap::DegreeMinuteSecond )
{ {
annotationString = p.toDegreesMinutesSeconds( mGridAnnotationPrecision ); annotationString = p.toDegreesMinutesSeconds( mGridAnnotationPrecision );
} }
else if ( mGridAnnotationFormat == QgsComposerMap::DegreeMinuteSecondNoSuffix )
{
annotationString = p.toDegreesMinutesSeconds( mGridAnnotationPrecision, false );
}
else if ( mGridAnnotationFormat == QgsComposerMap::DegreeMinuteSecondPadded )
{
annotationString = p.toDegreesMinutesSeconds( mGridAnnotationPrecision, true, true );
}
QStringList split = annotationString.split( "," ); QStringList split = annotationString.split( "," );
if ( coord == QgsComposerMap::Longitude ) if ( coord == QgsComposerMap::Longitude )

View File

@ -134,46 +134,188 @@ QString QgsPoint::toString( int thePrecision ) const
return QString( "%1,%2" ).arg( x ).arg( y ); return QString( "%1,%2" ).arg( x ).arg( y );
} }
QString QgsPoint::toDegreesMinutesSeconds( int thePrecision ) const QString QgsPoint::toDegreesMinutesSeconds( int thePrecision, const bool useSuffix, const bool padded ) const
{ {
int myDegreesX = int( qAbs( m_x ) ); //first, limit longitude to -360 to 360 degree range
float myFloatMinutesX = float(( qAbs( m_x ) - myDegreesX ) * 60 ); double myWrappedX = fmod( m_x, 360.0 );
//next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
if ( myWrappedX > 180.0 )
{
myWrappedX = myWrappedX - 360.0;
}
else if ( myWrappedX < -180.0 )
{
myWrappedX = myWrappedX + 360.0;
}
int myDegreesX = int( qAbs( myWrappedX ) );
double myFloatMinutesX = double(( qAbs( myWrappedX ) - myDegreesX ) * 60 );
int myIntMinutesX = int( myFloatMinutesX ); int myIntMinutesX = int( myFloatMinutesX );
float mySecondsX = float( myFloatMinutesX - myIntMinutesX ) * 60; double mySecondsX = double( myFloatMinutesX - myIntMinutesX ) * 60;
int myDegreesY = int( qAbs( m_y ) ); int myDegreesY = int( qAbs( m_y ) );
float myFloatMinutesY = float(( qAbs( m_y ) - myDegreesY ) * 60 ); double myFloatMinutesY = double(( qAbs( m_y ) - myDegreesY ) * 60 );
int myIntMinutesY = int( myFloatMinutesY ); int myIntMinutesY = int( myFloatMinutesY );
float mySecondsY = float( myFloatMinutesY - myIntMinutesY ) * 60; double mySecondsY = double( myFloatMinutesY - myIntMinutesY ) * 60;
QString myXHemisphere = m_x < 0 ? QObject::tr( "W" ) : QObject::tr( "E" ); //make sure rounding to specified precision doesn't create seconds >= 60
QString myYHemisphere = m_y < 0 ? QObject::tr( "S" ) : QObject::tr( "N" ); if ( qRound( mySecondsX * pow( 10, thePrecision ) ) >= 60 * pow( 10, thePrecision ) )
QString rep = QString::number( myDegreesX ) + QChar( 176 ) + {
QString::number( myIntMinutesX ) + QString( "'" ) + mySecondsX = qMax( mySecondsX - 60, 0.0 );
QString::number( mySecondsX, 'f', thePrecision ) + QString( "\"" ) + myIntMinutesX++;
if ( myIntMinutesX >= 60 )
{
myIntMinutesX -= 60;
myDegreesX++;
}
}
if ( qRound( mySecondsY * pow( 10, thePrecision ) ) >= 60 * pow( 10, thePrecision ) )
{
mySecondsY = qMax( mySecondsY - 60, 0.0 );
myIntMinutesY++;
if ( myIntMinutesY >= 60 )
{
myIntMinutesY -= 60;
myDegreesY++;
}
}
QString myXHemisphere;
QString myYHemisphere;
QString myXSign;
QString myYSign;
if ( useSuffix )
{
myXHemisphere = myWrappedX < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
myYHemisphere = m_y < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
}
else
{
if ( myWrappedX < 0 )
{
myXSign = QObject::tr( "-" );
}
if ( m_y < 0 )
{
myYSign = QObject::tr( "-" );
}
}
//check if coordinate is all zeros for the specified precision, and if so,
//remove the sign and hemisphere strings
if ( myDegreesX == 0 && myIntMinutesX == 0 && qRound( mySecondsX * pow( 10, thePrecision ) ) == 0 )
{
myXSign = QString();
myXHemisphere = QString();
}
if ( myDegreesY == 0 && myIntMinutesY == 0 && qRound( mySecondsY * pow( 10, thePrecision ) ) == 0 )
{
myYSign = QString();
myYHemisphere = QString();
}
//also remove directional prefix from 180 degree longitudes
if ( myDegreesX == 180 && myIntMinutesX == 0 && qRound( mySecondsX * pow( 10, thePrecision ) ) == 0 )
{
myXHemisphere = QString();
}
//pad minutes with leading digits if required
QString myMinutesX = padded ? QString( "%1" ).arg( myIntMinutesX, 2, 10, QChar( '0' ) ) : QString::number( myIntMinutesX );
QString myMinutesY = padded ? QString( "%1" ).arg( myIntMinutesY, 2, 10, QChar( '0' ) ) : QString::number( myIntMinutesY );
//pad seconds with leading digits if required
int digits = 2 + ( thePrecision == 0 ? 0 : 1 + thePrecision ); //1 for decimal place if required
QString myStrSecondsX = padded ? QString( "%1" ).arg( mySecondsX, digits, 'f', thePrecision, QChar( '0' ) ) : QString::number( mySecondsX, 'f', thePrecision );
QString myStrSecondsY = padded ? QString( "%1" ).arg( mySecondsY, digits, 'f', thePrecision, QChar( '0' ) ) : QString::number( mySecondsY, 'f', thePrecision );
QString rep = myXSign + QString::number( myDegreesX ) + QChar( 176 ) +
myMinutesX + QString( "'" ) +
myStrSecondsX + QString( "\"" ) +
myXHemisphere + QString( "," ) + myXHemisphere + QString( "," ) +
QString::number( myDegreesY ) + QChar( 176 ) + myYSign + QString::number( myDegreesY ) + QChar( 176 ) +
QString::number( myIntMinutesY ) + QString( "'" ) + myMinutesY + QString( "'" ) +
QString::number( mySecondsY, 'f', thePrecision ) + QString( "\"" ) + myStrSecondsY + QString( "\"" ) +
myYHemisphere; myYHemisphere;
return rep; return rep;
} }
QString QgsPoint::toDegreesMinutes( int thePrecision ) const QString QgsPoint::toDegreesMinutes( int thePrecision, const bool useSuffix, const bool padded ) const
{ {
int myDegreesX = int( qAbs( m_x ) ); //first, limit longitude to -360 to 360 degree range
float myFloatMinutesX = float(( qAbs( m_x ) - myDegreesX ) * 60 ); double myWrappedX = fmod( m_x, 360.0 );
//next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
if ( myWrappedX > 180.0 )
{
myWrappedX = myWrappedX - 360.0;
}
else if ( myWrappedX < -180.0 )
{
myWrappedX = myWrappedX + 360.0;
}
int myDegreesX = int( qAbs( myWrappedX ) );
double myFloatMinutesX = double(( qAbs( myWrappedX ) - myDegreesX ) * 60 );
int myDegreesY = int( qAbs( m_y ) ); int myDegreesY = int( qAbs( m_y ) );
float myFloatMinutesY = float(( qAbs( m_y ) - myDegreesY ) * 60 ); double myFloatMinutesY = double(( qAbs( m_y ) - myDegreesY ) * 60 );
QString myXHemisphere = m_x < 0 ? QObject::tr( "W" ) : QObject::tr( "E" ); //make sure rounding to specified precision doesn't create minutes >= 60
QString myYHemisphere = m_y < 0 ? QObject::tr( "S" ) : QObject::tr( "N" ); if ( qRound( myFloatMinutesX * pow( 10, thePrecision ) ) >= 60 * pow( 10, thePrecision ) )
QString rep = QString::number( myDegreesX ) + QChar( 176 ) + {
QString::number( myFloatMinutesX, 'f', thePrecision ) + QString( "'" ) + myFloatMinutesX = qMax( myFloatMinutesX - 60, 0.0 );
myDegreesX++;
}
if ( qRound( myFloatMinutesY * pow( 10, thePrecision ) ) >= 60 * pow( 10, thePrecision ) )
{
myFloatMinutesY = qMax( myFloatMinutesY - 60, 0.0 );
myDegreesY++;
}
QString myXHemisphere;
QString myYHemisphere;
QString myXSign;
QString myYSign;
if ( useSuffix )
{
myXHemisphere = myWrappedX < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
myYHemisphere = m_y < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
}
else
{
if ( myWrappedX < 0 )
{
myXSign = QObject::tr( "-" );
}
if ( m_y < 0 )
{
myYSign = QObject::tr( "-" );
}
}
//check if coordinate is all zeros for the specified precision, and if so,
//remove the sign and hemisphere strings
if ( myDegreesX == 0 && qRound( myFloatMinutesX * pow( 10, thePrecision ) ) == 0 )
{
myXSign = QString();
myXHemisphere = QString();
}
if ( myDegreesY == 0 && qRound( myFloatMinutesY * pow( 10, thePrecision ) ) == 0 )
{
myYSign = QString();
myYHemisphere = QString();
}
//also remove directional prefix from 180 degree longitudes
if ( myDegreesX == 180 && qRound( myFloatMinutesX * pow( 10, thePrecision ) ) == 0 )
{
myXHemisphere = QString();
}
//pad minutes with leading digits if required
int digits = 2 + ( thePrecision == 0 ? 0 : 1 + thePrecision ); //1 for decimal place if required
QString myStrMinutesX = padded ? QString( "%1" ).arg( myFloatMinutesX, digits, 'f', thePrecision, QChar( '0' ) ) : QString::number( myFloatMinutesX, 'f', thePrecision );
QString myStrMinutesY = padded ? QString( "%1" ).arg( myFloatMinutesY, digits, 'f', thePrecision, QChar( '0' ) ) : QString::number( myFloatMinutesY, 'f', thePrecision );
QString rep = myXSign + QString::number( myDegreesX ) + QChar( 176 ) +
myStrMinutesX + QString( "'" ) +
myXHemisphere + QString( "," ) + myXHemisphere + QString( "," ) +
QString::number( myDegreesY ) + QChar( 176 ) + myYSign + QString::number( myDegreesY ) + QChar( 176 ) +
QString::number( myFloatMinutesY, 'f', thePrecision ) + QString( "'" ) + myStrMinutesY + QString( "'" ) +
myYHemisphere; myYHemisphere;
return rep; return rep;
} }

View File

@ -129,16 +129,26 @@ class CORE_EXPORT QgsPoint
/** Return a string representation as degrees minutes seconds. /** Return a string representation as degrees minutes seconds.
* Its up to the calling function to ensure that this point can * Its up to the calling function to ensure that this point can
* be meaningfully represented in this form. * be meaningfully represented in this form.
* @param thePrecision number of decimal points to use for seconds
* @param useSuffix set to true to include a direction suffix (eg 'N'),
* set to false to use a "-" prefix for west and south coordinates
* @param padded set to true to force minutes and seconds to use two decimals,
* eg, '05' instead of '5'.
* @note added in QGIS 1.4 * @note added in QGIS 1.4
*/ */
QString toDegreesMinutesSeconds( int thePrecision ) const; QString toDegreesMinutesSeconds( int thePrecision, const bool useSuffix = true, const bool padded = false ) const;
/** Return a string representation as degrees minutes. /** Return a string representation as degrees minutes.
* Its up to the calling function to ensure that this point can * Its up to the calling function to ensure that this point can
* be meaningfully represented in this form. * be meaningfully represented in this form.
* @param thePrecision number of decimal points to use for minutes
* @param useSuffix set to true to include a direction suffix (eg 'N'),
* set to false to use a "-" prefix for west and south coordinates
* @param padded set to true to force minutes to use two decimals,
* eg, '05' instead of '5'.
* @note added in QGIS 1.9 * @note added in QGIS 1.9
*/ */
QString toDegreesMinutes( int thePrecision ) const; QString toDegreesMinutes( int thePrecision, const bool useSuffix = true, const bool padded = false ) const;
/*! Return the well known text representation for the point. /*! Return the well known text representation for the point.

View File

@ -38,6 +38,11 @@ class TestQgsPoint: public QObject
void cleanup();// will be called after every testfunction. void cleanup();// will be called after every testfunction.
void toString(); void toString();
void toDegreesMinutesSeconds(); void toDegreesMinutesSeconds();
void toDegreesMinutesSecondsNoSuffix();
void toDegreesMinutesSecondsPadded();
void toDegreesMinutes();
void toDegreesMinutesNoSuffix();
void toDegreesMinutesPadded();
void wellKnownText(); void wellKnownText();
void sqrDist(); void sqrDist();
void multiply(); void multiply();
@ -102,15 +107,17 @@ void TestQgsPoint::toString()
mReport += "<p>" + mPoint2.toString( 2 ) + "</p>"; mReport += "<p>" + mPoint2.toString( 2 ) + "</p>";
mReport += "<p>" + mPoint3.toString( 2 ) + "</p>"; mReport += "<p>" + mPoint3.toString( 2 ) + "</p>";
mReport += "<p>" + mPoint4.toString( 2 ) + "</p>"; mReport += "<p>" + mPoint4.toString( 2 ) + "</p>";
QVERIFY( mPoint1.toString( 2 ) == QString( "20.00,-20.00" ) ); QCOMPARE( mPoint1.toString( 2 ), QString( "20.00,-20.00" ) );
}; }
void TestQgsPoint::toDegreesMinutesSeconds() void TestQgsPoint::toDegreesMinutesSeconds()
{ {
mReport += "<p>Testing toDegreesMinutesSecods()</p>"; mReport += "<p>Testing toDegreesMinutesSeconds()</p>";
mReport += "<p>" + mPoint1.toDegreesMinutesSeconds( 2 ) + "</p>"; mReport += "<p>" + mPoint1.toDegreesMinutesSeconds( 2 ) + "</p>";
mReport += "<p>" + mPoint2.toDegreesMinutesSeconds( 2 ) + "</p>"; mReport += "<p>" + mPoint2.toDegreesMinutesSeconds( 2 ) + "</p>";
mReport += "<p>" + mPoint3.toDegreesMinutesSeconds( 2 ) + "</p>"; mReport += "<p>" + mPoint3.toDegreesMinutesSeconds( 2 ) + "</p>";
mReport += "<p>" + mPoint4.toDegreesMinutesSeconds( 2 ) + "</p>"; mReport += "<p>" + mPoint4.toDegreesMinutesSeconds( 2 ) + "</p>";
qDebug() << mPoint4.toDegreesMinutesSeconds( 2 ); qDebug() << mPoint4.toDegreesMinutesSeconds( 2 );
QString myControlString = QString( "80" ) + QChar( 176 ) + QString myControlString = QString( "80" ) + QChar( 176 ) +
QString( "0'0.00" ) + QString( "0'0.00" ) +
@ -119,26 +126,412 @@ void TestQgsPoint::toDegreesMinutesSeconds()
QString( "0'0.00" ) + QString( '"' ) + QString( "0'0.00" ) + QString( '"' ) +
QString( "N" ); QString( "N" );
qDebug() << myControlString; qDebug() << myControlString;
QVERIFY( mPoint4.toDegreesMinutesSeconds( 2 ) == myControlString ); QCOMPARE( mPoint4.toDegreesMinutesSeconds( 2 ), myControlString );
//check if longitudes > 180 or <-180 wrap around
myControlString = QString( "10" ) + QChar( 176 ) +
QString( "0'0.00\"E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00\"" );
QCOMPARE( QgsPoint( 370, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
myControlString = QString( "10" ) + QChar( 176 ) +
QString( "0'0.00\"W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00\"" );
QCOMPARE( QgsPoint( -370, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
myControlString = QString( "179" ) + QChar( 176 ) +
QString( "0'0.00\"W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00\"" );
QCOMPARE( QgsPoint( 181, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
myControlString = QString( "179" ) + QChar( 176 ) +
QString( "0'0.00\"E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00\"" );
QCOMPARE( QgsPoint( -181, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
myControlString = QString( "1" ) + QChar( 176 ) +
QString( "0'0.00\"W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00\"" );
QCOMPARE( QgsPoint( 359, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
myControlString = QString( "1" ) + QChar( 176 ) +
QString( "0'0.00\"E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00\"" );
QCOMPARE( QgsPoint( -359, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
//should be no directional suffixes for 0 degree coordinates
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00" ) + QString( '"' );
QCOMPARE( QgsPoint( 0, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
//should also be no directional suffix for 0 degree coordinates within specified precision
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutesSeconds( 2 ), myControlString );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutesSeconds( 2 ), myControlString );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00000" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00360\"N" );
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutesSeconds( 5 ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00000" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00360\"S" );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutesSeconds( 5 ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00360\"E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00000" ) + QString( '"' );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutesSeconds( 5 ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00360\"W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00000" ) + QString( '"' );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutesSeconds( 5 ), myControlString );
//test rounding does not create seconds >= 60
myControlString = QString( "100" ) + QChar( 176 ) +
QString( "0'0.00\"E" ) +
QString( ",100" ) + QChar( 176 ) +
QString( "0'0.00\"N" );
QCOMPARE( QgsPoint( 99.999999, 99.999999 ).toDegreesMinutesSeconds( 2 ), myControlString );
//should be no directional suffixes for 180 degree longitudes
myControlString = QString( "180" ) + QChar( 176 ) +
QString( "0'0.00" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00" ) + QString( '"' );
QCOMPARE( QgsPoint( 180, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
//should also be no directional suffix for 180 degree longitudes within specified precision
QCOMPARE( QgsPoint( 180.000001, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
QCOMPARE( QgsPoint( 179.999999, 0 ).toDegreesMinutesSeconds( 2 ), myControlString );
myControlString = QString( "179" ) + QChar( 176 ) +
QString( "59'59.99640\"W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00000" ) + QString( '"' );
QCOMPARE( QgsPoint( 180.000001, 0 ).toDegreesMinutesSeconds( 5 ), myControlString );
myControlString = QString( "179" ) + QChar( 176 ) +
QString( "59'59.99640\"E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00000" ) + QString( '"' );
QCOMPARE( QgsPoint( 179.999999, 0 ).toDegreesMinutesSeconds( 5 ), myControlString );
}
void TestQgsPoint::toDegreesMinutesSecondsNoSuffix()
{
QString myControlString = QString( "80" ) + QChar( 176 ) +
QString( "0'0.00" ) +
QString( '"' ) +
QString( ",20" ) + QChar( 176 ) +
QString( "0'0.00" ) + QString( '"' );
QCOMPARE( mPoint4.toDegreesMinutesSeconds( 2, false ), myControlString );
//test 0 lat/long
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00" ) + QString( '"' );
QVERIFY( QgsPoint( 0, 0 ).toDegreesMinutesSeconds( 2, false ) == myControlString );
//test near zero lat/long
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutesSeconds( 2, false ), myControlString );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutesSeconds( 2, false ), myControlString );
//should be no "-" prefix for near-zero lat/long when rounding to 2 decimal places
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutesSeconds( 2, false ), myControlString );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutesSeconds( 2, false ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00000" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00360" ) + QString( '"' );
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutesSeconds( 5, false ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00000" ) +
QString( '"' ) +
QString( ",-0" ) + QChar( 176 ) +
QString( "0'0.00360" ) + QString( '"' );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutesSeconds( 5, false ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0'0.00360" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00000" ) + QString( '"' );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutesSeconds( 5, false ), myControlString );
myControlString = QString( "-0" ) + QChar( 176 ) +
QString( "0'0.00360" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0'0.00000" ) + QString( '"' );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutesSeconds( 5, false ), myControlString );
}
void TestQgsPoint::toDegreesMinutesSecondsPadded()
{
QString myControlString = QString( "80" ) + QChar( 176 ) +
QString( "00'00.00" ) +
QString( '"' ) +
QString( "E,20" ) + QChar( 176 ) +
QString( "00'00.00" ) + QString( '"' ) +
QString( "N" );
qDebug() << myControlString;
QCOMPARE( mPoint4.toDegreesMinutesSeconds( 2, true, true ), myControlString );
//should be no directional suffixes for 0 degree coordinates
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00'00.00" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00'00.00" ) + QString( '"' );
QVERIFY( QgsPoint( 0, 0 ).toDegreesMinutesSeconds( 2, true, true ) == myControlString );
//should also be no directional suffix for 0 degree coordinates within specified precision
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutesSeconds( 2, true, true ), myControlString );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutesSeconds( 2, true, true ), myControlString );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutesSeconds( 2, true, true ), myControlString );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutesSeconds( 2, true, true ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00'00.00000" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00'00.00360\"N" );
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutesSeconds( 5, true, true ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00'00.00000" ) +
QString( '"' ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00'00.00360\"S" );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutesSeconds( 5, true, true ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00'00.00360\"E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00'00.00000" ) + QString( '"' );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutesSeconds( 5, true, true ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00'00.00360\"W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00'00.00000" ) + QString( '"' );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutesSeconds( 5, true, true ), myControlString );
}
void TestQgsPoint::toDegreesMinutes()
{
mReport += "<p>Testing toDegreesMinutes()</p>";
mReport += "<p>" + mPoint1.toDegreesMinutes( 2 ) + "</p>";
mReport += "<p>" + mPoint2.toDegreesMinutes( 2 ) + "</p>";
mReport += "<p>" + mPoint3.toDegreesMinutes( 2 ) + "</p>";
mReport += "<p>" + mPoint4.toDegreesMinutes( 2 ) + "</p>";
qDebug() << mPoint4.toDegreesMinutes( 2 );
QString myControlString = QString( "80" ) + QChar( 176 ) +
QString( "0.00'" ) +
QString( "E,20" ) + QChar( 176 ) +
QString( "0.00'N" );
qDebug() << myControlString;
QCOMPARE( mPoint4.toDegreesMinutes( 2 ), myControlString );
//check if longitudes > 180 or <-180 wrap around
myControlString = QString( "10" ) + QChar( 176 ) +
QString( "0.00'E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QCOMPARE( QgsPoint( 370, 0 ).toDegreesMinutes( 2 ), myControlString );
myControlString = QString( "10" ) + QChar( 176 ) +
QString( "0.00'W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QCOMPARE( QgsPoint( -370, 0 ).toDegreesMinutes( 2 ), myControlString );
myControlString = QString( "179" ) + QChar( 176 ) +
QString( "0.00'W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QCOMPARE( QgsPoint( 181, 0 ).toDegreesMinutes( 2 ), myControlString );
myControlString = QString( "179" ) + QChar( 176 ) +
QString( "0.00'E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QCOMPARE( QgsPoint( -181, 0 ).toDegreesMinutes( 2 ), myControlString );
myControlString = QString( "1" ) + QChar( 176 ) +
QString( "0.00'W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QCOMPARE( QgsPoint( 359, 0 ).toDegreesMinutes( 2 ), myControlString );
myControlString = QString( "1" ) + QChar( 176 ) +
QString( "0.00'E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QCOMPARE( QgsPoint( -359, 0 ).toDegreesMinutes( 2 ), myControlString );
//should be no directional suffixes for 0 degree coordinates
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QVERIFY( QgsPoint( 0, 0 ).toDegreesMinutes( 2 ) == myControlString );
//should also be no directional suffix for 0 degree coordinates within specified precision
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutes( 2 ), myControlString );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutes( 2 ), myControlString );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutes( 2 ), myControlString );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutes( 2 ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00000'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00006'N" );
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutes( 5 ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00000'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00006'S" );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutes( 5 ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00006'E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00000'" );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutes( 5 ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00006'W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00000'" );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutes( 5 ), myControlString );
//test rounding does not create minutes >= 60
myControlString = QString( "100" ) + QChar( 176 ) +
QString( "0.00'E" ) +
QString( ",100" ) + QChar( 176 ) +
QString( "0.00'N" );
QCOMPARE( QgsPoint( 99.999999, 99.999999 ).toDegreesMinutes( 2 ), myControlString );
//should be no directional suffixes for 180 degree longitudes
myControlString = QString( "180" ) + QChar( 176 ) +
QString( "0.00'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QCOMPARE( QgsPoint( 180, 0 ).toDegreesMinutes( 2 ), myControlString );
//should also be no directional suffix for 180 degree longitudes within specified precision
QCOMPARE( QgsPoint( 180.000001, 0 ).toDegreesMinutes( 2 ), myControlString );
QCOMPARE( QgsPoint( 179.999999, 0 ).toDegreesMinutes( 2 ), myControlString );
myControlString = QString( "179" ) + QChar( 176 ) +
QString( "59.99994'W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00000'" );
QCOMPARE( QgsPoint( 180.000001, 0 ).toDegreesMinutes( 5 ), myControlString );
myControlString = QString( "179" ) + QChar( 176 ) +
QString( "59.99994'E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00000'" );
QCOMPARE( QgsPoint( 179.999999, 0 ).toDegreesMinutes( 5 ), myControlString );
}
void TestQgsPoint::toDegreesMinutesNoSuffix()
{
QString myControlString = QString( "80" ) + QChar( 176 ) +
QString( "0.00'" ) +
QString( ",20" ) + QChar( 176 ) +
QString( "0.00'" );
QCOMPARE( mPoint4.toDegreesMinutes( 2, false ), myControlString );
//test 0 lat/long
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00'" );
QVERIFY( QgsPoint( 0, 0 ).toDegreesMinutes( 2, false ) == myControlString );
//test near zero lat/long
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutes( 2, false ), myControlString );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutes( 2, false ), myControlString );
//should be no "-" prefix for near-zero lat/long when rounding to 2 decimal places
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutes( 2, false ), myControlString );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutes( 2, false ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00000'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00006'" );
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutes( 5, false ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00000'" ) +
QString( ",-0" ) + QChar( 176 ) +
QString( "0.00006'" );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutes( 5, false ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "0.00006'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00000'" );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutes( 5, false ), myControlString );
myControlString = QString( "-0" ) + QChar( 176 ) +
QString( "0.00006'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "0.00000'" );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutes( 5, false ), myControlString );
}
void TestQgsPoint::toDegreesMinutesPadded()
{
QString myControlString = QString( "80" ) + QChar( 176 ) +
QString( "00.00'" ) +
QString( "E,20" ) + QChar( 176 ) +
QString( "00.00'N" );
qDebug() << myControlString;
QCOMPARE( mPoint4.toDegreesMinutes( 2, true, true ), myControlString );
//should be no directional suffixes for 0 degree coordinates
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00.00'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00.00'" );
QVERIFY( QgsPoint( 0, 0 ).toDegreesMinutes( 2, true, true ) == myControlString );
//should also be no directional suffix for 0 degree coordinates within specified precision
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutes( 2, true, true ), myControlString );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutes( 2, true, true ), myControlString );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutes( 2, true, true ), myControlString );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutes( 2, true, true ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00.00000'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00.00006'N" );
QCOMPARE( QgsPoint( 0, 0.000001 ).toDegreesMinutes( 5, true, true ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00.00000'" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00.00006'S" );
QCOMPARE( QgsPoint( 0, -0.000001 ).toDegreesMinutes( 5, true, true ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00.00006'E" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00.00000'" );
QCOMPARE( QgsPoint( 0.000001, 0 ).toDegreesMinutes( 5, true, true ), myControlString );
myControlString = QString( "0" ) + QChar( 176 ) +
QString( "00.00006'W" ) +
QString( ",0" ) + QChar( 176 ) +
QString( "00.00000'" );
QCOMPARE( QgsPoint( -0.000001, 0 ).toDegreesMinutes( 5, true, true ), myControlString );
}
};
void TestQgsPoint::wellKnownText() void TestQgsPoint::wellKnownText()
{ {
}; }
void TestQgsPoint::sqrDist() void TestQgsPoint::sqrDist()
{ {
}; }
void TestQgsPoint::multiply() void TestQgsPoint::multiply()
{ {
}; }
void TestQgsPoint::onSegment() void TestQgsPoint::onSegment()
{ {
}; }
QTEST_MAIN( TestQgsPoint ) QTEST_MAIN( TestQgsPoint )
#include "moc_testqgspoint.cxx" #include "moc_testqgspoint.cxx"