Learn how to calculate the length and area of geometries.

You can calculate the length of a line and determine the area of a polygon using the GeometryEngine. The best measurement method depends on the geometry’s spatial reference, the size of the area or distance being measured, and the accuracy required. Geodesic measurements account for the curvature of the Earth and are generally the best choice when using a geographic coordinate system. For projected coordinate systems, geodesic measurements can be used for measurements of any size and are especially useful for large distances or areas, or when the projection significantly distorts distance or area. Planar measurements can be appropriate for smaller distances or areas when using a projected coordinate system that is designed to preserve the property being measured, such as an equidistant or equal-area projection.
In this tutorial, you will use the geometry editor tool named VertexTool to draw graphics on the view. You will then use the geometry engine to calculate geodesic and planar lengths and areas for Web Mercator geometries to see the difference between the two measurements.
For more information on making measurements, see Make measurements.
For general information on spatial references, see Spatial references in Reference topics.
For specific information on spatial references in ArcGIS Maps SDKs for Native Apps, see Spatial references.
For detailed information on projected coordinate systems, including well-known IDs (WKIDs), areas of use, and maximum/minim latitude and longitude, download the Coordinate systems and transformation zip file and see the Projected Coordinate System tables PDF.
Prerequisites
Before starting this tutorial:
-
You need an ArcGIS Location Platform or ArcGIS Online account.
-
Your system meets the system requirements.
-
The ArcGIS Maps SDK for Qt, version 300.1.0 or later is installed.
-
The Qt 6.8.2 software development framework or later is installed.
Develop or Download
You have two options for completing this tutorial:
Option 1: Develop the code
To start the tutorial, complete the Display a map tutorial. This creates a map to display the Santa Monica Mountains in California using the topographic basemap from the ArcGIS Basemap Styles service
Open a Qt Creator project
-
Open the project you created by completing the Display a map tutorial.
-
Continue with the following instructions to make modifications for this, the find length and area, tutorial.
Update the location
The first thing you will do is update the center point location to be over the general area of England and zoom out quite a bit to see the entire country and part of Europe.
-
Open the Display_a_map.cpp file, in the
setupViewpoint()function, update thecenterandviewpointvariables to display the map over England:Display_a_map.cppvoid Display_a_map::setupViewpoint(){const Point center(-1.398323, 53.402541, SpatialReference::wgs84());const Viewpoint viewpoint(center, 10000000.0);m_mapView->setViewpointAsync(viewpoint);}
Set up the geometry editor and vertex tool
In order to calculate length and area measurements we need a mechanism to draw graphics on the map. These graphics can be created by using the GeometryEditor via the VertexTool.
-
In Projects, double-click Headers > Display_a_map.h to open the file.
-
Add a class declaration for the
GeometryEditor.Display_a_map.hnamespace Esri::ArcGISRuntime{class Map;class MapQuickView;class GeometryEditor;} -
Now add a private member
m_geometryEditorvariable for the geometry editor. Then save the file.Display_a_map.hprivate:Esri::ArcGISRuntime::MapQuickView* mapView() const;void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView);void setupViewpoint();Esri::ArcGISRuntime::GeometryEditor* m_geometryEditor = nullptr; -
In Projects, double-click Sources > Display_a_map.cpp to open the file.
-
Include the following classes as shown in the next code block.
Display_a_map.cpp#include "Display_a_map.h"#include "Map.h"#include "MapTypes.h"#include "MapQuickView.h"#include "Point.h"#include "Viewpoint.h"#include "SpatialReference.h"#include <QFuture>#include "GeometryEditor.h"#include "VertexTool.h" -
In the existing
setMapView(MapQuickView* mapView)function, add code to create aGeometryEditor, set theVertexTool, and then assign geometry editor to the map view. Then save the file.Display_a_map.cpp// Set the view (created in QML)void Display_a_map::setMapView(MapQuickView* mapView){if (!mapView || mapView == m_mapView){return;}m_mapView = mapView;m_mapView->setMap(m_map);m_geometryEditor = new GeometryEditor(this);m_geometryEditor->setTool(new VertexTool(this));m_mapView->setGeometryEditor(m_geometryEditor);setupViewpoint();emit mapViewChanged();}
Add UI buttons and add back-end logic for drawing
Now that we have the geometry editor with a vertex tool available, we need to add some UI buttons for drawing a Polyline and Polygon. We will also need a UI button to Delete geometries when you are finished sketching them on the map. Additionally, we need to code the back-end logic to have the buttons do something on the map. This means the ability to start and stop drawing a polyline and polygon.
-
In Projects, double-click Resources > qml\qml.qrc/qml/Display_a_mapForm.qml to open the file.
-
Add UI buttons to perform the polyline and polygon drawing. Also, add the delete button. Of course we will also need to wrap these controls in a nice visual container (Rectangle) and do some alignment formatting (Column) so things appear nicely on the screen. Then save the file.
Display_a_mapForm.qml// Declare the C++ instance that creates the map etc., and supply the view.Display_a_map {id: modelmapView: view}Rectangle {width: 300height: panelContent.implicitHeight + 20color: "#ffffff"opacity: 0.92radius: 6anchors {left: parent.lefttop: parent.topmargins: 15}Column {id: panelContentanchors.fill: parentanchors.margins: 10spacing: 8Label {text: "Find length and area"font.pixelSize: 18font.bold: true}Row {spacing: 6Button {text: "Polyline"onClicked: model.startPolyline()}Button {text: "Polygon"onClicked: model.startPolygon()}Button {text: "Delete"onClicked: model.deleteGeometry()}}}} -
In Projects, double-click Headers > Display_a_map.h to open the file.
-
Now add some Q_INVOKABLE variables to control the geometry-editing actions that are used by QML UI controls. Then save the file.
Display_a_map.hpublic:explicit Display_a_map(QObject* parent = nullptr);~Display_a_map() override;Q_INVOKABLE void startPolyline();Q_INVOKABLE void startPolygon();Q_INVOKABLE void deleteGeometry(); -
In the Display_a_map.cpp file, add back-end business logic methods to start a polyline editor, start a polygon editor, and deleting the current editing geometry.
Display_a_map.cpp// Set the view (created in QML)void Display_a_map::setMapView(MapQuickView* mapView){if (!mapView || mapView == m_mapView){return;}m_mapView = mapView;m_mapView->setMap(m_map);m_geometryEditor = new GeometryEditor(this);m_geometryEditor->setTool(new VertexTool(this));m_mapView->setGeometryEditor(m_geometryEditor);setupViewpoint();emit mapViewChanged();}void Display_a_map::startPolyline(){if (!m_geometryEditor)return;m_geometryEditor->stop();m_geometryEditor->start(GeometryType::Polyline);}void Display_a_map::startPolygon(){if (!m_geometryEditor)return;m_geometryEditor->stop();m_geometryEditor->start(GeometryType::Polygon);}void Display_a_map::deleteGeometry(){if (!m_geometryEditor)return;m_geometryEditor->stop();}
Add UI labels and add back-end logic for measurements
We are now nearing the completion steps to have a fully functional app. We will add UI labels for the display of the geodetic and planar measurements for the polyline and polygon as you add each vertex of the graphics. We will also add the functions to calculate the measurements using some static methods via the GeometryEngine API> Code will also be added to reset the label values when switching between the drawing of a polyline and polygon.
-
In Projects, double-click Resources > qml\qml.qrc/qml/Display_a_mapForm.qml to open the file. Then save the file.
-
Add UI labels to display the geodetic and planar values.
Display_a_mapForm.qmlRectangle {width: 300height: panelContent.implicitHeight + 20color: "#ffffff"opacity: 0.92radius: 6anchors {left: parent.lefttop: parent.topmargins: 15}Column {id: panelContentanchors.fill: parentanchors.margins: 10spacing: 8Label {text: "Find length and area"font.pixelSize: 18font.bold: true}Row {spacing: 6Button {text: "Polyline"onClicked: model.startPolyline()}Button {text: "Polygon"onClicked: model.startPolygon()}Button {text: "Delete"onClicked: model.deleteGeometry()}}Label {text: "Measurement type: " + model.measurementType}Label {text: "Geodetic: " + model.geodeticMeasurement + " " + model.displayUnits}Label {text: "Planar: " + model.planarMeasurement + " " + model.displayUnits}}} -
In Projects, double-click Headers > Display_a_map.h to open the file.
-
Now add some Q_PROPERTY variables used when a
measurementsChangednotification has occurred to update the GUI labels.Display_a_map.hQ_PROPERTY(Esri::ArcGISRuntime::MapQuickView* mapView READ mapView WRITE setMapView NOTIFY mapViewChanged)Q_PROPERTY(QString measurementType MEMBER m_measurementType NOTIFY measurementsChanged)Q_PROPERTY(QString geodeticMeasurement MEMBER m_geodeticMeasurement NOTIFY measurementsChanged)Q_PROPERTY(QString planarMeasurement MEMBER m_planarMeasurement NOTIFY measurementsChanged)Q_PROPERTY(QString displayUnits MEMBER m_displayUnits NOTIFY measurementsChanged) -
Add the
measurementsChangedsignal to detect when the measurement has changed.Display_a_map.hsignals:void mapViewChanged();void measurementsChanged(); -
Add the private helper
resetMeasurementsandupdateMeasurementsfunctions, and member variables to store and update measurement calculations. Then save the file.Display_a_map.hprivate:Esri::ArcGISRuntime::MapQuickView* mapView() const;void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView);void setupViewpoint();Esri::ArcGISRuntime::GeometryEditor* m_geometryEditor = nullptr;void resetMeasurements(const QString& measurementType, const QString& unitText);void updateMeasurements();QString m_measurementType = "measurement";QString m_geodeticMeasurement = "0";QString m_planarMeasurement = "0";QString m_displayUnits = "km"; -
In Projects, double-click Sources > Display_a_map.cpp to open the file.
-
Include the following
#includepreprocessor directives as shown in the next code block.Display_a_map.cpp#include "Display_a_map.h"#include "Map.h"#include "MapTypes.h"#include "MapQuickView.h"#include "Point.h"#include "Viewpoint.h"#include "SpatialReference.h"#include <QFuture>#include "GeometryEditor.h"#include "VertexTool.h"#include "AreaUnit.h"#include "Geometry.h"#include "GeometryEngine.h"#include "GeometryTypes.h"#include "LinearUnit.h" -
Add two new functions: the
resetMeasurementsfunction which resets the measurement operations to their initial state and theupdateMeasurementsfunction which reads the current geometry from theGeometryEngineand calculates geodetic and planar measurements for display in the GUI.Display_a_map.cppvoid Display_a_map::setupViewpoint(){const Point center(-1.398323, 53.402541, SpatialReference::wgs84());const Viewpoint viewpoint(center, 10000000.0);m_mapView->setViewpointAsync(viewpoint);}void Display_a_map::resetMeasurements(const QString& measurementType, const QString& unitText){m_measurementType = measurementType;m_displayUnits = unitText;m_geodeticMeasurement = "0";m_planarMeasurement = "0";emit measurementsChanged();}void Display_a_map::updateMeasurements(){if (!m_geometryEditor)return;const Geometry geometry = m_geometryEditor->geometry();if (geometry.isEmpty()){resetMeasurements(m_measurementType, m_displayUnits);return;}if (geometry.geometryType() == GeometryType::Polyline){m_measurementType = "length";m_displayUnits = "km";const double geodeticLengthKm = GeometryEngine::lengthGeodetic(geometry,LinearUnit::kilometers(),GeodeticCurveType::Geodesic);const double planarLengthKm = GeometryEngine::length(geometry) / 1000.0;m_geodeticMeasurement = QString::number(geodeticLengthKm, 'f', 2);m_planarMeasurement = QString::number(planarLengthKm, 'f', 2);emit measurementsChanged();return;}if (geometry.geometryType() == GeometryType::Polygon){m_measurementType = "area";m_displayUnits = "km²";const double geodeticAreaKm2 = qAbs(GeometryEngine::areaGeodetic(geometry,AreaUnit::squareKilometers(),GeodeticCurveType::Geodesic));const double planarAreaKm2 = qAbs(GeometryEngine::area(geometry) / 1000000.0);m_geodeticMeasurement = QString::number(geodeticAreaKm2, 'f', 2);m_planarMeasurement = QString::number(planarAreaKm2, 'f', 2);emit measurementsChanged();}} -
Now add the connect for the geometry editor’s geometry changed event that performs the
updateMeasurements.Display_a_map.cpp// Set the view (created in QML)void Display_a_map::setMapView(MapQuickView* mapView){if (!mapView || mapView == m_mapView){return;}m_mapView = mapView;m_mapView->setMap(m_map);m_geometryEditor = new GeometryEditor(this);m_geometryEditor->setTool(new VertexTool(this));m_mapView->setGeometryEditor(m_geometryEditor);connect(m_geometryEditor, &GeometryEditor::geometryChanged, this, &Display_a_map::updateMeasurements);setupViewpoint();emit mapViewChanged();} -
The final step we need to perform is to add calls to the
resetMeasurementsfunction from within the prior added functions:startPolyline,startPolygon, anddeleteGeometry. Then save the file.Display_a_map.cppvoid Display_a_map::startPolyline(){if (!m_geometryEditor)return;m_geometryEditor->stop();m_geometryEditor->start(GeometryType::Polyline);resetMeasurements("length", "km");}void Display_a_map::startPolygon(){if (!m_geometryEditor)return;m_geometryEditor->stop();m_geometryEditor->start(GeometryType::Polygon);resetMeasurements("area", "km²");}void Display_a_map::deleteGeometry(){if (!m_geometryEditor)return;m_geometryEditor->stop();resetMeasurements("measurement", "km");}
Set developer credentials
For the final steps of this tutorial, click the tab below that corresponds to the authentication type (API key authentication or User authentication) that you chose when you completed the Display a map tutorial.
Be sure to also provide the same authentication (API key or user authentication Client ID/Redirect URL) that you used for the Display a map tutorial.
Set the API Key
-
In the project Sources folder of Qt Creator, open the main.cpp file.
-
Modify the code to set the
accessTokenusing your API key access token (highlighted in yellow).main.cpp// The following methods grant an access token:// 1. User authentication: Grants a temporary access token associated with a user's ArcGIS account.// To generate a token, a user logs in to the app with an ArcGIS account that is part of an// organization in ArcGIS Online or ArcGIS Enterprise.// 2. API key authentication: Get a long-lived access token that gives your application access to// ArcGIS location services. Go to the tutorial at https://links.esri.com/create-an-api-key.// Copy the API Key access token.const QString accessToken = QString("");if (accessToken.isEmpty()){qWarning() << "Use of ArcGIS location services, such as the basemap styles service, requires" <<"you to authenticate with an ArcGIS account or set the API Key property.";}else{ArcGISRuntimeEnvironment::setApiKey(accessToken);} -
Save the main.cpp file.
Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.
Set path to the Qt Toolkit in the project
In the project Sources folder of Qt Creator, open the Display_a_map.pro file and locate the following lines and update PATH_TO_TOOLKIT variable with the path of the toolkitcpp.pri file (highlighted in yellow) or the OAuth dialog will not appear to enter your user credentials. Then save the file.
ARCGIS_RUNTIME_VERSION = 300.1.0include($$PWD/arcgisruntime.pri)
# TODO: You need to replace the <path_to_toolkit_repo> with a valid location where the Qt Toolkit# resides on your system, example: C:/arcgis-maps-sdk-toolkit-qt/uitools/toolkitcpp/toolkitcpp.pri# This block determines whether you've cloned your toolkitPATH_TO_TOOLKIT = "<path_to_toolkit_repo>/uitools/toolkitcpp/toolkitcpp.pri"
exists($${PATH_TO_TOOLKIT}) { message("Toolkit found") DEFINES += TOOLKIT_FOUND
# include the toolkitcpp.pri, which contains all the toolkit resources include($${PATH_TO_TOOLKIT})
qtHaveModule(webenginequick) { QT += webenginequick }} else { message("Toolkit not found in provided path. Either set PATH_TO_TOOLKIT or use an API Key")}Set developer credentials in the solution
In the project Sources folder of Qt Creator, open the Display_a_map.cpp file.
Set your values for the REDIRECT_URL and the CLIENT_ID strings (highlighted in yellow). Then save the file.
// Define the Redirect URL string obtained when creating the OAuth credentials. // TODO: You need to replace the "REDIRECT_URL" with your own valid string, // ex: "urn:ietf:wg:oauth:2.0:oob" const auto qStringRedirectUrl = QString{"REDIRECT_URL"}; // Define a unique identifier associated with an application registered with the // portal that assists with client/server OAuth authentication. // TODO: You need to replace the "CLIENT_ID" with your own valid string. const QString qStringClientId = QString{"CLIENT_ID"};Press Ctrl + R to run the app.
You should see a map centered on England with two buttons at the bottom of the screen. Click the Polyline button, and tap at least two points. The geodetic and planar length of the polyline should display below the map. Then click the Delete button to end the editing with the geometry editor control. Now click the Polygon button, and tap at least three points. The geodetic and planar area of the polygon should display. Then click the Delete button to end the editing with the geometry editor control.
Alternatively, you can download the tutorial solution, as follows.
Option 2: Download the solution
-
Click the
Download solutionlink underSolutionand unzip the file to a location on your machine. -
Open the .pro project file in Qt Creator.
Since the downloaded solution does not contain authentication credentials, you must set up authentication to create the developer credentials and add them to the project.
For the final steps of this tutorial, click the tab below that corresponds to the authentication type (API key authentication or User authentication) that you chose when you completed the Display a map tutorial.
Be sure to also provide the same authentication (API key or user authentication Client ID/Redirect URL) that you used for the Display a map tutorial.
Set developer credentials in the solution
Set the API Key
-
In the project Sources folder of Qt Creator, open the main.cpp file.
-
Modify the code to set the
accessTokenusing your API key access token (highlighted in yellow).main.cpp// The following methods grant an access token:// 1. User authentication: Grants a temporary access token associated with a user's ArcGIS account.// To generate a token, a user logs in to the app with an ArcGIS account that is part of an// organization in ArcGIS Online or ArcGIS Enterprise.// 2. API key authentication: Get a long-lived access token that gives your application access to// ArcGIS location services. Go to the tutorial at https://links.esri.com/create-an-api-key.// Copy the API Key access token.const QString accessToken = QString("");if (accessToken.isEmpty()){qWarning() << "Use of ArcGIS location services, such as the basemap styles service, requires" <<"you to authenticate with an ArcGIS account or set the API Key property.";}else{ArcGISRuntimeEnvironment::setApiKey(accessToken);} -
Save the main.cpp file.
Best Practice: The access token is stored directly in the code as a convenience for this tutorial. Do not store credentials directly in source code in a production environment.
Set path to the Qt Toolkit in the project
In the project Sources folder of Qt Creator, open the Display_a_map.pro file and locate the following lines and update PATH_TO_TOOLKIT variable with the path of the toolkitcpp.pri file (highlighted in yellow) or the OAuth dialog will not appear to enter your user credentials. Then save the file.
ARCGIS_RUNTIME_VERSION = 300.1.0include($$PWD/arcgisruntime.pri)
# TODO: You need to replace the <path_to_toolkit_repo> with a valid location where the Qt Toolkit# resides on your system, example: C:/arcgis-maps-sdk-toolkit-qt/uitools/toolkitcpp/toolkitcpp.pri# This block determines whether you've cloned your toolkitPATH_TO_TOOLKIT = "<path_to_toolkit_repo>/uitools/toolkitcpp/toolkitcpp.pri"
exists($${PATH_TO_TOOLKIT}) { message("Toolkit found") DEFINES += TOOLKIT_FOUND
# include the toolkitcpp.pri, which contains all the toolkit resources include($${PATH_TO_TOOLKIT})
qtHaveModule(webenginequick) { QT += webenginequick }} else { message("Toolkit not found in provided path. Either set PATH_TO_TOOLKIT or use an API Key")}Set developer credentials in the solution
-
In the project Sources folder of Qt Creator, open the Display_a_map.cpp file.
-
Set your values for the REDIRECT_URL and the CLIENT_ID strings (highlighted in yellow). Then save the file.
// Define the Redirect URL string obtained when creating the OAuth credentials. // TODO: You need to replace the "REDIRECT_URL" with your own valid string, // ex: "urn:ietf:wg:oauth:2.0:oob" const auto qStringRedirectUrl = QString{"REDIRECT_URL"}; // Define a unique identifier associated with an application registered with the // portal that assists with client/server OAuth authentication. // TODO: You need to replace the "CLIENT_ID" with your own valid string. const QString qStringClientId = QString{"CLIENT_ID"};Run the solution
Press Ctrl + R to run the app.
You should see a map centered on England with two buttons at the bottom of the screen. Click the Polyline button, and tap at least two points. The geodetic and planar length of the polyline should display below the map. Then click the Delete button to end the editing with the geometry editor control. Now click the Polygon button, and tap at least three points. The geodetic and planar area of the polygon should display. Then click the Delete button to end the editing with the geometry editor control.
What’s next?
Learn how to use additional API features, ArcGIS location services, and ArcGIS tools in these tutorials: