MSSQL几何,从形状内部的点到最近的边的距离

问题描述 投票:0回答:3

我有一个形状文件,我已将其作为带有几何列的表导入到 MSSQL 中。几何柱本质上是英国海岸线的轮廓。我被要求做的是能够提供纬度/经度并计算离海岸最近的距离

我已经确定我遇到的问题是我想要找到到形状最近边缘的距离的点在形状内,因此总是返回零距离。如果我尝试形状外的一个点(在海上),我会得到一个距离

我的问题是,有没有办法让SQL返回with内部的距离?如果不是那么有没有办法反转形状?

sql sql-server geometry distance
3个回答
1
投票

你的两个问题的答案都是热情的“是!”。这里。我们。去吧

(我)有办法让 SQL 返回内部距离吗?

确实有。您需要一种方法来计算多边形的边界(在本例中,多边形代表英国陆地)。虽然没有像

STBoundary()
数据类型那样的
geometry
方法,但我们可以使用
STRingN()
方法获得我们正在寻找的内容。具体来说,我们将使用
STRingN(1)
获得多边形中的第一个环(它应该代表多边形的外边界)。一个警告是,如果你有一个 MULTIPOLYGON 而不是一个普通的 POLYGON(比如,代表英格兰大陆和爱尔兰是独立的大陆的现实世界事实),你将不得不做一些工作来分别获得每个多边形的边界
STGeometryN()
然后从每个那些

中获得第一枚戒指

如果不是那么有没有办法反转形状?

幸运的是,在这种情况下我们不需要恢复到这个解决方案(但我确实赞扬你跳出框框的想法!)。我说“幸运的是”是因为它不适合一个好的/通用的解决方案。也就是说,如果该点不在英国怎么办?反转英国多边形会让您回到原来的状态。您可以在其中跳舞并执行诸如“获取到多边形及其反转的距离并取不为零的数字”之类的事情。但是反转多边形通常是一种有用的技术(因为你在形状中指定点的顺序很重要,有时你以“相反”的顺序提供它们,并最终得到整个世界的多边形和一个英国形的洞在里面)。所有这些都是冗长的说法:

ReorientObject()
方法就是您要找的。

现在对于一些完全不同的东西,一些代码:

declare @g geography = geography::STGeomFromText(
   'POLYGON ((10 11, 10 10, 11 10, 11 11, 10 11))',
   4326
),
    @p geography = geography::Point(10.5, 10.5, 4326);

-- get the distance from @p to the boundary of @g
select @g.RingN(1).STDistance(@p);

-- because I think it's neat, here's the
-- shortest line between @g and @p

select @p.ShortestLineTo(@g.RingN(1)).STLength();

-- for academics' sake, find the "inverse" of @g
select @g, @g.ReorientObject();

0
投票

如果您想要“多边形”内线串的距离或最短线,那么最好使用 MULTILINESTRING!

declare @poly geography = geography::STGeomFromText('MULTILINESTRING((
      2.644958 50.835404,  5.660705 50.779863, 5.776061 51.156926,  5.018005 51.411171, 
      4.254455 51.363178, 3.354564 51.383649,  2.545869 51.094872, 2.644958 50.835404 ))',4326)
declare @g geography = 0xE6100000011400000060487D49400000002079120C40000000005F804940000000A04B530C40

select @g
union all
select @g.ShortestLineTo(@poly)
union all
select @poly

0
投票

将 GEOGRAPHY 对象转换为 GEOMETRY,使用 STBoundary(),然后转换回来并针对新实例进行测试,现在是一个 LINESTRING:

DECLARE @geographyPolygon GEOGRAPHY = [geography]::[STGeomFromText]('POLYGON ((10 11, 10 10, 11 10, 11 11, 10 11))',4326);
DECLARE @point GEOGRAPHY = [geography]::[Point](10.5, 10.5, 4326);
-- convert to border linestring
DECLARE @geometry GEOMETRY = [geometry]::[STGeomFromWKB](@geographyPolygon.[STAsBinary](), 4326).[MakeValid]();
DECLARE @geographyBorder GEOGRAPHY = [geography]::[STGeomFromWKB](@geometry.[STBoundary]().[STAsBinary](), 4326);

SELECT
    LEFT(@geographyPolygon.[ToString](), CHARINDEX('(', @geographyPolygon.[ToString]()) - 1) AS [OriginalType]
   ,LEFT(@geographyBorder.[ToString](), CHARINDEX('(', @geographyBorder.[ToString]()) - 1) AS [BorderType]
   ,@point.[STDistance](@geographyBorder) AS [Distance];

当然你不必使用我用过的所有变量,这只是为了可读性,只需将所有代码放在一个选择中即可。

© www.soinside.com 2019 - 2024. All rights reserved.