diff --git a/LotsOfPolylinesRepro/WorkingWithMaps.sln b/LotsOfPolylinesRepro/WorkingWithMaps.sln
new file mode 100644
index 0000000..6abd84e
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps.sln
@@ -0,0 +1,27 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31611.283
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkingWithMaps", "WorkingWithMaps\WorkingWithMaps.csproj", "{09D2F154-E3FE-4377-B73C-2AA8028444A5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {61F7FB11-1E47-470C-91E2-47F8143E1572}
+ EndGlobalSection
+EndGlobal
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml
new file mode 100644
index 0000000..bf16747
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml.cs
new file mode 100644
index 0000000..5e6e813
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml.cs
@@ -0,0 +1,11 @@
+namespace WorkingWithMaps;
+
+public partial class App : Application
+{
+ public App()
+ {
+ InitializeComponent();
+
+ MainPage = new AppShell();
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml
new file mode 100644
index 0000000..a7c946c
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml.cs
new file mode 100644
index 0000000..b4e0944
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml.cs
@@ -0,0 +1,9 @@
+namespace WorkingWithMaps;
+
+public partial class AppShell : Shell
+{
+ public AppShell()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/MauiProgram.cs b/LotsOfPolylinesRepro/WorkingWithMaps/MauiProgram.cs
new file mode 100644
index 0000000..a3993cf
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/MauiProgram.cs
@@ -0,0 +1,25 @@
+using Microsoft.Extensions.Logging;
+
+namespace WorkingWithMaps;
+
+public static class MauiProgram
+{
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ })
+ .UseMauiMaps();
+
+#if DEBUG
+ builder.Logging.AddDebug();
+#endif
+
+ return builder.Build();
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Models/Position.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Models/Position.cs
new file mode 100644
index 0000000..bef88fa
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Models/Position.cs
@@ -0,0 +1,38 @@
+using System.ComponentModel;
+
+namespace WorkingWithMaps.Models
+{
+ public class Position : INotifyPropertyChanged
+ {
+ Location _location;
+
+ public string Address { get; }
+ public string Description { get; }
+
+ public Location Location
+ {
+ get => _location;
+ set
+ {
+ if (Location == null || !_location.Equals(value))
+ {
+ _location = value;
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Location)));
+ }
+ }
+ }
+
+ public Position(string address, string description, Location location)
+ {
+ Address = address;
+ Description = description;
+ Location = location;
+ }
+
+ #region INotifyPropertyChanged
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Models/RandomPosition.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Models/RandomPosition.cs
new file mode 100644
index 0000000..b72896c
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Models/RandomPosition.cs
@@ -0,0 +1,14 @@
+namespace WorkingWithMaps.Models
+{
+ static class RandomPosition
+ {
+ static Random Random = new Random(Environment.TickCount);
+
+ public static Location Next(Location location, double latitudeRange, double longitudeRange)
+ {
+ return new Location(
+ location.Latitude + (Random.NextDouble() * 2 - 1) * latitudeRange,
+ location.Longitude + (Random.NextDouble() * 2 - 1) * longitudeRange);
+ }
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/AndroidManifest.xml b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/AndroidManifest.xml
new file mode 100644
index 0000000..ae5d948
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/AndroidManifest.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainActivity.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainActivity.cs
new file mode 100644
index 0000000..06398d0
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainActivity.cs
@@ -0,0 +1,10 @@
+using Android.App;
+using Android.Content.PM;
+using Android.OS;
+
+namespace WorkingWithMaps;
+
+[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
+public class MainActivity : MauiAppCompatActivity
+{
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainApplication.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainApplication.cs
new file mode 100644
index 0000000..d1b99f9
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainApplication.cs
@@ -0,0 +1,15 @@
+using Android.App;
+using Android.Runtime;
+
+namespace WorkingWithMaps;
+
+[Application]
+public class MainApplication : MauiApplication
+{
+ public MainApplication(IntPtr handle, JniHandleOwnership ownership)
+ : base(handle, ownership)
+ {
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/Resources/values/colors.xml b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/Resources/values/colors.xml
new file mode 100644
index 0000000..c04d749
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/Resources/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #512BD4
+ #2B0B98
+ #2B0B98
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/AppDelegate.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/AppDelegate.cs
new file mode 100644
index 0000000..c054115
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/AppDelegate.cs
@@ -0,0 +1,9 @@
+using Foundation;
+
+namespace WorkingWithMaps;
+
+[Register("AppDelegate")]
+public class AppDelegate : MauiUIApplicationDelegate
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Info.plist b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Info.plist
new file mode 100644
index 0000000..e206a43
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Info.plist
@@ -0,0 +1,34 @@
+
+
+
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+ NSLocationAlwaysAndWhenInUseUsageDescription
+ Can we use your location at all times?
+ NSLocationWhenInUseUsageDescription
+ Can we use your location when your app is being used?
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Program.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Program.cs
new file mode 100644
index 0000000..dd647e1
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Program.cs
@@ -0,0 +1,15 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace WorkingWithMaps;
+
+public class Program
+{
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/Main.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/Main.cs
new file mode 100644
index 0000000..7da4ac5
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/Main.cs
@@ -0,0 +1,16 @@
+using System;
+using Microsoft.Maui;
+using Microsoft.Maui.Hosting;
+
+namespace WorkingWithMaps;
+
+class Program : MauiApplication
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+
+ static void Main(string[] args)
+ {
+ var app = new Program();
+ app.Run(args);
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/tizen-manifest.xml b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/tizen-manifest.xml
new file mode 100644
index 0000000..0c63b56
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/tizen-manifest.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ maui-appicon-placeholder
+
+
+
+
+ http://tizen.org/privilege/internet
+
+
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml
new file mode 100644
index 0000000..c3b5f8e
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml
@@ -0,0 +1,8 @@
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml.cs
new file mode 100644
index 0000000..807d7ba
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml.cs
@@ -0,0 +1,24 @@
+using Microsoft.UI.Xaml;
+
+// To learn more about WinUI, the WinUI project structure,
+// and more about our project templates, see: http://aka.ms/winui-project-info.
+
+namespace WorkingWithMaps.WinUI;
+
+///
+/// Provides application-specific behavior to supplement the default Application class.
+///
+public partial class App : MauiWinUIApplication
+{
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ }
+
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/Package.appxmanifest b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/Package.appxmanifest
new file mode 100644
index 0000000..2bcb11e
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/Package.appxmanifest
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+ $placeholder$
+ User Name
+ $placeholder$.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/app.manifest b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/app.manifest
new file mode 100644
index 0000000..a9848fa
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/app.manifest
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ true/PM
+ PerMonitorV2, PerMonitor
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/AppDelegate.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/AppDelegate.cs
new file mode 100644
index 0000000..c054115
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/AppDelegate.cs
@@ -0,0 +1,9 @@
+using Foundation;
+
+namespace WorkingWithMaps;
+
+[Register("AppDelegate")]
+public class AppDelegate : MauiUIApplicationDelegate
+{
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Info.plist b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Info.plist
new file mode 100644
index 0000000..d8412c2
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Info.plist
@@ -0,0 +1,36 @@
+
+
+
+
+ LSRequiresIPhoneOS
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ XSAppIconAssets
+ Assets.xcassets/appicon.appiconset
+ NSLocationAlwaysAndWhenInUseUsageDescription
+ Can we use your location at all times?
+ NSLocationWhenInUseUsageDescription
+ Can we use your location when your app is being used?
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Program.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Program.cs
new file mode 100644
index 0000000..dd647e1
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Program.cs
@@ -0,0 +1,15 @@
+using ObjCRuntime;
+using UIKit;
+
+namespace WorkingWithMaps;
+
+public class Program
+{
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Properties/launchSettings.json b/LotsOfPolylinesRepro/WorkingWithMaps/Properties/launchSettings.json
new file mode 100644
index 0000000..edf8aad
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Properties/launchSettings.json
@@ -0,0 +1,8 @@
+{
+ "profiles": {
+ "Windows Machine": {
+ "commandName": "MsixPackage",
+ "nativeDebugging": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appicon.svg b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appicon.svg
new file mode 100644
index 0000000..9d63b65
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appicon.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appiconfg.svg b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appiconfg.svg
new file mode 100644
index 0000000..21dfb25
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appiconfg.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Regular.ttf b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Regular.ttf
new file mode 100644
index 0000000..0a155fd
Binary files /dev/null and b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Regular.ttf differ
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Semibold.ttf b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Semibold.ttf
new file mode 100644
index 0000000..94f874f
Binary files /dev/null and b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Semibold.ttf differ
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Images/dotnet_bot.svg b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Images/dotnet_bot.svg
new file mode 100644
index 0000000..abfaff2
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Images/dotnet_bot.svg
@@ -0,0 +1,93 @@
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Raw/AboutAssets.txt b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Raw/AboutAssets.txt
new file mode 100644
index 0000000..15d6244
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Raw/AboutAssets.txt
@@ -0,0 +1,15 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories). Deployment of the asset to your application
+is automatically handled by the following `MauiAsset` Build Action within your `.csproj`.
+
+
+
+These files will be deployed with you package and will be accessible using Essentials:
+
+ async Task LoadMauiAsset()
+ {
+ using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
+ using var reader = new StreamReader(stream);
+
+ var contents = reader.ReadToEnd();
+ }
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Splash/splash.svg b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Splash/splash.svg
new file mode 100644
index 0000000..21dfb25
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Splash/splash.svg
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Colors.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Colors.xaml
new file mode 100644
index 0000000..245758b
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Colors.xaml
@@ -0,0 +1,44 @@
+
+
+
+
+ #512BD4
+ #DFD8F7
+ #2B0B98
+ White
+ Black
+ #E1E1E1
+ #C8C8C8
+ #ACACAC
+ #919191
+ #6E6E6E
+ #404040
+ #212121
+ #141414
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ #F7B548
+ #FFD590
+ #FFE5B9
+ #28C2D1
+ #7BDDEF
+ #C3F2F4
+ #3E8EED
+ #72ACF1
+ #A7CBF6
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Styles.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Styles.xaml
new file mode 100644
index 0000000..1ec9d55
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Styles.xaml
@@ -0,0 +1,384 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Templates/MapItemTemplateSelector.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Templates/MapItemTemplateSelector.cs
new file mode 100644
index 0000000..0265e5a
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Templates/MapItemTemplateSelector.cs
@@ -0,0 +1,15 @@
+using WorkingWithMaps.Models;
+
+namespace WorkingWithMaps.Templates;
+
+public class MapItemTemplateSelector : DataTemplateSelector
+{
+ public DataTemplate DefaultTemplate { get; set; }
+ public DataTemplate SanFranTemplate { get; set; }
+
+ protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
+ {
+ return ((Position)item).Address.Contains("San Francisco") ? SanFranTemplate : DefaultTemplate;
+ }
+}
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/ViewModels/PinItemsSourcePageViewModel.cs b/LotsOfPolylinesRepro/WorkingWithMaps/ViewModels/PinItemsSourcePageViewModel.cs
new file mode 100644
index 0000000..d16ff6a
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/ViewModels/PinItemsSourcePageViewModel.cs
@@ -0,0 +1,82 @@
+using System.Collections;
+using System.Collections.ObjectModel;
+using System.Windows.Input;
+using WorkingWithMaps.Models;
+
+namespace WorkingWithMaps.ViewModels;
+
+public class PinItemsSourcePageViewModel
+{
+ int _pinCreatedCount = 0;
+ readonly ObservableCollection _positions;
+
+ public IEnumerable Positions => _positions;
+
+ public ICommand AddLocationCommand { get; }
+ public ICommand RemoveLocationCommand { get; }
+ public ICommand ClearLocationsCommand { get; }
+ public ICommand UpdateLocationsCommand { get; }
+ public ICommand ReplaceLocationCommand { get; }
+
+ public PinItemsSourcePageViewModel()
+ {
+ _positions = new ObservableCollection()
+ {
+ new Position("New York, USA", "The City That Never Sleeps", new Location(40.67, -73.94)),
+ new Position("Los Angeles, USA", "City of Angels", new Location(34.11, -118.41)),
+ new Position("San Francisco, USA", "Bay City", new Location(37.77, -122.45))
+ };
+
+ AddLocationCommand = new Command(AddLocation);
+ RemoveLocationCommand = new Command(RemoveLocation);
+ ClearLocationsCommand = new Command(() => _positions.Clear());
+ UpdateLocationsCommand = new Command(UpdateLocations);
+ ReplaceLocationCommand = new Command(ReplaceLocation);
+ }
+
+ void AddLocation()
+ {
+ _positions.Add(NewPosition());
+ }
+
+ void RemoveLocation()
+ {
+ if (_positions.Any())
+ {
+ _positions.Remove(_positions.First());
+ }
+ }
+
+ void UpdateLocations()
+ {
+ if (!_positions.Any())
+ {
+ return;
+ }
+
+ double lastLatitude = _positions.Last().Location.Latitude;
+ foreach (Position position in Positions)
+ {
+ position.Location = new Location(lastLatitude, position.Location.Longitude);
+ }
+ }
+
+ void ReplaceLocation()
+ {
+ if (!_positions.Any())
+ {
+ return;
+ }
+
+ _positions[_positions.Count - 1] = NewPosition();
+ }
+
+ Position NewPosition()
+ {
+ _pinCreatedCount++;
+ return new Position(
+ $"Pin {_pinCreatedCount}",
+ $"Desc {_pinCreatedCount}",
+ RandomPosition.Next(new Location(39.8283459, -98.5794797), 8, 19));
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml
new file mode 100644
index 0000000..38ddcb4
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+ 37.79752
+ -122.40183
+
+
+ 0.01
+ 0.01
+
+
+
+
+
+
+
+
+ 37.79752
+ -122.40183
+
+
+
+
+
+
+ 250
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml.cs
new file mode 100644
index 0000000..af17a94
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml.cs
@@ -0,0 +1,9 @@
+namespace WorkingWithMaps.Views;
+
+public partial class CirclePage : ContentPage
+{
+ public CirclePage()
+ {
+ InitializeComponent();
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/CirclePageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/CirclePageCode.cs
new file mode 100644
index 0000000..7f16e19
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/CirclePageCode.cs
@@ -0,0 +1,39 @@
+using Microsoft.Maui.Controls.Maps;
+using Microsoft.Maui.Maps;
+using Map = Microsoft.Maui.Controls.Maps.Map;
+
+namespace WorkingWithMaps.Views.Code
+{
+ public class CirclePageCode : ContentPage
+ {
+ public CirclePageCode()
+ {
+ Map map = new Map();
+
+ Location location = new Location(37.79752, -122.40183);
+ Pin pin = new Pin
+ {
+ Label = "Microsoft San Francisco",
+ Address = "1355 Market St, San Francisco CA",
+ Type = PinType.Place,
+ Location = location
+ };
+ map.Pins.Add(pin);
+
+ Circle circle = new Circle
+ {
+ Center = location,
+ Radius = new Distance(250),
+ StrokeColor = Color.FromArgb("#88FF0000"),
+ StrokeWidth = 8,
+ FillColor = Color.FromArgb("#88FFC0CB")
+ };
+ map.MapElements.Add(circle);
+
+ Title = "Circle demo";
+ Content = map;
+
+ map.MoveToRegion(new MapSpan(location, 0.01, 0.01));
+ }
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/GeocoderPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/GeocoderPageCode.cs
new file mode 100644
index 0000000..464fafe
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/GeocoderPageCode.cs
@@ -0,0 +1,41 @@
+using Microsoft.Maui.Devices.Sensors;
+
+namespace WorkingWithMaps.Views.Code;
+
+public class GeocoderPageCode : ContentPage
+{
+ Label l = new Label();
+
+ public GeocoderPageCode()
+ {
+ Title = "Geocoder demo";
+
+ var b1 = new Button { Text = "Reverse geocode '37.808, -122.432'" };
+ b1.Clicked += async (sender, e) =>
+ {
+ Location fortMasonLocation = new Location(37.8044866, -122.4324132);
+ IEnumerable possibleAddresses = await Geocoding.Default.GetPlacemarksAsync(fortMasonLocation);
+ foreach (var a in possibleAddresses)
+ {
+ l.Text += a + "\n";
+ }
+ };
+
+ var b2 = new Button { Text = "Geocode '394 Pacific Ave'" };
+ b2.Clicked += async (sender, e) =>
+ {
+ var address = "394 Pacific Ave, San Francisco, California";
+ IEnumerable approximateLocations = await Geocoding.Default.GetLocationsAsync(address);
+ foreach (var p in approximateLocations)
+ {
+ l.Text += p.Latitude + ", " + p.Longitude + "\n";
+ }
+ };
+
+ StackLayout sl = new StackLayout { Padding = new Thickness(0, 20, 0, 0) };
+ sl.Add(b2);
+ sl.Add(b1);
+ sl.Add(l);
+ Content = sl;
+ }
+}
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapAppPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapAppPageCode.cs
new file mode 100644
index 0000000..8abbaa2
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapAppPageCode.cs
@@ -0,0 +1,71 @@
+namespace WorkingWithMaps.Views.Code;
+
+public class MapAppPageCode : ContentPage
+{
+ // WARNING: when adding latitude/longitude values be careful of localization.
+ // European (and other countries) use a comma as the separator, which will break the request
+ public MapAppPageCode()
+ {
+ Title = "Native map app demo";
+
+ var l = new Label
+ {
+ Text = "These buttons leave the current app and open the built-in Maps app for the platform"
+ };
+
+ var openLocation = new Button
+ {
+ Text = "Open location using built-in Maps app"
+ };
+ openLocation.Clicked += async (sender, e) =>
+ {
+ if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
+ {
+ //https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
+ await Launcher.OpenAsync("http://maps.apple.com/?q=394+Pacific+Ave+San+Francisco+CA");
+ }
+ else if (DeviceInfo.Current.Platform == DevicePlatform.Android)
+ {
+ // opens the Maps app directly
+ await Launcher.OpenAsync("geo:0,0?q=394+Pacific+Ave+San+Francisco+CA");
+ }
+ else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
+ {
+ await Launcher.OpenAsync("bingmaps:?where=394 Pacific Ave San Francisco CA");
+ }
+ };
+
+ var openDirections = new Button
+ {
+ Text = "Get directions using built-in Maps app"
+ };
+ openDirections.Clicked += async (sender, e) =>
+ {
+ if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
+ {
+ //https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
+ await Launcher.OpenAsync("http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino");
+ }
+ else if (DeviceInfo.Current.Platform == DevicePlatform.Android)
+ {
+ // opens the 'task chooser' so the user can pick Maps, Chrome or other mapping app
+ await Launcher.OpenAsync("http://maps.google.com/?daddr=San+Francisco,+CA&saddr=Mountain+View");
+ }
+ else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
+ {
+ await Launcher.OpenAsync("bingmaps:?rtp=adr.394 Pacific Ave San Francisco CA~adr.One Microsoft Way Redmond WA 98052");
+ }
+ };
+
+ StackLayout sl = new StackLayout
+ {
+ Padding = new Thickness(5, 20, 5, 0) ,
+ HorizontalOptions = LayoutOptions.Fill
+ };
+ sl.Add(l);
+ sl.Add(openLocation);
+ sl.Add(openDirections);
+
+ Content = sl;
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapRegionPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapRegionPageCode.cs
new file mode 100644
index 0000000..03150c2
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapRegionPageCode.cs
@@ -0,0 +1,22 @@
+using Microsoft.Maui.Maps;
+using Map = Microsoft.Maui.Controls.Maps.Map;
+
+namespace WorkingWithMaps.Views.Code;
+
+public class MapRegionPageCode : ContentPage
+{
+ public MapRegionPageCode()
+ {
+ Title = "Map region demo";
+
+ Location location = new Location(36.9628066, -122.0194722);
+ MapSpan mapSpan = new MapSpan(location, 0.01, 0.01);
+ //MapSpan mapSpan = MapSpan.FromCenterAndRadius(position, Distance.FromKilometers(0.444));
+
+ Map map = new Map(mapSpan);
+
+ StackLayout sl = new StackLayout { Margin = new Thickness(10) };
+ sl.Add(map);
+ Content = sl;
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapTypesPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapTypesPageCode.cs
new file mode 100644
index 0000000..53b1ff7
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapTypesPageCode.cs
@@ -0,0 +1,71 @@
+using Microsoft.Maui.Maps;
+using Map = Microsoft.Maui.Controls.Maps.Map;
+
+namespace WorkingWithMaps.Views.Code;
+
+public class MapTypesPageCode : ContentPage
+{
+ Map map;
+ public MapTypesPageCode()
+ {
+ Title = "Map types demo";
+
+ map = new Map();
+
+ // Create a Slider for zoom
+ Slider slider = new Slider(1, 18, 12)
+ {
+ Margin = new Thickness(20, 0, 20, 0)
+ };
+ slider.ValueChanged += (sender, e) =>
+ {
+ double zoomLevel = e.NewValue; // between 1 and 18
+ double latlongDegrees = 360 / Math.Pow(2, zoomLevel);
+ if (map.VisibleRegion != null)
+ {
+ map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongDegrees, latlongDegrees));
+ }
+ };
+
+ // Create buttons
+ Button streetButton = new Button { Text = "Street" };
+ Button satelliteButton = new Button { Text = "Satellite" };
+ Button hybridButton = new Button { Text = "Hybrid" };
+
+ streetButton.Clicked += OnButtonClicked;
+ satelliteButton.Clicked += OnButtonClicked;
+ hybridButton.Clicked += OnButtonClicked;
+
+ StackLayout buttons = new StackLayout
+ {
+ Spacing = 30,
+ HorizontalOptions = LayoutOptions.Center,
+ Orientation = StackOrientation.Horizontal,
+ Children = { streetButton, satelliteButton, hybridButton }
+ };
+
+ // Build the page
+ StackLayout stackLayout = new StackLayout();
+ stackLayout.Add(map);
+ stackLayout.Add(slider);
+ stackLayout.Add(buttons);
+ Content = stackLayout;
+ }
+
+ void OnButtonClicked(object sender, EventArgs e)
+ {
+ Button button = sender as Button;
+ switch (button.Text)
+ {
+ case "Street":
+ map.MapType = MapType.Street;
+ break;
+ case "Satellite":
+ map.MapType = MapType.Satellite;
+ break;
+ case "Hybrid":
+ map.MapType = MapType.Hybrid;
+ break;
+ }
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PinPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PinPageCode.cs
new file mode 100644
index 0000000..3cd2d38
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PinPageCode.cs
@@ -0,0 +1,68 @@
+using Microsoft.Maui.Controls.Maps;
+using Microsoft.Maui.Maps;
+using Map = Microsoft.Maui.Controls.Maps.Map;
+
+namespace WorkingWithMaps.Views.Code;
+
+public class PinPageCode : ContentPage
+{
+ public PinPageCode()
+ {
+ Title = "Pins demo";
+
+ Location location = new Location(36.9628066, -122.0194722);
+ MapSpan mapSpan = new MapSpan(location, 0.01, 0.01);
+
+ Map map = new Map(mapSpan);
+
+ Pin pin = new Pin
+ {
+ Label = "Santa Cruz",
+ Address = "The city with a boardwalk",
+ Type = PinType.Place,
+ Location = location
+ };
+ map.Pins.Add(pin);
+
+ Button button = new Button { Text = "Add more pins" };
+ button.Clicked += (sender, e) =>
+ {
+ Pin boardwalkPin = new Pin
+ {
+ Location = new Location(36.9641949, -122.0177232),
+ Label = "Boardwalk",
+ Address = "Santa Cruz",
+ Type = PinType.Place
+ };
+
+ boardwalkPin.MarkerClicked += async (s, args) =>
+ {
+ args.HideInfoWindow = true;
+ string pinName = ((Pin)s).Label;
+ await DisplayAlert("Pin Clicked", $"{pinName} was clicked.", "Ok");
+ };
+
+ Pin wharfPin = new Pin
+ {
+ Location = new Location(36.9571571, -122.0173544),
+ Label = "Wharf",
+ Address = "Santa Cruz",
+ Type = PinType.Place
+ };
+
+ wharfPin.InfoWindowClicked += async (s, args) =>
+ {
+ string pinName = ((Pin)s).Label;
+ await DisplayAlert("Info Window Clicked", $"The info window was clicked for {pinName}.", "Ok");
+ };
+
+ map.Pins.Add(boardwalkPin);
+ map.Pins.Add(wharfPin);
+ };
+
+ StackLayout sl = new StackLayout { Margin = new Thickness(10) };
+ sl.Add(map);
+ sl.Add(button);
+ Content = sl;
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PolygonsPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PolygonsPageCode.cs
new file mode 100644
index 0000000..508c0c8
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PolygonsPageCode.cs
@@ -0,0 +1,134 @@
+using Microsoft.Maui.Controls.Maps;
+using Microsoft.Maui.Maps;
+using Map = Microsoft.Maui.Controls.Maps.Map;
+
+namespace WorkingWithMaps.Views.Code;
+
+public class PolygonsPageCode : ContentPage
+{
+ Map map;
+ Polyline interstateBridge;
+ Polygon msWest;
+ Polygon msEast;
+
+ public PolygonsPageCode()
+ {
+ Title = "Polygon/Polyline Code demo";
+
+ map = new Map();
+
+ Button polygonButton = new Button
+ {
+ Text = "Show Campus (Polygons)"
+ };
+ polygonButton.Clicked += AddPolygonsClicked;
+
+ Button polylineButton = new Button
+ {
+ Text = "Show Access Road (Polyline)"
+ };
+ polylineButton.Clicked += AddPolylineClicked;
+
+ Button clearButton = new Button
+ {
+ Text = "Clear All"
+ };
+ clearButton.Clicked += ClearClicked;
+
+ msWest = new Polygon
+ {
+ StrokeColor = Color.FromArgb("#FF9900"),
+ StrokeWidth = 8,
+ FillColor = Color.FromArgb("#88FF9900"),
+ Geopath =
+ {
+ new Location(47.6458676, -122.1356007),
+ new Location(47.6458097, -122.142789),
+ new Location(47.6367593, -122.1428104),
+ new Location(47.6368027, -122.1398707),
+ new Location(47.6380172, -122.1376177),
+ new Location(47.640663, -122.1352359),
+ new Location(47.6426148, -122.1347209),
+ new Location(47.6458676, -122.1356007)
+ }
+ };
+
+ msEast = new Polygon
+ {
+ StrokeColor = Color.FromArgb("#1BA1E2"),
+ StrokeWidth = 8,
+ FillColor = Color.FromArgb("#881BA1E2"),
+ Geopath =
+ {
+ new Location(47.6368678, -122.137305),
+ new Location(47.6368894, -122.134655),
+ new Location(47.6359424, -122.134655),
+ new Location(47.6359496, -122.1325521),
+ new Location(47.6424124, -122.1325199),
+ new Location(47.642463, -122.1338932),
+ new Location(47.6406414, -122.1344833),
+ new Location(47.6384943, -122.1361248),
+ new Location(47.6372943, -122.1376912),
+ new Location(47.6368678, -122.137305),
+ }
+ };
+
+ interstateBridge = new Polyline
+ {
+ StrokeColor = Colors.Black,
+ StrokeWidth = 12,
+ Geopath =
+ {
+ new Location(47.6381401, -122.1317367),
+ new Location(47.6381473, -122.1350841),
+ new Location(47.6382847, -122.1353094),
+ new Location(47.6384582, -122.1354703),
+ new Location(47.6401136, -122.1360819),
+ new Location(47.6403883, -122.1364681),
+ new Location(47.6407426, -122.1377019),
+ new Location(47.6412558, -122.1404056),
+ new Location(47.6414148, -122.1418647),
+ new Location(47.6414654, -122.1432702)
+ }
+ };
+
+ StackLayout sl = new StackLayout();
+ sl.Add(map);
+ sl.Add(polygonButton);
+ sl.Add(polylineButton);
+ sl.Add(clearButton);
+ Content = sl;
+
+ map.MoveToRegion(
+ MapSpan.FromCenterAndRadius(
+ new Location(47.640663, -122.1376177), Distance.FromMiles(1)));
+ }
+
+ void AddPolylineClicked(object sender, EventArgs e)
+ {
+ if (!map.MapElements.Contains(interstateBridge))
+ {
+ map.MapElements.Add(interstateBridge);
+ }
+ }
+
+ void AddPolygonsClicked(object sender, EventArgs e)
+ {
+ if (!map.MapElements.Contains(msWest))
+ {
+ map.MapElements.Add(msWest);
+ }
+
+ if (!map.MapElements.Contains(msEast))
+ {
+ map.MapElements.Add(msEast);
+ }
+ }
+
+ void ClearClicked(object sender, EventArgs e)
+ {
+ map.MapElements.Remove(msWest);
+ map.MapElements.Remove(msEast);
+ map.MapElements.Remove(interstateBridge);
+ }
+}
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml
new file mode 100644
index 0000000..70b29e9
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml.cs
new file mode 100644
index 0000000..ea0df2f
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml.cs
@@ -0,0 +1,46 @@
+using Microsoft.Maui.Controls.Maps;
+using Microsoft.Maui.Devices.Sensors;
+
+namespace WorkingWithMaps.Views;
+
+public partial class GeocoderPage : ContentPage
+{
+ public GeocoderPage()
+ {
+ InitializeComponent();
+ }
+
+ async void OnGeocodeButtonClicked(object sender, EventArgs e)
+ {
+ if (!string.IsNullOrWhiteSpace(geocodeEntry.Text))
+ {
+ string address = geocodeEntry.Text;
+ IEnumerable approximateLocations = await Geocoding.Default.GetLocationsAsync(address);
+ Location location = approximateLocations.FirstOrDefault();
+ geocodedOutputLabel.Text = $"{location.Latitude}, {location.Longitude}";
+ }
+ }
+
+ async void OnReverseGeocodeButtonClicked(object sender, EventArgs e)
+ {
+ if (!string.IsNullOrWhiteSpace(reverseGeocodeEntry.Text))
+ {
+ string[] coordinates = reverseGeocodeEntry.Text.Split(',');
+ double? latitude = Convert.ToDouble(coordinates.FirstOrDefault());
+ double? longitude = Convert.ToDouble(coordinates.Skip(1).FirstOrDefault());
+
+ if (latitude != null && longitude != null)
+ {
+ Location location = new Location(latitude.Value, longitude.Value);
+
+ Location fortMasonLocation = new Location(37.8044866, -122.4324132);
+ IEnumerable possibleAddresses = await Geocoding.Default.GetPlacemarksAsync(location);
+ Placemark placemark = possibleAddresses?.FirstOrDefault();
+ if (placemark != null)
+ reverseGeocodedOutputLabel.Text = $"Thoroughfare: {placemark.Thoroughfare}, Locality: {placemark.Locality}, ZipCode: {placemark.PostalCode}";
+ else
+ reverseGeocodedOutputLabel.Text = string.Empty;
+ }
+ }
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/LotsOfPolylinesPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/LotsOfPolylinesPage.xaml
new file mode 100644
index 0000000..57b1b33
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/LotsOfPolylinesPage.xaml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/LotsOfPolylinesPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/LotsOfPolylinesPage.xaml.cs
new file mode 100644
index 0000000..0d55720
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/LotsOfPolylinesPage.xaml.cs
@@ -0,0 +1,45 @@
+using Microsoft.Maui.Controls.Maps;
+using Microsoft.Maui.Maps;
+
+namespace WorkingWithMaps.Views;
+
+public partial class LotsOfPolylinesPage : ContentPage
+{
+ public LotsOfPolylinesPage()
+ {
+ InitializeComponent();
+
+ MainThread.BeginInvokeOnMainThread(() => Render());
+ }
+
+ void Render()
+ {
+ Location NW = new(48.60660019765632, -121.6898628046794);
+ Location SW = new(34.932324583554866, -115.69598307100047);
+
+ // Change the count and steps to obtain different results. I see it falling over about here, but your mileage might vary
+ const int count = 92;
+ const int steps = 500;
+
+ Random rand = new((int)DateTime.Now.Ticks);
+
+ for (int i = 0; i < count; i++)
+ {
+ NW.Longitude += 0.8;
+ SW.Longitude += 0.8;
+
+ Polyline polyline = [];
+ polyline.StrokeColor = Colors.Red;
+
+ for (int step = 0; step < steps; step ++)
+ {
+ double longitudeJitter = rand.NextDouble() / 2;
+
+ polyline.Add(new Location(NW.Latitude - (NW.Latitude - SW.Latitude) * step / steps, NW.Longitude - (NW.Longitude - SW.Longitude) * step / steps + longitudeJitter));
+ }
+
+ this.Map.MapElements.Add(polyline);
+ this.Map.MoveToRegion(MapSpan.FromCenterAndRadius(new Location(40.383529471357214, -113.0223447653204), Distance.FromMiles(1300.0)));
+ }
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MainPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MainPage.xaml
new file mode 100644
index 0000000..d0fea64
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MainPage.xaml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MainPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MainPage.xaml.cs
new file mode 100644
index 0000000..da08c3e
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MainPage.xaml.cs
@@ -0,0 +1,22 @@
+using System.Windows.Input;
+
+namespace WorkingWithMaps.Views;
+
+public partial class MainPage : ContentPage
+{
+ public ICommand NavigateCommand { get; set; }
+
+ public MainPage()
+ {
+ InitializeComponent();
+
+ NavigateCommand = new Command(async (Type pageType) =>
+ {
+ Page page = (Page)Activator.CreateInstance(pageType);
+ await Navigation.PushAsync(page);
+ });
+
+ BindingContext = this;
+ }
+}
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapAppPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapAppPage.xaml
new file mode 100644
index 0000000..27c6a02
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapAppPage.xaml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapAppPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapAppPage.xaml.cs
new file mode 100644
index 0000000..ce60000
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapAppPage.xaml.cs
@@ -0,0 +1,47 @@
+namespace WorkingWithMaps.Views;
+
+// WARNING: when adding latitude/longitude values be careful of localization.
+// European (and other countries) use a comma as the separator, which will break the request
+public partial class MapAppPage : ContentPage
+{
+ public MapAppPage()
+ {
+ InitializeComponent();
+ }
+
+ async void OnLocationButtonClicked(object sender, EventArgs e)
+ {
+ if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
+ {
+ // https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
+ await Launcher.OpenAsync("http://maps.apple.com/?q=394+Pacific+Ave+San+Francisco+CA");
+ }
+ else if (DeviceInfo.Current.Platform == DevicePlatform.Android)
+ {
+ // opens the Maps app directly
+ await Launcher.OpenAsync("geo:0,0?q=394+Pacific+Ave+San+Francisco+CA");
+ }
+ else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
+ {
+ await Launcher.OpenAsync("bingmaps:?where=394 Pacific Ave San Francisco CA");
+ }
+ }
+
+ async void OnDirectionButtonClicked(object sender, EventArgs e)
+ {
+ if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst)
+ {
+ // https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html
+ await Launcher.OpenAsync("http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino");
+ }
+ else if (DeviceInfo.Current.Platform == DevicePlatform.Android)
+ {
+ // opens the 'task chooser' so the user can pick Maps, Chrome or other mapping app
+ await Launcher.OpenAsync("http://maps.google.com/?daddr=San+Francisco,+CA&saddr=Mountain+View");
+ }
+ else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
+ {
+ await Launcher.OpenAsync("bingmaps:?rtp=adr.394 Pacific Ave San Francisco CA~adr.One Microsoft Way Redmond WA 98052");
+ }
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapPropertiesPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapPropertiesPage.xaml
new file mode 100644
index 0000000..f023a54
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapPropertiesPage.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapPropertiesPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapPropertiesPage.xaml.cs
new file mode 100644
index 0000000..2031fe5
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapPropertiesPage.xaml.cs
@@ -0,0 +1,41 @@
+using System.Diagnostics;
+using Microsoft.Maui.Controls.Maps;
+
+namespace WorkingWithMaps.Views;
+
+public partial class MapPropertiesPage : ContentPage
+{
+ public MapPropertiesPage()
+ {
+ InitializeComponent();
+
+ scrollEnabledCheckBox.CheckedChanged += OnCheckBoxCheckedChanged;
+ zoomEnabledCheckBox.CheckedChanged += OnCheckBoxCheckedChanged;
+ }
+
+ void OnMapClicked(object sender, MapClickedEventArgs e)
+ {
+ Debug.WriteLine($"MapClick: {e.Location.Latitude}, {e.Location.Longitude}");
+ }
+
+ void OnCheckBoxCheckedChanged(object sender, CheckedChangedEventArgs e)
+ {
+ CheckBox checkBox = sender as CheckBox;
+
+ switch (checkBox.StyleId)
+ {
+ case "scrollEnabledCheckBox":
+ map.IsScrollEnabled = !map.IsScrollEnabled;
+ break;
+ case "zoomEnabledCheckBox":
+ map.IsZoomEnabled = !map.IsZoomEnabled;
+ break;
+ case "showUserCheckBox":
+ map.IsShowingUser = !map.IsShowingUser;
+ break;
+ case "showTrafficCheckBox":
+ map.IsTrafficEnabled = !map.IsTrafficEnabled;
+ break;
+ }
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapRegionPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapRegionPage.xaml
new file mode 100644
index 0000000..7089d56
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapRegionPage.xaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+ 36.9628066
+ -122.0194722
+
+
+ 0.01
+ 0.01
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapRegionPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapRegionPage.xaml.cs
new file mode 100644
index 0000000..88e0bf7
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapRegionPage.xaml.cs
@@ -0,0 +1,11 @@
+namespace WorkingWithMaps.Views;
+
+public partial class MapRegionPage : ContentPage
+{
+ public MapRegionPage()
+ {
+ InitializeComponent();
+ }
+}
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapTypesPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapTypesPage.xaml
new file mode 100644
index 0000000..7a7881e
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapTypesPage.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapTypesPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapTypesPage.xaml.cs
new file mode 100644
index 0000000..cd78f62
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/MapTypesPage.xaml.cs
@@ -0,0 +1,38 @@
+using Microsoft.Maui.Maps;
+
+namespace WorkingWithMaps.Views;
+
+public partial class MapTypesPage : ContentPage
+{
+ public MapTypesPage()
+ {
+ InitializeComponent();
+ }
+
+ void OnSliderValueChanged(object sender, ValueChangedEventArgs e)
+ {
+ double zoomLevel = e.NewValue;
+ double latlongDegrees = 360 / (Math.Pow(2, zoomLevel));
+ if (map.VisibleRegion != null)
+ {
+ map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongDegrees, latlongDegrees));
+ }
+ }
+
+ void OnButtonClicked(object sender, EventArgs e)
+ {
+ Button button = sender as Button;
+ switch (button.Text)
+ {
+ case "Street":
+ map.MapType = MapType.Street;
+ break;
+ case "Satellite":
+ map.MapType = MapType.Satellite;
+ break;
+ case "Hybrid":
+ map.MapType = MapType.Hybrid;
+ break;
+ }
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinItemsSourcePage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinItemsSourcePage.xaml
new file mode 100644
index 0000000..cc030b0
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinItemsSourcePage.xaml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinItemsSourcePage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinItemsSourcePage.xaml.cs
new file mode 100644
index 0000000..d15e28d
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinItemsSourcePage.xaml.cs
@@ -0,0 +1,20 @@
+using WorkingWithMaps.ViewModels;
+using Microsoft.Maui.Controls.Maps;
+using Microsoft.Maui.Maps;
+
+namespace WorkingWithMaps.Views;
+
+public partial class PinItemsSourcePage : ContentPage
+{
+ public PinItemsSourcePage()
+ {
+ InitializeComponent();
+ BindingContext = new PinItemsSourcePageViewModel();
+ map.MoveToRegion(MapSpan.FromCenterAndRadius(new Location(39.8283459, -98.5794797), Distance.FromMiles(1500)));
+ }
+
+ void OnMapClicked(object sender, MapClickedEventArgs e)
+ {
+ System.Diagnostics.Debug.WriteLine($"MapClick: {e.Location.Latitude}, {e.Location.Longitude}");
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinPage.xaml
new file mode 100644
index 0000000..fe32a3b
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinPage.xaml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+ 36.9628066
+ -122.0194722
+
+
+ 0.01
+ 0.01
+
+
+
+
+
+
+
+
+ 36.9628066
+ -122.0194722
+
+
+
+
+
+
+
+
+
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinPage.xaml.cs
new file mode 100644
index 0000000..665602c
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PinPage.xaml.cs
@@ -0,0 +1,48 @@
+using Microsoft.Maui.Controls.Maps;
+
+namespace WorkingWithMaps.Views;
+
+public partial class PinPage : ContentPage
+{
+ public PinPage()
+ {
+ InitializeComponent();
+ }
+
+ void OnButtonClicked(object sender, EventArgs e)
+ {
+ Pin boardwalkPin = new Pin
+ {
+ Location = new Location(36.9641949, -122.0177232),
+ Label = "Boardwalk",
+ Address = "Santa Cruz",
+ Type = PinType.Place
+ };
+ boardwalkPin.MarkerClicked += OnMarkerClickedAsync;
+
+ Pin wharfPin = new Pin
+ {
+ Location = new Location(36.9571571, -122.0173544),
+ Label = "Wharf",
+ Address = "Santa Cruz",
+ Type = PinType.Place
+ };
+ wharfPin.InfoWindowClicked += OnInfoWindowClickedAsync;
+
+ map.Pins.Add(boardwalkPin);
+ map.Pins.Add(wharfPin);
+ }
+
+ async void OnMarkerClickedAsync(object sender, PinClickedEventArgs e)
+ {
+ e.HideInfoWindow = true;
+ string pinName = ((Pin)sender).Label;
+ await DisplayAlert("Pin Clicked", $"{pinName} was clicked.", "Ok");
+ }
+
+ async void OnInfoWindowClickedAsync(object sender, PinClickedEventArgs e)
+ {
+ string pinName = ((Pin)sender).Label;
+ await DisplayAlert("Info Window Clicked", $"The info window was clicked for {pinName}.", "Ok");
+ }
+}
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/PolygonsPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PolygonsPage.xaml
new file mode 100644
index 0000000..27bc731
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PolygonsPage.xaml
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
+
+ 47.640663
+ -122.1376177
+
+
+ 0.1
+ 0.1
+
+
+
+
+
+
+
+
+ 47.6458676
+ -122.1356007
+
+
+
+
+ 47.6458097
+ -122.142789
+
+
+
+
+ 47.6367593
+ -122.1428104
+
+
+
+
+ 47.6368027
+ -122.1398707
+
+
+
+
+ 47.6380172
+ -122.1376177
+
+
+
+
+ 47.640663
+ -122.1352359
+
+
+
+
+ 47.6426148
+ -122.1347209
+
+
+
+
+ 47.6458676
+ -122.1356007
+
+
+
+
+
+
+
+
+ 47.6368678
+ -122.137305
+
+
+
+
+ 47.6368894
+ -122.134655
+
+
+
+
+ 47.6359424
+ -122.134655
+
+
+
+
+ 47.6359496
+ -122.1325521
+
+
+
+
+ 47.6424124
+ -122.1325199
+
+
+
+
+ 47.642463
+ -122.1338932
+
+
+
+
+ 47.6406414
+ -122.1344833
+
+
+
+
+ 47.6384943
+ -122.1361248
+
+
+
+
+ 47.6372943
+ -122.1376912
+
+
+
+
+ 47.6368678
+ -122.137305
+
+
+
+
+
+
+
+
+ 47.6381401
+ -122.1317367
+
+
+
+
+ 47.6381473
+ -122.1350841
+
+
+
+
+ 47.6382847
+ -122.1353094
+
+
+
+
+ 47.6384582
+ -122.1354703
+
+
+
+
+ 47.6401136
+ -122.1360819
+
+
+
+
+ 47.6403883
+ -122.1364681
+
+
+
+
+ 47.6407426
+ -122.1377019
+
+
+
+
+ 47.6412558
+ -122.1404056
+
+
+
+
+ 47.6414148
+ -122.1418647
+
+
+
+
+ 47.6414654
+ -122.1432702
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/PolygonsPage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PolygonsPage.xaml.cs
new file mode 100644
index 0000000..48d79d7
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/PolygonsPage.xaml.cs
@@ -0,0 +1,9 @@
+namespace WorkingWithMaps.Views;
+
+public partial class PolygonsPage : ContentPage
+{
+ public PolygonsPage()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/WorkingWithMaps.csproj b/LotsOfPolylinesRepro/WorkingWithMaps/WorkingWithMaps.csproj
new file mode 100644
index 0000000..9d41283
--- /dev/null
+++ b/LotsOfPolylinesRepro/WorkingWithMaps/WorkingWithMaps.csproj
@@ -0,0 +1,88 @@
+
+
+
+ net8.0-android34.0
+
+
+ Exe
+ WorkingWithMaps
+ true
+ true
+ enable
+
+
+ WorkingWithMaps
+
+
+ com.companyname.workingwithmaps
+ 7e34e122-9742-491c-b653-d8d5d44d77e0
+
+
+ 1.0
+ 1
+
+ 21.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+
+
+
+
+
+
+
+
+
+