解析MSDN几何数据类型

5 投票
2 回答
2148 浏览
提问于 2025-04-16 02:38

我有一个数据库,其中有一个字段存储空间坐标。我了解到这个字段是一个序列化的MSDN几何数据类型(http://msdn.microsoft.com/en-us/library/bb933973.aspx)。

我想用Python访问这个数据库,但不太清楚几何数据类型的格式是什么,或者有没有什么库可以把它解析成一组地理坐标。

链接中提到,微软在设计这个数据类型时使用了“开放地理空间联盟(OGC)标准”,这是否意味着这些空间坐标是按照这个标准来定义的呢?

有没有其他人有相关的经验呢?

任何帮助都将非常感谢!

2 个回答

1

"…如果有人知道几何 [数据类型] 的格式…"

SQL Server 的空间 GEOMETRYGEOGRAPHY 类型的二进制序列化格式在这里有说明:

[MS-SSCLRT]: Microsoft SQL Server CLR 类型序列化格式

"指定了由 SQL Server 管理的 GEOGRAPHY、GEOMETRY、HIERARCHYID 和 CLR 用户定义类型 (UDT) 结构的二进制格式."

这个说明写得很好,二进制格式也很容易理解,所以自己实现一个基本的解析器应该不成问题。

"…或者任何能够将其解析为一组 [地理坐标] 的 Python 库…"

通过 .NET 互操作使用 Microsoft.SqlServer.Types 来反序列化这些类型:

如果你不想自己实现反序列化器(其实应该挺简单的),但你可以找到一种方法从 Python 与 .NET 程序库进行交互——也许可以通过 pythonnet?——那么以下提示可能会对你有帮助:

这两个 T-SQL 类型 GEOMETRYGEOGRAPHY 是通过一个 .NET 程序库(Microsoft.SqlServer.Types)来实现的,它负责将数据从上面提到的二进制格式进行反序列化和序列化,还有一个非托管的 DLL(SqlServerSpatial….dll),里面几乎包含了所有其他内容(也就是空间操作的相关功能)。

如果你只对反序列化 SQL Server 的空间数据感兴趣,并且小心不要在 SqlGeometrySqlGeography 上调用任何空间函数,那么你可以使用 Microsoft.SqlServer.Types 来为你反序列化空间二进制数据,然后 使用你需要提供给 SqlGeometry.Populate 方法的 IGeometrySink110 实现来检查它

Microsoft.SqlServer.TypesSqlServerSpatial….dll 可以作为一个 .NET 项目的 NuGet 包,或者作为一个系统范围的 MSI 安装包 (SQLSysClrTypes.msi)。据我所知,这些 DLL 也会在安装 SQL Server 时自动安装。

已知文本 (WKT) 和已知二进制 (WKB):

还有一个选择是让 SQL Server 将空间值转换为已知文本 (WKT) 或 已知二进制 (WKB),可以使用 SELECT geometryColumn.STAsText()SELECT geometryColumn.STAsBinary(),然后寻找一个可以解析这些标准交换格式的 Python 库。

(有一点需要注意:如果你选择这个方法,要小心你的数据中是否包含圆弧。WKT 和 WKB 数据格式有不同的版本。它们最初是在开放地理空间联盟的简单特征访问规范中指定的;那个版本不支持圆弧。对圆曲线段的支持是在 SQL/MM 第 3 部分:空间标准中添加的,而 SQL Server 实现了这个标准。)

3

根据下面评论中的讨论(感谢MarkJ!):

  • geometry是一种.NET的数据类型,但它使用了自己特定的序列化格式;你可以选择整个列,然后通过在Reflector中打开Microsoft.SqlServer.Types.dll来重新实现这一点。
  • 或者你可以利用SQL Server对这种类型的支持,从数据库中读取geometry数据的属性,比如说可以用 select geocolumn.STX, geocolumn.STY from myTable; 这样的查询。
  • 或者你可以将整个值导出为GML格式,比如用 select geocolumn.AsGml() from myTable;,这样可以被Python的几何库处理,比如http://gispython.org/http://mapnik.org/http://www.qgis.org/wiki/Python_Bindings

我原本以为SQL Server会把CLR数据类型直接作为序列化的.NET对象存储在表中,但事实证明这是错误的。

撰写回答