mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-18 00:03:05 -04:00
Fix project unit confusion (pt 3): add area unit settings with a
ton of available area units (eg m2, km2, mi2, ft2, yd2, ha, ac, etc) Adds a new option in both the QGIS setting and project properties to set the units used for area measurements. Just like the distance setting, this defaults to the units set in QGIS options, but can then be overridden for specific projects. The setting is respected for area calculations in: - Attribute table field update bar - Field calculator calculations - Identify tool derived length and perimeter values Also adds unit tests to ensure that area calculated by attribute table update bar, field calculator and identify tool are consistent wrt ellipsoidal calculations and area units. TODO: make measure tool respect area setting (refs #13209, #4252 and fixes #12939, #2402, #4857)
This commit is contained in:
parent
35c2d185fb
commit
dfdcec8922
@ -105,10 +105,12 @@ class QgsDistanceArea
|
||||
|
||||
/** Measures the area of a geometry.
|
||||
* @param geometry geometry to measure
|
||||
* @returns area of geometry. For geometry collections, non surface geometries will be ignored
|
||||
* @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().
|
||||
* @note added in QGIS 2.12
|
||||
* @see measureLength()
|
||||
* @see measurePerimeter()
|
||||
* @see areaUnits()
|
||||
*/
|
||||
double measureArea( const QgsGeometry* geometry ) const;
|
||||
|
||||
@ -151,17 +153,47 @@ class QgsDistanceArea
|
||||
|
||||
/** Returns the units of distance for length calculations made by this object.
|
||||
* @note added in QGIS 2.14
|
||||
* @see areaUnits()
|
||||
*/
|
||||
QGis::UnitType lengthUnits() const;
|
||||
|
||||
/** Returns the units of area for areal calculations made by this object.
|
||||
* @note added in QGIS 2.14
|
||||
* @see lengthUnits()
|
||||
*/
|
||||
QgsUnitTypes::AreaUnit areaUnits() const;
|
||||
|
||||
//! measures polygon area
|
||||
double measurePolygon( const QList<QgsPoint>& points ) const;
|
||||
|
||||
//! compute bearing - in radians
|
||||
double bearing( const QgsPoint& p1, const QgsPoint& p2 ) const;
|
||||
|
||||
/** Returns a measurement formatted as a friendly string
|
||||
* @param value value of measurement
|
||||
* @param decimals number of decimal places to show
|
||||
* @param u unit of measurement
|
||||
* @param isArea set to true if measurement is an area measurement
|
||||
* @param keepBaseUnit set to false to allow conversion of large distances to more suitable units, eg meters
|
||||
* to kilometers
|
||||
* @return formatted measurement string
|
||||
* @see formatArea()
|
||||
*/
|
||||
//TODO QGIS 3.0 - remove isArea parameter (use AreaUnit variant instead), rename to formatDistance
|
||||
static QString textUnit( double value, int decimals, QGis::UnitType u, bool isArea, 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, eg square meters to
|
||||
* square kilometers
|
||||
* @returns formatted area string
|
||||
* @note added in QGIS 2.14
|
||||
* @see textUnit()
|
||||
*/
|
||||
static QString formatArea( double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit = false );
|
||||
|
||||
//! Helper for conversion between physical units
|
||||
// TODO QGIS 3.0 - remove this method, as its behaviour is non-intuitive.
|
||||
void convertMeasurement( double &measure /In,Out/, QGis::UnitType &measureUnits /In,Out/, QGis::UnitType displayUnits, bool isArea ) const;
|
||||
@ -169,12 +201,25 @@ class QgsDistanceArea
|
||||
/** 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 lengthUnits().
|
||||
* was calculated by this class, ie that its unit of length is equal to lengthUnits().
|
||||
* @param toUnits distance unit to convert measurement to
|
||||
* @returns converted distance
|
||||
* @see convertAreaMeasurement()
|
||||
* @note added in QGIS 2.14
|
||||
*/
|
||||
double convertLengthMeasurement( double length, QGis::UnitType toUnits ) const;
|
||||
|
||||
/** 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().
|
||||
* @param toUnits area unit to convert measurement to
|
||||
* @returns converted area
|
||||
* @see convertLengthMeasurement()
|
||||
* @note added in QGIS 2.14
|
||||
*/
|
||||
double convertAreaMeasurement( double area, QgsUnitTypes::AreaUnit toUnits ) const;
|
||||
|
||||
protected:
|
||||
//! measures polygon area and perimeter, vertices are extracted from WKB
|
||||
// @note not available in python bindings
|
||||
|
@ -250,9 +250,16 @@ class QgsProject : QObject
|
||||
|
||||
/** Convenience function to query default distance measurement units for project.
|
||||
* @note added in QGIS 2.14
|
||||
* @see areaUnits()
|
||||
*/
|
||||
QGis::UnitType distanceUnits() const;
|
||||
|
||||
/** Convenience function to query default area measurement units for project.
|
||||
* @note added in QGIS 2.14
|
||||
* @see distanceUnits()
|
||||
*/
|
||||
QgsUnitTypes::AreaUnit areaUnits() const;
|
||||
|
||||
/** Return project's home path
|
||||
@return home path of project (or QString::null if not set) */
|
||||
QString homePath() const;
|
||||
|
@ -111,13 +111,23 @@ class QgsMapToolIdentify : QgsMapTool
|
||||
private:
|
||||
|
||||
//! Private helper
|
||||
virtual void convertMeasurement( QgsDistanceArea &calc, double &measure, QGis::UnitType &u, bool isArea );
|
||||
//! @deprecated use displayDistanceUnits() and displayAreaUnits() instead
|
||||
virtual void convertMeasurement( QgsDistanceArea &calc, double &measure, QGis::UnitType &u, bool isArea ) /Deprecated/;
|
||||
|
||||
/** Transforms the measurements of derived attributes in the desired units*/
|
||||
virtual QGis::UnitType displayUnits();
|
||||
/** Transforms the measurements of derived attributes in the desired units
|
||||
* @deprecated use displayDistanceUnits() and displayAreaUnits() instead
|
||||
*/
|
||||
virtual QGis::UnitType displayUnits() /Deprecated/;
|
||||
|
||||
/** Desired units for distance display.
|
||||
* @note added in QGIS 2.14
|
||||
* @see displayAreaUnits()
|
||||
*/
|
||||
virtual QGis::UnitType displayDistanceUnits();
|
||||
virtual QGis::UnitType displayDistanceUnits() const;
|
||||
|
||||
/** Desired units for area display.
|
||||
* @note added in QGIS 2.14
|
||||
* @see displayDistanceUnits()
|
||||
*/
|
||||
virtual QgsUnitTypes::AreaUnit displayAreaUnits() const;
|
||||
};
|
||||
|
@ -367,6 +367,7 @@ void QgsAttributeTableDialog::runFieldCalculation( QgsVectorLayer* layer, const
|
||||
QgsExpression exp( expression );
|
||||
exp.setGeomCalculator( *myDa );
|
||||
exp.setDistanceUnits( QgsProject::instance()->distanceUnits() );
|
||||
exp.setAreaUnits( QgsProject::instance()->areaUnits() );
|
||||
bool useGeometry = exp.needsGeometry();
|
||||
|
||||
QgsFeatureRequest request( mMainView->masterModel()->request() );
|
||||
@ -818,6 +819,7 @@ void QgsAttributeTableDialog::setFilterExpression( const QString& filterString )
|
||||
|
||||
filterExpression.setGeomCalculator( myDa );
|
||||
filterExpression.setDistanceUnits( QgsProject::instance()->distanceUnits() );
|
||||
filterExpression.setAreaUnits( QgsProject::instance()->areaUnits() );
|
||||
QgsFeatureRequest request( mMainView->masterModel()->request() );
|
||||
request.setSubsetOfAttributes( filterExpression.referencedColumns(), mLayer->fields() );
|
||||
if ( !fetchGeom )
|
||||
|
@ -165,6 +165,7 @@ void QgsFieldCalculator::accept()
|
||||
QgsExpression exp( calcString );
|
||||
exp.setGeomCalculator( myDa );
|
||||
exp.setDistanceUnits( QgsProject::instance()->distanceUnits() );
|
||||
exp.setAreaUnits( QgsProject::instance()->areaUnits() );
|
||||
|
||||
QgsExpressionContext expContext;
|
||||
expContext << QgsExpressionContextUtils::globalScope()
|
||||
|
@ -184,20 +184,16 @@ void QgsMapToolIdentifyAction::deactivate()
|
||||
QgsMapTool::deactivate();
|
||||
}
|
||||
|
||||
QGis::UnitType QgsMapToolIdentifyAction::displayUnits()
|
||||
{
|
||||
// Get the units for display
|
||||
QSettings settings;
|
||||
bool ok = false;
|
||||
QGis::UnitType unit = QgsUnitTypes::decodeDistanceUnit( settings.value( "/qgis/measure/displayunits" ).toString(), &ok );
|
||||
return ok ? unit : QGis::Meters;
|
||||
}
|
||||
|
||||
QGis::UnitType QgsMapToolIdentifyAction::displayDistanceUnits()
|
||||
QGis::UnitType QgsMapToolIdentifyAction::displayDistanceUnits() const
|
||||
{
|
||||
return QgsProject::instance()->distanceUnits();
|
||||
}
|
||||
|
||||
QgsUnitTypes::AreaUnit QgsMapToolIdentifyAction::displayAreaUnits() const
|
||||
{
|
||||
return QgsProject::instance()->areaUnits();
|
||||
}
|
||||
|
||||
void QgsMapToolIdentifyAction::handleCopyToClipboard( QgsFeatureStore & featureStore )
|
||||
{
|
||||
QgsDebugMsg( QString( "features count = %1" ).arg( featureStore.features().size() ) );
|
||||
|
@ -80,8 +80,8 @@ class APP_EXPORT QgsMapToolIdentifyAction : public QgsMapToolIdentify
|
||||
|
||||
QgsIdentifyResultsDialog *resultsDialog();
|
||||
|
||||
virtual QGis::UnitType displayUnits() override;
|
||||
virtual QGis::UnitType displayDistanceUnits() override;
|
||||
virtual QGis::UnitType displayDistanceUnits() const override;
|
||||
virtual QgsUnitTypes::AreaUnit displayAreaUnits() const override;
|
||||
|
||||
};
|
||||
|
||||
|
@ -482,6 +482,22 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl ) :
|
||||
radMeters->setChecked( true );
|
||||
}
|
||||
|
||||
mAreaUnitsComboBox->addItem( tr( "Square meters" ), QgsUnitTypes::SquareMeters );
|
||||
mAreaUnitsComboBox->addItem( tr( "Square kilometers" ), QgsUnitTypes::SquareKilometers );
|
||||
mAreaUnitsComboBox->addItem( tr( "Square feet" ), QgsUnitTypes::SquareFeet );
|
||||
mAreaUnitsComboBox->addItem( tr( "Square yards" ), QgsUnitTypes::SquareYards );
|
||||
mAreaUnitsComboBox->addItem( tr( "Square miles" ), QgsUnitTypes::SquareMiles );
|
||||
mAreaUnitsComboBox->addItem( tr( "Hectares" ), QgsUnitTypes::Hectares );
|
||||
mAreaUnitsComboBox->addItem( tr( "Acres" ), QgsUnitTypes::Acres );
|
||||
mAreaUnitsComboBox->addItem( tr( "Square nautical miles" ), QgsUnitTypes::SquareNauticalMiles );
|
||||
mAreaUnitsComboBox->addItem( tr( "Square degrees" ), QgsUnitTypes::SquareDegrees );
|
||||
mAreaUnitsComboBox->addItem( tr( "Map units" ), QgsUnitTypes::UnknownAreaUnit );
|
||||
|
||||
QgsUnitTypes::AreaUnit areaUnits = QgsUnitTypes::decodeAreaUnit( mSettings->value( "/qgis/measure/areaunits" ).toString(), &ok );
|
||||
if ( !ok )
|
||||
areaUnits = QgsUnitTypes::SquareMeters;
|
||||
mAreaUnitsComboBox->setCurrentIndex( mAreaUnitsComboBox->findData( areaUnits ) );
|
||||
|
||||
QButtonGroup* angleButtonGroup = new QButtonGroup( this );
|
||||
angleButtonGroup->addButton( mDegreesRadioButton );
|
||||
angleButtonGroup->addButton( mRadiansRadioButton );
|
||||
@ -1263,6 +1279,9 @@ void QgsOptions::saveOptions()
|
||||
mSettings->setValue( "/qgis/measure/displayunits", QgsUnitTypes::encodeUnit( QGis::Meters ) );
|
||||
}
|
||||
|
||||
QgsUnitTypes::AreaUnit areaUnit = static_cast< QgsUnitTypes::AreaUnit >( mAreaUnitsComboBox->itemData( mAreaUnitsComboBox->currentIndex() ).toInt() );
|
||||
mSettings->setValue( "/qgis/measure/areaunits", QgsUnitTypes::encodeUnit( areaUnit ) );
|
||||
|
||||
QString angleUnitString = "degrees";
|
||||
if ( mRadiansRadioButton->isChecked() )
|
||||
{
|
||||
|
@ -91,6 +91,17 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
|
||||
mDistanceUnitsCombo->addItem( tr( "Degrees" ), QGis::Degrees );
|
||||
mDistanceUnitsCombo->addItem( tr( "Map units" ), QGis::UnknownUnit );
|
||||
|
||||
mAreaUnitsCombo->addItem( tr( "Square meters" ), QgsUnitTypes::SquareMeters );
|
||||
mAreaUnitsCombo->addItem( tr( "Square kilometers" ), QgsUnitTypes::SquareKilometers );
|
||||
mAreaUnitsCombo->addItem( tr( "Square feet" ), QgsUnitTypes::SquareFeet );
|
||||
mAreaUnitsCombo->addItem( tr( "Square yards" ), QgsUnitTypes::SquareYards );
|
||||
mAreaUnitsCombo->addItem( tr( "Square miles" ), QgsUnitTypes::SquareMiles );
|
||||
mAreaUnitsCombo->addItem( tr( "Hectares" ), QgsUnitTypes::Hectares );
|
||||
mAreaUnitsCombo->addItem( tr( "Acres" ), QgsUnitTypes::Acres );
|
||||
mAreaUnitsCombo->addItem( tr( "Square nautical miles" ), QgsUnitTypes::SquareNauticalMiles );
|
||||
mAreaUnitsCombo->addItem( tr( "Square degrees" ), QgsUnitTypes::SquareDegrees );
|
||||
mAreaUnitsCombo->addItem( tr( "Map units" ), QgsUnitTypes::UnknownAreaUnit );
|
||||
|
||||
connect( buttonBox->button( QDialogButtonBox::Apply ), SIGNAL( clicked() ), this, SLOT( apply() ) );
|
||||
connect( this, SIGNAL( accepted() ), this, SLOT( apply() ) );
|
||||
connect( projectionSelector, SIGNAL( sridSelected( QString ) ), this, SLOT( srIdUpdated() ) );
|
||||
@ -165,6 +176,7 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
|
||||
mCoordinateDisplayComboBox->setCurrentIndex( mCoordinateDisplayComboBox->findData( DecimalDegrees ) );
|
||||
|
||||
mDistanceUnitsCombo->setCurrentIndex( mDistanceUnitsCombo->findData( QgsProject::instance()->distanceUnits() ) );
|
||||
mAreaUnitsCombo->setCurrentIndex( mAreaUnitsCombo->findData( QgsProject::instance()->areaUnits() ) );
|
||||
|
||||
//get the color selections and set the button color accordingly
|
||||
int myRedInt = QgsProject::instance()->readNumEntry( "Gui", "/SelectionColorRedPart", 255 );
|
||||
@ -791,6 +803,9 @@ void QgsProjectProperties::apply()
|
||||
QGis::UnitType distanceUnits = static_cast< QGis::UnitType >( mDistanceUnitsCombo->itemData( mDistanceUnitsCombo->currentIndex() ).toInt() );
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( distanceUnits ) );
|
||||
|
||||
QgsUnitTypes::AreaUnit areaUnits = static_cast< QgsUnitTypes::AreaUnit >( mAreaUnitsCombo->itemData( mAreaUnitsCombo->currentIndex() ).toInt() );
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( areaUnits ) );
|
||||
|
||||
QgsProject::instance()->writeEntry( "Paths", "/Absolute", cbxAbsolutePath->currentIndex() == 0 );
|
||||
|
||||
if ( mEllipsoidList.at( mEllipsoidIndex ).acronym.startsWith( "PARAMETER" ) )
|
||||
@ -1247,6 +1262,20 @@ void QgsProjectProperties::updateGuiForMapUnits( QGis::UnitType units )
|
||||
mCoordinateDisplayComboBox->setItemText( idx, mapUnitString );
|
||||
}
|
||||
}
|
||||
|
||||
//also update unit combo boxes
|
||||
idx = mDistanceUnitsCombo->findData( QGis::UnknownUnit );
|
||||
if ( idx >= 0 )
|
||||
{
|
||||
QString mapUnitString = tr( "Map units (%1)" ).arg( QgsUnitTypes::toString( units ) );
|
||||
mDistanceUnitsCombo->setItemText( idx, mapUnitString );
|
||||
}
|
||||
idx = mAreaUnitsCombo->findData( QgsUnitTypes::UnknownAreaUnit );
|
||||
if ( idx >= 0 )
|
||||
{
|
||||
QString mapUnitString = tr( "Map units (%1)" ).arg( QgsUnitTypes::toString( QgsUnitTypes::distanceToAreaUnit( units ) ) );
|
||||
mAreaUnitsCombo->setItemText( idx, mapUnitString );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsProjectProperties::srIdUpdated()
|
||||
|
@ -539,6 +539,12 @@ QGis::UnitType QgsDistanceArea::lengthUnits() const
|
||||
return willUseEllipsoid() ? QGis::Meters : mCoordTransform->sourceCrs().mapUnits();
|
||||
}
|
||||
|
||||
QgsUnitTypes::AreaUnit QgsDistanceArea::areaUnits() const
|
||||
{
|
||||
return willUseEllipsoid() ? QgsUnitTypes::SquareMeters :
|
||||
QgsUnitTypes::distanceToAreaUnit( mCoordTransform->sourceCrs().mapUnits() );
|
||||
}
|
||||
|
||||
QgsConstWkbPtr QgsDistanceArea::measurePolygon( QgsConstWkbPtr wkbPtr, double* area, double* perimeter, bool hasZptr ) const
|
||||
{
|
||||
if ( !wkbPtr )
|
||||
@ -1091,6 +1097,141 @@ QString QgsDistanceArea::textUnit( double value, int decimals, QGis::UnitType u,
|
||||
return QLocale::system().toString( value, 'f', decimals ) + unitLabel;
|
||||
}
|
||||
|
||||
QString QgsDistanceArea::formatArea( double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit )
|
||||
{
|
||||
QString unitLabel;
|
||||
|
||||
switch ( unit )
|
||||
{
|
||||
case QgsUnitTypes::SquareMeters:
|
||||
{
|
||||
if ( keepBaseUnit )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " m²" );
|
||||
}
|
||||
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareKilometers, QgsUnitTypes::SquareMeters ) )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " km²" );
|
||||
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareMeters, QgsUnitTypes::SquareKilometers );
|
||||
}
|
||||
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::Hectares, QgsUnitTypes::SquareMeters ) )
|
||||
{
|
||||
unitLabel = QObject::tr( " ha" );
|
||||
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareMeters, QgsUnitTypes::Hectares );
|
||||
}
|
||||
else
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " m²" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::SquareKilometers:
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " km²" );
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::SquareFeet:
|
||||
{
|
||||
if ( keepBaseUnit )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " ft²" );
|
||||
}
|
||||
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareMiles, QgsUnitTypes::SquareFeet ) )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " mi²" );
|
||||
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareFeet, QgsUnitTypes::SquareMiles );
|
||||
}
|
||||
else
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " ft²" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::SquareYards:
|
||||
{
|
||||
if ( keepBaseUnit )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " yd²" );
|
||||
}
|
||||
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareMiles, QgsUnitTypes::SquareYards ) )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " mi²" );
|
||||
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareYards, QgsUnitTypes::SquareMiles );
|
||||
}
|
||||
else
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " yd²" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::SquareMiles:
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " mi²" );
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::Hectares:
|
||||
{
|
||||
if ( keepBaseUnit )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " ha" );
|
||||
}
|
||||
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareKilometers, QgsUnitTypes::Hectares ) )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " km²" );
|
||||
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::Hectares, QgsUnitTypes::SquareKilometers );
|
||||
}
|
||||
else
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " ha" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::Acres:
|
||||
{
|
||||
if ( keepBaseUnit )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " ac" );
|
||||
}
|
||||
else if ( qAbs( area ) > QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::SquareMiles, QgsUnitTypes::Acres ) )
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " mi²" );
|
||||
area = area * QgsUnitTypes::fromUnitToUnitFactor( QgsUnitTypes::Acres, QgsUnitTypes::SquareMiles );
|
||||
}
|
||||
else
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " ac" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::SquareNauticalMiles:
|
||||
{
|
||||
unitLabel = QObject::trUtf8( " nm²" );
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::SquareDegrees:
|
||||
{
|
||||
unitLabel = QObject::tr( " sq.deg." );
|
||||
break;
|
||||
}
|
||||
|
||||
case QgsUnitTypes::UnknownAreaUnit:
|
||||
{
|
||||
unitLabel.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QLocale::system().toString( area, 'f', decimals ) + unitLabel;
|
||||
}
|
||||
|
||||
void QgsDistanceArea::convertMeasurement( double &measure, QGis::UnitType &measureUnits, QGis::UnitType displayUnits, bool isArea ) const
|
||||
{
|
||||
// Helper for converting between meters and feet and degrees and NauticalMiles...
|
||||
@ -1136,3 +1277,16 @@ double QgsDistanceArea::convertLengthMeasurement( double length, QGis::UnitType
|
||||
return result;
|
||||
}
|
||||
|
||||
double QgsDistanceArea::convertAreaMeasurement( double area, QgsUnitTypes::AreaUnit toUnits ) const
|
||||
{
|
||||
// get the conversion factor between the specified units
|
||||
QgsUnitTypes::AreaUnit measureUnits = areaUnits();
|
||||
double factorUnits = QgsUnitTypes::fromUnitToUnitFactor( measureUnits, toUnits );
|
||||
|
||||
double result = area * factorUnits;
|
||||
QgsDebugMsg( QString( "Converted area of %1 %2 to %3 %4" ).arg( area )
|
||||
.arg( QgsUnitTypes::toString( measureUnits ) )
|
||||
.arg( result )
|
||||
.arg( QgsUnitTypes::toString( toUnits ) ) );
|
||||
return result;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <QList>
|
||||
#include "qgscoordinatetransform.h"
|
||||
#include "qgswkbptr.h"
|
||||
#include "qgsunittypes.h"
|
||||
|
||||
class QgsGeometry;
|
||||
class QgsAbstractGeometryV2;
|
||||
@ -139,10 +140,12 @@ class CORE_EXPORT QgsDistanceArea
|
||||
|
||||
/** Measures the area of a geometry.
|
||||
* @param geometry geometry to measure
|
||||
* @returns area of geometry. For geometry collections, non surface geometries will be ignored
|
||||
* @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().
|
||||
* @note added in QGIS 2.12
|
||||
* @see measureLength()
|
||||
* @see measurePerimeter()
|
||||
* @see areaUnits()
|
||||
*/
|
||||
double measureArea( const QgsGeometry* geometry ) const;
|
||||
|
||||
@ -194,17 +197,47 @@ class CORE_EXPORT QgsDistanceArea
|
||||
|
||||
/** Returns the units of distance for length calculations made by this object.
|
||||
* @note added in QGIS 2.14
|
||||
* @see areaUnits()
|
||||
*/
|
||||
QGis::UnitType lengthUnits() const;
|
||||
|
||||
/** Returns the units of area for areal calculations made by this object.
|
||||
* @note added in QGIS 2.14
|
||||
* @see lengthUnits()
|
||||
*/
|
||||
QgsUnitTypes::AreaUnit areaUnits() const;
|
||||
|
||||
//! measures polygon area
|
||||
double measurePolygon( const QList<QgsPoint>& points ) const;
|
||||
|
||||
//! compute bearing - in radians
|
||||
double bearing( const QgsPoint& p1, const QgsPoint& p2 ) const;
|
||||
|
||||
/** Returns a measurement formatted as a friendly string
|
||||
* @param value value of measurement
|
||||
* @param decimals number of decimal places to show
|
||||
* @param u unit of measurement
|
||||
* @param isArea set to true if measurement is an area measurement
|
||||
* @param keepBaseUnit set to false to allow conversion of large distances to more suitable units, eg meters
|
||||
* to kilometers
|
||||
* @return formatted measurement string
|
||||
* @see formatArea()
|
||||
*/
|
||||
//TODO QGIS 3.0 - remove isArea parameter (use AreaUnit variant instead), rename to formatDistance
|
||||
static QString textUnit( double value, int decimals, QGis::UnitType u, bool isArea, 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, eg square meters to
|
||||
* square kilometers
|
||||
* @returns formatted area string
|
||||
* @note added in QGIS 2.14
|
||||
* @see textUnit()
|
||||
*/
|
||||
static QString formatArea( double area, int decimals, QgsUnitTypes::AreaUnit unit, bool keepBaseUnit = false );
|
||||
|
||||
//! Helper for conversion between physical units
|
||||
// TODO QGIS 3.0 - remove this method, as its behaviour is non-intuitive.
|
||||
void convertMeasurement( double &measure, QGis::UnitType &measureUnits, QGis::UnitType displayUnits, bool isArea ) const;
|
||||
@ -212,12 +245,25 @@ class CORE_EXPORT QgsDistanceArea
|
||||
/** 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 lengthUnits().
|
||||
* was calculated by this class, ie that its unit of length is equal to lengthUnits().
|
||||
* @param toUnits distance unit to convert measurement to
|
||||
* @returns converted distance
|
||||
* @see convertAreaMeasurement()
|
||||
* @note added in QGIS 2.14
|
||||
*/
|
||||
double convertLengthMeasurement( double length, QGis::UnitType toUnits ) const;
|
||||
|
||||
/** 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().
|
||||
* @param toUnits area unit to convert measurement to
|
||||
* @returns converted area
|
||||
* @see convertLengthMeasurement()
|
||||
* @note added in QGIS 2.14
|
||||
*/
|
||||
double convertAreaMeasurement( double area, QgsUnitTypes::AreaUnit toUnits ) const;
|
||||
|
||||
protected:
|
||||
//! measures polygon area and perimeter, vertices are extracted from WKB
|
||||
// @note not available in python bindings
|
||||
|
@ -1662,7 +1662,9 @@ static QVariant fcnGeomArea( const QVariantList&, const QgsExpressionContext* co
|
||||
QgsDistanceArea* calc = parent->geomCalculator();
|
||||
if ( calc )
|
||||
{
|
||||
return QVariant( calc->measureArea( f.constGeometry() ) );
|
||||
double area = calc->measureArea( f.constGeometry() );
|
||||
area = calc->convertAreaMeasurement( area, parent->areaUnits() );
|
||||
return QVariant( area );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3427,6 +3429,16 @@ void QgsExpression::setDistanceUnits( QGis::UnitType unit )
|
||||
d->mDistanceUnit = unit;
|
||||
}
|
||||
|
||||
QgsUnitTypes::AreaUnit QgsExpression::areaUnits() const
|
||||
{
|
||||
return d->mAreaUnit;
|
||||
}
|
||||
|
||||
void QgsExpression::setAreaUnits( QgsUnitTypes::AreaUnit unit )
|
||||
{
|
||||
d->mAreaUnit = unit;
|
||||
}
|
||||
|
||||
void QgsExpression::acceptVisitor( QgsExpression::Visitor& v ) const
|
||||
{
|
||||
if ( d->mRootNode )
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "qgis.h"
|
||||
|
||||
#include "qgsunittypes.h"
|
||||
|
||||
class QgsFeature;
|
||||
class QgsGeometry;
|
||||
@ -268,6 +268,7 @@ class CORE_EXPORT QgsExpression
|
||||
* (used by $length, $area and $perimeter functions only)
|
||||
* @see setGeomCalculator()
|
||||
* @see distanceUnits()
|
||||
* @see areaUnits()
|
||||
*/
|
||||
QgsDistanceArea *geomCalculator();
|
||||
|
||||
@ -284,6 +285,7 @@ class CORE_EXPORT QgsExpression
|
||||
* @note distances are only converted when a geomCalculator() has been set
|
||||
* @note added in QGIS 2.14
|
||||
* @see setDistanceUnits()
|
||||
* @see areaUnits()
|
||||
*/
|
||||
QGis::UnitType distanceUnits() const;
|
||||
|
||||
@ -291,9 +293,26 @@ class CORE_EXPORT QgsExpression
|
||||
* @note distances are only converted when a geomCalculator() has been set
|
||||
* @note added in QGIS 2.14
|
||||
* @see distanceUnits()
|
||||
* @see setAreaUnits()
|
||||
*/
|
||||
void setDistanceUnits( QGis::UnitType unit );
|
||||
|
||||
/** Returns the desired areal units for calculations involving geomCalculator(), eg "$area".
|
||||
* @note areas are only converted when a geomCalculator() has been set
|
||||
* @note added in QGIS 2.14
|
||||
* @see setAreaUnits()
|
||||
* @see distanceUnits()
|
||||
*/
|
||||
QgsUnitTypes::AreaUnit areaUnits() const;
|
||||
|
||||
/** Sets the desired areal units for calculations involving geomCalculator(), eg "$area".
|
||||
* @note areas are only converted when a geomCalculator() has been set
|
||||
* @note added in QGIS 2.14
|
||||
* @see areaUnits()
|
||||
* @see setDistanceUnits()
|
||||
*/
|
||||
void setAreaUnits( QgsUnitTypes::AreaUnit unit );
|
||||
|
||||
/** This function currently replaces each expression between [% and %]
|
||||
* in the string with the result of its evaluation on the feature
|
||||
* passed as argument.
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "qgsexpression.h"
|
||||
#include "qgsdistancearea.h"
|
||||
#include "qgsunittypes.h"
|
||||
|
||||
///@cond
|
||||
/**
|
||||
@ -39,6 +40,7 @@ class QgsExpressionPrivate
|
||||
, mScale( 0 )
|
||||
, mCalc( nullptr )
|
||||
, mDistanceUnit( QGis::UnknownUnit )
|
||||
, mAreaUnit( QgsUnitTypes::UnknownAreaUnit )
|
||||
{}
|
||||
|
||||
QgsExpressionPrivate( const QgsExpressionPrivate& other )
|
||||
@ -50,6 +52,7 @@ class QgsExpressionPrivate
|
||||
, mExp( other.mExp )
|
||||
, mCalc( other.mCalc )
|
||||
, mDistanceUnit( other.mDistanceUnit )
|
||||
, mAreaUnit( other.mAreaUnit )
|
||||
{}
|
||||
|
||||
~QgsExpressionPrivate()
|
||||
@ -70,6 +73,7 @@ class QgsExpressionPrivate
|
||||
|
||||
QSharedPointer<QgsDistanceArea> mCalc;
|
||||
QGis::UnitType mDistanceUnit;
|
||||
QgsUnitTypes::AreaUnit mAreaUnit;
|
||||
};
|
||||
///@endcond
|
||||
|
||||
|
@ -454,9 +454,10 @@ void QgsProject::clear()
|
||||
writeEntry( "PositionPrecision", "/DecimalPlaces", 2 );
|
||||
writeEntry( "Paths", "/Absolute", false );
|
||||
|
||||
//copy default distance units to project
|
||||
//copy default units to project
|
||||
QSettings s;
|
||||
writeEntry( "Measurement", "/DistanceUnits", s.value( "/qgis/measure/displayunits" ).toString() );
|
||||
writeEntry( "Measurement", "/AreaUnits", s.value( "/qgis/measure/areaunits" ).toString() );
|
||||
|
||||
setDirty( false );
|
||||
}
|
||||
@ -2077,6 +2078,19 @@ QGis::UnitType QgsProject::distanceUnits() const
|
||||
return ok ? type : QGis::Meters;
|
||||
}
|
||||
|
||||
QgsUnitTypes::AreaUnit QgsProject::areaUnits() const
|
||||
{
|
||||
QString areaUnitString = QgsProject::instance()->readEntry( "Measurement", "/AreaUnits", QString() );
|
||||
if ( !areaUnitString.isEmpty() )
|
||||
return QgsUnitTypes::decodeAreaUnit( areaUnitString );
|
||||
|
||||
//fallback to QGIS default area unit
|
||||
QSettings s;
|
||||
bool ok = false;
|
||||
QgsUnitTypes::AreaUnit type = QgsUnitTypes::decodeAreaUnit( s.value( "/qgis/measure/areaunits" ).toString(), &ok );
|
||||
return ok ? type : QgsUnitTypes::SquareMeters;
|
||||
}
|
||||
|
||||
void QgsProjectBadLayerDefaultHandler::handleBadLayers( const QList<QDomNode>& /*layers*/, const QDomDocument& /*projectDom*/ )
|
||||
{
|
||||
// just ignore any bad layers
|
||||
|
@ -32,6 +32,7 @@
|
||||
//for the snap settings
|
||||
#include "qgssnapper.h"
|
||||
#include "qgstolerance.h"
|
||||
#include "qgsunittypes.h"
|
||||
|
||||
//#include <QDomDocument>
|
||||
|
||||
@ -295,9 +296,16 @@ class CORE_EXPORT QgsProject : public QObject
|
||||
|
||||
/** Convenience function to query default distance measurement units for project.
|
||||
* @note added in QGIS 2.14
|
||||
* @see areaUnits()
|
||||
*/
|
||||
QGis::UnitType distanceUnits() const;
|
||||
|
||||
/** Convenience function to query default area measurement units for project.
|
||||
* @note added in QGIS 2.14
|
||||
* @see distanceUnits()
|
||||
*/
|
||||
QgsUnitTypes::AreaUnit areaUnits() const;
|
||||
|
||||
/** Return project's home path
|
||||
@return home path of project (or QString::null if not set) */
|
||||
QString homePath() const;
|
||||
|
@ -398,10 +398,8 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeatur
|
||||
else if ( geometryType == QGis::Polygon )
|
||||
{
|
||||
double area = calc.measureArea( feature->constGeometry() );
|
||||
|
||||
QGis::UnitType myDisplayUnits;
|
||||
convertMeasurement( calc, area, myDisplayUnits, true ); // area and myDisplayUnits are out params
|
||||
QString str = calc.textUnit( area, 3, myDisplayUnits, true );
|
||||
area = calc.convertAreaMeasurement( area, displayAreaUnits() );
|
||||
QString str = formatArea( area );
|
||||
derivedAttributes.insert( tr( "Area" ), str );
|
||||
|
||||
double perimeter = calc.measurePerimeter( feature->constGeometry() );
|
||||
@ -647,8 +645,10 @@ void QgsMapToolIdentify::convertMeasurement( QgsDistanceArea &calc, double &meas
|
||||
// Get the canvas units
|
||||
QGis::UnitType myUnits = mCanvas->mapUnits();
|
||||
|
||||
Q_NOWARN_DEPRECATED_PUSH
|
||||
calc.convertMeasurement( measure, myUnits, displayUnits(), isArea );
|
||||
u = displayUnits();
|
||||
Q_NOWARN_DEPRECATED_POP
|
||||
}
|
||||
|
||||
QGis::UnitType QgsMapToolIdentify::displayUnits()
|
||||
@ -656,12 +656,17 @@ QGis::UnitType QgsMapToolIdentify::displayUnits()
|
||||
return mCanvas->mapUnits();
|
||||
}
|
||||
|
||||
QGis::UnitType QgsMapToolIdentify::displayDistanceUnits()
|
||||
QGis::UnitType QgsMapToolIdentify::displayDistanceUnits() const
|
||||
{
|
||||
return mCanvas->mapUnits();
|
||||
}
|
||||
|
||||
QString QgsMapToolIdentify::formatDistance( double distance )
|
||||
QgsUnitTypes::AreaUnit QgsMapToolIdentify::displayAreaUnits() const
|
||||
{
|
||||
return QgsUnitTypes::distanceToAreaUnit( mCanvas->mapUnits() );
|
||||
}
|
||||
|
||||
QString QgsMapToolIdentify::formatDistance( double distance ) const
|
||||
{
|
||||
QSettings settings;
|
||||
bool baseUnit = settings.value( "/qgis/measure/keepbaseunit", false ).toBool();
|
||||
@ -669,6 +674,14 @@ QString QgsMapToolIdentify::formatDistance( double distance )
|
||||
return QgsDistanceArea::textUnit( distance, 3, displayDistanceUnits(), false, baseUnit );
|
||||
}
|
||||
|
||||
QString QgsMapToolIdentify::formatArea( double area ) const
|
||||
{
|
||||
QSettings settings;
|
||||
bool baseUnit = settings.value( "/qgis/measure/keepbaseunit", false ).toBool();
|
||||
|
||||
return QgsDistanceArea::formatArea( area, 3, displayAreaUnits(), baseUnit );
|
||||
}
|
||||
|
||||
void QgsMapToolIdentify::formatChanged( QgsRasterLayer *layer )
|
||||
{
|
||||
QgsDebugMsg( "Entered" );
|
||||
|
@ -158,20 +158,37 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
|
||||
private:
|
||||
|
||||
//! Private helper
|
||||
virtual void convertMeasurement( QgsDistanceArea &calc, double &measure, QGis::UnitType &u, bool isArea );
|
||||
//! @deprecated use displayDistanceUnits() and displayAreaUnits() instead
|
||||
Q_DECL_DEPRECATED virtual void convertMeasurement( QgsDistanceArea &calc, double &measure, QGis::UnitType &u, bool isArea );
|
||||
|
||||
/** Transforms the measurements of derived attributes in the desired units*/
|
||||
virtual QGis::UnitType displayUnits();
|
||||
/** Transforms the measurements of derived attributes in the desired units
|
||||
* @deprecated use displayDistanceUnits() and displayAreaUnits() instead
|
||||
*/
|
||||
Q_DECL_DEPRECATED virtual QGis::UnitType displayUnits();
|
||||
|
||||
/** Desired units for distance display.
|
||||
* @note added in QGIS 2.14
|
||||
* @see displayAreaUnits()
|
||||
*/
|
||||
virtual QGis::UnitType displayDistanceUnits();
|
||||
virtual QGis::UnitType displayDistanceUnits() const;
|
||||
|
||||
/** Desired units for area display.
|
||||
* @note added in QGIS 2.14
|
||||
* @see displayDistanceUnits()
|
||||
*/
|
||||
virtual QgsUnitTypes::AreaUnit displayAreaUnits() const;
|
||||
|
||||
/** Format a distance into a suitable string for display to the user
|
||||
* @note added in QGIS 2.14
|
||||
* @see formatArea()
|
||||
*/
|
||||
QString formatDistance( double distance );
|
||||
QString formatDistance( double distance ) const;
|
||||
|
||||
/** Format a distance into a suitable string for display to the user
|
||||
* @note added in QGIS 2.14
|
||||
* @see formatDistance()
|
||||
*/
|
||||
QString formatArea( double area ) const;
|
||||
|
||||
QMap< QString, QString > featureDerivedAttributes( QgsFeature *feature, QgsMapLayer *layer, const QgsPoint& layerPoint = QgsPoint() );
|
||||
|
||||
|
@ -308,7 +308,7 @@
|
||||
<item>
|
||||
<widget class="QStackedWidget" name="mOptionsStackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>6</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="mOptionsPageGeneral">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
@ -1825,7 +1825,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-224</y>
|
||||
<y>0</y>
|
||||
<width>949</width>
|
||||
<height>802</height>
|
||||
</rect>
|
||||
@ -2988,9 +2988,9 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-24</y>
|
||||
<y>0</y>
|
||||
<width>949</width>
|
||||
<height>602</height>
|
||||
<height>635</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_30">
|
||||
@ -3141,34 +3141,6 @@
|
||||
<string>Measure tool</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_21">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="textLabel1_10">
|
||||
<property name="text">
|
||||
<string>Rubberband color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="textLabel1_11">
|
||||
<property name="text">
|
||||
<string>Preferred measurements units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QRadioButton" name="radMeters">
|
||||
<property name="text">
|
||||
<string>&Meters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QRadioButton" name="radFeet">
|
||||
<property name="text">
|
||||
<string>Feet</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QRadioButton" name="radNautical">
|
||||
<property name="text">
|
||||
@ -3176,6 +3148,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QRadioButton" name="mDegreesRadioButton">
|
||||
<property name="text">
|
||||
<string>Degrees</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QRadioButton" name="radDegrees">
|
||||
<property name="text">
|
||||
@ -3183,74 +3162,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="mAngleUnitsLabel">
|
||||
<property name="text">
|
||||
<string>Preferred angle units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QRadioButton" name="mDegreesRadioButton">
|
||||
<property name="text">
|
||||
<string>Degrees</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<item row="7" column="2">
|
||||
<widget class="QRadioButton" name="mRadiansRadioButton">
|
||||
<property name="text">
|
||||
<string>Radians</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="mAngleUnitsLabel">
|
||||
<property name="text">
|
||||
<string>Decimal places</string>
|
||||
<string>Preferred angle units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="mDecimalPlacesSpinBox"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="toolTip">
|
||||
<string>If unchecked large numbers will be converted from m. to km. and from ft. to miles</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Keep base unit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="mKeepBaseUnitCheckBox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3">
|
||||
<widget class="QRadioButton" name="mGonRadioButton">
|
||||
<property name="text">
|
||||
<string>Gon</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="3">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>191</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QgsColorButtonV2" name="pbnMeasureColor">
|
||||
<property name="sizePolicy">
|
||||
@ -3276,6 +3204,88 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QRadioButton" name="radMeters">
|
||||
<property name="text">
|
||||
<string>&Meters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QRadioButton" name="radFeet">
|
||||
<property name="text">
|
||||
<string>Feet</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="toolTip">
|
||||
<string>If unchecked large numbers will be converted from m. to km. and from ft. to miles</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Keep base unit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="3">
|
||||
<widget class="QRadioButton" name="mGonRadioButton">
|
||||
<property name="text">
|
||||
<string>Gon</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="textLabel1_10">
|
||||
<property name="text">
|
||||
<string>Rubberband color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="textLabel1_11">
|
||||
<property name="text">
|
||||
<string>Preferred measurements units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="3">
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>191</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Decimal places</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="mKeepBaseUnitCheckBox">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="textLabel1_14">
|
||||
<property name="text">
|
||||
<string>Preferred area units</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="mAreaUnitsComboBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -3484,8 +3494,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>965</width>
|
||||
<height>578</height>
|
||||
<width>514</width>
|
||||
<height>307</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_39">
|
||||
@ -3688,8 +3698,8 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-90</y>
|
||||
<width>949</width>
|
||||
<y>0</y>
|
||||
<width>570</width>
|
||||
<height>668</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -4234,8 +4244,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>965</width>
|
||||
<height>578</height>
|
||||
<width>474</width>
|
||||
<height>372</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
@ -4372,8 +4382,8 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-69</y>
|
||||
<width>949</width>
|
||||
<y>0</y>
|
||||
<width>574</width>
|
||||
<height>647</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -4619,8 +4629,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>965</width>
|
||||
<height>578</height>
|
||||
<width>305</width>
|
||||
<height>226</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_32">
|
||||
@ -4727,8 +4737,8 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>-162</y>
|
||||
<width>949</width>
|
||||
<y>0</y>
|
||||
<width>542</width>
|
||||
<height>740</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -5207,12 +5217,6 @@
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QgsColorButtonV2</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>qgscolorbuttonv2.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsCollapsibleGroupBox</class>
|
||||
<extends>QGroupBox</extends>
|
||||
@ -5220,9 +5224,9 @@
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsProjectionSelectionWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">qgsprojectionselectionwidget.h</header>
|
||||
<class>QgsColorButtonV2</class>
|
||||
<extends>QToolButton</extends>
|
||||
<header>qgscolorbuttonv2.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
@ -5231,17 +5235,23 @@
|
||||
<header location="global">qgscolorschemelist.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsScaleComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>qgsscalecombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsVariableEditorWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">qgsvariableeditorwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsProjectionSelectionWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">qgsprojectionselectionwidget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsScaleComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>qgsscalecombobox.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QgsSettingsTree</class>
|
||||
<extends>QWidget</extends>
|
||||
@ -5370,6 +5380,7 @@
|
||||
<tabstop>radFeet</tabstop>
|
||||
<tabstop>radNautical</tabstop>
|
||||
<tabstop>radDegrees</tabstop>
|
||||
<tabstop>mAreaUnitsComboBox</tabstop>
|
||||
<tabstop>mDegreesRadioButton</tabstop>
|
||||
<tabstop>mRadiansRadioButton</tabstop>
|
||||
<tabstop>mGonRadioButton</tabstop>
|
||||
|
@ -485,25 +485,9 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLineEdit" name="leSemiMinor"/>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="mDistanceUnitsCombo"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="leSemiMajor"/>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="cmbEllipsoid"/>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Units for distance measurement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_41">
|
||||
<property name="text">
|
||||
@ -511,6 +495,22 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_28">
|
||||
<property name="text">
|
||||
<string>Units for distance measurement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="cmbEllipsoid"/>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLineEdit" name="leSemiMinor"/>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="leSemiMajor"/>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_42">
|
||||
<property name="text">
|
||||
@ -518,6 +518,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Units for area measurement</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="4">
|
||||
<widget class="QComboBox" name="mAreaUnitsCombo"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -880,7 +890,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>379</width>
|
||||
<height>562</height>
|
||||
<height>582</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
@ -2539,6 +2549,7 @@
|
||||
<tabstop>leSemiMajor</tabstop>
|
||||
<tabstop>leSemiMinor</tabstop>
|
||||
<tabstop>mDistanceUnitsCombo</tabstop>
|
||||
<tabstop>mAreaUnitsCombo</tabstop>
|
||||
<tabstop>mCoordinateDisplayComboBox</tabstop>
|
||||
<tabstop>radAutomatic</tabstop>
|
||||
<tabstop>radManual</tabstop>
|
||||
|
@ -39,6 +39,7 @@ class TestQgsAttributeTable : public QObject
|
||||
void init() {} // will be called before each testfunction is executed.
|
||||
void cleanup() {} // will be called after every testfunction.
|
||||
void testFieldCalculation();
|
||||
void testFieldCalculationArea();
|
||||
|
||||
private:
|
||||
QgisApp * mQgisApp;
|
||||
@ -115,5 +116,57 @@ void TestQgsAttributeTable::testFieldCalculation()
|
||||
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 0.001 ) );
|
||||
}
|
||||
|
||||
void TestQgsAttributeTable::testFieldCalculationArea()
|
||||
{
|
||||
//test $area field calculation
|
||||
|
||||
//create a temporary layer
|
||||
QScopedPointer< QgsVectorLayer> tempLayer( new QgsVectorLayer( "Polygon?crs=epsg:3111&field=pk:int&field=col1:double", "vl", "memory" ) );
|
||||
QVERIFY( tempLayer->isValid() );
|
||||
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
|
||||
f1.setAttribute( "pk", 1 );
|
||||
f1.setAttribute( "col1", 0.0 );
|
||||
|
||||
QgsPolyline polygonRing3111;
|
||||
polygonRing3111 << QgsPoint( 2484588, 2425722 ) << QgsPoint( 2482767, 2398853 ) << QgsPoint( 2520109, 2397715 ) << QgsPoint( 2520792, 2425494 ) << QgsPoint( 2484588, 2425722 );
|
||||
QgsPolygon polygon3111;
|
||||
polygon3111 << polygonRing3111;
|
||||
f1.setGeometry( QgsGeometry::fromPolygon( polygon3111 ) );
|
||||
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );
|
||||
|
||||
// set project CRS and ellipsoid
|
||||
QgisApp::instance()->mapCanvas()->setCrsTransformEnabled( true );
|
||||
QgsCoordinateReferenceSystem srs( 3111, QgsCoordinateReferenceSystem::EpsgCrsId );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4() );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSID", ( int ) srs.srsid() );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCrs", srs.authid() );
|
||||
QgsProject::instance()->writeEntry( "Measure", "/Ellipsoid", QString( "WGS84" ) );
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( QgsUnitTypes::SquareMeters ) );
|
||||
|
||||
// run area calculation
|
||||
QScopedPointer< QgsAttributeTableDialog > dlg( new QgsAttributeTableDialog( tempLayer.data() ) );
|
||||
tempLayer->startEditing();
|
||||
dlg->runFieldCalculation( tempLayer.data(), "col1", "$area" );
|
||||
tempLayer->commitChanges();
|
||||
// check result
|
||||
QgsFeatureIterator fit = tempLayer->dataProvider()->getFeatures();
|
||||
QgsFeature f;
|
||||
QVERIFY( fit.nextFeature( f ) );
|
||||
double expected = 1009089817.0;
|
||||
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 1.0 ) );
|
||||
|
||||
// change project area unit, check calculation respects unit
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( QgsUnitTypes::SquareMiles ) );
|
||||
QScopedPointer< QgsAttributeTableDialog > dlg2( new QgsAttributeTableDialog( tempLayer.data() ) );
|
||||
tempLayer->startEditing();
|
||||
dlg2->runFieldCalculation( tempLayer.data(), "col1", "$area" );
|
||||
tempLayer->commitChanges();
|
||||
// check result
|
||||
fit = tempLayer->dataProvider()->getFeatures();
|
||||
QVERIFY( fit.nextFeature( f ) );
|
||||
expected = 389.6117565069;
|
||||
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 0.001 ) );
|
||||
}
|
||||
|
||||
QTEST_MAIN( TestQgsAttributeTable )
|
||||
#include "testqgsattributetable.moc"
|
||||
|
@ -39,6 +39,7 @@ class TestQgsFieldCalculator : public QObject
|
||||
void init() {} // will be called before each testfunction is executed.
|
||||
void cleanup() {} // will be called after every testfunction.
|
||||
void testLengthCalculations();
|
||||
void testAreaCalculations();
|
||||
|
||||
private:
|
||||
QgisApp * mQgisApp;
|
||||
@ -126,5 +127,67 @@ void TestQgsFieldCalculator::testLengthCalculations()
|
||||
|
||||
}
|
||||
|
||||
void TestQgsFieldCalculator::testAreaCalculations()
|
||||
{
|
||||
//test area calculation respects ellipsoid and project area units
|
||||
|
||||
//create a temporary layer
|
||||
QScopedPointer< QgsVectorLayer> tempLayer( new QgsVectorLayer( "Polygon?crs=epsg:3111&field=pk:int&field=col1:double", "vl", "memory" ) );
|
||||
QVERIFY( tempLayer->isValid() );
|
||||
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
|
||||
f1.setAttribute( "pk", 1 );
|
||||
f1.setAttribute( "col1", 0.0 );
|
||||
|
||||
QgsPolyline polygonRing3111;
|
||||
polygonRing3111 << QgsPoint( 2484588, 2425722 ) << QgsPoint( 2482767, 2398853 ) << QgsPoint( 2520109, 2397715 ) << QgsPoint( 2520792, 2425494 ) << QgsPoint( 2484588, 2425722 );
|
||||
QgsPolygon polygon3111;
|
||||
polygon3111 << polygonRing3111;
|
||||
f1.setGeometry( QgsGeometry::fromPolygon( polygon3111 ) );
|
||||
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );
|
||||
|
||||
// set project CRS and ellipsoid
|
||||
QgisApp::instance()->mapCanvas()->setCrsTransformEnabled( true );
|
||||
QgsCoordinateReferenceSystem srs( 3111, QgsCoordinateReferenceSystem::EpsgCrsId );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4() );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSID", ( int ) srs.srsid() );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCrs", srs.authid() );
|
||||
QgsProject::instance()->writeEntry( "Measure", "/Ellipsoid", QString( "WGS84" ) );
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( QgsUnitTypes::SquareMeters ) );
|
||||
|
||||
// run area calculation
|
||||
tempLayer->startEditing();
|
||||
QScopedPointer< QgsFieldCalculator > calc( new QgsFieldCalculator( tempLayer.data() ) );
|
||||
|
||||
// this next part is fragile, and may need to be modified if the dialog changes:
|
||||
calc->mUpdateExistingGroupBox->setChecked( true );
|
||||
calc->mExistingFieldComboBox->setCurrentIndex( 1 );
|
||||
calc->builder->setExpressionText( "$area" );
|
||||
calc->accept();
|
||||
|
||||
tempLayer->commitChanges();
|
||||
|
||||
// check result
|
||||
QgsFeatureIterator fit = tempLayer->dataProvider()->getFeatures();
|
||||
QgsFeature f;
|
||||
QVERIFY( fit.nextFeature( f ) );
|
||||
double expected = 1009089817.0;
|
||||
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 1.0 ) );
|
||||
|
||||
// change project area unit, check calculation respects unit
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( QgsUnitTypes::SquareMiles ) );
|
||||
tempLayer->startEditing();
|
||||
QScopedPointer< QgsFieldCalculator > calc2( new QgsFieldCalculator( tempLayer.data() ) );
|
||||
calc2->mUpdateExistingGroupBox->setChecked( true );
|
||||
calc2->mExistingFieldComboBox->setCurrentIndex( 1 );
|
||||
calc2->builder->setExpressionText( "$area" );
|
||||
calc2->accept();
|
||||
tempLayer->commitChanges();
|
||||
// check result
|
||||
fit = tempLayer->dataProvider()->getFeatures();
|
||||
QVERIFY( fit.nextFeature( f ) );
|
||||
expected = 389.6117565069;
|
||||
QVERIFY( qgsDoubleNear( f.attribute( "col1" ).toDouble(), expected, 0.001 ) );
|
||||
}
|
||||
|
||||
QTEST_MAIN( TestQgsFieldCalculator )
|
||||
#include "testqgsfieldcalculator.moc"
|
||||
|
@ -39,6 +39,7 @@ class TestQgsMapToolIdentifyAction : public QObject
|
||||
void cleanup(); // will be called after every testfunction.
|
||||
void lengthCalculation(); //test calculation of derived length attributes
|
||||
void perimeterCalculation(); //test calculation of derived perimeter attribute
|
||||
void areaCalculation(); //test calculation of derived area attribute
|
||||
|
||||
private:
|
||||
QgsMapCanvas* canvas;
|
||||
@ -179,6 +180,63 @@ void TestQgsMapToolIdentifyAction::perimeterCalculation()
|
||||
QVERIFY( qgsDoubleNear( perimeter, 79.715, 0.001 ) );
|
||||
}
|
||||
|
||||
void TestQgsMapToolIdentifyAction::areaCalculation()
|
||||
{
|
||||
QSettings s;
|
||||
s.setValue( "/qgis/measure/keepbaseunit", true );
|
||||
|
||||
//create a temporary layer
|
||||
QScopedPointer< QgsVectorLayer> tempLayer( new QgsVectorLayer( "Polygon?crs=epsg:3111&field=pk:int&field=col1:double", "vl", "memory" ) );
|
||||
QVERIFY( tempLayer->isValid() );
|
||||
QgsFeature f1( tempLayer->dataProvider()->fields(), 1 );
|
||||
f1.setAttribute( "pk", 1 );
|
||||
f1.setAttribute( "col1", 0.0 );
|
||||
|
||||
QgsPolyline polygonRing3111;
|
||||
polygonRing3111 << QgsPoint( 2484588, 2425722 ) << QgsPoint( 2482767, 2398853 ) << QgsPoint( 2520109, 2397715 ) << QgsPoint( 2520792, 2425494 ) << QgsPoint( 2484588, 2425722 );
|
||||
QgsPolygon polygon3111;
|
||||
polygon3111 << polygonRing3111;
|
||||
f1.setGeometry( QgsGeometry::fromPolygon( polygon3111 ) );
|
||||
tempLayer->dataProvider()->addFeatures( QgsFeatureList() << f1 );
|
||||
|
||||
// set project CRS and ellipsoid
|
||||
QgsCoordinateReferenceSystem srs( 3111, QgsCoordinateReferenceSystem::EpsgCrsId );
|
||||
canvas->setCrsTransformEnabled( true );
|
||||
canvas->setDestinationCrs( srs );
|
||||
canvas->setExtent( f1.geometry()->boundingBox() );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSProj4String", srs.toProj4() );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCRSID", ( int ) srs.srsid() );
|
||||
QgsProject::instance()->writeEntry( "SpatialRefSys", "/ProjectCrs", srs.authid() );
|
||||
QgsProject::instance()->writeEntry( "Measure", "/Ellipsoid", QString( "WGS84" ) );
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( QgsUnitTypes::SquareMeters ) );
|
||||
|
||||
QgsPoint mapPoint = canvas->getCoordinateTransform()->transform( 2484588, 2425722 );
|
||||
|
||||
QScopedPointer< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) );
|
||||
QList<QgsMapToolIdentify::IdentifyResult> result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
|
||||
QCOMPARE( result.length(), 1 );
|
||||
QString derivedArea = result.at( 0 ).mDerivedAttributes[tr( "Area" )];
|
||||
double area = derivedArea.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
|
||||
QVERIFY( qgsDoubleNear( area, 1009089817.0, 1.0 ) );
|
||||
|
||||
//check that project units are respected
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( QgsUnitTypes::SquareMiles ) );
|
||||
result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
|
||||
QCOMPARE( result.length(), 1 );
|
||||
derivedArea = result.at( 0 ).mDerivedAttributes[tr( "Area" )];
|
||||
area = derivedArea.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
|
||||
QVERIFY( qgsDoubleNear( area, 389.6117, 0.001 ) );
|
||||
|
||||
//test unchecked "keep base units" setting
|
||||
s.setValue( "/qgis/measure/keepbaseunit", false );
|
||||
QgsProject::instance()->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( QgsUnitTypes::SquareFeet ) );
|
||||
result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer*>() << tempLayer.data() );
|
||||
QCOMPARE( result.length(), 1 );
|
||||
derivedArea = result.at( 0 ).mDerivedAttributes[tr( "Area" )];
|
||||
area = derivedArea.remove( ',' ).split( ' ' ).at( 0 ).toDouble();
|
||||
QVERIFY( qgsDoubleNear( area, 389.6117, 0.001 ) );
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN( TestQgsMapToolIdentifyAction )
|
||||
#include "testqgsmaptoolidentifyaction.moc"
|
||||
|
@ -1325,17 +1325,38 @@ class TestQgsExpression: public QObject
|
||||
// test area without geomCalculator
|
||||
QgsExpression expArea( "$area" );
|
||||
QVariant vArea = expArea.evaluate( &context );
|
||||
QCOMPARE( vArea.toDouble(), 1005640568.0 );
|
||||
double expected = 1005640568.0;
|
||||
QVERIFY( qgsDoubleNear( vArea.toDouble(), expected, 1.0 ) );
|
||||
// units should not be converted if no geometry calculator set
|
||||
expArea.setAreaUnits( QgsUnitTypes::SquareFeet );
|
||||
vArea = expArea.evaluate( &context );
|
||||
QVERIFY( qgsDoubleNear( vArea.toDouble(), expected, 1.0 ) );
|
||||
expArea.setAreaUnits( QgsUnitTypes::SquareNauticalMiles );
|
||||
vArea = expArea.evaluate( &context );
|
||||
QVERIFY( qgsDoubleNear( vArea.toDouble(), expected, 1.0 ) );
|
||||
|
||||
// test area with geomCalculator
|
||||
expArea.setGeomCalculator( da );
|
||||
vArea = expArea.evaluate( &context );
|
||||
QVERIFY( qgsDoubleNear( vArea.toDouble(), 1009089817.0, 1.0 ) );
|
||||
QgsExpression expArea2( "$area" );
|
||||
expArea2.setGeomCalculator( da );
|
||||
vArea = expArea2.evaluate( &context );
|
||||
expected = 1009089817.0;
|
||||
QVERIFY( qgsDoubleNear( vArea.toDouble(), expected, 1.0 ) );
|
||||
// test unit conversion
|
||||
expArea2.setAreaUnits( QgsUnitTypes::SquareMeters ); //default units should be square meters
|
||||
vArea = expArea2.evaluate( &context );
|
||||
QVERIFY( qgsDoubleNear( vArea.toDouble(), expected, 1.0 ) );
|
||||
expArea2.setAreaUnits( QgsUnitTypes::UnknownAreaUnit ); //unknown units should not be converted
|
||||
vArea = expArea2.evaluate( &context );
|
||||
QVERIFY( qgsDoubleNear( vArea.toDouble(), expected, 1.0 ) );
|
||||
expArea2.setAreaUnits( QgsUnitTypes::SquareMiles );
|
||||
expected = 389.6117565069;
|
||||
vArea = expArea2.evaluate( &context );
|
||||
QVERIFY( qgsDoubleNear( vArea.toDouble(), expected, 0.001 ) );
|
||||
|
||||
// test perimeter without geomCalculator
|
||||
QgsExpression expPerimeter( "$perimeter" );
|
||||
QVariant vPerimeter = expPerimeter.evaluate( &context );
|
||||
double expected = 128282.086;
|
||||
expected = 128282.086;
|
||||
QVERIFY( qgsDoubleNear( vPerimeter.toDouble(), expected, 0.001 ) );
|
||||
// units should not be converted if no geometry calculator set
|
||||
expPerimeter.setDistanceUnits( QGis::Feet );
|
||||
|
@ -87,6 +87,8 @@ void TestQgsProject::testProjectUnits()
|
||||
{
|
||||
//test setting and retrieving project units
|
||||
|
||||
// DISTANCE
|
||||
|
||||
//first set a default QGIS distance unit
|
||||
QSettings s;
|
||||
s.setValue( "/qgis/measure/displayunits", QgsUnitTypes::encodeUnit( QGis::Feet ) );
|
||||
@ -103,6 +105,23 @@ void TestQgsProject::testProjectUnits()
|
||||
//test setting new units for project
|
||||
prj->writeEntry( "Measurement", "/DistanceUnits", QgsUnitTypes::encodeUnit( QGis::NauticalMiles ) );
|
||||
QCOMPARE( prj->distanceUnits(), QGis::NauticalMiles );
|
||||
|
||||
// AREA
|
||||
|
||||
//first set a default QGIS area unit
|
||||
s.setValue( "/qgis/measure/areaunits", QgsUnitTypes::encodeUnit( QgsUnitTypes::SquareYards ) );
|
||||
|
||||
// new project should inherit QGIS default area unit
|
||||
prj->clear();
|
||||
QCOMPARE( prj->areaUnits(), QgsUnitTypes::SquareYards );
|
||||
|
||||
//changing default QGIS unit should not affect existing project
|
||||
s.setValue( "/qgis/measure/areaunits", QgsUnitTypes::encodeUnit( QgsUnitTypes::Acres ) );
|
||||
QCOMPARE( prj->areaUnits(), QgsUnitTypes::SquareYards );
|
||||
|
||||
//test setting new units for project
|
||||
prj->writeEntry( "Measurement", "/AreaUnits", QgsUnitTypes::encodeUnit( QgsUnitTypes::Acres ) );
|
||||
QCOMPARE( prj->areaUnits(), QgsUnitTypes::Acres );
|
||||
}
|
||||
|
||||
|
||||
|
@ -191,6 +191,10 @@ class TestQgsDistanceArea(unittest.TestCase):
|
||||
self.assertAlmostEqual(distance, 247555.57, delta=0.01)
|
||||
self.assertEqual(units, QGis.Meters)
|
||||
|
||||
# test converting the resultant length
|
||||
distance = da.convertLengthMeasurement(distance, QGis.NauticalMiles)
|
||||
self.assertAlmostEqual(distance, 133.669, delta=0.01)
|
||||
|
||||
# now try with a source CRS which is in feet
|
||||
da.setSourceCrs(27469)
|
||||
da.setEllipsoidalMode(False)
|
||||
@ -201,6 +205,10 @@ class TestQgsDistanceArea(unittest.TestCase):
|
||||
self.assertAlmostEqual(distance, 2.23606797, delta=0.000001)
|
||||
self.assertEqual(units, QGis.Feet)
|
||||
|
||||
# test converting the resultant length
|
||||
distance = da.convertLengthMeasurement(distance, QGis.Meters)
|
||||
self.assertAlmostEqual(distance, 0.6815, delta=0.001)
|
||||
|
||||
da.setEllipsoidalMode(True)
|
||||
# now should be in Meters again
|
||||
distance = da.measureLine(QgsPoint(1, 1), QgsPoint(2, 3))
|
||||
@ -209,6 +217,83 @@ class TestQgsDistanceArea(unittest.TestCase):
|
||||
self.assertAlmostEqual(distance, 0.67953772, delta=0.000001)
|
||||
self.assertEqual(units, QGis.Meters)
|
||||
|
||||
# test converting the resultant length
|
||||
distance = da.convertLengthMeasurement(distance, QGis.Feet)
|
||||
self.assertAlmostEqual(distance, 2.2294, delta=0.001)
|
||||
|
||||
def testAreaMeasureAndUnits(self):
|
||||
"""Test a variety of area measurements in different CRS and ellipsoid modes, to check that the
|
||||
calculated areas and units are always consistent
|
||||
"""
|
||||
|
||||
da = QgsDistanceArea()
|
||||
da.setSourceCrs(3452)
|
||||
da.setEllipsoidalMode(False)
|
||||
da.setEllipsoid("NONE")
|
||||
daCRS = QgsCoordinateReferenceSystem()
|
||||
daCRS.createFromSrsId(da.sourceCrs())
|
||||
|
||||
polygon = QgsGeometry.fromPolygon(
|
||||
[[
|
||||
QgsPoint(0, 0), QgsPoint(1, 0), QgsPoint(1, 1), QgsPoint(2, 1), QgsPoint(2, 2), QgsPoint(0, 2), QgsPoint(0, 0),
|
||||
]]
|
||||
)
|
||||
|
||||
# We check both the measured area AND the units, in case the logic regarding
|
||||
# ellipsoids and units changes in future
|
||||
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.SquareDegrees) or
|
||||
(abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.SquareMeters))
|
||||
|
||||
da.setEllipsoid("WGS84")
|
||||
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.SquareDegrees) or
|
||||
(abs(area - 37176087091.5) < 0.1 and units == QgsUnitTypes.SquareMeters))
|
||||
|
||||
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)
|
||||
self.assertEqual(units, QgsUnitTypes.SquareMeters)
|
||||
|
||||
# test converting the resultant area
|
||||
area = da.convertAreaMeasurement(area, QgsUnitTypes.SquareMiles)
|
||||
self.assertAlmostEqual(area, 14446.7378, delta=0.001)
|
||||
|
||||
# now try with a source CRS which is in feet
|
||||
da.setSourceCrs(27469)
|
||||
da.setEllipsoidalMode(False)
|
||||
# measurement should be in square feet
|
||||
area = da.measureArea(polygon)
|
||||
units = da.areaUnits()
|
||||
print "measured {} in {}".format(area, QgsUnitTypes.toString(units))
|
||||
self.assertAlmostEqual(area, 3.0, delta=0.000001)
|
||||
self.assertEqual(units, QgsUnitTypes.SquareFeet)
|
||||
|
||||
# test converting the resultant area
|
||||
area = da.convertAreaMeasurement(area, QgsUnitTypes.SquareYards)
|
||||
self.assertAlmostEqual(area, 0.333333, delta=0.001)
|
||||
|
||||
da.setEllipsoidalMode(True)
|
||||
# now should be in Square Meters again
|
||||
area = da.measureArea(polygon)
|
||||
units = da.areaUnits()
|
||||
print "measured {} in {}".format(area, QgsUnitTypes.toString(units))
|
||||
self.assertAlmostEqual(area, 0.256102704082, delta=0.000001)
|
||||
self.assertEqual(units, QgsUnitTypes.SquareMeters)
|
||||
|
||||
# test converting the resultant area
|
||||
area = da.convertAreaMeasurement(area, QgsUnitTypes.SquareYards)
|
||||
self.assertAlmostEqual(area, 0.30629, delta=0.0001)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user