多边形

适用于:Microsoft Fabric Microsoft Fabric SQL 数据库中Microsoft Fabric Warehouse 中的 SQL Server Azure SQL 数据库 Azure SQL 托管实例 SQL 分析终结点

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 显示接受的 多边形 实例可能不是有效的 多边形 实例。 @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 实例必须能够容纳在单个半球的内部。 任何大于半球的对象都无法存储。

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

  • 如果方法的结果不适合在单个半球内,则需要输入两个地理实例(例如,和STDifference())的地理数据类型方法(例如STIntersection()STUnion()STSymDifference())将返回 null。 STBuffer() 如果输出超过单个半球,也将返回 null。

利用 ReorientObject(geography 数据类型)扩展方法,可以反转方向。

示例

示例 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)