Is there a way to Transform a point to another SRID using EntityFrameworkCore?
previously I used ST_Transform(ST_GeomFromText(@coord,4326),32661)
My current code looks like this
var postgisGeometry = new PostgisPoint(lon, lat) {SRID = 4326};
The SRID of the coord is 4326 and needs to become 32661 This is done for backwards compatibility reasons and there is no option converting the database to another SRID
Is there a geometry library or a PostGIS EntityFrameworkCore method to transform a point to another SRID
The release version Npgsql.EntityFrameworkCore.PostgreSQL
Entity Framework Core provider for PostgreSQL does not support spatial types.
The good news is that spatial types support and support for some spatial operations SQL translations are already available as a pre-release candidate.
If you want to use these libraries, you need to also use the pre-realease candidate version of Entify Framework Core.
First, uninstall your existing entity framework or npgsql packages.
One of the packages needed (GeoAPI) is not available in the standard NuGet source so we are gonna use the myget.org source.
To use it, you need to add a new NuGet source in Visual Studio by going to Tools -> Options -> NuGet Package Manager -> Packages Sources
Create a new source and name it myget.org and use the following URL in the source text field:
https://www.myget.org/F/imageprocessor/api/v3/index.json
Remember to click on update to save the changes, otherwise they are not saved (weird, I know).
To add the required packages, use the Package Manager Console (View -> Other Windows -> Package Manager Console) and select myget.org from the Package Source drop down, then, execute the following commands:
Install-Package Microsoft.EntityFrameworkCore -Version 2.1.0-rc1-final
Install-Package GeoAPI -Version 1.7.5-pre024
Install-Package Npgsql -Version 4.0.0-rc1
Install-Package Npgsql.EntityFrameworkCore.PostgreSQL -Version 2.1.0-rc1
Install-Package Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite -Version 2.1.0-rc1
Once your packages are installed, in your DbContext
class, override OnConfiguring
to add the UseNetTopologySuite
option:
protected override void OnConfiguring(DbContextOptionsBuilder builder)
{
builder.UseNpgsql("Host=localhost;Database=your_database;
Username=your_user;Password=your_password",
o => o.UseNetTopologySuite());
}
To make sure that the extension is supported by your database add the following to your DbContext:
protected override void OnModelCreating(ModelBuilder builder)
{
builder.HasPostgresExtension("postgis");
}
Now you should be able to use PostgreSql spatial types and translate some operations to SQL, (e.g. ST_Area
, ST_Contains
, ST_As_Text
, etc.).
The whole list of supported operations and how to use them in your EF queries is available here: http://www.npgsql.org/efcore/mapping/nts.html#operation-translation
Unfortunately ST_Transform
or ST_Project
do not seem to be supported as of now, but there is a link in the Website above where you can contact the developers and request them to be added.
In the meantime, you can use GDAL to transform the projection of your coordinates.
Install the package:
Install-Package Gdal.Core -Version 1.0.0
This package provides a multi-platform wrapper for GDAL for .NET core so you need to install the libraries and they should be accessible by your program.
You can find binaries for Windows and Linux here: https://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries
If you are using Windows you can use the following installer: http://download.osgeo.org/osgeo4w/osgeo4w-setup-x86_64.exe
Just select "Express Desktop Install" and GDAL in the "Select Packages" window.
By default the needed libraries are installed in C:\OSGeo4W64\bin.
You need to add this folder to your system path and restart Visual Studio.
By the way, to convert the coordinates, from all the libraries in C:\OSGeo4W64\bin I think you only need proj.dll so may be you can include this in your project (make sure it is copied to the output of your project) and then it should work and you don't need to install GDAL.
Here is an example of how to use it for the coordinate systems provided in your question:
using System;
using NetTopologySuite.Geometries;
using OSGeo.OSR;
using OSGeo.OGR;
namespace YourNamespace
{
public class SomeLocation
{
public int Id { get; set; }
public string Name { get; set; }
public Point Location { get; } = new Point(40.1234, 1.4321) { SRID = 4326 };
public Point LocationUpsNorth { get { return Wgs84ToWgs84UpsNorth(Location); } }
private static NetTopologySuite.Geometries.Point Wgs84ToWgs84UpsNorth(Point location)
{
if (location.SRID != 4326)
throw new Exception("Unsupported coordinate system: " + location.SRID);
OSGeo.OSR.SpatialReference wgs84Src = new OSGeo.OSR.SpatialReference("");
wgs84Src.ImportFromProj4("+proj=longlat +datum=WGS84 +no_defs");
OSGeo.OSR.SpatialReference stereoNorthPoleDest = new OSGeo.OSR.SpatialReference("");
stereoNorthPoleDest.ImportFromProj4("+proj=stere +lat_0=90 +lat_ts=90 +lon_0=0 +k=0.994 +x_0=2000000 +y_0=2000000 +datum=WGS84 +units=m +no_defs");
OSGeo.OSR.CoordinateTransformation ct = new OSGeo.OSR.CoordinateTransformation(wgs84Src, stereoNorthPoleDest);
double[] point = new double[3];
point[0] = location.X;
point[1] = location.Y;
point[2] = location.Z;
ct.TransformPoint(point);
return new Point(point[0], point[1]);
}
}
}
Result
Input: POINT (40.1234 1.4321)
Output: POINT (9944217.1796359234 -7426244.9918885585)
References:
http://www.npgsql.org/efcore/mapping/nts.html
http://spatialreference.org/ref/epsg/32661/