我如何告诉 SQL 服务器正确处理大多边形?
How can I tell SQL Server to treat large polygons properly?
我想在 SQL 服务器数据库中将大正方形表示为多边形。这个多边形几乎横跨整个地图。
这里是边界坐标(经纬度)
North-East Corner: { 83.4871233224387, 63.5599894667969 }
South-West Corner: { -3.62943382709019, 86.0599894667969 }
这是它在地图上的样子(这些是缩小的 google 地图的地图边界)
这是 SQL 服务器在我尝试绘制多边形时的想法:
declare @p5 sys.geography;
set @p5 = geography::STGeomFromText('POLYGON((86.0599894667969 -3.62943382709019, 63.5599894667969 -3.62943382709019, 63.5599894667969 83.4871233224387, 86.0599894667969 83.4871233224387, 86.0599894667969 -3.62943382709019))', 4326);
select @p5
它认为我没有正确遵循左手法则,但我是,我只想要一个绝对大的多边形。
如果我使用 reorientobject,我会得到相反的结果,这也不是我想要的:
将这两点绘制在地图上以供参考:
我该如何解决这个问题?
我无法以优雅的方式解释这里发生的事情,但我能够破解出一个与您正在寻找的内容非常接近的多边形:
declare @p1 geography = geography::STGeomFromText('
POLYGON((
63 83,
0 83,
0 -3,
63 -3,
63 83
))', 4326)
,@p2 geography = geography::STGeomFromText('
POLYGON((
86 83,
86 -3,
180 -3,
180 83,
86 83
))', 4326)
,@p3 geography = geography::STGeomFromText('
POLYGON((
180 83,
180 -3,
-90 -3,
-90 83,
180 83
))', 4326)
,@p4 geography = geography::STGeomFromText('
POLYGON((
-90 83,
-90 -3,
0 -3,
0 83,
-90 83
))', 4326);
select @p1.STUnion(@p2).STUnion(@p3).STUnion(@p4).STAsText();
编辑:我确实有一些时间研究它并想出了一个合理的行为解释而不是 SQL 中的错误。对于任意四个这样的点(即盒子的角),它们定义了四种不同的形状。我将根据我们在这里处理的具体案例来描述它们,但我认为它具有概括性。
这四种形状是:OP 在原始多边形上调用 ReorientObject
时获得的小框、它的补码(又名原始多边形)、所需形状和 它补充。
此外,请注意,在环中指定点的顺序并不重要。这正是我们在这里描述的内容(即环)。地理多边形不一定是,坦率地说,在一般情况下可能不是正方形。
一旦你接受了后者,那么很容易只获得四种形状中的两种,这并不是一个飞跃。还请注意,在这四个点定义的四个多边形中,其中三个非常大。所以,我猜测 SQL 有一种启发式方法,能够找出其中最小的,因为坦率地说,这更可能在现实世界的应用程序中定义。然后,根据定义点的顺序,您可以得到该多边形(即四个多边形中最小的一个)或其补码。
和本一样,我无法解释发生了什么。我对坐标顺序进行了两倍、三倍甚至四倍的检查,但找不到任何东西来确定它为什么会创建带孔的地球(本质上)。您的订单是 SW -> SE -> NE -> NW -> WS - 完全符合我的要求,我怀疑这可能是 SQL 方面的错误。
然而,有一件事立即提醒我,这些坐标不适用于 google 地图上的那个视图 - 相信我 - 我已经与他们合作太久了。估计你的坐标应该更近一些:
西南:经度 78,纬度 7
NE:长 44 纬度 83。
显示标记的 google 地图显示了为什么您的 ReorientObject() 调用实际上产生了正确的结果(即使您不需要重新定向任何东西)。
尽管如此,这里有一个更好的创建边界框的方法:
-- Define NE
declare @ne geography = geography::Point(83.4871233224387, 63.5599894667969, 4326);
- Define SW
declare @sw geography = geography::Point(-3.62943382709019, 86.0599894667969, 4326);
-- Define BOX
declare @box geography = geography::STGeomFromWKB(geometry::STGeomFromWKB(@ne.STUnion(@sw).STAsBinary(), 4326).STEnvelope().STAsBinary(), 4326);
select @box -- shows polygon
select @box.ToString -- shows WKT
有趣的是,坐标顺序被定义为好像地理是一个洞 - 它是 SE -> SW -> NW -> NE -> SE,保持内部在右边。这对 GEOMETRY 是正确的,但对 GEOGRAPHY 不正确,但它会产生正确的答案。这就是为什么我认为它可能是一个错误? - 或者我遗漏了什么。
最后,解释创建框:
- 取两个点的并集(创建一个 MULTIPOINT 类型的几何体)
- 将 MULTIPOINT 转换为几何类型
- 使用几何类型的 STEnvelope() 方法创建包含四肢的边界框
- 转换为 BOX (POLYGON) 返回地理类型
希望对您(以及其他任何人)有所帮助。
我想在 SQL 服务器数据库中将大正方形表示为多边形。这个多边形几乎横跨整个地图。
这里是边界坐标(经纬度)
North-East Corner: { 83.4871233224387, 63.5599894667969 }
South-West Corner: { -3.62943382709019, 86.0599894667969 }
这是它在地图上的样子(这些是缩小的 google 地图的地图边界)
这是 SQL 服务器在我尝试绘制多边形时的想法:
declare @p5 sys.geography;
set @p5 = geography::STGeomFromText('POLYGON((86.0599894667969 -3.62943382709019, 63.5599894667969 -3.62943382709019, 63.5599894667969 83.4871233224387, 86.0599894667969 83.4871233224387, 86.0599894667969 -3.62943382709019))', 4326);
select @p5
它认为我没有正确遵循左手法则,但我是,我只想要一个绝对大的多边形。
如果我使用 reorientobject,我会得到相反的结果,这也不是我想要的:
将这两点绘制在地图上以供参考:
我该如何解决这个问题?
我无法以优雅的方式解释这里发生的事情,但我能够破解出一个与您正在寻找的内容非常接近的多边形:
declare @p1 geography = geography::STGeomFromText('
POLYGON((
63 83,
0 83,
0 -3,
63 -3,
63 83
))', 4326)
,@p2 geography = geography::STGeomFromText('
POLYGON((
86 83,
86 -3,
180 -3,
180 83,
86 83
))', 4326)
,@p3 geography = geography::STGeomFromText('
POLYGON((
180 83,
180 -3,
-90 -3,
-90 83,
180 83
))', 4326)
,@p4 geography = geography::STGeomFromText('
POLYGON((
-90 83,
-90 -3,
0 -3,
0 83,
-90 83
))', 4326);
select @p1.STUnion(@p2).STUnion(@p3).STUnion(@p4).STAsText();
编辑:我确实有一些时间研究它并想出了一个合理的行为解释而不是 SQL 中的错误。对于任意四个这样的点(即盒子的角),它们定义了四种不同的形状。我将根据我们在这里处理的具体案例来描述它们,但我认为它具有概括性。
这四种形状是:OP 在原始多边形上调用 ReorientObject
时获得的小框、它的补码(又名原始多边形)、所需形状和 它补充。
此外,请注意,在环中指定点的顺序并不重要。这正是我们在这里描述的内容(即环)。地理多边形不一定是,坦率地说,在一般情况下可能不是正方形。
一旦你接受了后者,那么很容易只获得四种形状中的两种,这并不是一个飞跃。还请注意,在这四个点定义的四个多边形中,其中三个非常大。所以,我猜测 SQL 有一种启发式方法,能够找出其中最小的,因为坦率地说,这更可能在现实世界的应用程序中定义。然后,根据定义点的顺序,您可以得到该多边形(即四个多边形中最小的一个)或其补码。
和本一样,我无法解释发生了什么。我对坐标顺序进行了两倍、三倍甚至四倍的检查,但找不到任何东西来确定它为什么会创建带孔的地球(本质上)。您的订单是 SW -> SE -> NE -> NW -> WS - 完全符合我的要求,我怀疑这可能是 SQL 方面的错误。
然而,有一件事立即提醒我,这些坐标不适用于 google 地图上的那个视图 - 相信我 - 我已经与他们合作太久了。估计你的坐标应该更近一些:
西南:经度 78,纬度 7 NE:长 44 纬度 83。
显示标记的 google 地图显示了为什么您的 ReorientObject() 调用实际上产生了正确的结果(即使您不需要重新定向任何东西)。
尽管如此,这里有一个更好的创建边界框的方法:
-- Define NE
declare @ne geography = geography::Point(83.4871233224387, 63.5599894667969, 4326);
- Define SW
declare @sw geography = geography::Point(-3.62943382709019, 86.0599894667969, 4326);
-- Define BOX
declare @box geography = geography::STGeomFromWKB(geometry::STGeomFromWKB(@ne.STUnion(@sw).STAsBinary(), 4326).STEnvelope().STAsBinary(), 4326);
select @box -- shows polygon
select @box.ToString -- shows WKT
有趣的是,坐标顺序被定义为好像地理是一个洞 - 它是 SE -> SW -> NW -> NE -> SE,保持内部在右边。这对 GEOMETRY 是正确的,但对 GEOGRAPHY 不正确,但它会产生正确的答案。这就是为什么我认为它可能是一个错误? - 或者我遗漏了什么。
最后,解释创建框:
- 取两个点的并集(创建一个 MULTIPOINT 类型的几何体)
- 将 MULTIPOINT 转换为几何类型
- 使用几何类型的 STEnvelope() 方法创建包含四肢的边界框
- 转换为 BOX (POLYGON) 返回地理类型
希望对您(以及其他任何人)有所帮助。