// Accept user click point and find nearest target geometry point
        private async Task GetNearestCoordAsync(bool vertexOnly)
        {
            var target = _targetLayer.Graphics.Select(g => g.Geometry).FirstOrDefault();

            if (target == null)
            {
                return;
            }

            txtInstruct.Text = "Click the map to find the nearest coordinate in the selected geometry";
            var point = await mapView.Editor.RequestPointAsync();

            ProximityResult result = null;

            if (vertexOnly)
            {
                result = GeometryEngine.NearestVertexInGeometry(target, point);
            }
            else
            {
                result = GeometryEngine.NearestCoordinateInGeometry(target, point);
            }

            _coordinateLayer.Graphics.Clear();
            _coordinateLayer.Graphics.Add(new Graphic(point, _userPointSymbol));
            _coordinateLayer.Graphics.Add(new Graphic(result.Point));

            txtResult.Visibility = Visibility.Visible;
            txtResult.Text       = string.Format("Nearest Point: Index: {0}, Distance: {1:0.000}", result.PointIndex, result.Distance);
        }
        private async void StartButton_Click(object sender, RoutedEventArgs e)
        {
            inputGraphicsLayer.Graphics.Clear();

            //hide ui elements
            InstructionsTextBlock.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
            StartButton.Visibility           = Windows.UI.Xaml.Visibility.Collapsed;
            ResultsTextBlock.Visibility      = Visibility.Collapsed;

            //show ui elements
            PolylineInstructionsTextBlock.Visibility = Windows.UI.Xaml.Visibility.Visible;
            PointInstructionsTextBlock.Visibility    = Windows.UI.Xaml.Visibility.Collapsed;


            //Get the user's input geometry and add it to the map
            inputPolylineGeometry = (await mapView1.Editor.RequestShapeAsync(DrawShape.Polyline)) as Polyline;
            inputGraphicsLayer.Graphics.Add(new Graphic {
                Geometry = inputPolylineGeometry
            });

            PolylineInstructionsTextBlock.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
            PointInstructionsTextBlock.Visibility    = Windows.UI.Xaml.Visibility.Visible;


            inputPointGeometry = (await mapView1.Editor.RequestShapeAsync(DrawShape.Point)) as MapPoint;
            inputGraphicsLayer.Graphics.Add(new Graphic {
                Geometry = inputPointGeometry, Symbol = new SimpleMarkerSymbol {
                    Color = Colors.Red, Size = 12
                }
            });

            //Convert to WebMercator so that we can get the results in meters
            var wmPolyline = GeometryEngine.Project(inputPolylineGeometry, SpatialReferences.WebMercator);
            var wmPoint    = GeometryEngine.Project(inputPointGeometry, SpatialReferences.WebMercator) as MapPoint;

            var result = GeometryEngine.NearestCoordinateInGeometry(wmPolyline, wmPoint);



            var resultStr = string.Format("Distance : {0} meters", result.Distance.ToString("n3"));

            ResultsTextBlock.Text                    = resultStr;
            ResultsTextBlock.Visibility              = Visibility.Visible;
            StartButton.Visibility                   = Windows.UI.Xaml.Visibility.Visible;
            ResetButton.Visibility                   = Windows.UI.Xaml.Visibility.Collapsed;
            PointInstructionsTextBlock.Visibility    = Windows.UI.Xaml.Visibility.Collapsed;
            PolylineInstructionsTextBlock.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        }
        /// <summary>
        /// Call this to set your current location and update directions based on that.
        /// </summary>
        /// <param name="location"></param>
        public void SetCurrentLocation(MapPoint location)
        {
            RouteDirection closest         = null;
            double         distance        = double.NaN;
            MapPoint       snappedLocation = null;
            Route          direction       = null;

            // Find the route part that we are currently on by snapping to each segment and see which one is the closest
            foreach (var dir in m_route.Routes)
            {
                var closestCandidate = (from a in dir.RouteDirections
                                        where a.Geometry is Polyline
                                        select new { Direction = a, Proximity = GeometryEngine.NearestCoordinateInGeometry(a.Geometry, location) }).OrderBy(b => b.Proximity.Distance).FirstOrDefault();
                if (double.IsNaN(distance) || distance < closestCandidate.Proximity.Distance)
                {
                    distance        = closestCandidate.Proximity.Distance;
                    closest         = closestCandidate.Direction;
                    snappedLocation = closestCandidate.Proximity.Point;
                    direction       = dir;
                }
            }
            if (closest != null)
            {
                var directions = direction.RouteDirections.ToList();
                var idx        = directions.IndexOf(closest);
                if (idx < directions.Count)
                {
                    RouteDirection next = directions[idx + 1];

                    //calculate how much is left of current route segment
                    var      segment           = closest.Geometry as Polyline;
                    var      proximity         = GeometryEngine.NearestVertexInGeometry(segment, snappedLocation);
                    double   frac              = 1 - GetFractionAlongLine(segment, proximity, snappedLocation);
                    TimeSpan timeLeft          = new TimeSpan((long)(closest.Time.Ticks * frac));
                    double   segmentLengthLeft = (Convert.ToDouble(closest.GetLength(LinearUnits.Meters))) * frac;
                    //Sum up the time and lengths for the remaining route segments
                    TimeSpan totalTimeLeft = timeLeft;
                    double   totallength   = segmentLengthLeft;
                    for (int i = idx + 1; i < directions.Count; i++)
                    {
                        totalTimeLeft += directions[i].Time;
                        totallength   += directions[i].GetLength(LinearUnits.Meters);
                    }

                    //Update properties
                    TimeToWaypoint        = TimeSpan.FromSeconds(Math.Round(timeLeft.TotalSeconds));
                    TimeToDestination     = TimeSpan.FromSeconds(Math.Round(totalTimeLeft.TotalSeconds));
                    DistanceToWaypoint    = Math.Round(segmentLengthLeft);
                    DistanceToDestination = Math.Round(totallength);
                    SnappedLocation       = snappedLocation;
                    var maneuverType = next.ManeuverType;
#if NETFX_CORE || WINDOWS_PHONE
                    ManeuverImage = new Uri(string.Format("ms-appx:///Assets/Maneuvers/{0}.png", maneuverType));
#else
                    ManeuverImage = new Uri(string.Format("pack://application:,,,/Assets/Maneuvers/{0}.png", maneuverType));
#endif
                    NextManeuver = next.Text;

                    RaisePropertiesChanged(new string[] {
                        "NextManeuver", "SnappedLocation", "CurrentDirection", "TimeToWaypoint",
                        "DistanceToDestination", "DistanceToWaypoint", "TimeToDestination",
                        "MilesToDestination", "MilesToWaypoint", "ManeuverImage"
                    });
                }
            }
        }