c# - 在 C# 中将 UTM 坐标解析为 DBGeography

标签 c# spatial

我正在用 C# 编写一个 WinForms 应用程序。我需要确保 Datatable 中的两个 Datarow 之间的距离不会超过 100 公里。每行在单独的 DataColumn 中都有一个 UTM 带、东距和北距。所有坐标都使用相同的基准,但有些具有不同的区域(否则,我将只使用 pythag 数学,因为 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 区)。

我发现很少有关于使用这些东西的文档……据我所知,我的 SRID 是正确的(我从 this site 中提取它们)。我以前用 Lat+Longs 做过这种事情,而且效果很好。我只是找不到适合 UTM 的语法。

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;
        }
    }
}

最佳答案

为了解决这个问题,我在姊妹网站上偶然发现了这篇文章 here .我认为 DbGeography 基于 SQL Server 的地理数据类型,而 DbGeometry 同样是基于几何数据类型。

一些相关的花絮:

The geography datatype, EPSG:4326, is in degrees, which is why your POINT(257306 142708) is failing, as it falls out of the (-180,180), (-90,90) range.

...

The solution ... to use a geometry datatype instead, ie, projected, not geographic.

所以我将我的代码更改为:

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

它似乎解析得很好。不过,帖子的最后一部分让我担心:

SQL Server insists on there being a SRID, even though you can't actually do anything useful with it, such as convert for one coordinate system to another. It can get really confusing if you accidentally mix geometries with different SRIDs as you will simply get no results (witout warning, but this is an aside).

因此,当我最终执行 if (Trap1.Distance(Trap2) > 100000) 时......当我在不同的 SRID 中有两个不同的点时,我有一半期望它会发生故障.我会测试并写下我发现的评论。

关于c# - 在 C# 中将 UTM 坐标解析为 DBGeography,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48835261/

相关文章:

r - 取网格化(坐标排序)年度时间数据集的 30 年平均值

R - 将空间频率数据绘制为矩阵

c# - 序列化嵌套对象 (json.net)

c# - 从代码隐藏访问 web.config key

python - 如何在 python 中漂亮地打印四叉树?

r - 计算光栅的质心

r - 如何加快从栅格中提取缓冲区中土地覆盖类型的比例?

c# - 在 SpecRun/SpecFlow 测试执行报告中插入屏幕截图

C# 线程 - resetThread 是 'variable' 但像 'method' 一样使用

c# - WPF/MVVM - 如何处理双击 ViewModel 中的 TreeViewItems?