Python PostGIS ST_ClosestPoint 函数

1 投票
1 回答
1669 浏览
提问于 2025-04-17 08:03

我在用我的Python脚本发出一个SQL命令时遇到了困难。到目前为止,我尝试了这些,第一种例子运行得很好,但其他的都不行。

#working SQL = "SELECT ST_Distance(ST_Transform(ST_GeomFromText(%s, 4326),27700),ST_Transform(ST_GeomFromText(%s, 4326),27700));"
#newPointSQL = "SELECT ST_ClosestPoint(ST_GeomFromText(%s),ST_GeomFromText(%s));"
#newPointSQL = "SELECT ST_As_Text(ST_ClosestPoint(ST_GeomFromText(%s), ST_GeomFromText(%s)));"
#newPointSQL = "SELECT ST_AsText(ST_ClosestPoint(ST_GeomFromEWKT(%s), ST_GeomFromText(%s)));"
#newPointSQL = "SELECT ST_AsText(ST_Line_Interpolate_Point(ST_GeomFromText(%s),ST_Line_Locate_Point(ST_GeomFromText(%s),ST_GeomFromText(%s))));"

newPointData = (correctionPathLine,pointToCorrect) - ( MULTILINESTRING((-3.16427109855617 55.9273798550064,-3.16462372283029 55.9273883602162)), POINT(-3.164667 55.92739)) 

我的数据提取得还不错,因为第一个SQL执行成功了。问题出在我使用ST_ClosestPoint函数的时候。有没有人能发现我哪里用错了?我是不是把ST_ClosestPoint用错了?在最后一个例子中,我确实修改了我的数据(以防有人注意到),但它还是无法执行。

1 个回答

0

我不知道你在处理什么样的几何图形,但我之前也遇到过类似的问题,特别是关于多条线段(MultiLineStrings)。我发现当多条线段无法合并时,ST_Line_Locate_Point这个函数就不管用了。你可以通过使用ST_LineMerge函数来判断多条线段是否可以合并。我根据以前的邮件列表写了一个pl/pgSQL函数,并且做了一些性能上的优化。这个函数只适用于多条线段和单条线段(LineStrings),不过可以很容易地修改成适用于多边形(Polygons)。首先,它会检查几何图形是否只有一个维度,如果是的话,你可以使用旧的ST_Line_Interpolate_Point和ST_Line_Locate_Point的组合。如果不是,那你就得对多条线段中的每一条线段都进行同样的操作。此外,我还添加了一个ST_LineMerge,以确保在1.5版本之前也能兼容:

CREATE OR REPLACE FUNCTION ST_MultiLine_Nearest_Point(amultiline geometry,apoint geometry) 
  RETURNS geometry AS
$BODY$
DECLARE
    mindistance float8;
    adistance float8;
    nearestlinestring geometry;
    nearestpoint geometry;
    simplifiedline geometry;
    line geometry;
BEGIN
        simplifiedline:=ST_LineMerge(amultiline);
        IF ST_NumGeometries(simplifiedline) <= 1 THEN
            nearestpoint:=ST_Line_Interpolate_Point(simplifiedline, ST_Line_Locate_Point(simplifiedline,apoint) );
            RETURN nearestpoint;
      END IF;
--      *Change your mindistance according to your projection, it should be stupidly big*
        mindistance := 100000; 
        FOR line IN SELECT (ST_Dump(simplifiedline)).geom as geom LOOP
                adistance:=ST_Distance(apoint,line);
            IF adistance < mindistance THEN
                mindistance:=adistance;
                nearestlinestring:=line; 
            END IF;
        END LOOP;
        RETURN ST_Line_Interpolate_Point(nearestlinestring,ST_Line_Locate_Point(nearestlinestring,apoint));
    END;
    $BODY$
      LANGUAGE 'plpgsql' IMMUTABLE STRICT; 

更新:

正如@Nicklas Avén所提到的,ST_Closest_Point()应该可以正常工作,ST_Closest_Point是在1.5版本中新增的。

撰写回答