多边形

适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例

Polygon 是存储为一系列点的二维表面,这些点定义一个外部边界环和零个或多个内部环。

Polygon 实例

可以从至少具有三个不同点的环中构建一个 Polygon 实例。 Polygon 实例也可以为空。

Polygon 的外部环和任意内部环定义了其边界。 环内部的空间定义了 Polygon 的内部。

下图显示了 Polygon 实例的示例。

几何 Polygon 实例的示例

如图中所示:

  1. 图 1 是由外部环定义其边界的 Polygon 实例。

  2. 图 2 是由外部环和两个内部环定义其边界的 Polygon 实例。 内部环内的面积是 Polygon 实例的外部环的一部分。

  3. 图 3 是一个有效的 Polygon 实例,因为其内部环在单个切点处相交。

接受的实例

已接受的 Polygon 实例是可以在不引发异常的情况下存储到 geometrygeography 变量中的实例。 下面是一些已接受的 Polygon 实例:

  • 空的 Polygon 实例
  • 包含一个可接受外部环 (LineString) 和零个或多个可接受内部环 (LineString) 的 Polygon 实例

为了让环 (LineString) 可接受,必须满足以下条件。

  • LineString 实例必须是已接受的实例。
  • LineString 实例至少必须有四个点。
  • LineString 实例的起始点和结束点必须相同。

下面的示例显示接受的 Polygon 实例。

DECLARE @g1 geometry = 'POLYGON EMPTY';  
DECLARE @g2 geometry = 'POLYGON((1 1, 3 3, 3 1, 1 1))';  
DECLARE @g3 geometry = 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5),(0 0, 3 0, 3 3, 0 3, 0 0))';  
DECLARE @g4 geometry = 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5),(3 0, 6 0, 6 3, 3 3, 3 0))';  
DECLARE @g5 geometry = 'POLYGON((1 1, 1 1, 1 1, 1 1))';  

@g4@g5 显示接受的 Polygon 实例可能不是有效的 Polygon 实例。 @g5 还显示 Polygon 实例只需包含一个具有任意四个点的环便可以被接受。

以下示例引发 System.FormatException ,因为 Polygon 实例未被接受。

DECLARE @g1 geometry = 'POLYGON((1 1, 3 3, 1 1))';  
DECLARE @g2 geometry = 'POLYGON((1 1, 3 3, 3 1, 1 5))';  

@g1 未被接受,因为外部环的 LineString 实例不包含足够的点。 @g2 未被接受,因为外部环 LineString 实例的起始点与结束点不同。 以下示例有一个可接受的外部环,但内部环不可接受。 这也会引发 System.FormatException

DECLARE @g geometry = 'POLYGON((-5 -5, -5 5, 5 5, 5 -5, -5 -5),(0 0, 3 0, 0 0))';  

有效实例

Polygon 的内部环在单个切点处既可与自身接触也可彼此接触,但如果 Polygon 的内部环交叉,则该实例无效。

下面的示例显示有效的 Polygon 实例。

DECLARE @g1 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20))';  
DECLARE @g2 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0))';  
DECLARE @g3 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 0 10, -5 -10, -10 0))';  
SELECT @g1.STIsValid(), @g2.STIsValid(), @g3.STIsValid();  

@g3 有效,因为两个内部环在一个点相切并且没有相互交叉。 以下示例显示无效的 Polygon 实例。

DECLARE @g1 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (20 0, 0 10, 0 -20, 20 0))';  
DECLARE @g2 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (5 0, 1 5, 1 -5, 5 0))';  
DECLARE @g3 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 0 10, 0 -10, -10 0))';  
DECLARE @g4 geometry = 'POLYGON((-20 -20, -20 20, 20 20, 20 -20, -20 -20), (10 0, 0 10, 0 -10, 10 0), (-10 0, 1 5, 0 -10, -10 0))';  
DECLARE @g5 geometry = 'POLYGON((10 0, 0 10, 0 -10, 10 0), (-20 -20, -20 20, 20 20, 20 -20, -20 -20) )';  
DECLARE @g6 geometry = 'POLYGON((1 1, 1 1, 1 1, 1 1))';  
SELECT @g1.STIsValid(), @g2.STIsValid(), @g3.STIsValid(), @g4.STIsValid(), @g5.STIsValid(), @g6.STIsValid();  

