diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..269bc19 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,45 @@ +# Catch all for anything we forgot. Add rules if you get CRLF to LF warnings. +* text=auto + +# Text files that should be normalized to LF in odb. +*.cs text eol=lf diff=csharp +*.xaml text +*.config text +*.c text +*.h text +*.cpp text +*.hpp text + +*.sln text +*.csproj text +*.vcxproj text + +*.md text +*.tt text +*.sh text +*.ps1 text +*.cmd text +*.bat text +*.markdown text +*.msbuild text + + +# Binary files that should not be normalized or diffed +*.png binary +*.jpg binary +*.gif binary +*.ico binary +*.rc binary + +*.pfx binary +*.snk binary +*.dll binary +*.exe binary +*.lib binary +*.exp binary +*.pdb binary +*.sdf binary +*.7z binary + +# Generated file should just use CRLF, it's fiiine +SolutionInfo.cs text eol=crlf diff=csharp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..902fec9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,237 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directory +AppPackages/ +BundleArtifacts/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe + +# FAKE - F# Make +.fake/ + +# Tools +tools/ + +# Packaging +packaging/ \ No newline at end of file diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..a83b1ef --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,18 @@ +# Deploying a new release + + +When we're ready to deploy a new release, we need to do the following steps: + +* Create a branch named `release`. +* Update [`ReleaseNotes.md`](ReleaseNotes.md). Note that the format is +important as we parse the version out and use that for the NuGet packages. +* Push the branch to GitHub and create a pull request. This will kick off the +AppVeyor build of the NuGet package with this new version. If you're impatient, you can run `.\build CreatePackages` and get the packages locally. If your having issues creating a package read: https://github.com/octokit/octokit.net/issues/899 +* Test! +* When you're satisfied with this release, push the package to NuGet. +* Create a tag `git tag v#.#.#`. For example, to create a tag for 1.0.0 +`git tag v1.0.0` +* Push the tag to the server. `git push --tags` +* Accept the pull request. +* Create a [new release](https://github.com/ghuntley/geocoordinate/releases/new) +using the tag you just created and pasting in the release notes you just wrote up \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..c4e4284 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,50 @@ +# Microsoft Public License (Ms-PL) + +This license governs use of the accompanying software. If you use the software, +you accept this license. If you do not accept the license, do not use the +software. + +1. Definitions +The terms "reproduce," "reproduction," "derivative works," and "distribution" +have the same meaning here as under U.S. copyright law. A "contribution" is the +original software, or any additions or changes to the software. A "contributor" +is any person that distributes its contribution under this license. "Licensed +patents" are a contributor's patent claims that read directly on its +contribution. + +2. Grant of Rights + +(A) Copyright Grant- Subject to the terms of this license, including the license +conditions and limitations in section 3, each contributor grants you a +non-exclusive, worldwide, royalty-free copyright license to reproduce its +contribution, prepare derivative works of its contribution, and distribute its +contribution or any derivative works that you create. + +(B) Patent Grant- Subject +to the terms of this license, including the license conditions and limitations +in section 3, each contributor grants you a non-exclusive, worldwide, +royalty-free license under its licensed patents to make, have made, use, sell, +offer for sale, import, and/or otherwise dispose of its contribution in the +software or derivative works of the contribution in the software. + +3. Conditions and Limitations + +(A) No Trademark License- This license does not grant you rights to use any +contributors' name, logo, or trademarks. +(B) If you bring a patent claim against any contributor over patents that you +claim are infringed by the software, your patent license from such contributor +to the software ends automatically. +(C) If you distribute any portion of the software, you must retain all +copyright, patent, trademark, and attribution notices that are present in the +software. +(D) If you distribute any portion of the software in source code form, you may +do so only under this license by including a complete copy of this license with +your distribution. If you distribute any portion of the software in compiled or +object code form, you may only do so under a license that complies with this +license. +(E) The software is licensed "as-is." You bear the risk of using it. The +contributors give no express warranties, guarantees or conditions. You may have +additional consumer rights under your local laws which this license cannot +change. To the extent permitted under your local laws, the contributors exclude +the implied warranties of merchantability, fitness for a particular purpose and +non-infringement. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8a0c963 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +![Icon](https://i.imgur.com/OfoiwTs.png) +# GeoCoordinate + +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](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. + +# Supported Platforms + +* Mono +* .NET 4.5 +* .NET Core +* Windows Phone 8.x +* Universal Windows Platform +* Xamarin iOS +* Xamarin Android + +# Installation +Installation is done via NuGet: + + PM> Install-Package GeoCoordinate + +# Usage + + GeoCoordinate pin1 = new GeoCoordinate(lat, lng); + GeoCoordinate pin2 = new GeoCoordinate(lat, lng); + + double distanceBetween = pin1.GetDistanceTo(pin2); + +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 + +# With thanks to +* The icon "[Map Marker](https://thenounproject.com/term/map-marker/60112)" designed by [julianne](https://thenounproject.com/janne232) from The Noun Project. \ No newline at end of file diff --git a/RELEASENOTES.md b/RELEASENOTES.md new file mode 100644 index 0000000..3584ba8 --- /dev/null +++ b/RELEASENOTES.md @@ -0,0 +1,2 @@ +### New in 0.1.0 (released 2016/01/05) +* Initial release \ No newline at end of file diff --git a/SolutionInfo.cs b/SolutionInfo.cs new file mode 100644 index 0000000..df440e6 --- /dev/null +++ b/SolutionInfo.cs @@ -0,0 +1,13 @@ +// +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyProductAttribute("GeoCoordinate")] +[assembly: AssemblyVersionAttribute("0.1.0")] +[assembly: AssemblyFileVersionAttribute("0.1.0")] +[assembly: ComVisibleAttribute(false)] +namespace System { + internal static class AssemblyVersionInformation { + internal const string Version = "0.1.0"; + } +} diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..9a67022 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,14 @@ + +init: + - git config --global core.autocrlf input +build_script: + - cmd: build.cmd BuildApp +# - cmd: build.cmd UnitTests + - cmd: build.cmd CreatePackages +test: off +nuget: + account_feed: true + project_feed: true +artifacts: +- path: 'packaging\*.nupkg' + name: GeoCoordinatePackages \ No newline at end of file diff --git a/assets/.gitkeep b/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/assets/noun_60112_cc.png b/assets/noun_60112_cc.png new file mode 100644 index 0000000..7ce74ff Binary files /dev/null and b/assets/noun_60112_cc.png differ diff --git a/assets/noun_60112_cc_cropped.png b/assets/noun_60112_cc_cropped.png new file mode 100644 index 0000000..2eace02 Binary files /dev/null and b/assets/noun_60112_cc_cropped.png differ diff --git a/build.cmd b/build.cmd new file mode 100644 index 0000000..4bf7b28 --- /dev/null +++ b/build.cmd @@ -0,0 +1,38 @@ +@echo off + +"tools\nuget\nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.1.0" +"tools\nuget\nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" +"tools\nuget\nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" +:Build +cls + +SET TARGET="Default" + +IF NOT [%1]==[] (set TARGET="%1") + +SET BUILDMODE="Release" +IF NOT [%2]==[] (set BUILDMODE="%2") + +:: because we want to run specific steps inline on qed +:: we need to break the dependency chain +:: this ensures we do a build before running any tests + +if %TARGET%=="Default" (SET RunBuild=1) +if %TARGET%=="RunUnitTests" (SET RunBuild=1) +if %TARGET%=="RunIntegrationTests" (SET RunBuild=1) +if %TARGET%=="CreatePackages" (SET RunBuild=1) + +if NOT "%RunBuild%"=="" ( +"tools\FAKE.Core\tools\Fake.exe" "build.fsx" "target=BuildApp" "buildMode=%BUILDMODE%" +) + +"tools\FAKE.Core\tools\Fake.exe" "build.fsx" "target=%TARGET%" "buildMode=%BUILDMODE%" + +rem Bail if we're running a TeamCity build. +if defined TEAMCITY_PROJECT_NAME goto Quit + +rem Bail if we're running a MyGet build. +if /i "%BuildRunner%"=="MyGet" goto Quit + +:Quit +exit /b %errorlevel% \ No newline at end of file diff --git a/build.fsx b/build.fsx new file mode 100644 index 0000000..5bdd163 --- /dev/null +++ b/build.fsx @@ -0,0 +1,145 @@ +#r @"tools/FAKE.Core/tools/FakeLib.dll" +#load "tools/SourceLink.Fake/tools/SourceLink.fsx" +open Fake +open System +open SourceLink + +let authors = ["Geoffrey Huntley"] + +// project name and description +let projectName = "GeoCoordinate" +let projectDescription = "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." +let projectSummary = projectDescription + +// directories +let buildDir = "./src/GeoCoordinatePortable/bin" +let testResultsDir = "./testresults" +let packagingRoot = "./packaging/" +let packagingDir = packagingRoot @@ "GeoCoordinatePortable" + +let releaseNotes = + ReadFile "RELEASENOTES.md" + |> ReleaseNotesHelper.parseReleaseNotes + +let buildMode = getBuildParamOrDefault "buildMode" "Release" + +MSBuildDefaults <- { + MSBuildDefaults with + ToolsVersion = Some "14.0" + Verbosity = Some MSBuildVerbosity.Minimal } + +Target "Clean" (fun _ -> + CleanDirs [buildDir; testResultsDir; packagingRoot; packagingDir] +) + +open Fake.AssemblyInfoFile +open Fake.Testing + +Target "AssemblyInfo" (fun _ -> + CreateCSharpAssemblyInfo "./SolutionInfo.cs" + [ Attribute.Product projectName + Attribute.Version releaseNotes.AssemblyVersion + Attribute.FileVersion releaseNotes.AssemblyVersion + Attribute.ComVisible false ] +) + +Target "CheckProjects" (fun _ -> + !! "./src/GeoCoordinatePortable/GeoCoordinatePortable*.csproj" + |> Fake.MSBuild.ProjectSystem.CompareProjectsTo "./src/GeoCoordinatePortable/GeoCoordinatePortable.csproj" +) + + +Target "FixProjects" (fun _ -> + !! "./src/GeoCoordinatePortable/GeoCoordinatePortable*.csproj" + |> Fake.MSBuild.ProjectSystem.FixProjectFiles "./src/GeoCoordinatePortable/GeoCoordinatePortable.csproj" +) + +let setParams defaults = { + defaults with + ToolsVersion = Some("14.0") + Targets = ["Build"] + Properties = + [ + "Configuration", buildMode + ] + } + +let Exec command args = + let result = Shell.Exec(command, args) + if result <> 0 then failwithf "%s exited with error %d" command result + +Target "BuildApp" (fun _ -> + build setParams "./src/GeoCoordinatePortable.sln" + |> DoNothing +) + +Target "BuildMono" (fun _ -> + // xbuild does not support msbuild tools version 14.0 and that is the reason + // for using the xbuild command directly instead of using msbuild + Exec "xbuild" "./src/GeoCoordinatePortable.sln /t:Build /tv:12.0 /v:m /p:RestorePackages='False' /p:Configuration='Release' /logger:Fake.MsBuildLogger+ErrorLogger,'../src/GeoCoordinatePortable.net/tools/FAKE.Core/tools/FakeLib.dll'" + +) + +// Target "UnitTests" (fun _ -> +// !! (sprintf "./src/GeoCoordinatePortable.Tests/bin/%s/**/GeoCoordinatePortable.Tests*.dll" buildMode) +// |> xUnit2 (fun p -> +// {p with +// HtmlOutputPath = Some (testResultsDir @@ "xunit.html") }) +// ) + +Target "SourceLink" (fun _ -> + [ "./src/GeoCoordinatePortable/GeoCoordinatePortable.csproj" ] + |> Seq.iter (fun pf -> + let proj = VsProj.LoadRelease pf + let url = "https://raw.githubusercontent.com/ghuntley/GeoCoordinatePortable/{0}/%var2%" + SourceLink.Index proj.Compiles proj.OutputFilePdb __SOURCE_DIRECTORY__ url + ) +) + +Target "CreateGeoCoordinatePortablePackage" (fun _ -> + let portableDir = packagingDir @@ "lib/portable-net45+wp80+win+wpa81/" + CleanDirs [portableDir] + + CopyFile portableDir (buildDir @@ "Release/GeoCoordinatePortable.dll") + CopyFile portableDir (buildDir @@ "Release/GeoCoordinatePortable.XML") + CopyFile portableDir (buildDir @@ "Release/GeoCoordinatePortable.pdb") + CopyFiles packagingDir ["LICENSE.md"; "README.md"; "RELEASENOTES.md"] + + NuGet (fun p -> + {p with + Authors = authors + Project = projectName + Description = projectDescription + OutputPath = packagingRoot + Summary = projectSummary + WorkingDir = packagingDir + Version = releaseNotes.AssemblyVersion + ReleaseNotes = toLines releaseNotes.Notes + AccessKey = getBuildParamOrDefault "nugetkey" "" + Publish = hasBuildParam "nugetkey" }) "src/GeoCoordinate.nuspec" +) + +Target "Default" DoNothing + +Target "CreatePackages" DoNothing + +"Clean" + ==> "AssemblyInfo" + ==> "CheckProjects" + ==> "BuildApp" + +"Clean" + ==> "AssemblyInfo" + ==> "CheckProjects" + ==> "BuildMono" + +//"UnitTests" +// ==> "Default" + +"SourceLink" + ==> "CreatePackages" + +"CreateGeoCoordinatePortablePackage" + ==> "CreatePackages" + +RunTargetOrDefault "Default" \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..e05e63a --- /dev/null +++ b/build.sh @@ -0,0 +1,18 @@ +#!/bin/bash +if test "$OS" = "Windows_NT" +then + # use .Net + +"./tools/nuget/nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" +"./tools/nuget/nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" +"./tools/nuget/nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" +packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx +else + # use mono +mono "./tools/nuget/NuGet.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" +mono "./tools/nuget/NuGet.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" +mono "./tools/nuget/NuGet.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" +mono "./tools/nuget/NuGet.exe" "install" "System.Net.Http" "-OutputDirectory" "tools" +mono "./tools/nuget/NuGet.exe" "install" "Microsoft.Net.Http" "-OutputDirectory" "tools" +mono ./tools/FAKE.Core/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx +fi \ No newline at end of file diff --git a/contrib/.gitkeep b/contrib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/licenses/.gitkeep b/licenses/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/.gitkeep b/src/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/GeoCoordinate.nuspec b/src/GeoCoordinate.nuspec new file mode 100644 index 0000000..58d4482 --- /dev/null +++ b/src/GeoCoordinate.nuspec @@ -0,0 +1,25 @@ + + + + @project@ + @build.number@ + @authors@ + @authors@ + @summary@ + https://github.com/ghuntley/geocoordinate/blob/master/LICENSE.md + https://github.com/ghuntley/geocoordinate + https://i.imgur.com/OfoiwTs.png + false + @description@ + @releaseNotes@ + Copyright Geoffrey Huntley 2016 + GeoCoordinate GeoCoordinatePortable system.device.location.geocoordinate + + + + + + + + + \ No newline at end of file diff --git a/src/GeoCoordinatePortable.sln b/src/GeoCoordinatePortable.sln new file mode 100644 index 0000000..0016934 --- /dev/null +++ b/src/GeoCoordinatePortable.sln @@ -0,0 +1,38 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoCoordinatePortable", "GeoCoordinatePortable\GeoCoordinatePortable.csproj", "{3F8D76E7-1AF6-40F5-960F-13C4DFA80935}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{4DB8F23A-14DF-429C-88F4-7FD3B21FFDD8}" + ProjectSection(SolutionItems) = preProject + ..\.gitattributes = ..\.gitattributes + ..\.gitignore = ..\.gitignore + ..\appveyor.yaml = ..\appveyor.yaml + ..\build.cmd = ..\build.cmd + ..\build.fsx = ..\build.fsx + ..\build.sh = ..\build.sh + ..\DEPLOYMENT.md = ..\DEPLOYMENT.md + GeoCoordinate.nuspec = GeoCoordinate.nuspec + ..\LICENSE.md = ..\LICENSE.md + ..\README.md = ..\README.md + ..\RELEASENOTES.md = ..\RELEASENOTES.md + SolutionInfo.cs = SolutionInfo.cs + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3F8D76E7-1AF6-40F5-960F-13C4DFA80935}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F8D76E7-1AF6-40F5-960F-13C4DFA80935}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F8D76E7-1AF6-40F5-960F-13C4DFA80935}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F8D76E7-1AF6-40F5-960F-13C4DFA80935}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/GeoCoordinatePortable/GeoCoordinate.cs b/src/GeoCoordinatePortable/GeoCoordinate.cs new file mode 100644 index 0000000..3f4cb86 --- /dev/null +++ b/src/GeoCoordinatePortable/GeoCoordinate.cs @@ -0,0 +1,332 @@ +using System; +using System.Globalization; + +namespace GeoCoordinatePortable +{ + public class GeoCoordinate : IEquatable + { + public static readonly GeoCoordinate Unknown = new GeoCoordinate(); + private double _course = double.NaN; + private double _horizontalAccuracy = double.NaN; + private double _latitude = double.NaN; + private double _longitude = double.NaN; + private double _speed = double.NaN; + private double _verticalAccuracy = double.NaN; + + + // + /// Initializes a new instance of GeoCoordinate that has no data fields set. + /// + public GeoCoordinate() + { + } + + /// + /// Initializes a new instance of the GeoCoordinate class from latitude and longitude data. + /// + /// The latitude of the location. May range from -90.0 to 90.0. + /// The longitude of the location. May range from -180.0 to 180.0. + /// Latitude or longitude is out of range. + public GeoCoordinate(double latitude, double longitude) + : this(latitude, longitude, double.NaN) + { + } + + /// + /// Initializes a new instance of the GeoCoordinate class from latitude, longitude, and altitude data. + /// + /// Latitude. May range from -90.0 to 90.0. + /// Longitude. May range from -180.0 to 180.0 + /// The altitude in meters. May be negative, 0, positive, or Double.NaN, if unknown. + /// + /// latitude, longitude or altitude is out of range. + /// + public GeoCoordinate(double latitude, double longitude, double altitude) + : this(latitude, longitude, altitude, double.NaN, double.NaN, double.NaN, double.NaN) + { + } + + /// + /// Initializes a new instance of the GeoCoordinate class from latitude, longitude, altitude, horizontal accuracy, + /// vertical accuracy, speed, and course. + /// + /// The latitude of the location. May range from -90.0 to 90.0. + /// The longitude of the location. May range from -180.0 to 180.0. + /// The altitude in meters. May be negative, 0, positive, or Double.NaN, if unknown. + /// + /// The accuracy of the latitude and longitude coordinates, in meters. Must be greater + /// than or equal to 0. If a value of 0 is supplied to this constructor, the HorizontalAccuracy property will be set to + /// Double.NaN. + /// + /// + /// The accuracy of the altitude, in meters. Must be greater than or equal to 0. If a value + /// of 0 is supplied to this constructor, the VerticalAccuracy property will be set to Double.NaN. + /// + /// + /// The speed measured in meters per second. May be negative, 0, positive, or Double.NaN, if unknown. + /// A negative speed can indicate moving in reverse. + /// + /// + /// The direction of travel, rather than orientation. This parameter is measured in degrees relative + /// to true north. Must range from 0 to 360.0, or be Double.NaN. + /// + /// + /// If latitude, longitude, horizontalAccuracy, verticalAccuracy, course is out of range. + /// + public GeoCoordinate(double latitude, double longitude, double altitude, double horizontalAccuracy, + double verticalAccuracy, double speed, double course) + { + Latitude = latitude; + Longitude = longitude; + Altitude = altitude; + HorizontalAccuracy = horizontalAccuracy; + VerticalAccuracy = verticalAccuracy; + Speed = speed; + Course = course; + } + + /// + /// Gets or sets the latitude of the GeoCoordinate. + /// + /// + /// Latitude of the location. + /// + /// Latitude is set outside the valid range. + public double Latitude + { + get { return _latitude; } + set + { + if (value > 90.0 || value < -90.0) + { + throw new ArgumentOutOfRangeException("Latitude", "Argument must be in range of -90 to 90"); + } + _latitude = value; + } + } + + /// + /// Gets or sets the longitude of the GeoCoordinate. + /// + /// + /// The longitude. + /// + /// Longitude is set outside the valid range. + public double Longitude + { + get { return _longitude; } + set + { + if (value > 180.0 || value < -180.0) + { + throw new ArgumentOutOfRangeException("Longitude", "Argument must be in range of -180 to 180"); + } + _longitude = value; + } + } + + /// + /// Gets or sets the accuracy of the latitude and longitude that is given by the GeoCoordinate, in meters. + /// + /// + /// The accuracy of the latitude and longitude, in meters. + /// + /// HorizontalAccuracy is set outside the valid range. + public double HorizontalAccuracy + { + get { return _horizontalAccuracy; } + set + { + if (value < 0.0) + throw new ArgumentOutOfRangeException("HorizontalAccuracy", "Argument must be non negative"); + _horizontalAccuracy = value == 0.0 ? double.NaN : value; + } + } + + /// + /// Gets or sets the accuracy of the altitude given by the GeoCoordinate, in meters. + /// + /// + /// The accuracy of the altitude, in meters. + /// + /// VerticalAccuracy is set outside the valid range. + public double VerticalAccuracy + { + get { return _verticalAccuracy; } + set + { + if (value < 0.0) + throw new ArgumentOutOfRangeException("VerticalAccuracy", "Argument must be non negative"); + _verticalAccuracy = value == 0.0 ? double.NaN : value; + } + } + + /// + /// Gets or sets the speed in meters per second. + /// + /// + /// The speed in meters per second. The speed must be greater than or equal to zero, or Double.NaN. + /// + /// Speed is set outside the valid range. + public double Speed + { + get { return _speed; } + set + { + if (value < 0.0) + throw new ArgumentOutOfRangeException("speed", "Argument must be non negative"); + _speed = value; + } + } + + /// + /// Gets or sets the heading in degrees, relative to true north. + /// + /// + /// The heading in degrees, relative to true north. + /// + /// Course is set outside the valid range. + public double Course + { + get { return _course; } + set + { + if (value < 0.0 || value > 360.0) + throw new ArgumentOutOfRangeException("course", "Argument must be in range 0 to 360"); + _course = value; + } + } + + /// + /// Gets a value that indicates whether the GeoCoordinate does not contain latitude or longitude data. + /// + /// + /// true if the GeoCoordinate does not contain latitude or longitude data; otherwise, false. + /// + public bool IsUnknown => Equals(Unknown); + + + /// + /// Gets the altitude of the GeoCoordinate, in meters. + /// + /// + /// The altitude, in meters. + /// + public double Altitude { get; set; } = double.NaN; + + /// + /// Determines if the GeoCoordinate object is equivalent to the parameter, based solely on latitude and longitude. + /// + /// + /// true if the GeoCoordinate objects are equal; otherwise, false. + /// + /// The GeoCoordinate object to compare to the calling object. + public bool Equals(GeoCoordinate other) + { + if (other == null) + return false; + var num = Latitude; + if (!num.Equals(other.Latitude)) + return false; + num = Longitude; + return num.Equals(other.Longitude); + } + + /// + /// Determines whether two GeoCoordinate objects refer to the same location. + /// + /// + /// true, if the GeoCoordinate objects are determined to be equivalent; otherwise, false. + /// + /// The first GeoCoordinate to compare. + /// The second GeoCoordinate to compare. + public static bool operator ==(GeoCoordinate left, GeoCoordinate right) + { + if (left == null) + return right == null; + return left.Equals(right); + } + + /// + /// Determines whether two GeoCoordinate objects correspond to different locations. + /// + /// + /// true, if the GeoCoordinate objects are determined to be different; otherwise, false. + /// + /// The first GeoCoordinate to compare. + /// The second GeoCoordinate to compare. + public static bool operator !=(GeoCoordinate left, GeoCoordinate right) + { + return !(left == right); + } + + /// + /// Returns the distance between the latitude and longitude coordinates that are specified by this GeoCoordinate and + /// another specified GeoCoordinate. + /// + /// + /// The distance between the two coordinates, in meters. + /// + /// The GeoCoordinate for the location to calculate the distance to. + public double GetDistanceTo(GeoCoordinate other) + { + if (double.IsNaN(Latitude) || double.IsNaN(Longitude) || double.IsNaN(other.Latitude) || + double.IsNaN(other.Longitude)) + { + throw new ArgumentException("Argument latitude or longitude is not a number"); + } + var d1 = Latitude*(Math.PI/180.0); + var num1 = Longitude*(Math.PI/180.0); + var d2 = other.Latitude*(Math.PI/180.0); + var num2 = other.Longitude*(Math.PI/180.0) - num1; + var d3 = Math.Pow(Math.Sin((d2 - d1)/2.0), 2.0) + + Math.Cos(d1)*Math.Cos(d2)*Math.Pow(Math.Sin(num2/2.0), 2.0); + return 6376500.0*(2.0*Math.Atan2(Math.Sqrt(d3), Math.Sqrt(1.0 - d3))); + } + + /// + /// Serves as a hash function for the GeoCoordinate. + /// + /// + /// A hash code for the current GeoCoordinate. + /// + public override int GetHashCode() + { + return Latitude.GetHashCode() ^ Longitude.GetHashCode(); + } + + /// + /// Determines if a specified GeoCoordinate is equal to the current GeoCoordinate, based solely on latitude and + /// longitude. + /// + /// + /// true, if the GeoCoordinate objects are equal; otherwise, false. + /// + /// The object to compare the GeoCoordinate to. + public override bool Equals(object obj) + { + if (!(obj is GeoCoordinate)) + { + return base.Equals(obj); + } + return Equals(obj as GeoCoordinate); + } + + /// + /// Returns a string that contains the latitude and longitude. + /// + /// + /// A string that contains the latitude and longitude, separated by a comma. + /// + public override string ToString() + { + if (this == Unknown) + { + return "Unknown"; + } + + return + $"{Latitude.ToString("G", CultureInfo.InvariantCulture)}, {Longitude.ToString("G", CultureInfo.InvariantCulture)}"; + } + } +} \ No newline at end of file diff --git a/src/GeoCoordinatePortable/GeoCoordinatePortable.csproj b/src/GeoCoordinatePortable/GeoCoordinatePortable.csproj new file mode 100644 index 0000000..28513ed --- /dev/null +++ b/src/GeoCoordinatePortable/GeoCoordinatePortable.csproj @@ -0,0 +1,52 @@ + + + + + 10.0 + Debug + AnyCPU + {3F8D76E7-1AF6-40F5-960F-13C4DFA80935} + Library + Properties + GeoCoordinatePortable + GeoCoordinatePortable + en-US + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile111 + v4.5 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\GeoCoordinatePortable.xml + + + + + + + + + + + \ No newline at end of file diff --git a/src/GeoCoordinatePortable/Properties/AssemblyInfo.cs b/src/GeoCoordinatePortable/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..10ac09a --- /dev/null +++ b/src/GeoCoordinatePortable/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Resources; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly: AssemblyTitle("GeoCoordinate")] +[assembly: + AssemblyDescription( + "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." + )] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("https://ghuntley.com/; ghuntley@ghuntley.com")] +[assembly: AssemblyProduct("GeoCoordinate")] +[assembly: AssemblyCopyright("Copyright © Geoffrey Huntley 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] + +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs new file mode 100644 index 0000000..f5df90c --- /dev/null +++ b/src/SolutionInfo.cs @@ -0,0 +1,26 @@ +// +using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; + + +[assembly: AssemblyTitle("GeoCoordinatePortable")] +[assembly: + AssemblyDescription( + "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." + )] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("https://ghuntley.com/")] +[assembly: AssemblyProduct("GeoCoordinate")] +[assembly: AssemblyCopyright("Copyright © Geoffrey Huntley 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("en")] +[assembly: AssemblyVersionAttribute("0.1.0")] +[assembly: AssemblyFileVersionAttribute("0.11.0")] +[assembly: ComVisibleAttribute(false)] +namespace System { + internal static class AssemblyVersionInformation { + internal const string Version = "0.1.0"; + } +} diff --git a/tools/nuget/NuGet.exe b/tools/nuget/NuGet.exe new file mode 100644 index 0000000..9f8781d Binary files /dev/null and b/tools/nuget/NuGet.exe differ