Наконец, я разработал интересное решение, я объясню свое решение шаг за шагом, так как я уверен, что другие сталкиваются с аналогичными проблемами.
Во-первых, нужно знать, в какой проекции находятся данные (src) и какую проекцию вы хотели бы иметь (dst). Обычно dst равно EPSG:4326
, EPSG:3857
или WGS48
. Для этого решения мне нужно было найти правильную математику, стоящую за этим, поэтому я использовал этот веб-сайт https://mygeodata.cloud/cs2cs/, чтобы найти правильный формат для src и dst (если вы знакомы с R
, для этого есть функция, также называемая spTransform
). Другая причина в том, что я собираюсь использовать компонент Proj4 для этого преобразования. Еще одним важным шагом является преобразование в GeoJson, поскольку эти веб-карты могут читать файлы GeoJson. Я не хотел записывать свои данные в физические файлы GeoJson, поэтому сделал преобразование по требованию в MSSQL (не нужно записывать куда-то в виде файла GeoJson).
- Сделайте библиотеку на C# и получите dll.
- Импортируйте это в MSSQL
- Наслаждайся этим
Код для первой части: Установите DotSpatial через Nugget.
using Microsoft.SqlServer.Server;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class classval
{
public string line;
public string src;
public string dst;
public classval(string line, string src, string dst)
{
this.line = line;
this.src = src;
this.dst = dst;
}
}
public class CLRProjection
{
private static IEnumerable<classval> ConvertedEnumerable(string line, string src, string dst)
{
return new List<classval> { new classval(line, src, dst) };
}
[SqlFunction(FillRowMethodName = "FillRow")]
public static IEnumerable ToLatLong(string Geometry, string src, string dst)
{
return ConvertedEnumerable(Geometry, src, dst);
}
private static void FillRow(Object classvalobj, out string Geometry, out string srcprj, out string dstprj)
{
classval geomobj = (classval)classvalobj;
string _geometry = geomobj.line; //"POLYGON ((1736946.0983 5923253.9175,....))";
string proj4_src = geomobj.src; //"+proj=tmerc +lat_0=0 +lon_0=173 +k=0.9996 +x_0=1600000 +y_0=10000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs ";
string proj4_dst = geomobj.dst;//"+proj=longlat +datum=WGS84 +no_defs";
_geometry = _geometry.Replace(",", " , ");
_geometry = _geometry.Remove(0, _geometry.IndexOf('('));
_geometry = _geometry.Replace("(", "[ ");
_geometry = _geometry.Replace(")", " ]");
string[] splitbycomma = _geometry.Split(',');
foreach (var itembycomma in splitbycomma)
{
string tmpitem = itembycomma;
tmpitem = tmpitem.Replace('[', ' ');
tmpitem = tmpitem.Replace(']', ' ');
tmpitem = tmpitem.Trim();
string[] splitbyspace = tmpitem.Split(' ');
for (int ibs = 0; ibs < splitbyspace.Length - 1; ibs++)
{
double[] x = { double.Parse(splitbyspace[ibs]) };
double[] y = { double.Parse(splitbyspace[ibs + 1]) };
double[] z = new double[x.Length];
//rewrite xy array for input into Proj4
double[] xy = new double[2 * x.Length];
int ixy = 0;
for (int i = 0; i <= x.Length - 1; i++)
{
xy[ixy] = x[i];
xy[ixy + 1] = y[i];
z[i] = 0;
ixy += 2;
}
double[] xy_geometry = new double[xy.Length];
Array.Copy(xy, xy_geometry, xy.Length);
DotSpatial.Projections.ProjectionInfo src =
DotSpatial.Projections.ProjectionInfo.FromProj4String(proj4_src);
DotSpatial.Projections.ProjectionInfo trg =
DotSpatial.Projections.ProjectionInfo.FromProj4String(proj4_dst);
DotSpatial.Projections.Reproject.ReprojectPoints(xy, z, src, trg, 0, x.Length);
ixy = 0;
for (int i = 0; i <= x.Length - 1; i++)
{
_geometry = _geometry.Replace(xy_geometry[ixy].ToString() + " ", "[" + xy[ixy + 1].ToString() + " , ");
_geometry = _geometry.Replace(xy_geometry[ixy + 1].ToString() + " ", xy[ixy].ToString() + " ] ");
_geometry = _geometry.Replace("- ", "-");
string tt = (i + 1 + " " + xy[ixy] + " " + xy[ixy + 1]);
ixy += 2;
}
}
}
_geometry = _geometry.Replace(" ", " ");
_geometry = _geometry.Replace(" [ ", "[");
_geometry = _geometry.Replace(" ] ", "]");
_geometry = _geometry.Replace(" , ", ",");
srcprj = proj4_src;
dstprj = proj4_dst;
Geometry = _geometry;
}
}
Код для второй части (Внутри MSSQL)
ALTER DATABASE test SET trustworthy ON
CREATE ASSEMBLY CLRFunctionAssem
FROM N'C:\Users\...\bin\Debug\Convertor_Projection.dll'
WITH PERMISSION_SET = UNSAFE
GO
CREATE FUNCTION dbo.ToLatLong(@Geometry nvarchar(max), @src nvarchar(max),@dst nvarchar(max))
RETURNS TABLE
( _geom nvarchar(max) ,srcprj nvarchar(max) ,dstprj nvarchar(max)
) with execute as caller
AS
EXTERNAL NAME CLRFunctionAssem.[CLRProjection].[ToLatLong]
код MSSQL
SELECT
[parcelid]
,[Geom1]
,[stastxt]
,conv._geom
FROM [test].[dbo].[TEST_JSON] as a CROSS APPLY dbo.ToLatLong (a.
[stastxt],'+proj=tmerc +lat_0=0 +lon_0=173 +k=0.9996 +x_0=1600000 +y_0=10000000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs','+proj=longlat +datum=WGS84 +no_defs') as conv
where [stastxt] is not null
MSSQL2016 имеет JSON функциональность, в то время как в старых версиях такой возможности нет.
Вывод
Ресурсы, которые мне помогли:
1 ,2,3 а>
person
Mohsen Sichani
schedule
15.06.2017