多边形
适用于: SQL Server Azure SQL 数据库 Azure SQL 托管实例
Polygon 是存储为一系列点的二维表面,这些点定义一个外部边界环和零个或多个内部环。
Polygon 实例
可以从至少具有三个不同点的环中构建一个 Polygon 实例。 Polygon 实例也可以为空。
Polygon 的外部环和任意内部环定义了其边界。 环内部的空间定义了 Polygon 的内部。
下图显示了 Polygon 实例的示例。
如图中所示:
图 1 是由外部环定义其边界的 Polygon 实例。
图 2 是由外部环和两个内部环定义其边界的 Polygon 实例。 内部环内的面积是 Polygon 实例的外部环的一部分。
图 3 是一个有效的 Polygon 实例,因为其内部环在单个切点处相交。
接受的实例
已接受的 Polygon 实例是可以在不引发异常的情况下存储到 geometry 或 geography 变量中的实例。 下面是一些已接受的 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)
。 如果给出的 Polygon
是 POLYGON((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 数据类型)