├── .gitattributes ├── .gitignore ├── GitReleaseManager.yaml ├── GitVersion.yml ├── LICENSE.md ├── README.md ├── appveyor.yml ├── assets ├── .gitkeep ├── noun_60112_cc.png └── noun_60112_cc_cropped.png ├── build.cake ├── build.cmd ├── contrib └── .gitkeep ├── licenses └── .gitkeep ├── src ├── .gitkeep ├── CommonSolutionInfo.cs ├── GeoCoordinate.nuspec ├── GeoCoordinatePortable.sln ├── GeoCoordinatePortable │ ├── GeoCoordinate.cs │ ├── GeoCoordinatePortable.csproj │ ├── GeoPosition.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ └── project.json ├── GeoCoordinatePortableTests │ ├── Assert.cs │ ├── GeoCoordinatePortableTests.csproj │ ├── GeoCoordinateTests.cs │ └── Properties │ │ └── AssemblyInfo.cs └── SolutionInfo.cs └── tools └── nuget └── NuGet.exe /.gitattributes: -------------------------------------------------------------------------------- 1 | # Catch all for anything we forgot. Add rules if you get CRLF to LF warnings. 2 | * text=auto 3 | 4 | # Text files that should be normalized to LF in odb. 5 | *.cs text eol=lf diff=csharp 6 | *.xaml text 7 | *.config text 8 | *.c text 9 | *.h text 10 | *.cpp text 11 | *.hpp text 12 | 13 | *.sln text 14 | *.csproj text 15 | *.vcxproj text 16 | 17 | *.md text 18 | *.tt text 19 | *.sh text 20 | *.ps1 text 21 | *.cmd text 22 | *.bat text 23 | *.markdown text 24 | *.msbuild text 25 | 26 | 27 | # Binary files that should not be normalized or diffed 28 | *.png binary 29 | *.jpg binary 30 | *.gif binary 31 | *.ico binary 32 | *.rc binary 33 | 34 | *.pfx binary 35 | *.snk binary 36 | *.dll binary 37 | *.exe binary 38 | *.lib binary 39 | *.exp binary 40 | *.pdb binary 41 | *.sdf binary 42 | *.7z binary 43 | 44 | # Generated file should just use CRLF, it's fiiine 45 | SolutionInfo.cs text eol=crlf diff=csharp 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | *.lock.json 45 | artifacts/ 46 | *.nuget.props 47 | *.nuget.targets 48 | 49 | *_i.c 50 | *_p.c 51 | *_i.h 52 | *.ilk 53 | *.meta 54 | *.obj 55 | *.pch 56 | *.pdb 57 | *.pgc 58 | *.pgd 59 | *.rsp 60 | *.sbr 61 | *.tlb 62 | *.tli 63 | *.tlh 64 | *.tmp 65 | *.tmp_proj 66 | *.log 67 | *.vspscc 68 | *.vssscc 69 | .builds 70 | *.pidb 71 | *.svclog 72 | *.scc 73 | 74 | # Chutzpah Test files 75 | _Chutzpah* 76 | 77 | # Visual C++ cache files 78 | ipch/ 79 | *.aps 80 | *.ncb 81 | *.opendb 82 | *.opensdf 83 | *.sdf 84 | *.cachefile 85 | 86 | # Visual Studio profiler 87 | *.psess 88 | *.vsp 89 | *.vspx 90 | *.sap 91 | 92 | # TFS 2012 Local Workspace 93 | $tf/ 94 | 95 | # Guidance Automation Toolkit 96 | *.gpState 97 | 98 | # ReSharper is a .NET coding add-in 99 | _ReSharper*/ 100 | *.[Rr]e[Ss]harper 101 | *.DotSettings.user 102 | 103 | # JustCode is a .NET coding add-in 104 | .JustCode 105 | 106 | # TeamCity is a build add-in 107 | _TeamCity* 108 | 109 | # DotCover is a Code Coverage Tool 110 | *.dotCover 111 | 112 | # NCrunch 113 | _NCrunch_* 114 | .*crunch*.local.xml 115 | nCrunchTemp_* 116 | 117 | # MightyMoose 118 | *.mm.* 119 | AutoTest.Net/ 120 | 121 | # Web workbench (sass) 122 | .sass-cache/ 123 | 124 | # Installshield output folder 125 | [Ee]xpress/ 126 | 127 | # DocProject is a documentation generator add-in 128 | DocProject/buildhelp/ 129 | DocProject/Help/*.HxT 130 | DocProject/Help/*.HxC 131 | DocProject/Help/*.hhc 132 | DocProject/Help/*.hhk 133 | DocProject/Help/*.hhp 134 | DocProject/Help/Html2 135 | DocProject/Help/html 136 | 137 | # Click-Once directory 138 | publish/ 139 | 140 | # Publish Web Output 141 | *.[Pp]ublish.xml 142 | *.azurePubxml 143 | # TODO: Comment the next line if you want to checkin your web deploy settings 144 | # but database connection strings (with potential passwords) will be unencrypted 145 | *.pubxml 146 | *.publishproj 147 | 148 | # NuGet Packages 149 | *.nupkg 150 | # The packages folder can be ignored because of Package Restore 151 | **/packages/* 152 | # except build/, which is used as an MSBuild target. 153 | !**/packages/build/ 154 | # Uncomment if necessary however generally it will be regenerated when needed 155 | #!**/packages/repositories.config 156 | 157 | # Windows Azure Build Output 158 | csx/ 159 | *.build.csdef 160 | 161 | # Windows Azure Emulator 162 | ecf/ 163 | rcf/ 164 | 165 | # Windows Store app package directory 166 | AppPackages/ 167 | BundleArtifacts/ 168 | 169 | # Visual Studio cache files 170 | # files ending in .cache can be ignored 171 | *.[Cc]ache 172 | # but keep track of directories ending in .cache 173 | !*.[Cc]ache/ 174 | 175 | # Others 176 | ClientBin/ 177 | ~$* 178 | *~ 179 | *.dbmdl 180 | *.dbproj.schemaview 181 | *.pfx 182 | *.publishsettings 183 | node_modules/ 184 | orleans.codegen.cs 185 | 186 | # RIA/Silverlight projects 187 | Generated_Code/ 188 | 189 | # Backup & report files from converting an old project file 190 | # to a newer Visual Studio version. Backup files are not needed, 191 | # because we have git ;-) 192 | _UpgradeReport_Files/ 193 | Backup*/ 194 | UpgradeLog*.XML 195 | UpgradeLog*.htm 196 | 197 | # SQL Server files 198 | *.mdf 199 | *.ldf 200 | 201 | # Business Intelligence projects 202 | *.rdl.data 203 | *.bim.layout 204 | *.bim_*.settings 205 | 206 | # Microsoft Fakes 207 | FakesAssemblies/ 208 | 209 | # GhostDoc plugin setting file 210 | *.GhostDoc.xml 211 | 212 | # Node.js Tools for Visual Studio 213 | .ntvs_analysis.dat 214 | 215 | # Visual Studio 6 build log 216 | *.plg 217 | 218 | # Visual Studio 6 workspace options file 219 | *.opt 220 | 221 | # Visual Studio LightSwitch build output 222 | **/*.HTMLClient/GeneratedArtifacts 223 | **/*.DesktopClient/GeneratedArtifacts 224 | **/*.DesktopClient/ModelManifest.xml 225 | **/*.Server/GeneratedArtifacts 226 | **/*.Server/ModelManifest.xml 227 | _Pvt_Extensions 228 | 229 | # Paket dependency manager 230 | .paket/paket.exe 231 | 232 | # FAKE - F# Make 233 | .fake/ 234 | 235 | # Tools 236 | tools/ 237 | 238 | # ReactiveUI 239 | artifacts/ 240 | src/CommonAssemblyInfo.cs 241 | src/ReactiveUI.Events/Events_*.cs 242 | -------------------------------------------------------------------------------- /GitReleaseManager.yaml: -------------------------------------------------------------------------------- 1 | create: 2 | include-footer: true 3 | footer-heading: Where to get it 4 | footer-content: You can download this release from [nuget.org](https://www.nuget.org/packages/akavache/{milestone}) 5 | footer-includes-milestone: true 6 | milestone-replace-text: '{milestone}' 7 | export: 8 | include-created-date-in-title: true 9 | created-date-string-format: MMMM dd, yyyy 10 | perform-regex-removal: true 11 | regex-text: '### Where to get it(\r\n)*You can .*\)' 12 | multiline-regex: true 13 | issue-labels-include: 14 | - Breaking change 15 | - Feature 16 | - Bug 17 | - Improvement 18 | - Documentation 19 | issue-labels-exclude: 20 | - Build 21 | issue-labels-alias: 22 | - name: Documentation 23 | header: Documentation 24 | plural: Documentation -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | assembly-versioning-scheme: None 2 | branches: 3 | master: 4 | mode: ContinuousDelivery 5 | tag: 6 | increment: Patch 7 | prevent-increment-of-merged-branch-version: true 8 | track-merge-target: false 9 | dev(elop)?(ment)?$: 10 | mode: ContinuousDeployment 11 | tag: alpha 12 | increment: Minor 13 | prevent-increment-of-merged-branch-version: false 14 | track-merge-target: true -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # Microsoft Public License (Ms-PL) 2 | 3 | This license governs use of the accompanying software. If you use the software, 4 | you accept this license. If you do not accept the license, do not use the 5 | software. 6 | 7 | 1. Definitions 8 | The terms "reproduce," "reproduction," "derivative works," and "distribution" 9 | have the same meaning here as under U.S. copyright law. A "contribution" is the 10 | original software, or any additions or changes to the software. A "contributor" 11 | is any person that distributes its contribution under this license. "Licensed 12 | patents" are a contributor's patent claims that read directly on its 13 | contribution. 14 | 15 | 2. Grant of Rights 16 | 17 | (A) Copyright Grant- Subject to the terms of this license, including the license 18 | conditions and limitations in section 3, each contributor grants you a 19 | non-exclusive, worldwide, royalty-free copyright license to reproduce its 20 | contribution, prepare derivative works of its contribution, and distribute its 21 | contribution or any derivative works that you create. 22 | 23 | (B) Patent Grant- Subject 24 | to the terms of this license, including the license conditions and limitations 25 | in section 3, each contributor grants you a non-exclusive, worldwide, 26 | royalty-free license under its licensed patents to make, have made, use, sell, 27 | offer for sale, import, and/or otherwise dispose of its contribution in the 28 | software or derivative works of the contribution in the software. 29 | 30 | 3. Conditions and Limitations 31 | 32 | (A) No Trademark License- This license does not grant you rights to use any 33 | contributors' name, logo, or trademarks. 34 | (B) If you bring a patent claim against any contributor over patents that you 35 | claim are infringed by the software, your patent license from such contributor 36 | to the software ends automatically. 37 | (C) If you distribute any portion of the software, you must retain all 38 | copyright, patent, trademark, and attribution notices that are present in the 39 | software. 40 | (D) If you distribute any portion of the software in source code form, you may 41 | do so only under this license by including a complete copy of this license with 42 | your distribution. If you distribute any portion of the software in compiled or 43 | object code form, you may only do so under a license that complies with this 44 | license. 45 | (E) The software is licensed "as-is." You bear the risk of using it. The 46 | contributors give no express warranties, guarantees or conditions. You may have 47 | additional consumer rights under your local laws which this license cannot 48 | change. To the extent permitted under your local laws, the contributors exclude 49 | the implied warranties of merchantability, fitness for a particular purpose and 50 | non-infringement. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Icon](https://i.imgur.com/OfoiwTs.png) 2 | # GeoCoordinate [![Build status](https://ci.appveyor.com/api/projects/status/k18x42mpj4bp93rn?svg=true)](https://ci.appveyor.com/project/ghuntley/geocoordinate) 3 | 4 | 5 | GeoCoordinate is a portable class library (in v1.1.x) or netstandard v1.1 (from v2.x.x) compatible implementation of System.Device.Location.GeoCoordinate. It is an exact 1:1 API compliant implementation and will be supported until MSFT [sees it fit to embed the type](https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/5221530-geocoordinate-class-included-in-portable-class-lib). Which at that point this implementation will cease development/support and you will be able to simply remove this package and everything will still work. 6 | 7 | # Supported Platforms 8 | 9 | * Mono 10 | * .NET 4.5 11 | * .NET Core 12 | * Windows Phone 8.x 13 | * Universal Windows Platform 14 | * Xamarin iOS 15 | * Xamarin Android 16 | 17 | # Installation 18 | Installation is done via NuGet: 19 | 20 | PM> Install-Package GeoCoordinate 21 | 22 | # Usage 23 | 24 | GeoCoordinate pin1 = new GeoCoordinate(lat, lng); 25 | GeoCoordinate pin2 = new GeoCoordinate(lat, lng); 26 | 27 | double distanceBetween = pin1.GetDistanceTo(pin2); 28 | 29 | For more examples, refer to the MSDN reference documentation over at: https://msdn.microsoft.com/en-us/library/system.device.location.geocoordinate(v=vs.110).aspx 30 | 31 | # With thanks to 32 | * The icon "[Map Marker](https://thenounproject.com/term/map-marker/60112)" designed by [julianne](https://thenounproject.com/janne232) from The Noun Project. 33 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # configuration for "master" branch 2 | - 3 | configuration: Release 4 | branches: 5 | only: 6 | - master 7 | version: 1.0.{build} 8 | environment: 9 | GITHUB_USERNAME: 10 | secure: 0Q9MvUId56SizmZwCf0cgg== 11 | GITHUB_TOKEN: 12 | secure: R3xA9iMXfUUtFd3wuL38pcDa0/BjjpBvNcGShr5LRibZtBoOVSH47Jat75rwaGur 13 | NUGET_SOURCE: https://www.nuget.org/api/v2/package 14 | NUGET_APIKEY: 15 | secure: 0g2AqQxgiAIFhqoJbbmEPrJa15Z8U5xYT6vQe43Gocuxbjw74hBAIKbU+Cj65UNd 16 | build_script: 17 | - ps: >- 18 | ./build.cmd 19 | artifacts: 20 | - path: artifacts/* 21 | - path: '**/bin/*' 22 | test: off 23 | 24 | # configuration for "develop" branch 25 | - 26 | configuration: Development 27 | branches: 28 | except: 29 | - master 30 | 31 | version: 1.0.{build} 32 | environment: 33 | NUGET_SOURCE: https://www.myget.org/F/akavache/api/v2/package 34 | NUGET_APIKEY: 35 | secure: YP/3KxC2ffsuHNaolPXj66JVGzSjON9FcR2S2OEzn9c6SV14oPzUh1ySyeT+G+aA 36 | build_script: 37 | - ps: >- 38 | ./bootstrap.ps1 39 | 40 | ./build.cmd 41 | artifacts: 42 | - path: artifacts/* 43 | - path: '**/bin/*' 44 | test: off 45 | 46 | # "fall back" configuration for all other branches 47 | # no "branches" section defined 48 | # do not deploy at all 49 | - 50 | configuration: Development -------------------------------------------------------------------------------- /assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghuntley/geocoordinate/b8c4d99c738bcbd1e86114c9174bf7e179c22e7a/assets/.gitkeep -------------------------------------------------------------------------------- /assets/noun_60112_cc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghuntley/geocoordinate/b8c4d99c738bcbd1e86114c9174bf7e179c22e7a/assets/noun_60112_cc.png -------------------------------------------------------------------------------- /assets/noun_60112_cc_cropped.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghuntley/geocoordinate/b8c4d99c738bcbd1e86114c9174bf7e179c22e7a/assets/noun_60112_cc_cropped.png -------------------------------------------------------------------------------- /build.cake: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////// 2 | // ADDINS 3 | ////////////////////////////////////////////////////////////////////// 4 | 5 | #addin "Cake.FileHelpers" 6 | 7 | ////////////////////////////////////////////////////////////////////// 8 | // TOOLS 9 | ////////////////////////////////////////////////////////////////////// 10 | 11 | #tool "GitReleaseManager" 12 | #tool "GitVersion.CommandLine" 13 | #tool "GitLink" 14 | 15 | ////////////////////////////////////////////////////////////////////// 16 | // ARGUMENTS 17 | ////////////////////////////////////////////////////////////////////// 18 | 19 | var target = Argument("target", "Default"); 20 | if (string.IsNullOrWhiteSpace(target)) 21 | { 22 | target = "Default"; 23 | } 24 | 25 | ////////////////////////////////////////////////////////////////////// 26 | // PREPARATION 27 | ////////////////////////////////////////////////////////////////////// 28 | 29 | // Should MSBuild & GitLink treat any errors as warnings? 30 | var treatWarningsAsErrors = false; 31 | 32 | // Build configuration 33 | var local = BuildSystem.IsLocalBuild; 34 | var isRunningOnUnix = IsRunningOnUnix(); 35 | var isRunningOnWindows = IsRunningOnWindows(); 36 | 37 | var isRunningOnAppVeyor = AppVeyor.IsRunningOnAppVeyor; 38 | var isPullRequest = AppVeyor.Environment.PullRequest.IsPullRequest; 39 | var isRepository = StringComparer.OrdinalIgnoreCase.Equals("ghuntley/geocoordinate", AppVeyor.Environment.Repository.Name); 40 | 41 | var isReleaseBranch = StringComparer.OrdinalIgnoreCase.Equals("master", AppVeyor.Environment.Repository.Branch); 42 | var isTagged = AppVeyor.Environment.Repository.Tag.IsTag; 43 | 44 | var githubOwner = "ghuntley"; 45 | var githubRepository = "geocoordinate"; 46 | var githubUrl = string.Format("https://github.com/{0}/{1}", githubOwner, githubRepository); 47 | 48 | // Version 49 | var gitVersion = GitVersion(); 50 | var majorMinorPatch = gitVersion.MajorMinorPatch; 51 | var semVersion = gitVersion.SemVer; 52 | var informationalVersion = gitVersion.InformationalVersion; 53 | var nugetVersion = gitVersion.NuGetVersion; 54 | var buildVersion = gitVersion.FullBuildMetaData; 55 | 56 | // Artifacts 57 | var artifactDirectory = "./artifacts/"; 58 | var packageWhitelist = new[] { "GeoCoordinate", "GeoCoordinate.Core", "GeoCoordinate.Deprecated", "GeoCoordinate.Mobile", "GeoCoordinate.Sqlite3" }; 59 | 60 | // Macros 61 | Action Abort = () => { throw new Exception("a non-recoverable fatal error occurred."); }; 62 | 63 | Action RestorePackages = (solution) => 64 | { 65 | NuGetRestore(solution); 66 | }; 67 | 68 | Action Package = (nuspec, basePath) => 69 | { 70 | CreateDirectory(artifactDirectory); 71 | 72 | Information("Packaging {0} using {1} as the BasePath.", nuspec, basePath); 73 | 74 | NuGetPack(nuspec, new NuGetPackSettings { 75 | Authors = new [] { "Geoffrey Huntley" }, 76 | Owners = new [] { "ghuntley" }, 77 | 78 | ProjectUrl = new Uri(githubUrl), 79 | IconUrl = new Uri("https://i.imgur.com/OfoiwTs.png"), 80 | LicenseUrl = new Uri("https://opensource.org/licenses/MS-PL"), 81 | Copyright = "Copyright (c) Geoffrey Huntley", 82 | RequireLicenseAcceptance = false, 83 | 84 | Version = nugetVersion, 85 | Tags = new [] { "GeoCoordinate" ,"GeoCoordinatePortable", "system.device.location.geocoordinate" }, 86 | ReleaseNotes = new [] { string.Format("{0}/releases", githubUrl) }, 87 | 88 | Symbols = false, 89 | Verbosity = NuGetVerbosity.Detailed, 90 | OutputDirectory = artifactDirectory, 91 | BasePath = basePath, 92 | }); 93 | }; 94 | 95 | Action SourceLink = (solutionFileName) => 96 | { 97 | GitLink("./", new GitLinkSettings() { 98 | RepositoryUrl = githubUrl, 99 | SolutionFileName = solutionFileName, 100 | 101 | // nb: I would love to set this to `treatErrorsAsWarnings` which defaults to `false` but GitLink trips over GeoCoordinate.Tests :/ 102 | // Handling project 'GeoCoordinate.Tests' 103 | // No pdb file found for 'GeoCoordinate.Tests', is project built in 'Release' mode with pdb files enabled? Expected file is 'C:\Dropbox\OSS\GeoCoordinate\GeoCoordinate\src\GeoCoordinate.Tests\GeoCoordinate.Tests.pdb' 104 | ErrorsAsWarnings = true, 105 | }); 106 | }; 107 | 108 | 109 | /////////////////////////////////////////////////////////////////////////////// 110 | // SETUP / TEARDOWN 111 | /////////////////////////////////////////////////////////////////////////////// 112 | Setup((context) => 113 | { 114 | Information("Building version {0} of GeoCoordinate. (isTagged: {1})", informationalVersion, isTagged); 115 | }); 116 | 117 | Teardown((context) => 118 | { 119 | // Executed AFTER the last task. 120 | }); 121 | 122 | ////////////////////////////////////////////////////////////////////// 123 | // TASKS 124 | ////////////////////////////////////////////////////////////////////// 125 | 126 | Task("Build") 127 | .IsDependentOn("RestorePackages") 128 | .IsDependentOn("UpdateAssemblyInfo") 129 | .Does (() => 130 | { 131 | Action build = (solution) => 132 | { 133 | // UWP (project.json) needs to be restored before it will build. 134 | RestorePackages(solution); 135 | 136 | Information("Building {0}", solution); 137 | 138 | MSBuild(solution, new MSBuildSettings() 139 | .SetConfiguration("Release") 140 | .WithProperty("NoWarn", "1591") // ignore missing XML doc warnings 141 | .WithProperty("TreatWarningsAsErrors", treatWarningsAsErrors.ToString()) 142 | .SetVerbosity(Verbosity.Minimal) 143 | .SetNodeReuse(false)); 144 | 145 | SourceLink(solution); 146 | }; 147 | 148 | build("./src/GeoCoordinatePortable.sln"); 149 | }); 150 | 151 | Task("UpdateAppVeyorBuildNumber") 152 | .WithCriteria(() => isRunningOnAppVeyor) 153 | .Does(() => 154 | { 155 | AppVeyor.UpdateBuildVersion(buildVersion); 156 | }); 157 | 158 | Task("UpdateAssemblyInfo") 159 | .IsDependentOn("UpdateAppVeyorBuildNumber") 160 | .Does (() => 161 | { 162 | var file = "./src/CommonAssemblyInfo.cs"; 163 | 164 | CreateAssemblyInfo(file, new AssemblyInfoSettings { 165 | Product = "GeoCoordinate", 166 | Version = majorMinorPatch, 167 | FileVersion = majorMinorPatch, 168 | InformationalVersion = informationalVersion, 169 | Copyright = "Copyright (c) Geoffrey Huntley" 170 | }); 171 | }); 172 | 173 | Task("RestorePackages").Does (() => 174 | { 175 | RestorePackages("./src/GeoCoordinatePortable.sln"); 176 | }); 177 | 178 | Task("RunUnitTests") 179 | .IsDependentOn("Build") 180 | .Does(() => 181 | { 182 | XUnit2("./src/GeoCoordinate.Tests/bin/x64/Release/GeoCoordinate.Tests.dll", new XUnit2Settings { 183 | OutputDirectory = artifactDirectory, 184 | XmlReportV1 = false, 185 | NoAppDomain = false 186 | }); 187 | }); 188 | 189 | Task("Package") 190 | .IsDependentOn("Build") 191 | .IsDependentOn("RunUnitTests") 192 | .Does (() => 193 | { 194 | Package("./src/GeoCoordinate.nuspec", "./src/GeoCoordinatePortable"); 195 | }); 196 | 197 | Task("PublishPackages") 198 | .IsDependentOn("RunUnitTests") 199 | .IsDependentOn("Package") 200 | .WithCriteria(() => !local) 201 | .WithCriteria(() => !isPullRequest) 202 | .WithCriteria(() => isRepository) 203 | .Does (() => 204 | { 205 | if (isReleaseBranch && !isTagged) 206 | { 207 | Information("Packages will not be published as this release has not been tagged."); 208 | return; 209 | } 210 | 211 | // Resolve the API key. 212 | var apiKey = EnvironmentVariable("NUGET_APIKEY"); 213 | if (string.IsNullOrEmpty(apiKey)) 214 | { 215 | throw new Exception("The NUGET_APIKEY environment variable is not defined."); 216 | } 217 | 218 | var source = EnvironmentVariable("NUGET_SOURCE"); 219 | if (string.IsNullOrEmpty(source)) 220 | { 221 | throw new Exception("The NUGET_SOURCE environment variable is not defined."); 222 | } 223 | 224 | // only push whitelisted packages. 225 | foreach(var package in packageWhitelist) 226 | { 227 | // only push the package which was created during this build run. 228 | var packagePath = artifactDirectory + File(string.Concat(package, ".", nugetVersion, ".nupkg")); 229 | 230 | // Push the package. 231 | NuGetPush(packagePath, new NuGetPushSettings { 232 | Source = source, 233 | ApiKey = apiKey 234 | }); 235 | } 236 | }); 237 | 238 | Task("CreateRelease") 239 | .IsDependentOn("RunUnitTests") 240 | .IsDependentOn("Package") 241 | .WithCriteria(() => !local) 242 | .WithCriteria(() => !isPullRequest) 243 | .WithCriteria(() => isRepository) 244 | .WithCriteria(() => isReleaseBranch) 245 | .WithCriteria(() => !isTagged) 246 | .Does (() => 247 | { 248 | var username = EnvironmentVariable("GITHUB_USERNAME"); 249 | if (string.IsNullOrEmpty(username)) 250 | { 251 | throw new Exception("The GITHUB_USERNAME environment variable is not defined."); 252 | } 253 | 254 | var token = EnvironmentVariable("GITHUB_TOKEN"); 255 | if (string.IsNullOrEmpty(token)) 256 | { 257 | throw new Exception("The GITHUB_TOKEN environment variable is not defined."); 258 | } 259 | 260 | GitReleaseManagerCreate(username, token, githubOwner, githubRepository, new GitReleaseManagerCreateSettings { 261 | Milestone = majorMinorPatch, 262 | Name = majorMinorPatch, 263 | Prerelease = true, 264 | TargetCommitish = "master" 265 | }); 266 | }); 267 | 268 | Task("PublishRelease") 269 | .IsDependentOn("RunUnitTests") 270 | .IsDependentOn("Package") 271 | .WithCriteria(() => !local) 272 | .WithCriteria(() => !isPullRequest) 273 | .WithCriteria(() => isRepository) 274 | .WithCriteria(() => isReleaseBranch) 275 | .WithCriteria(() => isTagged) 276 | .Does (() => 277 | { 278 | var username = EnvironmentVariable("GITHUB_USERNAME"); 279 | if (string.IsNullOrEmpty(username)) 280 | { 281 | throw new Exception("The GITHUB_USERNAME environment variable is not defined."); 282 | } 283 | 284 | var token = EnvironmentVariable("GITHUB_TOKEN"); 285 | if (string.IsNullOrEmpty(token)) 286 | { 287 | throw new Exception("The GITHUB_TOKEN environment variable is not defined."); 288 | } 289 | 290 | // only push whitelisted packages. 291 | foreach(var package in packageWhitelist) 292 | { 293 | // only push the package which was created during this build run. 294 | var packagePath = artifactDirectory + File(string.Concat(package, ".", nugetVersion, ".nupkg")); 295 | 296 | GitReleaseManagerAddAssets(username, token, githubOwner, githubRepository, majorMinorPatch, packagePath); 297 | } 298 | 299 | GitReleaseManagerClose(username, token, githubOwner, githubRepository, majorMinorPatch); 300 | }); 301 | 302 | ////////////////////////////////////////////////////////////////////// 303 | // TASK TARGETS 304 | ////////////////////////////////////////////////////////////////////// 305 | 306 | Task("Default") 307 | .IsDependentOn("CreateRelease") 308 | .IsDependentOn("PublishPackages") 309 | .IsDependentOn("PublishRelease") 310 | .Does (() => 311 | { 312 | 313 | }); 314 | 315 | 316 | ////////////////////////////////////////////////////////////////////// 317 | // EXECUTION 318 | ////////////////////////////////////////////////////////////////////// 319 | 320 | RunTarget(target); 321 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | tools\nuget\nuget.exe update -self 3 | tools\nuget\nuget.exe install xunit.runner.console -OutputDirectory tools -ExcludeVersion 4 | tools\nuget\nuget.exe install Cake -OutputDirectory tools -ExcludeVersion 5 | 6 | tools\Cake\Cake.exe build.cake --target=%1 7 | 8 | exit /b %errorlevel% 9 | -------------------------------------------------------------------------------- /contrib/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghuntley/geocoordinate/b8c4d99c738bcbd1e86114c9174bf7e179c22e7a/contrib/.gitkeep -------------------------------------------------------------------------------- /licenses/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghuntley/geocoordinate/b8c4d99c738bcbd1e86114c9174bf7e179c22e7a/licenses/.gitkeep -------------------------------------------------------------------------------- /src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghuntley/geocoordinate/b8c4d99c738bcbd1e86114c9174bf7e179c22e7a/src/.gitkeep -------------------------------------------------------------------------------- /src/CommonSolutionInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyProductAttribute("GeoCoordinate")] 6 | [assembly: AssemblyVersionAttribute("0.1.0")] 7 | [assembly: AssemblyFileVersionAttribute("0.1.0")] 8 | [assembly: ComVisibleAttribute(false)] 9 | namespace System { 10 | internal static class AssemblyVersionInformation { 11 | internal const string Version = "0.1.0"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/GeoCoordinate.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $$version$$ 5 | 6 | 7 | 8 | 9 | 10 | GeoCoordinate 11 | GeoCoordinate 12 | GeoCoordinate is a portable class library (in v1.1.x) or netstandard v1.1 (from v2.x.x) implementation of System.Device.Location.GeoCoordinate. It is an exact 1:1 API compliant implementation and will be supported until MSFT sees it fit to embed the type. Which at that point this implementation will cease development/support and you will be able to simply remove this package and everything will still work. 13 | GeoCoordinate is a portable class library (in v1.1.x) or netstandard v1.1 (from v2.x.x) implementation of System.Device.Location.GeoCoordinate. It is an exact 1:1 API compliant implementation and will be supported until MSFT sees it fit to embed the type. Which at that point this implementation will cease development/support and you will be able to simply remove this package and everything will still work. 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/GeoCoordinatePortable.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoCoordinatePortable", "GeoCoordinatePortable\GeoCoordinatePortable.csproj", "{3F8D76E7-1AF6-40F5-960F-13C4DFA80935}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4DB8F23A-14DF-429C-88F4-7FD3B21FFDD8}" 9 | ProjectSection(SolutionItems) = preProject 10 | ..\.gitattributes = ..\.gitattributes 11 | ..\.gitignore = ..\.gitignore 12 | ..\appveyor.yaml = ..\appveyor.yaml 13 | ..\build.cmd = ..\build.cmd 14 | ..\build.fsx = ..\build.fsx 15 | ..\build.sh = ..\build.sh 16 | ..\DEPLOYMENT.md = ..\DEPLOYMENT.md 17 | GeoCoordinate.nuspec = GeoCoordinate.nuspec 18 | ..\LICENSE.md = ..\LICENSE.md 19 | ..\README.md = ..\README.md 20 | ..\RELEASENOTES.md = ..\RELEASENOTES.md 21 | SolutionInfo.cs = SolutionInfo.cs 22 | EndProjectSection 23 | EndProject 24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoCoordinatePortableTests", "GeoCoordinatePortableTests\GeoCoordinatePortableTests.csproj", "{DA4A4A8E-A3AE-4630-AE81-3F944E407532}" 25 | EndProject 26 | Global 27 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 28 | Debug|Any CPU = Debug|Any CPU 29 | Release|Any CPU = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 32 | {3F8D76E7-1AF6-40F5-960F-13C4DFA80935}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {3F8D76E7-1AF6-40F5-960F-13C4DFA80935}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {3F8D76E7-1AF6-40F5-960F-13C4DFA80935}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {3F8D76E7-1AF6-40F5-960F-13C4DFA80935}.Release|Any CPU.Build.0 = Release|Any CPU 36 | {DA4A4A8E-A3AE-4630-AE81-3F944E407532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {DA4A4A8E-A3AE-4630-AE81-3F944E407532}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {DA4A4A8E-A3AE-4630-AE81-3F944E407532}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {DA4A4A8E-A3AE-4630-AE81-3F944E407532}.Release|Any CPU.Build.0 = Release|Any CPU 40 | EndGlobalSection 41 | GlobalSection(SolutionProperties) = preSolution 42 | HideSolutionNode = FALSE 43 | EndGlobalSection 44 | EndGlobal 45 | -------------------------------------------------------------------------------- /src/GeoCoordinatePortable/GeoCoordinate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace GeoCoordinatePortable 5 | { 6 | /// 7 | /// Represents a geographical location that is determined by latitude and longitude 8 | /// coordinates. May also include altitude, accuracy, speed, and course information. 9 | /// 10 | public class GeoCoordinate : IEquatable 11 | { 12 | /// 13 | /// Represents a object that has unknown latitude and longitude fields. 14 | /// 15 | public static readonly GeoCoordinate Unknown = new GeoCoordinate(); 16 | private double _course; 17 | private double _horizontalAccuracy; 18 | private double _latitude; 19 | private double _longitude; 20 | private double _speed; 21 | private double _verticalAccuracy; 22 | 23 | /// 24 | /// Initializes a new instance of GeoCoordinate that has no data fields set. 25 | /// 26 | public GeoCoordinate() 27 | : this(double.NaN, double.NaN) 28 | { 29 | } 30 | 31 | /// 32 | /// Initializes a new instance of the GeoCoordinate class from latitude and longitude data. 33 | /// 34 | /// The latitude of the location. May range from -90.0 to 90.0. 35 | /// The longitude of the location. May range from -180.0 to 180.0. 36 | /// Latitude or longitude is out of range. 37 | public GeoCoordinate(double latitude, double longitude) 38 | : this(latitude, longitude, double.NaN) 39 | { 40 | } 41 | 42 | /// 43 | /// Initializes a new instance of the GeoCoordinate class from latitude, longitude, and altitude data. 44 | /// 45 | /// Latitude. May range from -90.0 to 90.0. 46 | /// Longitude. May range from -180.0 to 180.0 47 | /// The altitude in meters. May be negative, 0, positive, or Double.NaN, if unknown. 48 | /// 49 | /// latitude, longitude or altitude is out of range. 50 | /// 51 | public GeoCoordinate(double latitude, double longitude, double altitude) 52 | : this(latitude, longitude, altitude, double.NaN, double.NaN, double.NaN, double.NaN) 53 | { 54 | } 55 | 56 | /// 57 | /// Initializes a new instance of the GeoCoordinate class from latitude, longitude, altitude, horizontal accuracy, 58 | /// vertical accuracy, speed, and course. 59 | /// 60 | /// The latitude of the location. May range from -90.0 to 90.0. 61 | /// The longitude of the location. May range from -180.0 to 180.0. 62 | /// The altitude in meters. May be negative, 0, positive, or Double.NaN, if unknown. 63 | /// 64 | /// The accuracy of the latitude and longitude coordinates, in meters. Must be greater 65 | /// than or equal to 0. If a value of 0 is supplied to this constructor, the HorizontalAccuracy property will be set to 66 | /// Double.NaN. 67 | /// 68 | /// 69 | /// The accuracy of the altitude, in meters. Must be greater than or equal to 0. If a value 70 | /// of 0 is supplied to this constructor, the VerticalAccuracy property will be set to Double.NaN. 71 | /// 72 | /// 73 | /// The speed measured in meters per second. May be negative, 0, positive, or Double.NaN, if unknown. 74 | /// A negative speed can indicate moving in reverse. 75 | /// 76 | /// 77 | /// The direction of travel, rather than orientation. This parameter is measured in degrees relative 78 | /// to true north. Must range from 0 to 360.0, or be Double.NaN. 79 | /// 80 | /// 81 | /// If latitude, longitude, horizontalAccuracy, verticalAccuracy, course is out of range. 82 | /// 83 | public GeoCoordinate(double latitude, double longitude, double altitude, double horizontalAccuracy, 84 | double verticalAccuracy, double speed, double course) 85 | { 86 | Latitude = latitude; 87 | Longitude = longitude; 88 | Altitude = altitude; 89 | HorizontalAccuracy = horizontalAccuracy; 90 | VerticalAccuracy = verticalAccuracy; 91 | Speed = speed; 92 | Course = course; 93 | } 94 | 95 | /// 96 | /// Gets or sets the latitude of the GeoCoordinate. 97 | /// 98 | /// 99 | /// Latitude of the location. 100 | /// 101 | /// Latitude is set outside the valid range. 102 | public double Latitude 103 | { 104 | get { return _latitude; } 105 | set 106 | { 107 | if (value > 90.0 || value < -90.0) 108 | { 109 | throw new ArgumentOutOfRangeException("Latitude", "Argument must be in range of -90 to 90"); 110 | } 111 | _latitude = value; 112 | } 113 | } 114 | 115 | /// 116 | /// Gets or sets the longitude of the GeoCoordinate. 117 | /// 118 | /// 119 | /// The longitude. 120 | /// 121 | /// Longitude is set outside the valid range. 122 | public double Longitude 123 | { 124 | get { return _longitude; } 125 | set 126 | { 127 | if (value > 180.0 || value < -180.0) 128 | { 129 | throw new ArgumentOutOfRangeException("Longitude", "Argument must be in range of -180 to 180"); 130 | } 131 | _longitude = value; 132 | } 133 | } 134 | 135 | /// 136 | /// Gets or sets the accuracy of the latitude and longitude that is given by the GeoCoordinate, in meters. 137 | /// 138 | /// 139 | /// The accuracy of the latitude and longitude, in meters. 140 | /// 141 | /// HorizontalAccuracy is set outside the valid range. 142 | public double HorizontalAccuracy 143 | { 144 | get { return _horizontalAccuracy; } 145 | set 146 | { 147 | if (value < 0.0) 148 | throw new ArgumentOutOfRangeException("HorizontalAccuracy", "Argument must be non negative"); 149 | _horizontalAccuracy = value == 0.0 ? double.NaN : value; 150 | } 151 | } 152 | 153 | /// 154 | /// Gets or sets the accuracy of the altitude given by the GeoCoordinate, in meters. 155 | /// 156 | /// 157 | /// The accuracy of the altitude, in meters. 158 | /// 159 | /// VerticalAccuracy is set outside the valid range. 160 | public double VerticalAccuracy 161 | { 162 | get { return _verticalAccuracy; } 163 | set 164 | { 165 | if (value < 0.0) 166 | throw new ArgumentOutOfRangeException("VerticalAccuracy", "Argument must be non negative"); 167 | _verticalAccuracy = value == 0.0 ? double.NaN : value; 168 | } 169 | } 170 | 171 | /// 172 | /// Gets or sets the speed in meters per second. 173 | /// 174 | /// 175 | /// The speed in meters per second. The speed must be greater than or equal to zero, or Double.NaN. 176 | /// 177 | /// Speed is set outside the valid range. 178 | public double Speed 179 | { 180 | get { return _speed; } 181 | set 182 | { 183 | if (value < 0.0) 184 | throw new ArgumentOutOfRangeException("speed", "Argument must be non negative"); 185 | _speed = value; 186 | } 187 | } 188 | 189 | /// 190 | /// Gets or sets the heading in degrees, relative to true north. 191 | /// 192 | /// 193 | /// The heading in degrees, relative to true north. 194 | /// 195 | /// Course is set outside the valid range. 196 | public double Course 197 | { 198 | get { return _course; } 199 | set 200 | { 201 | if (value < 0.0 || value > 360.0) 202 | throw new ArgumentOutOfRangeException("course", "Argument must be in range 0 to 360"); 203 | _course = value; 204 | } 205 | } 206 | 207 | /// 208 | /// Gets a value that indicates whether the GeoCoordinate does not contain latitude or longitude data. 209 | /// 210 | /// 211 | /// true if the GeoCoordinate does not contain latitude or longitude data; otherwise, false. 212 | /// 213 | public bool IsUnknown => Equals(Unknown); 214 | 215 | /// 216 | /// Gets the altitude of the GeoCoordinate, in meters. 217 | /// 218 | /// 219 | /// The altitude, in meters. 220 | /// 221 | public double Altitude { get; set; } 222 | 223 | /// 224 | /// Determines if the GeoCoordinate object is equivalent to the parameter, based solely on latitude and longitude. 225 | /// 226 | /// 227 | /// true if the GeoCoordinate objects are equal; otherwise, false. 228 | /// 229 | /// The GeoCoordinate object to compare to the calling object. 230 | public bool Equals(GeoCoordinate other) 231 | { 232 | if (ReferenceEquals(other, null)) 233 | return false; 234 | 235 | var num = Latitude; 236 | 237 | if (!num.Equals(other.Latitude)) 238 | return false; 239 | 240 | num = Longitude; 241 | 242 | return num.Equals(other.Longitude); 243 | } 244 | 245 | /// 246 | /// Determines whether two GeoCoordinate objects refer to the same location. 247 | /// 248 | /// 249 | /// true, if the GeoCoordinate objects are determined to be equivalent; otherwise, false. 250 | /// 251 | /// The first GeoCoordinate to compare. 252 | /// The second GeoCoordinate to compare. 253 | public static bool operator ==(GeoCoordinate left, GeoCoordinate right) 254 | { 255 | if (ReferenceEquals(left, null)) 256 | return ReferenceEquals(right, null); 257 | 258 | return left.Equals(right); 259 | } 260 | 261 | /// 262 | /// Determines whether two GeoCoordinate objects correspond to different locations. 263 | /// 264 | /// 265 | /// true, if the GeoCoordinate objects are determined to be different; otherwise, false. 266 | /// 267 | /// The first GeoCoordinate to compare. 268 | /// The second GeoCoordinate to compare. 269 | public static bool operator !=(GeoCoordinate left, GeoCoordinate right) 270 | { 271 | return !(left == right); 272 | } 273 | 274 | /// 275 | /// Returns the distance between the latitude and longitude coordinates that are specified by this GeoCoordinate and 276 | /// another specified GeoCoordinate. 277 | /// 278 | /// 279 | /// The distance between the two coordinates, in meters. 280 | /// 281 | /// The GeoCoordinate for the location to calculate the distance to. 282 | public double GetDistanceTo(GeoCoordinate other) 283 | { 284 | if (double.IsNaN(Latitude) || double.IsNaN(Longitude) || double.IsNaN(other.Latitude) || 285 | double.IsNaN(other.Longitude)) 286 | { 287 | throw new ArgumentException("Argument latitude or longitude is not a number"); 288 | } 289 | 290 | var d1 = Latitude * (Math.PI / 180.0); 291 | var num1 = Longitude * (Math.PI / 180.0); 292 | var d2 = other.Latitude * (Math.PI / 180.0); 293 | var num2 = other.Longitude * (Math.PI / 180.0) - num1; 294 | var d3 = Math.Pow(Math.Sin((d2 - d1) / 2.0), 2.0) + 295 | Math.Cos(d1) * Math.Cos(d2) * Math.Pow(Math.Sin(num2 / 2.0), 2.0); 296 | 297 | return 6376500.0 * (2.0 * Math.Atan2(Math.Sqrt(d3), Math.Sqrt(1.0 - d3))); 298 | } 299 | 300 | /// 301 | /// Serves as a hash function for the GeoCoordinate. 302 | /// 303 | /// 304 | /// A hash code for the current GeoCoordinate. 305 | /// 306 | public override int GetHashCode() 307 | { 308 | return Latitude.GetHashCode() ^ Longitude.GetHashCode(); 309 | } 310 | 311 | /// 312 | /// Determines if a specified GeoCoordinate is equal to the current GeoCoordinate, based solely on latitude and 313 | /// longitude. 314 | /// 315 | /// 316 | /// true, if the GeoCoordinate objects are equal; otherwise, false. 317 | /// 318 | /// The object to compare the GeoCoordinate to. 319 | public override bool Equals(object obj) 320 | { 321 | return Equals(obj as GeoCoordinate); 322 | } 323 | 324 | /// 325 | /// Returns a string that contains the latitude and longitude. 326 | /// 327 | /// 328 | /// A string that contains the latitude and longitude, separated by a comma. 329 | /// 330 | public override string ToString() 331 | { 332 | if (this == Unknown) 333 | { 334 | return "Unknown"; 335 | } 336 | 337 | return 338 | $"{Latitude.ToString("G", CultureInfo.InvariantCulture)}, {Longitude.ToString("G", CultureInfo.InvariantCulture)}"; 339 | } 340 | } 341 | } -------------------------------------------------------------------------------- /src/GeoCoordinatePortable/GeoCoordinatePortable.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 14.0 6 | Debug 7 | AnyCPU 8 | {3F8D76E7-1AF6-40F5-960F-13C4DFA80935} 9 | Library 10 | Properties 11 | GeoCoordinatePortable 12 | GeoCoordinatePortable 13 | en-US 14 | 512 15 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 16 | 17 | 18 | v5.0 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Release\netstandard1.1\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | bin\Release\netstandard1.1\GeoCoordinatePortable.XML 29 | 30 | 31 | pdbonly 32 | true 33 | bin\Release\netstandard1.1\ 34 | TRACE 35 | prompt 36 | 4 37 | bin\Release\netstandard1.1\GeoCoordinatePortable.xml 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 56 | -------------------------------------------------------------------------------- /src/GeoCoordinatePortable/GeoPosition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeoCoordinatePortable 4 | { 5 | /// 6 | /// Contains location data of a type specified by the type parameter of the class 7 | /// 8 | /// The type of the location data. 9 | public class GeoPosition 10 | { 11 | /// 12 | /// Initializes a new instance of the class. 13 | /// 14 | public GeoPosition() 15 | { 16 | } 17 | 18 | /// 19 | /// Initializes a new instance of the class 20 | /// with a timestamp and position. 21 | /// 22 | /// The time the location data was obtained. 23 | /// The location data to use to initialize the object. 24 | public GeoPosition(DateTimeOffset timestamp, T location) 25 | { 26 | Timestamp = timestamp; 27 | Location = location; 28 | } 29 | 30 | /// 31 | /// Gets or sets the location data for the object. 32 | /// 33 | /// 34 | /// An object of type T that contains the location data for the object. 35 | /// 36 | public T Location { get; set; } 37 | 38 | /// 39 | /// Gets or sets the time when the location data was obtained. 40 | /// 41 | /// 42 | /// A that contains the time the location data was created. 43 | /// 44 | public DateTimeOffset Timestamp { get; set; } 45 | } 46 | } -------------------------------------------------------------------------------- /src/GeoCoordinatePortable/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("GeoCoordinate")] 9 | [assembly: 10 | AssemblyDescription( 11 | "GeoCoordinate is a Portable Class Library compatible implementation of System.Device.Location.GeoCoordinate. It is an exact 1:1 API compliant implementation and will be supported until MSFT sees it fit to embed the type. Which at that point this implementation will cease development/support and you will be able to simply remove this package and everything will still work." 12 | )] 13 | [assembly: AssemblyConfiguration("")] 14 | [assembly: AssemblyCompany("https://ghuntley.com/; ghuntley@ghuntley.com")] 15 | [assembly: AssemblyProduct("GeoCoordinate")] 16 | [assembly: AssemblyCopyright("Copyright © Geoffrey Huntley 2016")] 17 | [assembly: AssemblyTrademark("")] 18 | [assembly: AssemblyCulture("")] 19 | [assembly: NeutralResourcesLanguage("en")] 20 | 21 | // Version information for an assembly consists of the following four values: 22 | // 23 | // Major Version 24 | // Minor Version 25 | // Build Number 26 | // Revision 27 | // 28 | // You can specify all the values or you can default the Build and Revision Numbers 29 | // by using the '*' as shown below: 30 | // [assembly: AssemblyVersion("1.0.*")] 31 | 32 | [assembly: AssemblyVersion("1.0.0.0")] 33 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /src/GeoCoordinatePortable/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "supports": {}, 3 | "dependencies": { 4 | "Microsoft.NETCore.Portable.Compatibility": "1.0.1", 5 | "NETStandard.Library": "1.6.0" 6 | }, 7 | "frameworks": { 8 | "netstandard1.1": {} 9 | } 10 | } -------------------------------------------------------------------------------- /src/GeoCoordinatePortableTests/Assert.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GeoCoordinatePortableTests.Assertations 4 | { 5 | public static class Assert 6 | { 7 | public static T Throws(Action action) where T : Exception 8 | { 9 | try 10 | { 11 | action(); 12 | } 13 | catch (Exception ex) 14 | { 15 | var exOfT = ex as T; 16 | 17 | if (exOfT != null) 18 | return exOfT; 19 | 20 | throw; 21 | } 22 | 23 | throw new Microsoft.VisualStudio.TestTools.UnitTesting.AssertFailedException("Expected to throw " + typeof(T).Name + "."); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/GeoCoordinatePortableTests/GeoCoordinatePortableTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {DA4A4A8E-A3AE-4630-AE81-3F944E407532} 7 | Library 8 | Properties 9 | GeoCoordinatePortableTests 10 | GeoCoordinatePortableTests 11 | v4.5 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | {3F8D76E7-1AF6-40F5-960F-13C4DFA80935} 61 | GeoCoordinatePortable 62 | 63 | 64 | 65 | 66 | 67 | 68 | False 69 | 70 | 71 | False 72 | 73 | 74 | False 75 | 76 | 77 | False 78 | 79 | 80 | 81 | 82 | 83 | 84 | 91 | -------------------------------------------------------------------------------- /src/GeoCoordinatePortableTests/GeoCoordinateTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | //using System.Device.Location; 3 | using GeoCoordinatePortable; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace GeoCoordinatePortableTests 7 | { 8 | [TestClass] 9 | public class GeoCoordinateTests 10 | { 11 | private GeoCoordinate _UnitUnderTest; 12 | 13 | [TestMethod] 14 | public void GeoCoordinate_ConstructorWithDefaultValues_DoesNotThrow() 15 | { 16 | _UnitUnderTest = new GeoCoordinate(Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN); 17 | } 18 | 19 | [TestMethod] 20 | public void GeoCoordinate_ConstructorWithParameters_ReturnsInstanceWithExpectedValues() 21 | { 22 | var latitude = 42D; 23 | var longitude = 44D; 24 | var altitude = 46D; 25 | var horizontalAccuracy = 48D; 26 | var verticalAccuracy = 50D; 27 | var speed = 52D; 28 | var course = 54D; 29 | var isUnknown = false; 30 | _UnitUnderTest = new GeoCoordinate(latitude, longitude, altitude, horizontalAccuracy, verticalAccuracy, speed, course); 31 | 32 | Assert.AreEqual(latitude, _UnitUnderTest.Latitude); 33 | Assert.AreEqual(longitude, _UnitUnderTest.Longitude); 34 | Assert.AreEqual(altitude, _UnitUnderTest.Altitude); 35 | Assert.AreEqual(horizontalAccuracy, _UnitUnderTest.HorizontalAccuracy); 36 | Assert.AreEqual(verticalAccuracy, _UnitUnderTest.VerticalAccuracy); 37 | Assert.AreEqual(speed, _UnitUnderTest.Speed); 38 | Assert.AreEqual(course, _UnitUnderTest.Course); 39 | Assert.AreEqual(isUnknown, _UnitUnderTest.IsUnknown); 40 | } 41 | 42 | [TestMethod] 43 | public void GeoCoordinate_DefaultConstructor_ReturnsInstanceWithDefaultValues() 44 | { 45 | Assert.AreEqual(Double.NaN, _UnitUnderTest.Altitude); 46 | Assert.AreEqual(Double.NaN, _UnitUnderTest.Course); 47 | Assert.AreEqual(Double.NaN, _UnitUnderTest.HorizontalAccuracy); 48 | Assert.IsTrue(_UnitUnderTest.IsUnknown); 49 | Assert.AreEqual(Double.NaN, _UnitUnderTest.Latitude); 50 | Assert.AreEqual(Double.NaN, _UnitUnderTest.Longitude); 51 | Assert.AreEqual(Double.NaN, _UnitUnderTest.Speed); 52 | Assert.AreEqual(Double.NaN, _UnitUnderTest.VerticalAccuracy); 53 | } 54 | 55 | [TestMethod] 56 | public void GeoCoordinate_EqualsOperatorWithNullParameters_DoesNotThrow() 57 | { 58 | GeoCoordinate first = null; 59 | GeoCoordinate second = null; 60 | Assert.IsTrue(first == second); 61 | 62 | first = new GeoCoordinate(); 63 | Assert.IsFalse(first == second); 64 | 65 | first = null; 66 | second = new GeoCoordinate(); 67 | Assert.IsFalse(first == second); 68 | } 69 | 70 | [TestMethod] 71 | public void GeoCoordinate_EqualsTwoInstancesWithDifferentValuesExceptLongitudeAndLatitude_ReturnsTrue() 72 | { 73 | var first = new GeoCoordinate(11, 12, 13, 14, 15, 16, 17); 74 | var second = new GeoCoordinate(11, 12, 14, 15, 16, 17, 18); 75 | 76 | Assert.IsTrue(first.Equals(second)); 77 | } 78 | 79 | [TestMethod] 80 | public void GeoCoordinate_EqualsTwoInstancesWithSameValues_ReturnsTrue() 81 | { 82 | var first = new GeoCoordinate(11, 12, 13, 14, 15, 16, 17); 83 | var second = new GeoCoordinate(11, 12, 13, 14, 15, 16, 17); 84 | 85 | Assert.IsTrue(first.Equals(second)); 86 | } 87 | 88 | [TestMethod] 89 | public void GeoCoordinate_EqualsWithOtherTypes_ReturnsFalse() 90 | { 91 | var something = new Nullable(42); 92 | Assert.IsFalse(_UnitUnderTest.Equals(something)); 93 | } 94 | 95 | [TestMethod] 96 | public void GeoCoordinate_GetDistanceTo_ReturnsExpectedDistance() 97 | { 98 | var start = new GeoCoordinate(1, 1); 99 | var end = new GeoCoordinate(5, 5); 100 | var distance = start.GetDistanceTo(end); 101 | var expected = 629060.759879635; 102 | var delta = distance - expected; 103 | 104 | Assert.IsTrue(delta < 1e-8); 105 | } 106 | 107 | [TestMethod] 108 | public void GeoCoordinate_GetDistanceToWithNaNCoordinates_ThrowsArgumentException() 109 | { 110 | Assertations.Assert.Throws(() => new GeoCoordinate(Double.NaN, 1).GetDistanceTo(new GeoCoordinate(5, 5))); 111 | Assertations.Assert.Throws(() => new GeoCoordinate(1, Double.NaN).GetDistanceTo(new GeoCoordinate(5, 5))); 112 | Assertations.Assert.Throws(() => new GeoCoordinate(1, 1).GetDistanceTo(new GeoCoordinate(Double.NaN, 5))); 113 | Assertations.Assert.Throws(() => new GeoCoordinate(1, 1).GetDistanceTo(new GeoCoordinate(5, Double.NaN))); 114 | } 115 | 116 | [TestMethod] 117 | public void GeoCoordinate_GetHashCode_OnlyReactsOnLongitudeAndLatitude() 118 | { 119 | _UnitUnderTest.Latitude = 2; 120 | _UnitUnderTest.Longitude = 3; 121 | var firstHash = _UnitUnderTest.GetHashCode(); 122 | 123 | _UnitUnderTest.Altitude = 4; 124 | _UnitUnderTest.Course = 5; 125 | _UnitUnderTest.HorizontalAccuracy = 6; 126 | _UnitUnderTest.Speed = 7; 127 | _UnitUnderTest.VerticalAccuracy = 8; 128 | var secondHash = _UnitUnderTest.GetHashCode(); 129 | 130 | Assert.AreEqual(firstHash, secondHash); 131 | } 132 | 133 | [TestMethod] 134 | public void GeoCoordinate_GetHashCode_SwitchingLongitudeAndLatitudeReturnsSameHashCodes() 135 | { 136 | _UnitUnderTest.Latitude = 2; 137 | _UnitUnderTest.Longitude = 3; 138 | var firstHash = _UnitUnderTest.GetHashCode(); 139 | 140 | _UnitUnderTest.Latitude = 3; 141 | _UnitUnderTest.Longitude = 2; 142 | var secondHash = _UnitUnderTest.GetHashCode(); 143 | 144 | Assert.AreEqual(firstHash, secondHash); 145 | } 146 | 147 | [TestMethod] 148 | public void GeoCoordinate_IsUnknownIfLongitudeAndLatitudeIsNaN_ReturnsTrue() 149 | { 150 | _UnitUnderTest.Longitude = 1; 151 | _UnitUnderTest.Latitude = Double.NaN; 152 | Assert.IsFalse(_UnitUnderTest.IsUnknown); 153 | 154 | _UnitUnderTest.Longitude = Double.NaN; 155 | _UnitUnderTest.Latitude = 1; 156 | Assert.IsFalse(_UnitUnderTest.IsUnknown); 157 | 158 | _UnitUnderTest.Longitude = Double.NaN; 159 | _UnitUnderTest.Latitude = Double.NaN; 160 | Assert.IsTrue(_UnitUnderTest.IsUnknown); 161 | } 162 | 163 | [TestMethod] 164 | public void GeoCoordinate_NotEqualsOperatorWithNullParameters_DoesNotThrow() 165 | { 166 | GeoCoordinate first = null; 167 | GeoCoordinate second = null; 168 | Assert.IsFalse(first != second); 169 | 170 | first = new GeoCoordinate(); 171 | Assert.IsTrue(first != second); 172 | 173 | first = null; 174 | second = new GeoCoordinate(); 175 | Assert.IsTrue(first != second); 176 | } 177 | 178 | [TestMethod] 179 | public void GeoCoordinate_SetAltitude_ReturnsCorrectValue() 180 | { 181 | Assert.AreEqual(_UnitUnderTest.Altitude, Double.NaN); 182 | 183 | _UnitUnderTest.Altitude = 0; 184 | Assert.AreEqual(0, _UnitUnderTest.Altitude); 185 | 186 | _UnitUnderTest.Altitude = Double.MinValue; 187 | Assert.AreEqual(Double.MinValue, _UnitUnderTest.Altitude); 188 | 189 | _UnitUnderTest.Altitude = Double.MaxValue; 190 | Assert.AreEqual(Double.MaxValue, _UnitUnderTest.Altitude); 191 | } 192 | 193 | [TestMethod] 194 | public void GeoCoordinate_SetCourse_ThrowsOnInvalidValues() 195 | { 196 | Assertations.Assert.Throws(() => _UnitUnderTest.Course = -0.1); 197 | Assertations.Assert.Throws(() => _UnitUnderTest.Course = 360.1); 198 | Assertations.Assert.Throws(() => new GeoCoordinate(Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, -0.1)); 199 | Assertations.Assert.Throws(() => new GeoCoordinate(Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, 360.1)); 200 | } 201 | 202 | [TestMethod] 203 | public void GeoCoordinate_SetHorizontalAccuracy_ThrowsOnInvalidValues() 204 | { 205 | Assertations.Assert.Throws(() => _UnitUnderTest.HorizontalAccuracy = -0.1); 206 | Assertations.Assert.Throws(() => new GeoCoordinate(Double.NaN, Double.NaN, Double.NaN, -0.1, Double.NaN, Double.NaN, Double.NaN)); 207 | } 208 | 209 | [TestMethod] 210 | public void GeoCoordinate_SetHorizontalAccuracyToZero_ReturnsNaNInProperty() 211 | { 212 | _UnitUnderTest = new GeoCoordinate(Double.NaN, Double.NaN, Double.NaN, 0, Double.NaN, Double.NaN, Double.NaN); 213 | Assert.AreEqual(Double.NaN, _UnitUnderTest.HorizontalAccuracy); 214 | } 215 | 216 | [TestMethod] 217 | public void GeoCoordinate_SetLatitude_ThrowsOnInvalidValues() 218 | { 219 | Assertations.Assert.Throws(() => _UnitUnderTest.Latitude = 90.1); 220 | Assertations.Assert.Throws(() => _UnitUnderTest.Latitude = -90.1); 221 | Assertations.Assert.Throws(() => new GeoCoordinate(90.1, Double.NaN)); 222 | Assertations.Assert.Throws(() => new GeoCoordinate(-90.1, Double.NaN)); 223 | } 224 | 225 | [TestMethod] 226 | public void GeoCoordinate_SetLongitude_ThrowsOnInvalidValues() 227 | { 228 | Assertations.Assert.Throws(() => _UnitUnderTest.Longitude = 180.1); 229 | Assertations.Assert.Throws(() => _UnitUnderTest.Longitude = -180.1); 230 | Assertations.Assert.Throws(() => new GeoCoordinate(Double.NaN, 180.1)); 231 | Assertations.Assert.Throws(() => new GeoCoordinate(Double.NaN, -180.1)); 232 | } 233 | 234 | [TestMethod] 235 | public void GeoCoordinate_SetSpeed_ThrowsOnInvalidValues() 236 | { 237 | Assertations.Assert.Throws(() => _UnitUnderTest.Speed = -0.1); 238 | Assertations.Assert.Throws(() => new GeoCoordinate(Double.NaN, Double.NaN, Double.NaN, Double.NaN, Double.NaN, -1, Double.NaN)); 239 | } 240 | 241 | [TestMethod] 242 | public void GeoCoordinate_SetVerticalAccuracy_ThrowsOnInvalidValues() 243 | { 244 | Assertations.Assert.Throws(() => _UnitUnderTest.VerticalAccuracy = -0.1); 245 | Assertations.Assert.Throws(() => new GeoCoordinate(Double.NaN, Double.NaN, Double.NaN, Double.NaN, -0.1, Double.NaN, Double.NaN)); 246 | } 247 | 248 | [TestMethod] 249 | public void GeoCoordinate_SetVerticalAccuracyToZero_ReturnsNaNInProperty() 250 | { 251 | _UnitUnderTest = new GeoCoordinate(Double.NaN, Double.NaN, Double.NaN, Double.NaN, 0, Double.NaN, Double.NaN); 252 | Assert.AreEqual(Double.NaN, _UnitUnderTest.VerticalAccuracy); 253 | } 254 | 255 | [TestMethod] 256 | public void GeoCoordinate_ToString_ReturnsLongitudeAndLatitude() 257 | { 258 | Assert.AreEqual("Unknown", _UnitUnderTest.ToString()); 259 | 260 | _UnitUnderTest.Latitude = 1; 261 | _UnitUnderTest.Longitude = Double.NaN; 262 | Assert.AreEqual("1, NaN", _UnitUnderTest.ToString()); 263 | 264 | _UnitUnderTest.Latitude = Double.NaN; 265 | _UnitUnderTest.Longitude = 1; 266 | Assert.AreEqual("NaN, 1", _UnitUnderTest.ToString()); 267 | } 268 | 269 | [TestInitialize] 270 | public void Initialize() 271 | { 272 | _UnitUnderTest = new GeoCoordinate(); 273 | } 274 | } 275 | } -------------------------------------------------------------------------------- /src/GeoCoordinatePortableTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GeoCoordinatePortableTests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("FEV GmbH")] 12 | [assembly: AssemblyProduct("GeoCoordinatePortableTests")] 13 | [assembly: AssemblyCopyright("Copyright © FEV GmbH 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("c80faa3e-cad2-4a35-ae90-1a3366f575f4")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/SolutionInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System.Reflection; 3 | using System.Resources; 4 | using System.Runtime.InteropServices; 5 | 6 | 7 | [assembly: AssemblyTitle("GeoCoordinatePortable")] 8 | [assembly: 9 | AssemblyDescription( 10 | "GeoCoordinate is a Portable Class Library compatible implementation of System.Device.Location.GeoCoordinate. It is an exact 1:1 API compliant implementation and will be supported until MSFT sees it fit to embed the type. Which at that point this implementation will cease development/support and you will be able to simply remove this package and everything will still work." 11 | )] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("https://ghuntley.com/")] 14 | [assembly: AssemblyProduct("GeoCoordinate")] 15 | [assembly: AssemblyCopyright("Copyright © Geoffrey Huntley 2016")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | [assembly: NeutralResourcesLanguage("en")] 19 | [assembly: AssemblyVersionAttribute("0.1.0")] 20 | [assembly: AssemblyFileVersionAttribute("0.11.0")] 21 | [assembly: ComVisibleAttribute(false)] 22 | namespace System { 23 | internal static class AssemblyVersionInformation { 24 | internal const string Version = "0.1.0"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tools/nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ghuntley/geocoordinate/b8c4d99c738bcbd1e86114c9174bf7e179c22e7a/tools/nuget/NuGet.exe --------------------------------------------------------------------------------