Skip to content

Instantly share code, notes, and snippets.

@dotMorten
Last active December 27, 2015 05:09
Show Gist options
  • Save dotMorten/7272239 to your computer and use it in GitHub Desktop.
Save dotMorten/7272239 to your computer and use it in GitHub Desktop.
A custom location provider that randomly accelerates and changes heading for simple in-house testing of location
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Location;
using System;
using System.Linq;
using System.Threading.Tasks;
#if NETFX_CORE
using Windows.Foundation;
using Windows.UI.Xaml;
#else
using System.Windows.Threading;
using System.Windows;
#endif
namespace MortensGists
{
/// <summary>
/// A custom location provider that randomly accelerates and changes heading for
/// simple in-house testing of location
/// </summary>
public class RandomLocationProvider : ILocationProvider
{
private static Random randomizer = new Random();
private DispatcherTimer timer;
LocationInfo oldPosition;
public RandomLocationProvider()
{
timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(1) };
timer.Tick += timer_Tick;
// Default start location
StartLatitude = 34.057104;
StartLongitude = -117.196816;
}
/// <summary>
/// Called when the position timer triggers, and calculates the next position based on current speed and heading,
/// and adds a little randomization to current heading, speed and accuracy.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void timer_Tick(object sender, object e)
{
if (oldPosition == null)
{
oldPosition = new LocationInfo()
{
Location = new MapPoint(StartLongitude, StartLatitude, SpatialReferences.Wgs84),
Speed = 0,
Course = 0,
HorizontalAccuracy = 20,
};
}
var now = DateTime.Now;
TimeSpan timeParsed = timer.Interval;
double acceleration = randomizer.NextDouble() * 5 - 2.5;
double deltaSpeed = acceleration * timeParsed.TotalSeconds;
double newSpeed = Math.Max(0, deltaSpeed + oldPosition.Speed);
double deltaCourse = randomizer.NextDouble() * 30 - 15;
double newCourse = deltaCourse + oldPosition.Course;
while (newCourse < 0) newCourse += 360;
while (newCourse >= 360) newCourse -= 360;
double distanceTravelled = (newSpeed + oldPosition.Speed) * .5 * timeParsed.TotalSeconds;
double accuracy = Math.Min(500, Math.Max(20, oldPosition.HorizontalAccuracy + (randomizer.NextDouble() * 100 - 50)));
var pos = GeometryEngine.GeodesicMove(new MapPoint[] { oldPosition.Location }, distanceTravelled, Units.Meters, newCourse).First();
var newPosition = new LocationInfo()
{
Location = pos,
Speed = newSpeed,
Course = newCourse,
HorizontalAccuracy = accuracy,
};
oldPosition = newPosition;
if (LocationChanged != null)
LocationChanged(this, oldPosition);
}
/// <summary>
/// Gets or sets the start latitude.
/// </summary>
/// <value>
/// The start latitude.
/// </value>
public double StartLatitude { get; set; }
/// <summary>
/// Gets or sets the start longitude.
/// </summary>
/// <value>
/// The start longitude.
/// </value>
public double StartLongitude { get; set; }
public System.Threading.Tasks.Task StartAsync()
{
timer.Start();
return Task.FromResult<bool>(true);
}
public System.Threading.Tasks.Task StopAsync()
{
timer.Stop();
return Task.FromResult<bool>(true);
}
public event EventHandler<LocationInfo> LocationChanged;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment