Измените проекцию в MSSQL для веб-картографии (Leaflet, Openlayer, OpenStreetMaps, GoogleAPI, ) на WSG48 или любой другой формат.

У меня есть некоторые данные WKT/WKB на сервере MSSQL, подобные этому, и я хотел бы показать их на карте с помощью листовок, Openlayer, OpenStreetMaps или GoogleAPI. Мои данные выглядят так:

POLYGON ((1736946.0983 5923253.9175, 1736895.6852 5923333.9451, 1736936.0082 5923356.6991, ......))

в этом формате

 EPSG:2193

как показано ниже

введите здесь описание изображения и хотите преобразовать их в

  WGS48 or EPSG:4326

Я пытаюсь добавить их в листовку, и кажется, что мне нужно преобразовать эти данные в соответствующий формат, например:

[[42.353770, -71.103606], [42.355447, -71.104475], [42.362681, -71.089830], [42.361829, -71.079230]]

К сожалению, я не уверен, как сделать это преобразование.

Я пробовал некоторые подходы, подобные этим

[1.]. Ошибка:

 A .NET Framework error occurred during execution of user-defined routine or aggregate "geography": 
 System.FormatException: 24201: Latitude values must be between -90 and 90 degrees.

[2.] Запрос:

select  GEOGRAPHY::STPolyFromText ([stastxt],4326) from mytable
Error:
 A .NET Framework error occurred during execution of user-defined routine or aggregate "geography": 
 System.FormatException: 24201: Latitude values must be between -90 and 90 degrees.

[3.] Нет успех

[4.] Я могу видеть эти данные как слой в GeoServer, когда я устанавливаю Declared SRS как EPSG:2193

После более подробного изучения этого вопроса возник вопрос:

Могу ли я сделать это преобразование только на сервере MSSQL или в Leaflet, или мне нужно использовать некоторые другие инструменты, такие как Proj4net, и заменить '(' на '['?


person Mohsen Sichani    schedule 15.06.2017    source источник
comment
Вы должны преобразовать эти координаты в широту и долготу WGS84 (EPSG:3857) или определить соответствие CRS. Из какого района эти координаты?   -  person chrki    schedule 15.06.2017
comment
Спасибо Chrki, Новая Зеландия, я добавил больше информации к своему вопросу, как насчет преобразования '(' в MSSQL в '[' в листовке?   -  person Mohsen Sichani    schedule 15.06.2017
comment
Когда вы говорите, что у вас есть WKT в базе данных, я предполагаю, что он просто хранится в виде текста (на основе ваших предыдущих попыток преобразовать его в экземпляр geography). Откуда вы это взяли? Для меня это похоже на данные геометрии (в отличие от географии).   -  person Ben Thul    schedule 15.06.2017
comment
Да, это правда, Бен, я получил это от ([Geom].[STAsText]())   -  person Mohsen Sichani    schedule 15.06.2017
comment
Я скорректировал свой вопрос, так как нашел больше информации. Спасибо   -  person Mohsen Sichani    schedule 15.06.2017


Ответы (2)


Наконец, я разработал интересное решение, я объясню свое решение шаг за шагом, так как я уверен, что другие сталкиваются с аналогичными проблемами.

Во-первых, нужно знать, в какой проекции находятся данные (src) и какую проекцию вы хотели бы иметь (dst). Обычно dst равно EPSG:4326, EPSG:3857 или WGS48. Для этого решения мне нужно было найти правильную математику, стоящую за этим, поэтому я использовал этот веб-сайт https://mygeodata.cloud/cs2cs/, чтобы найти правильный формат для src и dst (если вы знакомы с R, для этого есть функция, также называемая spTransform). Другая причина в том, что я собираюсь использовать компонент Proj4 для этого преобразования. Еще одним важным шагом является преобразование в GeoJson, поскольку эти веб-карты могут читать файлы GeoJson. Я не хотел записывать свои данные в физические файлы GeoJson, поэтому сделал преобразование по требованию в MSSQL (не нужно записывать куда-то в виде файла GeoJson).

  1. Сделайте библиотеку на C# и получите dll.
  2. Импортируйте это в MSSQL
  3. Наслаждайся этим

Код для первой части: Установите 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

Вы можете использовать плагин Proj4Leaflet для преобразования в Leaflet.

person Ulrik    schedule 09.07.2017
comment
Это более быстрое решение по сравнению с моим, но оно не меняет ( на [, а также не меняет длинный и латный порядок. - person Mohsen Sichani; 10.07.2017