Files
Location-Tracker/LocationTrackerApp/MainPage.xaml.cs
Carlos Gutierrez fecd0ce968 Integration and add heat map demo
- Implemented OpenStreetMap using WebView with Leaflet.js
- Added OpenStreetMapView component with interactive map functionality
- Created heat map visualization with color-coded intensity
- Added 30 dummy location points around San Francisco Bay Area
- Implemented location tracking with real-time pin placement
- Added comprehensive UI with two-row button layout
- Features: Start/Stop tracking, Center map, Demo heat map, Clear demo, Reset map
- Added location count display and confirmation dialogs
- Updated project structure and documentation
- All functionality tested and working on Android emulator
2025-10-12 21:42:25 -04:00

270 lines
9.7 KiB
C#

using LocationTrackerApp.Components;
using LocationTrackerApp.Models;
namespace LocationTrackerApp;
public partial class MainPage : ContentPage
{
private bool _isTracking = false;
private List<LocationData> _trackedLocations = new();
public MainPage()
{
InitializeComponent();
InitializeMap();
}
private void InitializeMap()
{
// The OpenStreetMapView initializes itself with a default location
// Add some dummy location data to demonstrate heat map functionality
AddDummyLocationData();
}
private void AddDummyLocationData()
{
// Add dummy location data around San Francisco Bay Area to demonstrate heat map
var dummyLocations = new List<LocationData>
{
// Golden Gate Bridge area (high frequency)
new LocationData { Latitude = 37.8199, Longitude = -122.4783, Timestamp = DateTime.UtcNow.AddMinutes(-30) },
new LocationData { Latitude = 37.8200, Longitude = -122.4780, Timestamp = DateTime.UtcNow.AddMinutes(-29) },
new LocationData { Latitude = 37.8201, Longitude = -122.4777, Timestamp = DateTime.UtcNow.AddMinutes(-28) },
new LocationData { Latitude = 37.8198, Longitude = -122.4785, Timestamp = DateTime.UtcNow.AddMinutes(-27) },
new LocationData { Latitude = 37.8202, Longitude = -122.4775, Timestamp = DateTime.UtcNow.AddMinutes(-26) },
// Fisherman's Wharf area (medium frequency)
new LocationData { Latitude = 37.8080, Longitude = -122.4177, Timestamp = DateTime.UtcNow.AddMinutes(-25) },
new LocationData { Latitude = 37.8085, Longitude = -122.4175, Timestamp = DateTime.UtcNow.AddMinutes(-24) },
new LocationData { Latitude = 37.8082, Longitude = -122.4180, Timestamp = DateTime.UtcNow.AddMinutes(-23) },
// Union Square area (medium frequency)
new LocationData { Latitude = 37.7879, Longitude = -122.4075, Timestamp = DateTime.UtcNow.AddMinutes(-22) },
new LocationData { Latitude = 37.7882, Longitude = -122.4078, Timestamp = DateTime.UtcNow.AddMinutes(-21) },
new LocationData { Latitude = 37.7877, Longitude = -122.4072, Timestamp = DateTime.UtcNow.AddMinutes(-20) },
// Mission District area (low frequency)
new LocationData { Latitude = 37.7599, Longitude = -122.4148, Timestamp = DateTime.UtcNow.AddMinutes(-19) },
new LocationData { Latitude = 37.7602, Longitude = -122.4150, Timestamp = DateTime.UtcNow.AddMinutes(-18) },
// Castro District area (low frequency)
new LocationData { Latitude = 37.7611, Longitude = -122.4350, Timestamp = DateTime.UtcNow.AddMinutes(-17) },
// SOMA area (medium frequency)
new LocationData { Latitude = 37.7749, Longitude = -122.4194, Timestamp = DateTime.UtcNow.AddMinutes(-16) },
new LocationData { Latitude = 37.7752, Longitude = -122.4197, Timestamp = DateTime.UtcNow.AddMinutes(-15) },
new LocationData { Latitude = 37.7747, Longitude = -122.4191, Timestamp = DateTime.UtcNow.AddMinutes(-14) },
new LocationData { Latitude = 37.7750, Longitude = -122.4194, Timestamp = DateTime.UtcNow.AddMinutes(-13) },
// Financial District area (high frequency)
new LocationData { Latitude = 37.7946, Longitude = -122.3998, Timestamp = DateTime.UtcNow.AddMinutes(-12) },
new LocationData { Latitude = 37.7949, Longitude = -122.4001, Timestamp = DateTime.UtcNow.AddMinutes(-11) },
new LocationData { Latitude = 37.7944, Longitude = -122.3995, Timestamp = DateTime.UtcNow.AddMinutes(-10) },
new LocationData { Latitude = 37.7952, Longitude = -122.4004, Timestamp = DateTime.UtcNow.AddMinutes(-9) },
new LocationData { Latitude = 37.7947, Longitude = -122.3999, Timestamp = DateTime.UtcNow.AddMinutes(-8) },
new LocationData { Latitude = 37.7950, Longitude = -122.4002, Timestamp = DateTime.UtcNow.AddMinutes(-7) },
// North Beach area (low frequency)
new LocationData { Latitude = 37.8044, Longitude = -122.4098, Timestamp = DateTime.UtcNow.AddMinutes(-6) },
// Chinatown area (medium frequency)
new LocationData { Latitude = 37.7941, Longitude = -122.4078, Timestamp = DateTime.UtcNow.AddMinutes(-5) },
new LocationData { Latitude = 37.7944, Longitude = -122.4081, Timestamp = DateTime.UtcNow.AddMinutes(-4) },
new LocationData { Latitude = 37.7938, Longitude = -122.4075, Timestamp = DateTime.UtcNow.AddMinutes(-3) },
// Marina District area (low frequency)
new LocationData { Latitude = 37.8026, Longitude = -122.4430, Timestamp = DateTime.UtcNow.AddMinutes(-2) },
// Presidio area (low frequency)
new LocationData { Latitude = 37.7989, Longitude = -122.4662, Timestamp = DateTime.UtcNow.AddMinutes(-1) }
};
_trackedLocations.AddRange(dummyLocations);
UpdateLocationCount();
}
private void UpdateLocationCount()
{
LocationCountLabel.Text = $"Locations: {_trackedLocations.Count}";
}
private async void OnStartTrackingClicked(object? sender, EventArgs e)
{
try
{
if (!_isTracking)
{
// Request location permissions
var status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
if (status != PermissionStatus.Granted)
{
await DisplayAlert("Permission Required", "Location permission is required to track your location.", "OK");
return;
}
// Start location tracking
_isTracking = true;
StartTrackingBtn.Text = "Tracking...";
StartTrackingBtn.BackgroundColor = Colors.Orange;
StopTrackingBtn.IsEnabled = true;
// Simulate location tracking
_ = Task.Run(async () => await SimulateLocationTracking());
}
}
catch (Exception ex)
{
await DisplayAlert("Error", $"Failed to start tracking: {ex.Message}", "OK");
}
}
private void OnStopTrackingClicked(object? sender, EventArgs e)
{
try
{
if (_isTracking)
{
_isTracking = false;
StartTrackingBtn.Text = "Start Tracking";
StartTrackingBtn.BackgroundColor = Colors.Green;
StopTrackingBtn.IsEnabled = false;
}
}
catch (Exception ex)
{
DisplayAlert("Error", $"Failed to stop tracking: {ex.Message}", "OK");
}
}
private async Task SimulateLocationTracking()
{
while (_isTracking)
{
try
{
// Get current location
var location = await Geolocation.GetLocationAsync();
if (location != null)
{
// Update UI on main thread
MainThread.BeginInvokeOnMainThread(async () =>
{
// Add location to tracked locations
var locationData = new LocationData
{
Latitude = location.Latitude,
Longitude = location.Longitude,
Timestamp = DateTime.UtcNow
};
_trackedLocations.Add(locationData);
UpdateLocationCount();
// Add pin to OpenStreetMap
await MainMap.AddLocationPinAsync(location, $"Current Location {_trackedLocations.Count}", 0.8);
});
}
}
catch (Exception ex)
{
// Handle location errors
System.Diagnostics.Debug.WriteLine($"Location error: {ex.Message}");
}
// Wait 5 seconds before next update
await Task.Delay(5000);
}
}
private async void OnCenterMapClicked(object? sender, EventArgs e)
{
try
{
// Request location permissions if not already granted
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if (status != PermissionStatus.Granted)
{
status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
if (status != PermissionStatus.Granted)
{
await DisplayAlert("Permission Required", "Location permission is required to center the map.", "OK");
return;
}
}
// Get current location
var location = await Geolocation.GetLocationAsync();
if (location != null)
{
// Clear existing pins
await MainMap.ClearMapAsync();
// Add a pin for current location
await MainMap.AddLocationPinAsync(location, $"Your Location\nLat: {location.Latitude:F6}\nLng: {location.Longitude:F6}", 1.0);
await DisplayAlert("Location Found", $"Map centered on your location:\nLat: {location.Latitude:F6}\nLng: {location.Longitude:F6}", "OK");
}
else
{
await DisplayAlert("Error", "Unable to get your current location.", "OK");
}
}
catch (Exception ex)
{
await DisplayAlert("Error", $"Failed to center map: {ex.Message}", "OK");
}
}
private async void OnHeatMapClicked(object? sender, EventArgs e)
{
try
{
if (_trackedLocations.Any())
{
// Load tracked locations into the heat map
await MainMap.LoadLocationDataAsync(_trackedLocations);
await DisplayAlert("Heat Map", $"Heat map updated with {_trackedLocations.Count} locations.\n\nAreas with higher frequency appear in red/yellow, lower frequency in blue.", "OK");
}
else
{
await DisplayAlert("No Data", "No location data available. Start tracking to create a heat map.", "OK");
}
}
catch (Exception ex)
{
await DisplayAlert("Error", $"Failed to update heat map: {ex.Message}", "OK");
}
}
private async void OnClearDemoClicked(object? sender, EventArgs e)
{
try
{
var result = await DisplayAlert("Clear Demo Data", "Are you sure you want to clear all demo location data?", "Yes", "No");
if (result)
{
_trackedLocations.Clear();
await MainMap.ClearMapAsync();
UpdateLocationCount();
await DisplayAlert("Demo Cleared", "All demo location data has been cleared.", "OK");
}
}
catch (Exception ex)
{
await DisplayAlert("Error", $"Failed to clear demo data: {ex.Message}", "OK");
}
}
private async void OnResetMapClicked(object? sender, EventArgs e)
{
try
{
await MainMap.ClearMapAsync();
await DisplayAlert("Map Reset", "Map has been reset to default view.", "OK");
}
catch (Exception ex)
{
await DisplayAlert("Error", $"Failed to reset map: {ex.Message}", "OK");
}
}
}