@g1 无效,因为内部环在两个位置接触外部环。 @g2 无效,因为第二个内部环位于第一个内部环的内部。 @g3 无效,因为两个内部环在多个连续点接触。 @g4 无效,因为两个内部环的内部重叠。 @g5 无效,因为外部环不是第一个环形。 @g6 无效,因为环未至少具有三个不同的点。

空间数据的方向

在平面系统中,多边形的环方向并非重要因素。 SQL 规范的 OGC 简单特征未规定环顺序,并且 SQL Server 不会强制实施环的顺序。

在椭圆体系统中,没有方向的多边形无意义,或者模糊不清。 例如,赤道周围的环是否描述了北半球或南半球? 如果我们使用 geography 数据类型存储空间实例,必须指定环的方向并准确地描述实例的位置。

椭圆系统中的多边形的内部是由“左手定则”定义的:如果你想象自己沿着一个地理多边形的环行走,按照点的排列顺序,左边的区域被视为多边形的内部,右边的区域被视为多边形的外部。

逆时针方向

DECLARE @square GEOGRAPHY;
SET @square = GEOGRAPHY::STPolyFromText('POLYGON((0 20, 0 0, 20 0, 20 20, 0 20))', 4326);
SELECT @square;

“左侧规则”逆时针方向的可视化效果

顺时针方向

DECLARE @square GEOGRAPHY;
SET @square = GEOGRAPHY::STPolyFromText('POLYGON((0 20, 20 20, 20 0, 0 0, 0 20))', 4326);
SELECT @square;

“左侧规则”顺时针方向的可视化效果

在 SQL Server 中当兼容级别为 100 或更低时,geography 数据类型具有以下限制:

  • 每个 geography 实例必须能够容纳在单个半球的内部。 任何大于半球的对象都无法存储。

  • 使用开放地理空间联盟 (OGC) 熟知文本 (Well-Known Text, WKT) 或熟知二进制 (Well-Known Binary, WKB) 表示形式并且会产生大于一个半球的对象的任何 geography 实例都会引发一个 ArgumentException。

  • 如果方法的结果不能容纳于单个半球内部,则需要输入两个 geography 实例的 geography 数据类型方法(如 STIntersection()、STUnion()、STDifference() 和 STSymDifference())将会返回 Null。 如果输出超过单个半球,STBuffer() 也将返回 Null。

利用 ReorientObject 扩展方法可以反转方向。

示例

示例 A。

以下示例创建了一个带有间隙且 SRID 为 10 的简单 geometry Polygon 实例。

DECLARE @g geometry;  
SET @g = geometry::STPolyFromText(
    'POLYGON((0 0, 0 3, 3 3, 3 0, 0 0), (1 1, 1 2, 2 1, 1 1))',
    10);

示例 B。

可能输入无效的实例并转换为有效的 geometry 实例。 在以下 Polygon 示例中,内部环和外部环重叠且该实例无效。

DECLARE @g geometry;  
SET @g = geometry::Parse(
    'POLYGON((1 0, 0 1, 1 2, 2 1, 1 0), (2 0, 1 1, 2 2, 3 1, 2 0))'
    );  

示例 C.

在下面的示例中,无效实例通过 MakeValid()成为有效实例。

SET @g = @g.MakeValid();  
SELECT @g.ToString();  

以上示例中返回的 geometry 实例为 MultiPolygon

MULTIPOLYGON (((2 0, 3 1, 2 2, 1.5 1.5, 2 1, 1.5 0.5, 2 0)),
              ((1 0, 1.5 0.5, 1 1, 1.5 1.5, 1 2, 0 1, 1 0)))

示例 D。

下面是另一个演示将无效实例转换为有效的几何图形实例的示例。 在下面的示例中,已经使用完全相同的三个点创建了 Polygon 实例:

DECLARE @g geometry  
SET @g = geometry::Parse('POLYGON((1 3, 1 3, 1 3, 1 3))');  
SET @g = @g.MakeValid();  
SELECT @g.ToString()  

上面返回的几何图形实例是 Point(1 3)。 如果给出的 PolygonPOLYGON((1 3, 1 5, 1 3, 1 3)) ,则 MakeValid() 将返回 LINESTRING(1 3, 1 5)

另请参阅

STArea(geometry 数据类型)
STExteriorRing(geometry 数据类型)
STNumInteriorRing(geometry 数据类型)
STInteriorRingN(geometry 数据类型)
STCentroid(geometry 数据类型)
STPointOnSurface(geometry 数据类型)
MultiPolygon
空间数据 (SQL Server)
STIsValid(geography 数据类型)
STIsValid(geometry 数据类型)