Format coordinates in a variety of common notations.

Use case
The coordinate formatter can format a map location in WGS84 in a number of common coordinate notations. Parsing one of these formats to a location is also supported. Formats include decimal degrees; degrees, minutes, seconds; Universal Transverse Mercator (UTM), and United States National Grid (USNG).
How to use the sample
Click on the map to see a callout with the clicked location’s coordinate formatted in 4 different ways. You can also put a coordinate string in any of these formats in the text field. Hit Enter and the coordinate string will be parsed to a map location which the callout will move to.
How it works
- Get or create a map
Pointwith a spatial reference. - Use one of the static “to” methods on
CoordinateFormattersuch asCoordinateFormatter::toLatitudeLongitude(point, LatitudeLongitudeFormat::DecimalDegrees, 4)to get the formatted string. - To go from a formatted string to a
Point, use one of the “from” static methods likeCoordinateFormatter::fromUtm(coordinateString, map.spatialReference(), UtmConversionMode::LatitudeBandIndicators).
Relevant API
- CoordinateFormatter
- LatitudeLongitudeFormat
- UtmConversionMode
Tags
convert, coordinate, decimal degrees, degree minutes seconds, format, latitude, longitude, USNG, UTM
Sample Code
// [WriteFile Name=FormatCoordinates, Category=Geometry]// [Legal]// Copyright 2017 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
#ifdef PCH_BUILD#include "pch.hpp"#endif // PCH_BUILD
// sample headers#include "FormatCoordinates.h"
// ArcGIS Maps SDK headers#include "CoordinateFormatter.h"#include "Graphic.h"#include "GraphicListModel.h"#include "GraphicsOverlay.h"#include "GraphicsOverlayListModel.h"#include "Map.h"#include "MapQuickView.h"#include "MapTypes.h"#include "Point.h"#include "SimpleMarkerSymbol.h"#include "SpatialReference.h"#include "SymbolTypes.h"
using namespace Esri::ArcGISRuntime;
namespace{ // Initial point marker 'X' symbol appears. const Point startPoint(-117.195723, 34.056195, SpatialReference::wgs84());}
FormatCoordinates::FormatCoordinates(QObject* parent) : QObject(parent), m_map(new Map(BasemapStyle::ArcGISImageryStandard, this)), m_graphicsOverlay(new GraphicsOverlay(this)){ // create a graphic SimpleMarkerSymbol* symbol = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle::X, QColor(Qt::red), 15.0, this);
Graphic* graphic = new Graphic(startPoint, symbol, this);
// and add insert the graphic m_graphicsOverlay->graphics()->append(graphic);}
FormatCoordinates::~FormatCoordinates() = default;
void FormatCoordinates::init(){ qmlRegisterType<MapQuickView>("Esri.Samples", 1, 0, "MapView"); qmlRegisterType<FormatCoordinates>("Esri.Samples", 1, 0, "FormatCoordinatesSample");}
// handle case where the user changed one of the text fieldsvoid FormatCoordinates::handleTextUpdate(QString textType, QString text){ Point point = createPointFromText(textType, text); handleLocationUpdate(std::move(point));}
// handle case where user clicked on the mapvoid FormatCoordinates::handleLocationUpdate(Point point){ if (!point.isEmpty()) { m_mapView->graphicsOverlays()->at(0)->graphics()->at(0)->setGeometry(point); setTextFromPoint(point); }}
Point FormatCoordinates::createPointFromText(const QString& textType, const QString& text) const{ //! [FormatCoordinates CoordinateFormatter various text to point] if (strDecimalDegrees() == textType || strDegreesMinutesSeconds() == textType) { return CoordinateFormatter::fromLatitudeLongitude(text, m_map->spatialReference()); } if (strUsng() == textType) { return CoordinateFormatter::fromUsng(text, m_map->spatialReference()); } if (strUtm() == textType) { return CoordinateFormatter::fromUtm(text, m_map->spatialReference(), UtmConversionMode::LatitudeBandIndicators); } return Point(); //! [FormatCoordinates CoordinateFormatter various text to point]}
void FormatCoordinates::setTextFromPoint(Point point){ // last parm = decimal places m_coordinatesInDD = CoordinateFormatter::toLatitudeLongitude(point, LatitudeLongitudeFormat::DecimalDegrees, 6);
// last parm = decimal places m_coordinatesInDMS = CoordinateFormatter::toLatitudeLongitude(point, LatitudeLongitudeFormat::DegreesMinutesSeconds, 1);
//! [FormatCoordinates CoordinateFormatter point to USNG] int decimalPlaces = 5; bool addSpaces = true; m_coordinatesInUsng = CoordinateFormatter::toUsng(point, decimalPlaces, addSpaces); //! [FormatCoordinates CoordinateFormatter point to USNG]
// last parm = add spaces m_coordinatesInUtm = CoordinateFormatter::toUtm(point, UtmConversionMode::LatitudeBandIndicators, true);
emit coordinatesChanged();}
QString FormatCoordinates::coordinatesInDD() const{ return m_coordinatesInDD;}
QString FormatCoordinates::coordinatesInDMS() const{ return m_coordinatesInDMS;}
QString FormatCoordinates::coordinatesInUsng() const{ return m_coordinatesInUsng;}
QString FormatCoordinates::coordinatesInUtm() const{ return m_coordinatesInUtm;}
QString FormatCoordinates::strDecimalDegrees() const{ return tr("Degrees");}
QString FormatCoordinates::strDegreesMinutesSeconds() const{ return tr("DMS");}
QString FormatCoordinates::strUsng() const{ return tr("Usng");}
QString FormatCoordinates::strUtm() const{ return tr("Utm");}
void FormatCoordinates::setMapView(MapQuickView* mapView){ if (m_mapView) { m_mapView->setMap(nullptr); // Remove map from old mapView. m_mapView->graphicsOverlays()->clear(); // Remove Graphics overlays from old mapView. }
m_mapView = mapView;
if (!m_mapView) { return; }
// set map and graphics overlay on the map view m_mapView->setMap(m_map); m_mapView->graphicsOverlays()->append(m_graphicsOverlay);
// connect to the mouse clicked signal on the MapQuickView connect(m_mapView, &MapQuickView::mouseClicked, this, [this](QMouseEvent& mouseEvent) { // get the point from the mouse point Point mapPoint = m_mapView->screenToLocation(mouseEvent.position().x(), mouseEvent.position().y());
// using the point, refresh the graphic and the text handleLocationUpdate(std::move(mapPoint)); });
handleLocationUpdate(startPoint);}// [WriteFile Name=FormatCoordinates, Category=Geometry]// [Legal]// Copyright 2017 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
#ifndef FORMATCOORDINATES_H#define FORMATCOORDINATES_H
// ArcGIS Maps SDK headers#include "Point.h"
// Qt headers#include <QObject>
namespace Esri::ArcGISRuntime{class Map;class MapQuickView;class GraphicsOverlay;}
Q_MOC_INCLUDE("MapQuickView.h")
class FormatCoordinates : public QObject{ Q_OBJECT
Q_PROPERTY(Esri::ArcGISRuntime::MapQuickView* mapView MEMBER m_mapView WRITE setMapView) Q_PROPERTY(QString coordinatesInDD READ coordinatesInDD NOTIFY coordinatesChanged) Q_PROPERTY(QString coordinatesInDMS READ coordinatesInDMS NOTIFY coordinatesChanged) Q_PROPERTY(QString coordinatesInUsng READ coordinatesInUsng NOTIFY coordinatesChanged) Q_PROPERTY(QString coordinatesInUtm READ coordinatesInUtm NOTIFY coordinatesChanged) Q_PROPERTY(QString strDecimalDegrees READ strDecimalDegrees CONSTANT) Q_PROPERTY(QString strDegreesMinutesSeconds READ strDegreesMinutesSeconds CONSTANT) Q_PROPERTY(QString strUsng READ strUsng CONSTANT) Q_PROPERTY(QString strUtm READ strUtm CONSTANT)
public: explicit FormatCoordinates(QObject* parent = nullptr); ~FormatCoordinates() override;
static void init(); Q_INVOKABLE void handleTextUpdate(QString textType, QString text); Q_INVOKABLE void handleLocationUpdate(Esri::ArcGISRuntime::Point point);
signals: void coordinatesChanged();
private: QString coordinatesInDD() const; QString coordinatesInDMS() const; QString coordinatesInUsng() const; QString coordinatesInUtm() const; QString strDecimalDegrees() const; QString strDegreesMinutesSeconds() const; QString strUsng() const; QString strUtm() const;
void setMapView(Esri::ArcGISRuntime::MapQuickView* mapView);
Esri::ArcGISRuntime::Point createPointFromText(const QString& textType, const QString& text) const; void setTextFromPoint(Esri::ArcGISRuntime::Point point);
private: Esri::ArcGISRuntime::Map* m_map = nullptr; Esri::ArcGISRuntime::MapQuickView* m_mapView = nullptr; Esri::ArcGISRuntime::GraphicsOverlay* m_graphicsOverlay = nullptr;
QString m_coordinatesInDD; QString m_coordinatesInDMS; QString m_coordinatesInUsng; QString m_coordinatesInUtm;};
#endif // FORMATCOORDINATES_H// [WriteFile Name=FormatCoordinates, Category=Geometry]// [Legal]// Copyright 2017 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
import QtQuickimport QtQuick.Controlsimport QtQuick.Layoutsimport Esri.Samples
Item { clip: true
readonly property int fontPixelSize: 14 property string labelSuffix: ": "
FormatCoordinatesSample { id: model mapView: view }
Rectangle { anchors.fill: parent
GridLayout { columns: 2 anchors.fill: parent
MapView { id: view Layout.fillWidth: true Layout.fillHeight: true Layout.columnSpan: 2
Component.onCompleted: { // Set the focus on MapView to initially enable keyboard navigation forceActiveFocus(); } }
Text { id: labelDD font.pixelSize: fontPixelSize Layout.margins: 5 horizontalAlignment: Text.AlignRight text: model.strDecimalDegrees + labelSuffix }
TextField { id: textDD font.pixelSize: fontPixelSize text: model.coordinatesInDD.length === 0 ? "invalid point" : model.coordinatesInDD selectByMouse: true Layout.fillWidth: true Layout.margins: 5 onAccepted: { model.handleTextUpdate(model.strDecimalDegrees, text); } }
Text { id: labelDMS font.pixelSize: fontPixelSize Layout.margins: 5 horizontalAlignment: Text.AlignRight text: model.strDegreesMinutesSeconds + labelSuffix }
TextField { id: textDMS font.pixelSize: fontPixelSize selectByMouse: true Layout.margins: 5 text: model.coordinatesInDMS.length === 0 ? "invalid point" : model.coordinatesInDMS Layout.fillWidth: true onAccepted: { model.handleTextUpdate(model.strDegreesMinutesSeconds, text); } }
Text { id: labelUtm font.pixelSize: fontPixelSize Layout.margins: 5 horizontalAlignment: Text.AlignRight text: model.strUtm + labelSuffix }
TextField { id: textUtm font.pixelSize: fontPixelSize text: model.coordinatesInUtm.length === 0 ? "invalid point" : model.coordinatesInUtm selectByMouse: true Layout.fillWidth: true Layout.margins: 5 onAccepted: { model.handleTextUpdate(model.strUtm, text); } }
Text { id: labelUsng font.pixelSize: fontPixelSize Layout.margins: 5 horizontalAlignment: Text.AlignRight text: model.strUsng + labelSuffix }
TextField { id: textUsng font.pixelSize: fontPixelSize text: model.coordinatesInUsng.length === 0 ? "invalid point" : model.coordinatesInUsng selectByMouse: true Layout.fillWidth: true Layout.margins: 5 onAccepted: { model.handleTextUpdate(model.strUsng, text); } } } }}// [Legal]// Copyright 2015 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
// sample headers#include "FormatCoordinates.h"
// ArcGIS Maps SDK headers#include "ArcGISRuntimeEnvironment.h"
// Qt headers#include <QCommandLineParser>#include <QDir>#include <QGuiApplication>#include <QQmlApplicationEngine>#include <QQuickView>#include <QSettings>
// Platform specific headers#ifdef Q_OS_WIN#include <Windows.h>#endif
#define STRINGIZE(x) #x#define QUOTE(x) STRINGIZE(x)
using namespace Esri::ArcGISRuntime;
int main(int argc, char *argv[]){ Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setUseLegacyAuthentication(false); QGuiApplication app(argc, argv); app.setApplicationName(QString("FormatCoordinates"));
// Use of ArcGIS location services, such as basemap styles, geocoding, and routing services, // requires an access token. For more information see // https://links.esri.com/arcgis-runtime-security-auth.
// 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 { Esri::ArcGISRuntime::ArcGISRuntimeEnvironment::setApiKey(accessToken); }
// Initialize the sample FormatCoordinates::init();
// Initialize application view QQmlApplicationEngine engine;
QString arcGISRuntimeImportPath = QUOTE(ARCGIS_RUNTIME_IMPORT_PATH);
#if defined(LINUX_PLATFORM_REPLACEMENT) // On some linux platforms the string 'linux' is replaced with 1. // Fix the replacement paths which were created. QString replaceString = QUOTE(LINUX_PLATFORM_REPLACEMENT); arcGISRuntimeImportPath = arcGISRuntimeImportPath.replace(replaceString, "linux", Qt::CaseSensitive);#endif
// Add the import Path engine.addImportPath(QDir(QCoreApplication::applicationDirPath()).filePath("qml")); // Add the Runtime and Extras path engine.addImportPath(arcGISRuntimeImportPath);
// Set the source engine.load(QUrl("qrc:/Samples/Geometry/FormatCoordinates/main.qml"));
return app.exec();}// [WriteFile Name=FormatCoordinates, Category=Geometry]// [Legal]// Copyright 2018 Esri.//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.// [Legal]
import QtQuick.Controls
ApplicationWindow { visible: true width: 800 height: 600
FormatCoordinates { anchors.fill: parent }}