Skip To Content ArcGIS for Developers Sign In Dashboard

ArcGIS Runtime SDK for .NET

Geodesic operations

This code sample is available for these platforms:
View Sample on GitHub

Calculate a geodesic path between two points and measure its distance.

Image of geodesic operations

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

  1. A Point is created in New York City and displayed as a Graphic.
  2. When a click occurs on the MapView, a new Point is obtained from the mouse click. This Point is added as a Graphic.
  3. A Polyline is created with the two Point objects.
  4. GeometryEngine.DensifyGeodetic is executed by passing in the Polyline object, and the returned Geometry is added as a Graphic.
  5. GeometryEngine.LengthGeodetic is executed by passing in the two Point objects, and the returned number is displayed on the screen.

Relevant API

  • GeometryEngine.DensifyGeodetic
  • GeometryEngine.LengthGeodetic

About the data

The Imagery basemap provides the global context for the displayed geodesic line.

Tags

densify, distance, geodesic, geodetic

Sample Code

<UserControl
    x:Class="ArcGISRuntime.UWP.Samples.GeodesicOperations.GeodesicOperations"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:controls="using:Esri.ArcGISRuntime.UI.Controls">
    <Grid>
        <controls:MapView x:Name="MyMapView" />
        <Border Style="{StaticResource BorderStyle}">
            <StackPanel>
                <TextBlock x:Name="ResultsLabel"
                           Text="Tap to set an end point."
                           FontWeight="SemiBold"
                           TextAlignment="Center" />
            </StackPanel>
        </Border>
    </Grid>
</UserControl>
// 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.

using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.UI;
using Esri.ArcGISRuntime.UI.Controls;

namespace ArcGISRuntime.UWP.Samples.GeodesicOperations
{
    [ArcGISRuntime.Samples.Shared.Attributes.Sample(
        name: "Geodesic operations",
        category: "Geometry",
        description: "Calculate a geodesic path between two points and measure its distance.",
        instructions: "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.",
        tags: new[] { "densify", "distance", "geodesic", "geodetic" })]
    public partial class GeodesicOperations
    {
        // Hold references to the graphics.
        private Graphic _startLocationGraphic;
        private Graphic _endLocationGraphic;
        private Graphic _pathGraphic;

        public GeodesicOperations()
        {
            InitializeComponent();

            // Setup the control references and execute initialization.
            Initialize();
        }

        private void Initialize()
        {
            MyMapView.Map = new Map(Basemap.CreateImagery());

            // Create the graphics overlay and add it to the map view.
            GraphicsOverlay graphicsOverlay = new GraphicsOverlay();
            MyMapView.GraphicsOverlays.Add(graphicsOverlay);

            // Add a graphic at JFK to serve as the origin.
            MapPoint start = new MapPoint(-73.7781, 40.6413, SpatialReferences.Wgs84);
            SimpleMarkerSymbol startMarker = new SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, System.Drawing.Color.Blue, 10);
            _startLocationGraphic = new Graphic(start, startMarker);

            // Create the graphic for the destination.
            _endLocationGraphic = new Graphic
            {
                Symbol = startMarker
            };

            // Create the graphic for the path.
            _pathGraphic = new Graphic
            {
                Symbol = new SimpleLineSymbol(SimpleLineSymbolStyle.Dash, System.Drawing.Color.Blue, 5)
            };

            // Add the graphics to the overlay.
            graphicsOverlay.Graphics.Add(_startLocationGraphic);
            graphicsOverlay.Graphics.Add(_endLocationGraphic);
            graphicsOverlay.Graphics.Add(_pathGraphic);

            // Update end location when the user taps.
            MyMapView.GeoViewTapped += MyMapViewOnGeoViewTapped;
        }

        private void MyMapViewOnGeoViewTapped(object sender, GeoViewInputEventArgs geoViewInputEventArgs)
        {
            // Get the tapped point, projected to WGS84.
            MapPoint destination = (MapPoint)GeometryEngine.Project(geoViewInputEventArgs.Location, SpatialReferences.Wgs84);

            // Update the destination graphic.
            _endLocationGraphic.Geometry = destination;

            // Get the points that define the route polyline.
            PointCollection polylinePoints = new PointCollection(SpatialReferences.Wgs84)
            {
                (MapPoint)_startLocationGraphic.Geometry,
                destination
            };

            // Create the polyline for the two points.
            Polyline routeLine = new Polyline(polylinePoints);

            // Densify the polyline to show the geodesic curve.
            Geometry pathGeometry = GeometryEngine.DensifyGeodetic(routeLine, 1, LinearUnits.Kilometers, GeodeticCurveType.Geodesic);

            // Apply the curved line to the path graphic.
            _pathGraphic.Geometry = pathGeometry;

            // Calculate and show the distance.
            double distance = GeometryEngine.LengthGeodetic(pathGeometry, LinearUnits.Kilometers, GeodeticCurveType.Geodesic);
            ResultsLabel.Text = $"{(int)distance} kilometers";
        }
    }
}