Added geofencing (untested). Improved route handling

This commit is contained in:
2015-12-18 22:54:44 +01:00
parent e81007e9ec
commit 2f4b9227f1
19 changed files with 241 additions and 208 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

+1 -7
View File
@@ -23,7 +23,7 @@ namespace NavCityBreda.Helpers
if (!ValidateRouteObject(o, out error))
throw new FileLoadException("Invalid Route information in " + file + ", " + error);
Route r = new Route((string)o["name"], (string)o["description"], (string)o["landmarks"], Int32.Parse((string)o["minutes"]));
Route r = new Route((string)o["name"], (string)o["description"], (string)o["landmarks"]);
JToken[] waypoints = o["waypoints"].ToArray();
int count = 0;
@@ -69,12 +69,6 @@ namespace NavCityBreda.Helpers
error = "Landmarks missing";
}
if (o["minutes"].NullOrEmpty())
{
valid = false;
error = "Minutes missing";
}
if (o["waypoints"].NullOrEmpty())
{
valid = false;
+34
View File
@@ -157,5 +157,39 @@ namespace NavCityBreda.Helpers
return line;
}
public static MapPolyline GetRouteLine(List<BasicGeoposition> positions, Color color, int thickness = 10, bool dashed = false)
{
var line = new MapPolyline
{
StrokeThickness = thickness,
StrokeColor = color,
StrokeDashed = dashed,
ZIndex = 2
};
line.Path = new Geopath(positions);
return line;
}
public static MapPolyline GetRouteLine(BasicGeoposition p1, BasicGeoposition p2, Color color, int thickness = 10, bool dashed = false)
{
var line = new MapPolyline
{
StrokeThickness = thickness,
StrokeColor = color,
StrokeDashed = dashed,
ZIndex = 2
};
List<BasicGeoposition> plist = new List<BasicGeoposition>();
plist.Add(p1);
plist.Add(p2);
line.Path = new Geopath(plist);
return line;
}
}
}
+3 -2
View File
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Geolocation;
using Windows.Devices.Geolocation.Geofencing;
using Windows.Foundation;
using Windows.System;
@@ -56,8 +57,8 @@ namespace NavCityBreda.Model
case GeolocationAccessStatus.Allowed:
geo = new Geolocator {
DesiredAccuracy = PositionAccuracy.High,
//MovementThreshold = 1
ReportInterval = 5000
//MovementThreshold = 5
ReportInterval = 1500
};
Connected = true;
+39 -7
View File
@@ -6,6 +6,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Geolocation;
using Windows.Foundation;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls.Maps;
namespace NavCityBreda.Model
{
@@ -13,25 +16,54 @@ namespace NavCityBreda.Model
{
public string Description { get; private set; }
public string Image { get; private set; }
public bool Visited { get; set; }
private bool _visited;
public bool Visited
{
get { return _visited; }
set
{
_visited = value;
UpdateIconImage();
}
}
public string Id { get; private set; }
public MapIcon Icon { get; set; }
public Landmark(Geopoint p, string name, string desc, int num, string image_loc = "default.jpg") : base (p, name, num)
{
Visited = false;
Description = desc;
if (image_loc == "" || !File.Exists(Util.RouteImagesFolder + image_loc))
image_loc = "default.jpg";
Image = "/" + Util.RouteImagesFolder + image_loc;
Create(Location, name, desc, num, image_loc);
}
public Landmark(double la, double lo, string name, string desc, int num, string image_loc = "default.jpg") : base(la, lo, name, num)
{
Visited = false;
Create(Location, name, desc, num, image_loc);
}
private void Create(Geopoint p, string name, string desc, int num, string image_loc)
{
_visited = false;
Description = desc;
if (image_loc == "" || !File.Exists(Util.RouteImagesFolder + image_loc))
image_loc = "default.jpg";
Image = "/" + Util.RouteImagesFolder + image_loc;
Id = Name + "_" + Order;
Icon = new MapIcon();
Icon.Location = Location;
Icon.NormalizedAnchorPoint = new Point(0.5, 1.0);
Icon.Title = Name;
Icon.ZIndex = 10;
}
public void UpdateIconImage()
{
if(_visited)
Icon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/LandmarkVisited.png"));
else
Icon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/LandmarkNotVisited.png"));
}
}
}
+17 -6
View File
@@ -17,8 +17,15 @@ namespace NavCityBreda.Model
public string Name { get; private set; }
public string Description { get; private set; }
public string Landmarks { get; private set; }
public int Minutes { get; private set; }
public string LandmarksDescription { get; private set; }
public List<Landmark> Landmarks
{
get
{
return _waypoints.Where(l => l is Landmark).Cast<Landmark>().ToList();
}
}
private List<Waypoint> _waypoints;
public List<Waypoint> Waypoints { get { return _waypoints; } }
@@ -26,12 +33,11 @@ namespace NavCityBreda.Model
private MapRoute _route;
public MapRoute RouteObject { get { return _route; } }
public Route(string name, string desc, string landmarks, int minutes)
public Route(string name, string desc, string landmarks)
{
Name = name;
Description = desc;
Landmarks = landmarks;
Minutes = minutes;
LandmarksDescription = landmarks;
_waypoints = new List<Waypoint>();
}
@@ -63,7 +69,12 @@ namespace NavCityBreda.Model
public async Task<String> CalculateRoute()
{
_route = await Util.FindWalkingRoute(_waypoints.Select(p => p.Location).ToList());
return "";
return "success";
}
public void Reset()
{
Landmarks.ForEach(l => l.Visited = false);
}
}
}
+47 -4
View File
@@ -11,6 +11,12 @@ namespace NavCityBreda.Model
{
public class RouteManager
{
public delegate void StatusUpdateHandler(object sender, RouteStatusChangedEventArgs e);
public event StatusUpdateHandler OnStatusUpdate;
public delegate void PositionUpdateHandler(object sender, RoutePositionChangedEventArgs e);
public event PositionUpdateHandler OnPositionUpdate;
private List<Route> _routes;
public List<Route> Routes { get { return _routes; } }
@@ -34,16 +40,20 @@ namespace NavCityBreda.Model
public RouteManager()
{
_routes = new List<Route>();
_history = new List<Geoposition>();
LoadingElement = "Initializing...";
RouteState = State.STOPPED;
LoadRoutes();
App.Geo.PositionChanged += Geo_PositionChanged;
RouteState = State.STOPPED;
LoadRoutes();
}
private void Geo_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
if (RouteState == State.STARTED)
{
OnPositionUpdate(this, new RoutePositionChangedEventArgs(_history.Last(), args.Position));
_history.Add(args.Position);
}
}
private async void LoadRoutes()
@@ -63,21 +73,54 @@ namespace NavCityBreda.Model
LoadingElement = "Done";
}
private void UpdateStatus(State status)
{
RouteState = status;
// Make sure someone is listening to event
if (OnStatusUpdate == null) return;
OnStatusUpdate(this, new RouteStatusChangedEventArgs(status));
}
public void StartRoute(Route r)
{
_currentroute = r;
RouteState = State.STARTED;
_history.Add(App.Geo.Position);
UpdateStatus(State.STARTED);
}
public void StopRoute()
{
if (RouteState == State.STARTED)
{
_currentroute.Reset();
_currentroute = null;
RouteState = State.STOPPED;
UpdateStatus(State.STOPPED);
}
_history.Clear();
}
}
public class RouteStatusChangedEventArgs : EventArgs
{
public RouteManager.State Status { get; private set; }
public RouteStatusChangedEventArgs(RouteManager.State status)
{
Status = status;
}
}
public class RoutePositionChangedEventArgs : EventArgs
{
public Geoposition Old { get; private set; }
public Geoposition New { get; private set; }
public RoutePositionChangedEventArgs(Geoposition old, Geoposition notold)
{
Old = old;
New = notold;
}
}
}
+14 -9
View File
@@ -23,7 +23,7 @@
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<NoWarn>2008;CS4014</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
@@ -69,7 +69,7 @@
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<NoWarn>2008;CS4014;</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
@@ -90,6 +90,18 @@
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<Content Include="Assets\CurrentLocationArrow.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Assets\CurrentLocationRound.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Assets\LandmarkNotVisited.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Assets\LandmarkVisited.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="Assets\SplashScreen.scale-100.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@@ -99,12 +111,6 @@
<Content Include="Routes\Waypoints\historische_kilometer.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Routes\Waypoints\test_route_1.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Routes\Waypoints\test_route_2.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<PRIResource Include="Strings\ja-JP\Resources.resw" />
<PRIResource Include="Strings\de-DE\Resources.resw" />
<PRIResource Include="Strings\nl-NL\Resources.resw" />
@@ -135,7 +141,6 @@
<Compile Include="Model\RouteManager.cs" />
<Compile Include="Model\Waypoint.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModel\MapVM.cs" />
<Compile Include="ViewModel\MenuVM.cs" />
<Compile Include="ViewModel\RouteDetailVM.cs" />
<Compile Include="ViewModel\RouteVM.cs" />
@@ -2,7 +2,6 @@
"name": "Historische kilometer",
"description": "De historische kilometer door Breda",
"landmarks": "Kasteel van Breda, Grote Kerk, Stadhuis",
"minutes": 205,
"waypoints": [
{
"name": "VVV",
@@ -1,43 +0,0 @@
{
"name": "Test route 1",
"description": "Dit is een route om van alles mee te testen!\nHopelijk staat dit op een nieuwe regel.\n\rAnders dit.\r\nAnders dit 2.<br>Misschien dit.",
"landmarks": "Een stad, een bos en een meertje. Dit moet eigenlijk vrij kort zijn.",
"minutes": 15,
"waypoints": [
{
"name": "Test locatie 1",
"landmark": true,
"description": "Test locatie 1",
"latitude": 51.594112,
"longitude": 4.779417
},
{
"name": "Test locatie 2",
"landmark": true,
"description": "Test locatie 2",
"latitude": 51.593278,
"longitude": 4.779388
},
{
"name": "Test locatie 3",
"landmark": false,
"latitude": 51.5925,
"longitude": 4.779695
},
{
"name": "Test locatie 4",
"landmark": false,
"latitude": 51.5925,
"longitude": 4.779388
},
{
"name": "Test locatie 5",
"landmark": true,
"description": "Test locatie 5",
"latitude": 51.592833,
"longitude": 4.778472
}
]
}
@@ -1,43 +0,0 @@
{
"name": "Test route 2",
"description": "Dit is een route om van alles mee te testen!\nHopelijk staat dit op een nieuwe regel.\n\rAnders dit.\r\nAnders dit 2.<br>Misschien dit.",
"landmarks": "Een stad, een bos en een meertje. Dit moet eigenlijk vrij kort zijn.",
"minutes": 400,
"waypoints": [
{
"name": "Test locatie 6",
"landmark": true,
"description": "Test locatie 1",
"latitude": 51.594112,
"longitude": 4.779417
},
{
"name": "Test locatie 7",
"landmark": true,
"description": "Test locatie 2",
"latitude": 51.593278,
"longitude": 4.779388
},
{
"name": "Test locatie 8",
"landmark": false,
"latitude": 51.5925,
"longitude": 4.779695
},
{
"name": "Test locatie 9",
"landmark": false,
"latitude": 51.5925,
"longitude": 4.779388
},
{
"name": "Test locatie 10",
"landmark": true,
"description": "Test locatie 5",
"latitude": 51.592833,
"longitude": 4.778472
}
]
}
-47
View File
@@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Geolocation;
using Windows.UI.Core;
namespace NavCityBreda.ViewModel
{
class MapVM : INotifyPropertyChanged
{
CoreDispatcher dispatcher;
public MapVM()
{
dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
App.Geo.StatusChanged += Geo_StatusChanged;
App.Geo.PositionChanged += Geo_PositionChanged;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void Geo_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
{
dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
});
}
private void Geo_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
});
}
}
}
+2 -6
View File
@@ -34,11 +34,6 @@ namespace NavCityBreda.ViewModel
{
TimeSpan length = route.RouteObject.EstimatedDuration;
return length.Hours + "h " + length.Minutes + "m";
//int hours = route.Minutes / 60;
//int minutes = route.Minutes % 60;
//return hours + "h " + minutes + "m";
}
}
@@ -65,7 +60,7 @@ namespace NavCityBreda.ViewModel
{
get
{
return route.Waypoints.Where(p => p is Landmark).Cast<Landmark>().ToList();
return route.Landmarks;
}
}
@@ -89,6 +84,7 @@ namespace NavCityBreda.ViewModel
{
NotifyPropertyChanged(nameof(StartEnabled));
NotifyPropertyChanged(nameof(StopEnabled));
NotifyPropertyChanged(nameof(Landmarks));
}
+72 -24
View File
@@ -21,6 +21,9 @@ using System.Diagnostics;
using NavCityBreda.Helpers;
using Windows.UI;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Devices.Geolocation.Geofencing;
using Windows.UI.Core;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
@@ -38,56 +41,101 @@ namespace NavCityBreda.Views
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Enabled;
this.DataContext = new MapVM();
CurrentPosition = new MapIcon();
CurrentPosition.NormalizedAnchorPoint = new Point(0.5, 1.0);
CurrentPosition.Title = "Current Position";
CurrentPosition.NormalizedAnchorPoint = new Point(0.5, 0.5);
CurrentPosition.Title = "";
CurrentPosition.ZIndex = 999;
CurrentPosition.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/CurrentLocationRound.png"));
Map.MapElements.Add(CurrentPosition);
App.Geo.PositionChanged += Geo_PositionChanged;
GeofenceMonitor.Current.GeofenceStateChanged += Current_GeofenceStateChanged;
App.RouteManager.OnPositionUpdate += RouteManager_OnPositionUpdate;
App.RouteManager.OnStatusUpdate += RouteManager_OnStatusUpdate;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
private void Current_GeofenceStateChanged(GeofenceMonitor sender, object args)
{
if (App.RouteManager.CurrentRoute != null)
DrawRoute();
else
var reports = sender.ReadReports();
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
Map.MapElements.Clear();
Map.MapElements.Add(CurrentPosition);
}
foreach (GeofenceStateChangeReport report in reports)
{
GeofenceState state = report.NewState;
Geofence geofence = report.Geofence;
if (state == GeofenceState.Removed)
{
GeofenceMonitor.Current.Geofences.Remove(geofence);
}
else if (state == GeofenceState.Entered)
{
Landmark i = App.RouteManager.CurrentRoute.Landmarks.Where(t => t.Id == geofence.Id).First();
i.Visited = true;
Util.MainPage.Navigate(typeof(LandmarkView), i);
}
}
});
}
private void RouteManager_OnPositionUpdate(object sender, RoutePositionChangedEventArgs e)
{
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
MapPolyline linebit = Util.GetRouteLine(e.Old.Coordinate.Point.Position, e.New.Coordinate.Point.Position, Color.FromArgb(255, 155, 155, 155));
Map.MapElements.Add(linebit);
});
}
private void RouteManager_OnStatusUpdate(object sender, RouteStatusChangedEventArgs e)
{
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (e.Status == RouteManager.State.STARTED)
DrawRoute();
else
RemoveRoute();
});
}
private void Geo_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
DrawCurrenPosition(args.Position.Coordinate.Point);
});
}
private void DrawRoute()
{
Route r = App.RouteManager.CurrentRoute;
Settings.LOCAL_SETTINGS.Values["track"] = false;
GeofenceMonitor.Current.Geofences.Clear();
Map.MapElements.Clear();
Map.MapElements.Add(CurrentPosition);
foreach(Landmark l in r.Waypoints.Where(l => l is Landmark))
foreach(Landmark l in r.Landmarks)
{
MapIcon m = new MapIcon();
m.Location = l.Location;
m.NormalizedAnchorPoint = new Point(0.5, 1.0);
m.Title = l.Name;
m.ZIndex = 10;
Map.MapElements.Add(m);
GeofenceMonitor.Current.Geofences.Add(new Geofence(l.Id, new Geocircle(l.Location.Position, 10)));
l.UpdateIconImage();
Map.MapElements.Add(l.Icon);
}
Map.MapElements.Add(Util.GetRouteLine(App.RouteManager.CurrentRoute.RouteObject, Color.FromArgb(255, 100, 100, 255)));
Map.MapElements.Add(Util.GetRouteLine(App.RouteManager.CurrentRoute.RouteObject, Color.FromArgb(200, 100, 100, 255)));
ZoomRoute();
}
private void Geo_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
private void RemoveRoute()
{
Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () =>
{
DrawCurrenPosition(new Geopoint(args.Position.Coordinate.Point.Position));
});
Settings.LOCAL_SETTINGS.Values["track"] = true;
Map.MapElements.Clear();
DrawCurrenPosition(App.Geo.Position.Coordinate.Point);
}
private void DrawCurrenPosition(Geopoint p)
+11 -8
View File
@@ -55,19 +55,22 @@ namespace NavCityBreda.Views
this.DataContext = vm;
Util.MainPage.Title = route.Name;
Map.MapElements.Clear();
Zoom();
MapPolyline m = Util.GetRouteLine(route.RouteObject, Color.FromArgb(255, 100, 100, 255));
Map.MapElements.Add(m);
foreach (Landmark l in route.Waypoints.Where(l => l is Landmark))
Random rand = new Random();
foreach (Landmark l in route.Landmarks)
{
MapIcon mi = new MapIcon();
mi.Location = l.Location;
mi.NormalizedAnchorPoint = new Point(0.5, 1.0);
mi.Title = "";
mi.ZIndex = 10;
Map.MapElements.Add(mi);
int randint = rand.Next(0,20);
if (randint > 15)
l.Visited = true;
l.UpdateIconImage();
Map.MapElements.Add(l.Icon);
}
}
@@ -91,7 +94,7 @@ namespace NavCityBreda.Views
private void StopRouteButton_Click(object sender, RoutedEventArgs e)
{
App.RouteManager.StartRoute(null);
App.RouteManager.StopRoute();
Util.MainPage.Navigate(typeof(MapView));
}
}
+1 -1
View File
@@ -13,7 +13,7 @@
<DataTemplate x:Name="ListViewDataTemplate">
<StackPanel Margin="5,0,0,0" Grid.Column="0">
<TextBlock Text="{Binding Name}" FontSize="20" TextWrapping="NoWrap"/>
<TextBlock Text="{Binding Landmarks}" FontSize="14" TextWrapping="WrapWholeWords" />
<TextBlock Text="{Binding LandmarksDescription}" FontSize="14" TextWrapping="WrapWholeWords" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>