我已经编写了这个基本代码,它首先从多边形中提取多边形,然后是与内圆和外圆相对应的特定LineStrings:
DECLARE @SomeMultiPolygon GEOGRAPHY = 'MULTIPOLYGON (
((-2 -2, 2 -2, 2 2, -2 2, -2 -2), (-1 -0.5, 0 -0.5, 0 -1.5, -1 -1.5, -1 -0.5), (0 1, 1 1, 1 0, 0 0, 0 1))
, ((-4 -3, -4 -5, 0 -5, 0 -3, -4 -3)))';
SET @SomeMultiPolygon.STSrid = 4326;
DECLARE @i int = 1
DECLARE @Results TABLE ( Id INT IDENTITY(1,1), PolygonData GEOGRAPHY )
WHILE @i <= @SomeMultiPolygon.STNumGeometries()
BEGIN
INSERT INTO @Results VALUES (@SomeMultiPolygon.STGeometryN(@i))
SET @i = @i + 1
END
SELECT
Id,
PolygonData.STGeometryType(),
PolygonData,
PolygonData.STAsText() AS PolygonWkt,
PolygonData.NumRings() AS NumberOfRings
FROM @Results
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL
DROP TABLE #Temp
CREATE TABLE #Temp
(
ParentId INT,
SubPolygon GEOGRAPHY
)
DECLARE @Id INT, @InnerLoop INT, @SubPolygon GEOGRAPHY;
SELECT @Id = MAX(Id) FROM @Results
WHILE @Id >= 1
BEGIN
SELECT @InnerLoop = PolygonData.NumRings() FROM @Results WHERE Id = @Id
WHILE @InnerLoop > 0
BEGIN
SELECT @SubPolygon = PolygonData.RingN(@InnerLoop) FROM @Results WHERE Id = @Id
INSERT INTO #Temp
( ParentId, SubPolygon )
VALUES ( @Id,
@SubPolygon
)
SET @InnerLoop = @InnerLoop - 1;
END
SET @Id = @Id - 1
END
SELECT
*,
SubPolygon.STAsText() AS SubPolygonText,
SubPolygon.EnvelopeAngle() AS EnvelopeAngle
FROM #Temp
我是否正确地假设,如果EnvelopeAngle小于1度,则LineString对应于内圈?
顺便说一句,是否有基于集合的方法来实现上述目标 - 我并不是TSql中循环的粉丝。PS:
这是上述示例的可视化:
答案 0 :(得分:1)
按顺序回答您的问题:
我是否正确地假设,如果EnvelopeAngle小于1度,LineString对应一个内圈?
没有。这是您的测试数据的工件,但您不能一般地做出这个断言。你的问题来得很愉快,因为前几天我刚刚了解了EnvelopeAngle。我喜欢将它视为&#34;这个对象有多宽(以度为单位)?&#34;。如果您向上或向下重新缩放所有对象,则EnvelopeAngle启发式不再有效。
但是,我可能尝试的启发式是针对结果表中的给定ID,最大(按区域)是包含其他ID的那个。你也可以玩STDifference,但区域似乎最直接。
[我]有一套基于集合的方法来实现上述目标吗? - 我真的不喜欢TSql中的循环。
是的!这是:
DECLARE @SomeMultiPolygon GEOGRAPHY = 'MULTIPOLYGON (
(
(-2 -2, 2 -2, 2 2, -2 2, -2 -2),
(-1 -0.5, 0 -0.5, 0 -1.5, -1 -1.5, -1 -0.5),
(0 1, 1 1, 1 0, 0 0, 0 1)
)
, (
(-4 -3, -4 -5, 0 -5, 0 -3, -4 -3)
)
)';
SET @SomeMultiPolygon.STSrid = 4326;
DECLARE @Results TABLE (
Id INT IDENTITY(1,1),
PolygonData GEOGRAPHY
);
INSERT INTO @Results
( [PolygonData] )
SELECT @SomeMultiPolygon.STGeometryN([n].[n])
FROM Util.dbo.[Numbers] AS [n]
WHERE n <= @SomeMultiPolygon.STNumGeometries();
SELECT
Id,
PolygonData.STGeometryType(),
PolygonData,
PolygonData.STAsText() AS PolygonWkt,
PolygonData.NumRings() AS NumberOfRings
FROM @Results;
CREATE TABLE #Temp (
ParentId INT,
SubPolygon GEOGRAPHY
);
INSERT INTO [#Temp]
( [ParentId], [SubPolygon] )
SELECT r.ID, rings.[ring]
FROM @Results AS [r]
CROSS APPLY (
SELECT r.[PolygonData].RingN(n) AS ring
FROM [Util].[dbo].[Numbers] AS [n]
WHERE n <= r.[PolygonData].NumRings()
) AS rings;
SELECT
*,
SubPolygon.STAsText() AS SubPolygonText,
SubPolygon.EnvelopeAngle() AS EnvelopeAngle
FROM #Temp