# GeographicLib.NET **Repository Path**: bennywolf/GeographicLib.NET ## Basic Information - **Project Name**: GeographicLib.NET - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-05-24 - **Last Updated**: 2025-01-27 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # GeographicLib.NET [![release](https://github.com/noelex/GeographicLib.NET/actions/workflows/release.yml/badge.svg)](https://github.com/noelex/GeographicLib.NET/actions/workflows/release.yml) [![prerelease](https://github.com/noelex/GeographicLib.NET/actions/workflows/prerelease.yml/badge.svg)](https://github.com/noelex/GeographicLib.NET/actions/workflows/prerelease.yml) [GeographicLib](https://sourceforge.net/p/geographiclib) is a small set of C++ classes for performing conversions between geographic, UTM, UPS, MGRS, geocentric, and local cartesian coordinates,for gravity (e.g., EGM2008), geoid height and geomagnetic field (e.g., WMM2020) calculations, and for solving geodesic problems. GeographicLib.NET is a native .NET implementation of [GeographicLib](https://sourceforge.net/p/geographiclib) written in pure C#. ## What's different from NETGeographicLib Unlike NETGeographicLib, GeographicLib.NET is implemented in pure C# without binding the C++ GeograpbicLib library by using C++/CLI or P/Invoke, thus achieves higher level of portability. You should be able to use GeographicLib.NET with any target framework and platform that supports .NET Standard 2.0 or above. ## Features Bellow is a list of implemented features. - [x] Projections (`AlbersEqualArea`, `AzimuthalEquidistant`, `CassiniSoldner`, `Gnomonic`, `LambertConformalConic`, `PolarStereographic` and `TransverseMercator`) - [x] Geocodes (`GARS`, `Geohash`, `Georef`, `MGRS` and `OSGB`) - [x] Coordinate conversions (`UTMUPS`, `Geocentric` and `LocalCartesian`) - [x] Coordinate parsing/formatting (`DMS` and `GeoCoords`) - [x] Geodesic (`Geodesic`, `GeodesicLine`, `GeodesicExact` and `GeodesicLineExact`) - [x] Geodesic intersections (`Intersect`) - [x] Rhumb (`Rhumb` and `RhumbLine`) - [x] PolygonArea (`PolygonArea`, `PolygonArea`, `PolygonAreaExact` and `PolygonAreaRhumb`) - [x] Geoid (`Geoid`) - [x] GravityModel (`GravityCircle`, `NormalGravity` and `GravityModel`) - [x] MagneticModel (`MagneticModel`, `MagneticCircle`) - [x] Auxiliary classes (`MathEx`, `Ellipoid`, `EllipticFunction`, `SphericalHarmonic`, `AuxAngle`, `AuxLatitude` and `DAuxLatitude`) `Geodesic` and `GeodesicExact` are tested with the [test set for geodesic](https://zenodo.org/record/32156#.YCFzsFBLQ_0). `TransverseMercator` and `TransverseMercatorExact` are tested with data generated by 64-bit `TransverseMercatorProj` utility ran on Windows. Managed implemetation of C mathematical functions in `MathEx` are tested with data generated by 64-bit Windows Universal C Runtime. ## Installing ### Stable ![Release](https://img.shields.io/nuget/v/GeographicLib.NET) Stable releases of GeographicLib.NET are hosted on NuGet. You can install them using the following command: ``` dotnet add package GeographicLib.NET ``` ### Preview ![Preview](https://img.shields.io/nuget/vpre/GeographicLib.NET) Preview versions of GeographicLib.NET are hosted on NuGet pre-release channel. You can install them using the following command: ``` dotnet add package GeographicLib.NET --prerelease ``` ## Usage This section lists some common usage examples of GeographicLib.NET. For detailed documentation, please refer [GeographicLib's documentation](https://geographiclib.sourceforge.io/C++/doc/index.html). ### Inverse calculation Distance from JFK to LHR. ```csharp double lat1 = 40.6, lon1 = -73.8, // JFK Airport lat2 = 51.6, lon2 = -0.5; // LHR Airport double arcLength = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2, out double distance); ``` ### Direct calculation The point 5500 km NE of JFK: ```csharp double lat1 = 40.6, lon1 = -73.8, s12 = 5500e3, azi1 = 51; double arcLength = Geodesic.WGS84.Direct(lat1, lon1, azi1, s12, out double lat2, out double lon2); ``` ### Geodesic intersection Find closest intersection of two geodesics: ```csharp Geodesic geod = Geodesic.WGS84; Intersect inter = new Intersect(geod); IGeodesicLine lineX = geod.Line(0, 0, 45), lineY = geod.Line(45, 10, 135); // Find displacement to closest intersection. // Where point.X is the displacement from the starting point of lineX, // and point.Y is the displacement from the starting point of lineY. Point point = inter.Closest(lineX, lineY); // Get the position of the intersection point by using the displacement on lineX. lineX.Position(point.X, out double latx, out double lonx); // Get the position of the intersection point by using the displacement on lineY. lineY.Position(point.Y, out double laty, out double lony); // (latx, lonx) and (laty, lony) should be pointing to the same location. Assert.AreEqual(latx, laty, 1e-12); Assert.AreEqual(lonx, lony, 1e-12); ``` ## Mathematical Functions GeographicLib uses several C mathematical functions that are not available in all versions of .NET. These functions are: - remquo - frexp - sincos (available since .NET 7.0, but not used due to [this issue](https://github.com/dotnet/runtime/issues/48776)) - hypot (available since .NET 7.0, but not used due to [this issue](https://github.com/dotnet/runtime/issues/75651)) - log1p (a naive implementation is available since .NET 7.0, not used by GeographicLib.NET) - expm1 (a naive implementation is available since .NET 7.0, not used by GeographicLib.NET) - exp2 (a naive implementation is available since .NET 7.0, not used by GeographicLib.NET) - log2 (available since .NET 5.0) - fma (available since .NET 5.0) - scalbn (available since .NET 5.0) - copysign (available since .NET 5.0) - atanh (available since .NET Standard 2.1) - asinh (available since .NET Standard 2.1) - cbrt (available since .NET Standard 2.1) GeographicLib.NET provides managed implementations (ported from [musl libc](https://musl.libc.org/)) and platform dependent native C wrappers for these functions. By default, the library will use the managed implementation when the corresponding math function is not provided by .NET runtime. You can also force the library to use platform dependent native C wrappers, by setting `GeographicLib.MathEx.UseManagedCMath` property to `false`. ## Performance ```ini BenchmarkDotNet v0.13.12, Windows 11 (10.0.22621.3155/22H2/2022Update/SunValley2) Intel Xeon CPU E5-2689 0 2.60GHz, 1 CPU, 16 logical and 8 physical cores .NET SDK 8.0.200 [Host] : .NET 6.0.27 (6.0.2724.6912), X64 RyuJIT AVX .NET 6.0 : .NET 6.0.27 (6.0.2724.6912), X64 RyuJIT AVX .NET 7.0 : .NET 7.0.16 (7.0.1624.6629), X64 RyuJIT AVX .NET 8.0 : .NET 8.0.2 (8.0.224.6711), X64 RyuJIT AVX ``` | Method | Job | Runtime | Target | Mean | Error | StdDev | Ratio | RatioSD | Allocated | Alloc Ratio | |-------- |--------- |--------- |-------------- |-----------:|---------:|---------:|------:|--------:|----------:|------------:| | **Direct** | **.NET 6.0** | **.NET 6.0** | **Geodesic** | **814.7 ns** | **15.27 ns** | **17.59 ns** | **1.00** | **0.00** | **-** | **NA** | | Direct | .NET 7.0 | .NET 7.0 | Geodesic | 765.3 ns | 10.03 ns | 9.38 ns | 0.94 | 0.02 | - | NA | | Direct | .NET 8.0 | .NET 8.0 | Geodesic | 804.1 ns | 12.70 ns | 14.63 ns | 0.99 | 0.02 | - | NA | | | | | | | | | | | | | | Inverse | .NET 6.0 | .NET 6.0 | Geodesic | 2,440.2 ns | 24.36 ns | 20.34 ns | 1.00 | 0.00 | - | NA | | Inverse | .NET 7.0 | .NET 7.0 | Geodesic | 2,278.6 ns | 25.80 ns | 22.87 ns | 0.93 | 0.01 | - | NA | | Inverse | .NET 8.0 | .NET 8.0 | Geodesic | 2,084.5 ns | 18.19 ns | 16.12 ns | 0.85 | 0.01 | - | NA | | | | | | | | | | | | | | **Direct** | **.NET 6.0** | **.NET 6.0** | **GeodesicExact** | **2,414.8 ns** | **44.92 ns** | **44.12 ns** | **1.00** | **0.00** | **-** | **NA** | | Direct | .NET 7.0 | .NET 7.0 | GeodesicExact | 2,335.3 ns | 19.53 ns | 17.31 ns | 0.97 | 0.02 | - | NA | | Direct | .NET 8.0 | .NET 8.0 | GeodesicExact | 2,331.7 ns | 18.35 ns | 17.17 ns | 0.97 | 0.02 | - | NA | | | | | | | | | | | | | | Inverse | .NET 6.0 | .NET 6.0 | GeodesicExact | 6,057.7 ns | 50.90 ns | 47.61 ns | 1.00 | 0.00 | - | NA | | Inverse | .NET 7.0 | .NET 7.0 | GeodesicExact | 6,029.2 ns | 51.33 ns | 48.02 ns | 1.00 | 0.01 | - | NA | | Inverse | .NET 8.0 | .NET 8.0 | GeodesicExact | 5,947.1 ns | 31.88 ns | 28.26 ns | 0.98 | 0.01 | - | NA | | | | | | | | | | | | | | **Direct** | **.NET 6.0** | **.NET 6.0** | **Rhumb** | **1,057.2 ns** | **12.27 ns** | **11.47 ns** | **1.00** | **0.00** | **-** | **NA** | | Direct | .NET 7.0 | .NET 7.0 | Rhumb | 1,046.5 ns | 16.96 ns | 15.04 ns | 0.99 | 0.02 | - | NA | | Direct | .NET 8.0 | .NET 8.0 | Rhumb | 943.8 ns | 7.27 ns | 6.07 ns | 0.89 | 0.01 | - | NA | | | | | | | | | | | | | | Inverse | .NET 6.0 | .NET 6.0 | Rhumb | 846.6 ns | 6.29 ns | 5.89 ns | 1.00 | 0.00 | - | NA | | Inverse | .NET 7.0 | .NET 7.0 | Rhumb | 841.4 ns | 8.24 ns | 7.30 ns | 0.99 | 0.01 | - | NA | | Inverse | .NET 8.0 | .NET 8.0 | Rhumb | 757.8 ns | 6.67 ns | 5.91 ns | 0.90 | 0.01 | - | NA | ## Change Log GeographicLib.NET adopts changes made in GeographicLib and aligns its version number with GeographicLib releases. Bellow is a list of stable releases of GeographicLib.NET and changes made in .NET side in each release. For changes adopted from GeographicLib, please refer the its change log [here](https://geographiclib.sourceforge.io/C++/doc/changes.html). ### Version 2.3.2 (released 2024/10/23) - **FIX** - [Strong name validation fails when loading GeographicLib.dll from .NET Framework application](https://github.com/noelex/GeographicLib.NET/issues/33) ### Version 2.3.1 (released 2024/03/20) - **NEW** - Improve performance of `Geodesic.Direct`, `Rhumb.Direct`, `GeodesicExact.Direct`, `GeodesicExact.Inverse` and their overloads/variants. These are now heap allocation free. - Allow constructing `MagneticModel` and `GravityModel` from `Stream` and byte array. ([#30](https://github.com/noelex/GeographicLib.NET/issues/30)) - `AuxLatitude` now implements `IEllipsoid` interface. - Parameter `p0` of `Intersect.Closest()` now defaults to `Point.Zero`. - **FIX** - Fixed wrong `GravityFlags` handling in `GravityCircle` class. ### Version 2.3.0 (released 2024/02/23) - **NEW** - Target .NET 7.0 and .NET 8.0. - Add managed implementation and libc wrapper for exp2. - Managed implementations and libc wrappers for log1p, expm1 and exp2 are now used for all versions of .NET, because the implementations provided by .NET runtime are just wrappers over `Math.Log` and `Math.Pow`. - **FIX** - [PolygonAreaExact seems to give incorrect results](https://github.com/noelex/GeographicLib.NET/issues/29). ### Version 2.1.2 (released 2023/01/17) - **FIX** - Fixed an issue where number and date time parsing may fail or produce unexpected result when working with number and date time formats provided by `CultureInfo.CurrentCulture`. This fixes [issue #27](https://github.com/noelex/GeographicLib.NET/issues/27). ### Version 2.0.0 (released 2022/08/24) - **NEW** - Add `IPolygonArea` interface to provide better support for unit testing and dependency injection. - Add `Count` and `IsPolyline` properties (corresponding to `NumPoints` and `Polyline` methods in GeographicLib) to `PolygonArea`. - Add a new method `Utility.FractionalYear` which can parse floating point number and date time string as fractional year. - [Allow constructing `Geoid` from `Stream` and byte array](https://github.com/noelex/GeographicLib.NET/discussions/22). - **FIX** - String accepting APIs now handle lowercase "nan" correctly. - Ensure consistent rounding mode (`MidpointRounding.ToEven`) across different runtimes when converting floating point number to string. - `MGRS.Reverse` now allows lowercase input. ### Version 1.52.1 (released 2022/04/12) - **NEW** - Target .NET 6.0 in addition to .NET 5.0, .NET Standard 2.1 and .NET Standard 2.0. - [Source Link](https://github.com/dotnet/sourcelink) support. - **BREAKING** - Fixed typos in `Ellipsoid`. (Renamed `SecondFlatterning` to `SecondFlattening` and `ThirdFlatterning` to `ThirdFlattening`) - **FIX** - Fixed an issue that `Freeze` method in `AlbersEqualArea`, `LambertConformalConic` and `PolarStereographic` was not working correctly. - Fixed duplicate instantiation of `WGS84` and `GRS80` static properties defined in `NormalGravity`. - [Add missing support for World Magnetic Model Format v2](https://github.com/noelex/GeographicLib.NET/issues/17). ### Version 1.52.0 (released 2021/07/07) - **BREAKING** - Modify overloads of `Forward` and `Reverse` in `AlbersEqualArea`, `AzimuthalEquidistant`, `CassiniSoldner` and `LambertConformalConic` to return coordinates as tuples. - Modify methods using `out` parameters defined in `NormalGravity`, `GravityModel`, `GravityCircle`, `MagneticModel` and `MagnegticCircle` to return results as tuples. - **NEW** - Add constructor overloads that accept `IEllipsoid` as parameter for `AlbersEqualArea` and `LambertConformalConic`. - Add managed implementation of `log2`. - Add overloads of `Direct` and `Inverse` in `Geodesic`/`GeodesicLine`, `GeodesicExact`/`GeodesicLineExact` and `Rhumb`/`RhumbLineExact`, that return the computation results as a single object. - Add definitions of popular reference ellipsoids in `Ellipsoid` class. - **FIX** - Fix stack overflow bug for `Forward(double lon0, double lat, double lon)` and `Reverse(double lon0, double x, double y)` in `TransverseMercatorExact`. ### Version 1.51.0 (released 2021/03/14) Initial stable release.