Postgis几何图形边界上最近的两个点

29

我有一个名为geofences的表,其中存储了多边形的geometry

我还有一个点A,它在这个几何体内部。我的目标是找到距离点A最近且在多边形几何体表面上的两个点。

在PostGIS中使用的函数:

CREATE OR REPLACE FUNCTION accuracyCheck(Polygon geometry
                                        ,decimal lat
                                        ,decimal lon)
  RETURNS VARCHAR AS
$BODY$

DECLARE height DECIMAL;
DECLARE accuracy VARCHAR(250);

BEGIN 

CREATE TEMPORARY TABLE closePointStorage AS
SELECT ST_AsText(ST_ClosestPoint(geometry
                                ,ST_GeomFromText('POINT(lat lon)',0)
                                )
                ) AS closestPoint
FROM  (
   SELECT ST_GeomFromText(geometry) as geometry
   FROM gfe_geofences
   WHERE is_active=true
   ) As tempName;

CREATE TEMPORARY TABLE areaStorage ON COMMIT DROP AS
SELECT ST_Area(ST_GeomFromText('Polygon((23.0808622876029 96.1304006624291
                                        ,28.0808622876029 99.1304006624291
                                        ,100              200
                                        ,23.0808622876029 96.1304006624291
                                        ))'
                              ,0)
              ) AS area;

CREATE TEMPORARY TABLE distanceStorage ON COMMIT DROP AS
SELECT ST_Distance(
          ST_GeomFromText('POINT(23.0808622876029 96.1304006624291)',-1)
         ,ST_GeomFromText('POINT(28.0808622876029 99.1304006624291)',-1)
         ) AS distance;

height = (SELECT area FROM areaStorage)
        /(0.5*(SELECT distance FROM distanceStorage));

IF height < (SELECT radius_meters
             FROM gfe_geofences Where is_active=true) THEN
   accuracy = "FullConfirm";
   RETURN accuracy;
ELSE
   accuracy = "PartiallyConfirm";
   RETURN accuracy;
END IF;

END;
$BODY$ LANGUAGE plpgsql;

我只想找到多边形几何图形边界上的两个点。就像我从查询中找到了一个点:

CREATE TEMPORARY TABLE closePointStorage AS
SELECT ST_AsText(ST_ClosestPoint(geometry
                                ,ST_GeomFromText('POINT(lat lon)',0)
                                )
                ) AS closestPoint 
FROM  (
   SELECT ST_GeomFromText(geometry) as geometry
   FROM gfe_geofences
   WHERE is_active=true
   ) 
AS tempName;

除此之外,我还需要找到一个距离比上面找到的点更远但比其他点更近的点。


1
你添加的注释非常难以解读。请更新你的问题,使用适当的格式来描述它的目的。同时,请对你的问题中的大函数进行一些解释:它应该做什么?它在哪里失败了?结果应该是什么样子的(例如值的示例)? - Erwin Brandstetter
如果你关心线段上的点,那么第二近的点就没有明确定义。想象一下你有一条直线y=1,和一个点x=2,y=2。这条直线上最接近的点是x=2,y=1。第二近的点将会“紧贴”在x=2,y=1旁边,但是对于你选择的任何一个点(比如说x=2.01,y=1),都会有另一个更近的点(x=2.005,y=1)。 - Cirdec
我想主要问题是“你想实现什么,为什么需要这两个点”。 - Markus Mikkolainen
如果多边形是对称三角形或正方形,且点A位于中心,则会出现3或4个等距离的点,该怎么办? - Markus Mikkolainen
问题不清楚,作者忽略了澄清的要求。 - Erwin Brandstetter
显示剩余3条评论
4个回答

1
使用ST_DumpPoints()来转储多边形的点,然后从中选择按照ST_Distance到A排序,限制为2个。所以大致是这样的。
SELECT * from ST_DumpPoints(poly) order by ST_Distance(A,geom) asc limit 2;

(假设这是一个内部选择,其中poly是多边形,A是要与之比较的点,geom是要比较的多边形中一个点的geom列)


这将自然地不会选择线上的点,只会选择多边形定义中的点。如果您可以按距离的平方对它们进行排序,那么速度会更快。 - Markus Mikkolainen

1
我假设您想找到多边形的边缘,以便最接近所问点。

distance from line problem

要获取点'C'到线段[A,B]的距离'd' 首先将所有点翻译,使得点A位于0,0

B -= A  //vector subtraction
C -= A

然后将B归一化,使其长度为1.0。
len = sqrt( B . B) //dotproduct of two vectors is the length squared
B /= len  //scalar divide by length

从A点出发,沿着与C垂直的方向寻找长度

dotp = B . C  //dot product again
closestPointOnLine =  B * dotp  //scalar multiply

现在获取距离。
diff = (C - ClosestPointOnLine)
d = sqrt(diff . diff)  

不确定如何在SQL中执行此操作。您需要针对多边形上的每个边执行以上操作,然后找到最小值“d”。

顺便提一下,B和C的叉积的符号现在将告诉您该点是否在多边形内部。


你的算法很好且易于理解,你做得很棒。我会尝试在SQL中使用相同的算法,因为我的依赖关系需要在SQL中实现这种算法。 - Satish Sharma

1

通常情况下,在边界多边形上,如果包括线条,则不存在第二个最接近的点。就像零没有第二个最接近的实数一样。 要么你只考虑像马库斯建议的那样在角落处的点。 要么你只有一个最接近的点。


1

1) 这是一个有点出人意料的想法,但是要找到离你目的地第二近的点,为什么不先找到最接近的点呢?

2) 或者更贴切于你的具体问题,

  • 找到一定范围内的点集,
  • 找到该集合与多边形边界上的点集的交集(我猜这可能是另一个PostGIS函数;我已经有一段时间没有使用过postG,所以不确定)

3) 更进一步,将你的数据集转储到Mongo中,并使用$near函数... http://docs.mongodb.org/manual/reference/operator/near/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接