Modularize distance and area formatting

This commit is contained in:
Matthias Kuhn 2017-03-03 18:14:01 +01:00
parent 2c82db5040
commit 56163e2810
8 changed files with 530 additions and 233 deletions

View File

@ -6,6 +6,7 @@ class QgsDistanceArea
%End
public:
//! Constructor
QgsDistanceArea();

View File

@ -11,6 +11,17 @@ class QgsUnitTypes
%End
public:
struct DistanceValue
{
double value;
QgsUnitTypes::DistanceUnit unit;
};
struct AreaValue
{
double value;
QgsUnitTypes::AreaUnit unit;
};
//! Units of distance
enum DistanceUnit
@ -191,6 +202,14 @@ class QgsUnitTypes
*/
static QString formatAngle( double angle, int decimals, AngleUnit unit );
static QgsUnitTypes::DistanceValue scaledDistance( double distance, QgsUnitTypes::DistanceUnit unit, int decimals, bool keepBaseUnit = false );
static QgsUnitTypes::AreaValue scaledArea( double area, QgsUnitTypes::AreaUnit unit, int decimals, bool keepBaseUnit = false );
static QString formatDistance( double distance, int decimals, QgsUnitTypes::DistanceUnit unit, bool keepBaseUnit = false );
static QString formatArea( double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit = false );
// RENDER UNITS
/** Encodes a render unit to a string.

View File

@ -233,6 +233,17 @@ inline double qgsRound( double x )
return x < 0.0 ? std::ceil( x - 0.5 ) : std::floor( x + 0.5 );
}
/**
* Returns a double \a number, rounded (as close as possible) to the specified number of \a places.
*
* @note Added in QGIS 3.0
*/
inline double qgsRound( double number, double places )
{
int scaleFactor = pow( 10, places );
return static_cast<double>( static_cast<qlonglong>( number * scaleFactor + 0.5 ) ) / scaleFactor;
}
/** Converts a string to a double in a permissive way, e.g., allowing for incorrect
* numbers of digits between thousand separators
* @param string string to convert

View File

@ -981,240 +981,12 @@ double QgsDistanceArea::computePolygonFlatArea( const QList<QgsPoint> &points )
QString QgsDistanceArea::formatDistance( double distance, int decimals, QgsUnitTypes::DistanceUnit unit, bool keepBaseUnit )
{
QString unitLabel;
switch ( unit )
{
case QgsUnitTypes::DistanceMeters:
if ( keepBaseUnit || qAbs( distance ) == 0.0 )
{
unitLabel = QObject::tr( " m" );
}
else if ( qAbs( distance ) > 1000.0 )
{
unitLabel = QObject::tr( " km" );
distance = distance / 1000;
}
else if ( qAbs( distance ) < 0.01 )
{
unitLabel = QObject::tr( " mm" );
distance = distance * 1000;
}
else if ( qAbs( distance ) < 0.1 )
{
unitLabel = QObject::tr( " cm" );
distance = distance * 100;
}
else
{
unitLabel = QObject::tr( " m" );
}
break;
case QgsUnitTypes::DistanceKilometers:
if ( keepBaseUnit || qAbs( distance ) >= 1.0 )
{
unitLabel = QObject::tr( " km" );
}
else
{
unitLabel = QObject::tr( " m" );
distance = distance * 1000;
}
break;
case QgsUnitTypes::DistanceFeet:
if ( qAbs( distance ) <= 5280.0 || keepBaseUnit )
{
unitLabel = QObject::tr( " ft" );
}
else
{
unitLabel = QObject::tr( " mi" );
distance /= 5280.0;
}
break;
case QgsUnitTypes::DistanceYards:
if ( qAbs( distance ) <= 1760.0 || keepBaseUnit )
{
unitLabel = QObject::tr( " yd" );
}
else
{
unitLabel = QObject::tr( " mi" );
distance /= 1760.0;
}
break;
case QgsUnitTypes::DistanceMiles:
if ( qAbs( distance ) >= 1.0 || keepBaseUnit )
{
unitLabel = QObject::tr( " mi" );
}
else
{
unitLabel = QObject::tr( " ft" );
distance *= 5280.0;
}
break;
case QgsUnitTypes::DistanceNauticalMiles:
unitLabel = QObject::tr( " NM" );
break;
case QgsUnitTypes::DistanceDegrees:
if ( qAbs( distance ) == 1.0 )
unitLabel = QObject::tr( " degree" );
else
unitLabel = QObject::tr( " degrees" );
break;
case QgsUnitTypes::DistanceUnknownUnit:
unitLabel.clear();
break;
default:
QgsDebugMsg( QString( "Error: not picked up map units - actual value = %1" ).arg( unit ) );
break;
}
return QStringLiteral( "%L1%2" ).arg( distance, 0, 'f', decimals ).arg( unitLabel );
return QgsUnitTypes::formatDistance( distance, decimals, unit, keepBaseUnit );
}
QString QgsDistanceArea::formatArea( double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit )
{
QString unitLabel;
switch ( unit )
{
case QgsUnitTypes::AreaSquareMeters:
{
if ( keepBaseUnit )
{
unitLabel = QObject::trUtf8( "" );
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareKilometers, QgsUnitTypes::AreaSquareMeters ) )
{
unitLabel = QObject::trUtf8( " km²" );
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMeters, QgsUnitTypes::AreaSquareKilometers );
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaHectares, QgsUnitTypes::AreaSquareMeters ) )
{
unitLabel = QObject::tr( " ha" );
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMeters, QgsUnitTypes::AreaHectares );
}
else
{
unitLabel = QObject::trUtf8( "" );
}
break;
}
case QgsUnitTypes::AreaSquareKilometers:
{
unitLabel = QObject::trUtf8( " km²" );
break;
}
case QgsUnitTypes::AreaSquareFeet:
{
if ( keepBaseUnit )
{
unitLabel = QObject::trUtf8( " ft²" );
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMiles, QgsUnitTypes::AreaSquareFeet ) )
{
unitLabel = QObject::trUtf8( " mi²" );
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareFeet, QgsUnitTypes::AreaSquareMiles );
}
else
{
unitLabel = QObject::trUtf8( " ft²" );
}
break;
}
case QgsUnitTypes::AreaSquareYards:
{
if ( keepBaseUnit )
{
unitLabel = QObject::trUtf8( " yd²" );
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMiles, QgsUnitTypes::AreaSquareYards ) )
{
unitLabel = QObject::trUtf8( " mi²" );
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareYards, QgsUnitTypes::AreaSquareMiles );
}
else
{
unitLabel = QObject::trUtf8( " yd²" );
}
break;
}
case QgsUnitTypes::AreaSquareMiles:
{
unitLabel = QObject::trUtf8( " mi²" );
break;
}
case QgsUnitTypes::AreaHectares:
{
if ( keepBaseUnit )
{
unitLabel = QObject::trUtf8( " ha" );
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareKilometers, QgsUnitTypes::AreaHectares ) )
{
unitLabel = QObject::trUtf8( " km²" );
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaHectares, QgsUnitTypes::AreaSquareKilometers );
}
else
{
unitLabel = QObject::trUtf8( " ha" );
}
break;
}
case QgsUnitTypes::AreaAcres:
{
if ( keepBaseUnit )
{
unitLabel = QObject::trUtf8( " ac" );
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMiles, QgsUnitTypes::AreaAcres ) )
{
unitLabel = QObject::trUtf8( " mi²" );
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaAcres, QgsUnitTypes::AreaSquareMiles );
}
else
{
unitLabel = QObject::trUtf8( " ac" );
}
break;
}
case QgsUnitTypes::AreaSquareNauticalMiles:
{
unitLabel = QObject::trUtf8( " nm²" );
break;
}
case QgsUnitTypes::AreaSquareDegrees:
{
unitLabel = QObject::tr( " sq.deg." );
break;
}
case QgsUnitTypes::AreaUnknownUnit:
{
unitLabel.clear();
break;
}
}
return QStringLiteral( "%L1%2" ).arg( area, 0, 'f', decimals ).arg( unitLabel );
return QgsUnitTypes::formatArea( area, decimals, unit, keepBaseUnit );
}
double QgsDistanceArea::convertLengthMeasurement( double length, QgsUnitTypes::DistanceUnit toUnits ) const

View File

@ -39,6 +39,7 @@ General purpose distance and area calculator.
class CORE_EXPORT QgsDistanceArea
{
public:
//! Constructor
QgsDistanceArea();

View File

@ -15,6 +15,7 @@
***************************************************************************/
#include "qgsunittypes.h"
#include "qgis.h"
/***************************************************************************
* This class is considered CRITICAL and any change MUST be accompanied with
@ -32,6 +33,8 @@ QgsUnitTypes::DistanceUnitType QgsUnitTypes::unitType( DistanceUnit unit )
case DistanceYards:
case DistanceMiles:
case DistanceKilometers:
case DistanceCentimeters:
case DistanceMillimeters:
return Standard;
case DistanceDegrees:
@ -94,6 +97,12 @@ QString QgsUnitTypes::encodeUnit( DistanceUnit unit )
case DistanceNauticalMiles:
return QStringLiteral( "nautical miles" );
case DistanceCentimeters:
return QStringLiteral( "cm" );
case DistanceMillimeters:
return QStringLiteral( "mm" );
}
return QString();
}
@ -125,6 +134,10 @@ QgsUnitTypes::DistanceUnit QgsUnitTypes::decodeDistanceUnit( const QString &stri
return DistanceYards;
if ( normalized == encodeUnit( DistanceMiles ) )
return DistanceMiles;
if ( normalized == encodeUnit( DistanceCentimeters ) )
return DistanceCentimeters;
if ( normalized == encodeUnit( DistanceMillimeters ) )
return DistanceMillimeters;
if ( normalized == encodeUnit( DistanceUnknownUnit ) )
return DistanceUnknownUnit;
@ -156,6 +169,12 @@ QString QgsUnitTypes::toString( DistanceUnit unit )
case DistanceDegrees:
return QObject::tr( "degrees", "distance" );
case DistanceCentimeters:
return QObject::tr( "UnitType", "centimeters" );
case DistanceMillimeters:
return QObject::tr( "UnitType", "millimeters" );
case DistanceUnknownUnit:
return QObject::tr( "<unknown>", "distance" );
@ -187,6 +206,12 @@ QString QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::DistanceUnit unit )
case DistanceDegrees:
return QObject::tr( "deg", "distance" );
case DistanceCentimeters:
return QObject::tr( "cm", "distance" );
case DistanceMillimeters:
return QObject::tr( "mm", "distance" );
case DistanceUnknownUnit:
return QString();
@ -221,6 +246,10 @@ QgsUnitTypes::DistanceUnit QgsUnitTypes::stringToDistanceUnit( const QString &st
return DistanceMiles;
if ( normalized == toString( DistanceDegrees ) )
return DistanceDegrees;
if ( normalized == toString( DistanceCentimeters ) )
return DistanceCentimeters;
if ( normalized == toString( DistanceCentimeters ) )
return DistanceCentimeters;
if ( normalized == toString( DistanceNauticalMiles ) )
return DistanceNauticalMiles;
if ( normalized == toString( DistanceUnknownUnit ) )
@ -244,6 +273,8 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
#define FEET_TO_METER 0.3048
#define NMILE_TO_METER 1852.0
#define KILOMETERS_TO_METER 1000.0
#define CENTIMETERS_TO_METER 0.01
#define MILLIMETERS_TO_METER 0.001
#define YARDS_TO_METER 0.9144
#define YARDS_TO_FEET 3.0
#define MILES_TO_METER 1609.344
@ -259,6 +290,10 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
return 1.0;
case DistanceKilometers:
return 1.0 / KILOMETERS_TO_METER;
case DistanceMillimeters:
return 1.0 / MILLIMETERS_TO_METER;
case DistanceCentimeters:
return 1.0 / CENTIMETERS_TO_METER;
case DistanceFeet:
return 1.0 / FEET_TO_METER;
case DistanceYards:
@ -283,6 +318,10 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
return KILOMETERS_TO_METER;
case DistanceKilometers:
return 1.0;
case DistanceCentimeters:
return KILOMETERS_TO_METER / CENTIMETERS_TO_METER;
case DistanceMillimeters:
return KILOMETERS_TO_METER / MILLIMETERS_TO_METER;
case DistanceFeet:
return KILOMETERS_TO_METER / FEET_TO_METER;
case DistanceYards:
@ -307,6 +346,10 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
return FEET_TO_METER;
case DistanceKilometers:
return FEET_TO_METER / KILOMETERS_TO_METER;
case DistanceCentimeters:
return FEET_TO_METER / CENTIMETERS_TO_METER;
case DistanceMillimeters:
return FEET_TO_METER / MILLIMETERS_TO_METER;
case DistanceFeet:
return 1.0;
case DistanceYards:
@ -331,6 +374,10 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
return YARDS_TO_METER;
case DistanceKilometers:
return YARDS_TO_METER / KILOMETERS_TO_METER;
case DistanceCentimeters:
return YARDS_TO_METER / CENTIMETERS_TO_METER;
case DistanceMillimeters:
return YARDS_TO_METER / MILLIMETERS_TO_METER;
case DistanceFeet:
return YARDS_TO_FEET;
case DistanceYards:
@ -355,6 +402,10 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
return MILES_TO_METER;
case DistanceKilometers:
return MILES_TO_METER / KILOMETERS_TO_METER;
case DistanceCentimeters:
return MILES_TO_METER / CENTIMETERS_TO_METER;
case DistanceMillimeters:
return MILES_TO_METER / MILLIMETERS_TO_METER;
case DistanceFeet:
return MILES_TO_METER / FEET_TO_METER;
case DistanceYards:
@ -379,6 +430,10 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
return DEGREE_TO_METER;
case DistanceKilometers:
return DEGREE_TO_METER / KILOMETERS_TO_METER;
case DistanceCentimeters:
return DEGREE_TO_METER / CENTIMETERS_TO_METER;
case DistanceMillimeters:
return DEGREE_TO_METER / MILLIMETERS_TO_METER;
case DistanceFeet:
return DEGREE_TO_METER / FEET_TO_METER;
case DistanceYards:
@ -403,6 +458,10 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
return NMILE_TO_METER;
case DistanceKilometers:
return NMILE_TO_METER / KILOMETERS_TO_METER;
case DistanceCentimeters:
return NMILE_TO_METER / CENTIMETERS_TO_METER;
case DistanceMillimeters:
return NMILE_TO_METER / MILLIMETERS_TO_METER;
case DistanceFeet:
return NMILE_TO_METER / FEET_TO_METER;
case DistanceYards:
@ -419,6 +478,62 @@ double QgsUnitTypes::fromUnitToUnitFactor( DistanceUnit fromUnit, DistanceUnit t
break;
}
case DistanceCentimeters:
{
switch ( toUnit )
{
case DistanceMeters:
return CENTIMETERS_TO_METER;
case DistanceKilometers:
return CENTIMETERS_TO_METER / KILOMETERS_TO_METER;;
case DistanceCentimeters:
return 1.0;
case DistanceMillimeters:
return CENTIMETERS_TO_METER / MILLIMETERS_TO_METER;
case DistanceFeet:
return CENTIMETERS_TO_METER / FEET_TO_METER;
case DistanceYards:
return CENTIMETERS_TO_METER / YARDS_TO_METER;
case DistanceMiles:
return CENTIMETERS_TO_METER / MILES_TO_METER;
case DistanceDegrees:
return CENTIMETERS_TO_METER / DEGREE_TO_METER;
case DistanceNauticalMiles:
return CENTIMETERS_TO_METER / NMILE_TO_METER;
case DistanceUnknownUnit:
break;
}
break;
}
case DistanceMillimeters:
{
switch ( toUnit )
{
case DistanceMeters:
return MILLIMETERS_TO_METER;
case DistanceKilometers:
return MILLIMETERS_TO_METER / KILOMETERS_TO_METER;
case DistanceCentimeters:
return MILLIMETERS_TO_METER / CENTIMETERS_TO_METER;
case DistanceMillimeters:
return 1.0;
case DistanceFeet:
return MILLIMETERS_TO_METER / FEET_TO_METER;
case DistanceYards:
return MILLIMETERS_TO_METER / YARDS_TO_METER;
case DistanceMiles:
return MILLIMETERS_TO_METER / MILES_TO_METER;
case DistanceDegrees:
return MILLIMETERS_TO_METER / DEGREE_TO_METER;
case DistanceNauticalMiles:
return MILLIMETERS_TO_METER / NMILE_TO_METER;
case DistanceUnknownUnit:
break;
}
break;
}
case DistanceUnknownUnit:
break;
}
@ -864,6 +979,12 @@ QgsUnitTypes::AreaUnit QgsUnitTypes::distanceToAreaUnit( DistanceUnit distanceUn
case DistanceKilometers:
return AreaSquareKilometers;
case DistanceCentimeters:
return AreaSquareMeters;
case DistanceMillimeters:
return AreaSquareMeters;
case DistanceFeet:
return AreaSquareFeet;
@ -1125,6 +1246,292 @@ QString QgsUnitTypes::formatAngle( double angle, int decimals, QgsUnitTypes::Ang
return QStringLiteral( "%L1%2" ).arg( angle, 0, 'f', decimals ).arg( unitLabel );
}
QgsUnitTypes::DistanceValue QgsUnitTypes::scaledDistance( double distance, QgsUnitTypes::DistanceUnit unit, int decimals, bool keepBaseUnit )
{
DistanceValue result;
switch ( unit )
{
case DistanceMeters:
if ( keepBaseUnit )
{
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceMeters;
}
else if ( qAbs( distance ) > 1000.0 )
{
result.value = qgsRound( distance / 1000, decimals );
result.unit = QgsUnitTypes::DistanceKilometers;
}
else if ( qAbs( distance ) < 0.01 )
{
result.value = qgsRound( distance * 1000, decimals );
result.unit = QgsUnitTypes::DistanceMillimeters;
}
else if ( qAbs( distance ) < 0.1 )
{
result.value = qgsRound( distance * 100, decimals );
result.unit = QgsUnitTypes::DistanceCentimeters;
}
else
{
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceMeters;
}
break;
case DistanceKilometers:
if ( keepBaseUnit || qAbs( distance ) >= 1.0 )
{
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceKilometers;
}
else
{
result.value = qgsRound( distance * 1000, decimals );
result.unit = QgsUnitTypes::DistanceMeters;
}
break;
case DistanceFeet:
if ( qAbs( distance ) <= 5280.0 || keepBaseUnit )
{
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceFeet;
}
else
{
result.value = qgsRound( distance / 5280.0, decimals );
result.unit = QgsUnitTypes::DistanceMiles;
}
break;
case DistanceYards:
if ( qAbs( distance ) <= 1760.0 || keepBaseUnit )
{
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceYards;
}
else
{
result.value = qgsRound( distance / 1760.0, decimals );
result.unit = QgsUnitTypes::DistanceMiles;
}
break;
case DistanceMiles:
if ( qAbs( distance ) >= 1.0 || keepBaseUnit )
{
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceMiles;
}
else
{
result.value = qgsRound( distance * 5280.0, decimals );
result.unit = QgsUnitTypes::DistanceFeet;
}
break;
case DistanceNauticalMiles:
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceNauticalMiles;
break;
case DistanceDegrees:
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceDegrees;
break;
case DistanceUnknownUnit:
result.value = qgsRound( distance, decimals );
result.unit = QgsUnitTypes::DistanceUnknownUnit;
break;
default:
result.value = qgsRound( distance, decimals );
result.unit = unit;
break;
}
return result;
}
QgsUnitTypes::AreaValue QgsUnitTypes::scaledArea( double area, QgsUnitTypes::AreaUnit unit, int decimals, bool keepBaseUnit )
{
AreaValue result;
switch ( unit )
{
case AreaSquareMeters:
{
if ( keepBaseUnit )
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareMeters;
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareKilometers, QgsUnitTypes::AreaSquareMeters ) )
{
result.value = qgsRound( area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMeters, QgsUnitTypes::AreaSquareKilometers ), decimals );
result.unit = QgsUnitTypes::AreaSquareKilometers;
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaHectares, QgsUnitTypes::AreaSquareMeters ) )
{
result.value = qgsRound( area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMeters, QgsUnitTypes::AreaHectares ), decimals );
result.unit = QgsUnitTypes::AreaHectares;
}
else
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareMeters;
}
break;
}
case AreaSquareKilometers:
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareKilometers;
break;
}
case AreaSquareFeet:
{
if ( keepBaseUnit )
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareFeet;
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMiles, QgsUnitTypes::AreaSquareFeet ) )
{
result.value = qgsRound( area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareFeet, QgsUnitTypes::AreaSquareMiles ), decimals );
result.unit = QgsUnitTypes::AreaSquareMiles;
}
else
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareFeet;
}
break;
}
case AreaSquareYards:
{
if ( keepBaseUnit )
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareYards;
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMiles, QgsUnitTypes::AreaSquareYards ) )
{
result.value = qgsRound( area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareYards, QgsUnitTypes::AreaSquareMiles ), decimals );
result.unit = QgsUnitTypes::AreaSquareMiles;
}
else
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareYards;
}
break;
}
case AreaSquareMiles:
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareMiles;
break;
}
case AreaHectares:
{
if ( keepBaseUnit )
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaHectares;
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareKilometers, QgsUnitTypes::AreaHectares ) )
{
result.value = qgsRound( area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaHectares, QgsUnitTypes::AreaSquareKilometers ), decimals );
result.unit = QgsUnitTypes::AreaSquareKilometers;
}
else
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaHectares;
}
break;
}
case AreaAcres:
{
if ( keepBaseUnit )
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaAcres;
}
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaSquareMiles, QgsUnitTypes::AreaAcres ) )
{
result.value = qgsRound( area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::AreaAcres, QgsUnitTypes::AreaSquareMiles ), decimals );
result.unit = QgsUnitTypes::AreaSquareMiles;
}
else
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaAcres;
}
break;
}
case AreaSquareNauticalMiles:
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareNauticalMiles;
break;
}
case AreaSquareDegrees:
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaSquareDegrees;
break;
}
case AreaUnknownUnit:
{
result.value = qgsRound( area, decimals );
result.unit = QgsUnitTypes::AreaUnknownUnit;
break;
}
}
return result;
}
QString QgsUnitTypes::formatDistance( double distance, int decimals, QgsUnitTypes::DistanceUnit unit, bool keepBaseUnit )
{
DistanceValue dist = scaledDistance( distance, unit, decimals, keepBaseUnit );
QString unitText;
if ( dist.unit != DistanceUnknownUnit )
unitText = QChar( ' ' ) + QgsUnitTypes::toAbbreviatedString( dist.unit );
return QStringLiteral( "%L1%2" ).arg( dist.value, 0, 'f', decimals ).arg( unitText );
}
QString QgsUnitTypes::formatArea( double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit )
{
AreaValue areaValue = scaledArea( area, unit, decimals, keepBaseUnit );
QString unitText;
if ( areaValue.unit != AreaUnknownUnit )
unitText = QChar( ' ' ) + QgsUnitTypes::toAbbreviatedString( areaValue.unit );
return QStringLiteral( "%L1%2" ).arg( areaValue.value, 0, 'f', decimals ).arg( unitText );
}
QString QgsUnitTypes::encodeUnit( RenderUnit unit )
{
switch ( unit )

View File

@ -38,7 +38,6 @@ class CORE_EXPORT QgsUnitTypes
Q_GADGET
public:
//! Units of distance
enum DistanceUnit
{
@ -49,6 +48,8 @@ class CORE_EXPORT QgsUnitTypes
DistanceYards, //!< Imperial yards
DistanceMiles, //!< Terrestrial miles
DistanceDegrees, //!< Degrees, for planar geographic CRS distance measurements
DistanceCentimeters, //!< Centimeters
DistanceMillimeters, //!< Millimeters
DistanceUnknownUnit, //!< Unknown distance unit
};
@ -100,6 +101,44 @@ class CORE_EXPORT QgsUnitTypes
RenderUnknownUnit, //!< Mixed or unknown units
};
/**
* A combination of distance value and unit.
*
* @note Added in QGIS 3.0
*/
struct DistanceValue
{
/**
* The value part of the distance. For 3.7 meters, this will be 3.7.
*/
double value;
/**
* The value part of the distance. For 3.7 meters, this will be QgsUnitTypes::DistanceMeters.
*/
QgsUnitTypes::DistanceUnit unit;
};
/**
* A combination of area value and unit.
*
* @note Added in QGIS 3.0
*/
struct AreaValue
{
/**
* The value part of the distance. For 3.7 square meters, this will be 3.7.
*/
double value;
/**
* The value part of the distance. For 3.7 square meters, this will be QgsUnitTypes::AreaSquareMeters.
*/
QgsUnitTypes::AreaUnit unit;
};
//! List of render units
typedef QList<RenderUnit> RenderUnitList;
@ -244,6 +283,53 @@ class CORE_EXPORT QgsUnitTypes
*/
Q_INVOKABLE static QString formatAngle( double angle, int decimals, AngleUnit unit );
/**
* Will convert a \a distance with a given \a unit to a distance value which is nice to display.
* It will convert between different units (e.g. from meters to kilometers or millimeters)
* if appropriate, unless forced otherwise with \a keepBaseUnit.
* The value will also be rounded to \a decimals (be prepared that the returned value is still a double so it will require
* further formatting when converting to a string).
*
* @note Added in QGIS 3.0
*/
Q_INVOKABLE static DistanceValue scaledDistance( double distance, QgsUnitTypes::DistanceUnit unit, int decimals, bool keepBaseUnit = false );
/**
* Will convert an \a area with a given \a unit to an area value which is nice to display.
* It will convert between different units (e.g. from square meters to square kilometers)
* if appropriate, unless forced otherwise with \a keepBaseUnit.
* The value will also be rounded to \a decimals (be prepared that the returned value is still a double so it will require
* further formatting when converting to a string).
*
* @note Added in QGIS 3.0
*/
Q_INVOKABLE static AreaValue scaledArea( double area, QgsUnitTypes::AreaUnit unit, int decimals, bool keepBaseUnit = false );
/** 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
* @param keepBaseUnit set to false to allow conversion of large distances to more suitable units, e.g., meters to
* kilometers
* @returns formatted distance string
* @note added in QGIS 3.0
* @see formatArea()
*/
Q_INVOKABLE static QString formatDistance( double distance, int decimals, QgsUnitTypes::DistanceUnit unit, bool keepBaseUnit = false );
/** 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
* @param keepBaseUnit set to false to allow conversion of large areas to more suitable units, e.g., square meters to
* square kilometers
* @returns formatted area string
* @note added in QGIS 3.0
* @see formatDistance()
*/
Q_INVOKABLE static QString formatArea( double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit = false );
// RENDER UNITS
/** Encodes a render unit to a string.

View File

@ -322,8 +322,8 @@ class TestQgsDistanceArea(unittest.TestCase):
self.assertEqual(QgsDistanceArea.formatDistance(0.5, 1, QgsUnitTypes.DistanceNauticalMiles, False), '0.5 NM')
self.assertEqual(QgsDistanceArea.formatDistance(1.5, 1, QgsUnitTypes.DistanceNauticalMiles, True), '1.5 NM')
self.assertEqual(QgsDistanceArea.formatDistance(1.5, 1, QgsUnitTypes.DistanceNauticalMiles, False), '1.5 NM')
self.assertEqual(QgsDistanceArea.formatDistance(1.5, 1, QgsUnitTypes.DistanceDegrees, True), '1.5 degrees')
self.assertEqual(QgsDistanceArea.formatDistance(1.0, 1, QgsUnitTypes.DistanceDegrees, False), '1.0 degree')
self.assertEqual(QgsDistanceArea.formatDistance(1.5, 1, QgsUnitTypes.DistanceDegrees, True), '1.5 deg')
self.assertEqual(QgsDistanceArea.formatDistance(1.0, 1, QgsUnitTypes.DistanceDegrees, False), '1.0 deg')
self.assertEqual(QgsDistanceArea.formatDistance(1.0, 1, QgsUnitTypes.DistanceUnknownUnit, False), '1.0')
QLocale.setDefault(QLocale.system())