View in QML C++ View on GitHub Sample viewer app
Calculate a geodesic path between two points and measure its distance.
Use case
A geodesic distance provides an accurate, real-world distance between two points. Visualizing flight paths between cities is a common example of a geodesic operation since the flight path between two airports takes into account the curvature of the earth, rather than following the planar path between those points, which appears as a straight line on a projected map.
How to use the sample
Click anywhere on the map. A line graphic will display the geodesic line between the two points. In addition, text that indicates the geodesic distance between the two points will be updated. Click elsewhere and a new line will be created.
How it works
Create a Point
in New York City and display it as a Graphic
.
Obtain a new point when a click occurs on the MapView
and add this point as a graphic.
Create a Polyline
from the two points.
Execute GeometryEngine::densifyGeodetic
by passing in the created polyine then create a graphic from the returned Geometry
.
Execute GeometryEngine::lengthGeodetic
by passing in the two points and display the returned length on the screen.
Relevant API
GeometryEngine::densifyGeodetic
GeometryEngine::lengthGeodetic
About the data
The Imagery basemap provides the global context for the displayed geodesic line.
densify, distance, geodesic, geodetic
Sample CodeGeodesicOperations.cpp GeodesicOperations.cpp GeodesicOperations.h GeodesicOperations.qml
Use dark colors for code blocks Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// [WriteFile Name=GeodesicOperations, 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]
# ifdef PCH_BUILD
# include "pch.hpp"
# endif // PCH_BUILD
# include "GeodesicOperations.h"
# include "Map.h"
# include "MapQuickView.h"
# include "GraphicsOverlay.h"
# include "Graphic.h"
# include "SimpleMarkerSymbol.h"
# include "SimpleLineSymbol.h"
# include "GeometryEngine.h"
# include "SpatialReference.h"
# include "PolylineBuilder.h"
# include "Point.h"
# include "MapTypes.h"
# include "GraphicsOverlayListModel.h"
# include "GraphicListModel.h"
# include "SymbolTypes.h"
# include "LinearUnit.h"
using namespace Esri::ArcGISRuntime;
GeodesicOperations:: GeodesicOperations (QQuickItem* parent /* = nullptr */ ):
QQuickItem (parent)
{
}
void GeodesicOperations::init ()
{
// Register the map view for QML
qmlRegisterType<MapQuickView>( "Esri.Samples" , 1 , 0 , "MapView" );
qmlRegisterType<GeodesicOperations>( "Esri.Samples" , 1 , 0 , "GeodesicOperationsSample" );
}
void GeodesicOperations::componentComplete ()
{
QQuickItem:: componentComplete ();
// find QML MapView component
m_mapView = findChild<MapQuickView*>( "mapView" );
// Create a map using the imagery basemap
m_map = new Map (BasemapStyle::ArcGISImageryStandard, this );
// Set map to map view
m_mapView-> setMap (m_map);
// Create a GraphicsOverlay
GraphicsOverlay* graphicsOverlay = new GraphicsOverlay ( this );
m_mapView-> graphicsOverlays ()-> append (graphicsOverlay);
// Create Graphic Symbols
SimpleMarkerSymbol* markerSymbol = new SimpleMarkerSymbol (SimpleMarkerSymbolStyle::Circle, QColor ( "blue" ), 10.0f /*size*/ , this );
SimpleLineSymbol* pathSymbol = new SimpleLineSymbol (SimpleLineSymbolStyle::Dash, QColor ( "blue" ), 5.0f /*width*/ , this );
// Create NYC graphic
const Point nycPoint ( -73.7781 , 40.6413 , SpatialReference( 4326 )) ;
m_nycGraphic = new Graphic (nycPoint, markerSymbol, this );
graphicsOverlay-> graphics ()-> append (m_nycGraphic);
// Create destination graphic
m_destinationGraphic = new Graphic ( this );
m_destinationGraphic-> setSymbol (markerSymbol);
graphicsOverlay-> graphics ()-> append (m_destinationGraphic);
// Create path graphic
m_pathGraphic = new Graphic ( this );
m_pathGraphic-> setSymbol (pathSymbol);
graphicsOverlay-> graphics ()-> append (m_pathGraphic);
// connect to mouse clicked signal
connect (m_mapView, &MapQuickView::mouseClicked, this , [ this , nycPoint](QMouseEvent& mouseEvent)
{
// re-project the point to match the NYC graphic
const Point clickedPoint = m_mapView-> screenToLocation (mouseEvent. position (). x (), mouseEvent. position (). y ());
const Point destination = geometry_cast<Point>(GeometryEngine:: project (clickedPoint, m_nycGraphic-> geometry (). spatialReference ()));
// update the destination graphic
m_destinationGraphic-> setGeometry (destination);
// create line with start/end points
const QList<Point> points = {nycPoint, destination};
const Polyline polyline = pointsToPolyline (points);
// densify the path as a geodesic curve and show it with the path graphic
constexpr double maxSegmentLength = 1.0 ;
const LinearUnit unitOfMeasurement (LinearUnitId::Kilometers);
constexpr GeodeticCurveType curveType = GeodeticCurveType::Geodesic;
const Geometry pathGeometry = GeometryEngine:: densifyGeodetic (polyline, maxSegmentLength, unitOfMeasurement, curveType);
// update the graphic
m_pathGraphic-> setGeometry (pathGeometry);
// calculate the path's geodetic length
m_distanceText = QString:: number (GeometryEngine:: lengthGeodetic (pathGeometry, unitOfMeasurement, curveType), 'f' , 2 );
emit distanceTextChanged ();
});
}
// helper function to create a new Polyline from a list of points
Polyline GeodesicOperations::pointsToPolyline ( const QList<Point>& points)
{
PolylineBuilder polylineBuilder (SpatialReference( 4326 )) ;
for ( const Point& point : points)
polylineBuilder. addPoint (point);
return polylineBuilder. toPolyline ();
}
QString GeodesicOperations::distanceText () const
{
return m_distanceText;
}