/// <summary> /// Calculates bearing between start and stop. /// </summary> /// <param name="start">Start coordinates.</param> /// <param name="stop">Stop coordinates.</param> /// <returns>The <see cref="System.Double" />.</returns> public static double BearingFrom(this Position start, Position stop) { var deltaLon = stop.Longitude - start.Longitude; var cosStop = Math.Cos(stop.Latitude); return Math.Atan2( (Math.Cos(start.Latitude) * Math.Sin(stop.Latitude)) - (Math.Sin(start.Latitude) * cosStop * Math.Cos(deltaLon)), Math.Sin(deltaLon) * cosStop); }
/// <summary> /// Initializes a new instance of the <see cref="Position" /> class. /// </summary> /// <param name="position">The position.</param> /// <exception cref="System.ArgumentNullException">position</exception> public Position(Position position) { if (position == null) { throw new ArgumentNullException("position"); } Timestamp = position.Timestamp; Latitude = position.Latitude; Longitude = position.Longitude; Altitude = position.Altitude; AltitudeAccuracy = position.AltitudeAccuracy; Accuracy = position.Accuracy; Heading = position.Heading; Speed = position.Speed; }
/// <summary> /// Calculates distance between two locations. /// </summary> /// <param name="a">Location a</param> /// <param name="b">Location b</param> /// <returns>The <see cref="System.Double" />The distance in meters</returns> public static double DistanceFrom(this Position a, Position b) { /* double distance = Math.Acos( (Math.Sin(a.Latitude) * Math.Sin(b.Latitude)) + (Math.Cos(a.Latitude) * Math.Cos(b.Latitude)) * Math.Cos(b.Longitude - a.Longitude)); * */ var dLat = b.Latitude.DegreesToRadians() - a.Latitude.DegreesToRadians(); var dLon = b.Longitude.DegreesToRadians() - a.Longitude.DegreesToRadians(); var a1 = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(a.Latitude.DegreesToRadians()) * Math.Cos(b.Latitude.DegreesToRadians()) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2); var distance = 2 * Math.Atan2(Math.Sqrt(a1), Math.Sqrt(1 - a1)); return EquatorRadius * distance; }
/// <summary> /// Handles the <see cref="E:ListenerPositionChanged" /> event. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="PositionEventArgs" /> instance containing the event data.</param> private void OnListenerPositionChanged(object sender, PositionEventArgs e) { if (!IsListening) // ignore anything that might come in afterwards { return; } lock (_positionSync) { _lastPosition = e.Position; var changed = PositionChanged; if (changed != null) { changed(this, e); } } }
/// <summary> /// Finishes the specified location. /// </summary> /// <param name="location">The location.</param> private void Finish(Location location) { var p = new Position(); if (location.HasAccuracy) { p.Accuracy = location.Accuracy; } if (location.HasAltitude) { p.Altitude = location.Altitude; } if (location.HasBearing) { p.Heading = location.Bearing; } if (location.HasSpeed) { p.Speed = location.Speed; } p.Longitude = location.Longitude; p.Latitude = location.Latitude; p.Timestamp = Geolocator.GetTimestamp(location); if (_finishedCallback != null) { _finishedCallback(); } _completionSource.TrySetResult(p); }
/// <summary> /// Initializes a new instance of the <see cref="PositionEventArgs"/> class. /// </summary> /// <param name="position">The position.</param> /// <exception cref="System.ArgumentNullException">position</exception> public PositionEventArgs(Position position) { if (position == null) { throw new ArgumentNullException("position"); } Position = position; }
/// <summary> /// Called when the location has changed. /// </summary> /// <param name="location">The new location, as a Location object.</param> /// <since version="Added in API level 1" /> /// <remarks> /// <para tool="javadoc-to-mdoc"> /// Called when the location has changed. /// </para> /// <para tool="javadoc-to-mdoc"> There are no restrictions on the use of the supplied Location object.</para> /// <para tool="javadoc-to-mdoc"> /// <format type="text/html"> /// <a /// href="http://developer.android.com/reference/android/location/LocationListener.html#onLocationChanged(android.location.Location)" /// target="_blank"> /// [Android Documentation] /// </a> /// </format> /// </para> /// </remarks> public void OnLocationChanged(Location location) { if (location.Provider != _activeProvider) { if (_activeProvider != null && _manager.IsProviderEnabled(_activeProvider)) { var pr = _manager.GetProvider(location.Provider); var lapsed = GetTimeSpan(location.Time) - GetTimeSpan(_lastLocation.Time); if (pr.Accuracy > _manager.GetProvider(_activeProvider).Accuracy && lapsed < _timePeriod.Add(_timePeriod)) { location.Dispose(); return; } } _activeProvider = location.Provider; } var previous = Interlocked.Exchange(ref _lastLocation, location); if (previous != null) { previous.Dispose(); } var p = new Position(); if (location.HasAccuracy) { p.Accuracy = location.Accuracy; } if (location.HasAltitude) { p.Altitude = location.Altitude; } if (location.HasBearing) { p.Heading = location.Bearing; } if (location.HasSpeed) { p.Speed = location.Speed; } p.Longitude = location.Longitude; p.Latitude = location.Latitude; p.Timestamp = Geolocator.GetTimestamp(location); var changed = PositionChanged; if (changed != null) { changed(this, new PositionEventArgs(p)); } }