Парсинг координат UTM в DBGeography на языке C#


Я пишу приложение WinForms на C#. Мне нужно убедиться, что никакие два Datarows в моем Datatable не находятся более чем в 100 км друг от друга. Каждая строка имеет зону UTM, Восток и Север в отдельных DataColumns. все координаты используют один и тот же датум, но некоторые имеют разные зоны (в противном случае я бы просто использовал математику Пифагора, поскольку UTM находятся в метрах). До сих пор я использую для этого следующий код, но мне кажется, что мой метод DbGeography.PointFromText работает не совсем правильно (см. * в коде), как когда код достигает строки кода С '**' в начале этого, я получаю ошибку говоря "24201: значения широты должны быть между -90 и 90 градусами". Я также пытался:

dtTrap.Rows[i]["TrapGeog"] = DbGeography.PointFromText(pointWellKnownText: "POINT M(" + dtTrap.Rows[i][intEastingIndex].ToString() + " " + dtTrap.Rows[i][intNorthingIndex].ToString() + " " + dtTrap.Rows[i][Zone].ToString() + ")", coordinateSystemId: SRID);

Только для того, чтобы он пожаловался, что" нет столбца № 17 " (17-моя зона UTM).

Я нашел очень мало документации для использования этого материала... насколько я могу судить, мои SRIDs верны (я вытащил их из этого сайта). Я уже делал подобные вещи, используя Lat + Longs раньше, и это сработало замечательно. Я просто не могу найти подходящего синтаксис для UTMs.
using System.Data.Entity.Spatial;
...
DataColumn dcGeog = new DataColumn("TrapGeog", typeof(DbGeography));
dtTrap.Columns.Add(dcGeog);
byte Zone;
Int16 SRID;
for (int i = 0; i < dtTrap.Rows.Count; ++i)
{
    if (dtTrap.Rows[i][intZoneIndex] != null
    && dtTrap.Rows[i][intNorthingIndex] != null
    && dtTrap.Rows[i][intEastingIndex] != null
    && byte.TryParse(dtTrap.Rows[i][intZoneIndex].ToString(), out Zone) == true)
    {
        if (Zone == 15) { SRID = 26915; }
        else if (Zone == 16) { SRID = 26916; }
        else if (Zone == 17) { SRID = 26917; }
        else { SRID = 26918; }
        // shove it in:
        try
        {
            *dtTrap.Rows[i]["TrapGeog"] = DbGeography.PointFromText(pointWellKnownText: "POINT(" + dtTrap.Rows[i][intEastingIndex].ToString() + " " + dtTrap.Rows[i][intNorthingIndex].ToString() + ")", coordinateSystemId: SRID);
        }
        catch (Exception ex)
        {
            if (ex.InnerException != null)
            {
                **MessageBox.Show(ex.InnerException.Message);
            }
            else
            {
                MessageBox.Show(ex.Message);
            }
        }

    }
}
for (int i = 0; i < dtTrap.Rows.Count - 1; ++i)
{
    for (int k = i + 1; k < dtTrap.Rows.Count; ++i)
    {
        DbGeography iTrap = (DbGeography)dtTrap.Rows[i]["TrapGeog"];
        DbGeography kTrap = (DbGeography)dtTrap.Rows[k]["TrapGeog"];
        if (iTrap.Distance(kTrap) > 100000)
        {
            sbErrorsAndWarningsLog.Append(@"Warning:  Line number " + (i + 2).ToString() + " on the Trap spreadsheet has coordinates that are at least 100 km away from row " + (k + 2).ToString() + "'s point.  Please check that these coordinates are correct.").AppendLine();
            boolWarningsFound = true;
            break;
        }
    }
}
2 7

2 ответа:

В моих поисках, чтобы выяснить это, я наткнулся на этот пост на сестринском сайте здесь. Я полагаю, что DbGeography основан на типе данных geography SQL Server, а DbGeometry - на типе данных geometry.

Некоторые уместные лакомые кусочки:

Тип данных geography, EPSG: 4326, находится в градусах, поэтому ваша точка(257306 142708) терпит неудачу, поскольку она выпадает из диапазона (-180,180), (-90,90).

...

Решение ... использование геометрического типа данных вместо этого, то есть проектируется, а не географически.

И поэтому я изменил свой код на:

DataColumn dcGeom = new DataColumn("TrapGeom", typeof(DbGeometry));
...
dtTrap.Rows[i]["TrapGeom"] = DbGeometry.PointFromText(pointWellKnownText: stPoint, coordinateSystemId: SRID);

И это, кажется, разбирать просто отлично. Хотя, последняя часть поста меня беспокоит:

SQL Server настаивает на существовании SRID, хотя на самом деле вы не можете сделать с ним ничего полезного, например, преобразовать одну систему координат в другую. Это может стать действительно запутанным, если вы случайно смешаете геометрию с различными Srid, так как вы просто не получите никаких результатов (witout предупреждение, но это в сторону).

И так, когда я наконец сделаю if (Trap1.Distance(Trap2) > 100000)... тогда я наполовину ожидаю, что он выйдет из строя, когда у меня есть две разные точки в разных Srid. Я проверю и напишу комментарий о том, что я найду.

Для лучшей отладки этой ошибки я рекомендую сначала проверить ваши входные данные.

string point = "";
try
{
    string point = "POINT(" + dtTrap.Rows[i][intEastingIndex].ToString() + " " + dtTrap.Rows[i][intNorthingIndex].ToString() + ")";

    dtTrap.Rows[i]["TrapGeog"] = DbGeography.PointFromText(pointWellKnownText: point, coordinateSystemId: SRID);
}
catch (Exception ex)
{
    System.Diagnostics.Debug.WriteLine("correct point? " + point);
    if (ex.InnerException != null)
    {
        MessageBox.Show(ex.InnerException.Message + " at " + point);
    }
    else
    {
        MessageBox.Show(ex.Message);
    }
}

Я предполагаю, что в вашей строке вместо точки или есть некоторая запятая .