【问题标题】:POSTGIS - find whether given point(lon, lat) is within geography column (representation of polygon) of tablePOSTGIS - 查找给定点(经度,纬度)是否在表格的地理列(多边形的表示)内
【发布时间】:2019-11-13 11:34:11
【问题描述】:

QN:对于 PostGIS 中提供的几何图形,ST_Within 函数出现错误。不确定实现 ST_Within 的第一个参数的方式是什么。

注意:变量经度和纬度是提供给函数的字符类型。但是,我无法构造传递给 ST_Within 的值。

从自定义函数中提取代码:

pointText := 'POINT(longitude ||   || latitude )';
result := (select p_code 
           from public.parking_lot 
           b where ST_Within (ST_GeomFromText(pointText)::geometry::geography,wkb_geography) limit 1);

编辑:2019 年 11 月 14 日 在@jim-jones 的建议下,我重新创建了我的函数,如下所示:

CREATE OR REPLACE FUNCTION public.returnParkingLot(
    longitude character,
    latitude character)
  RETURNS character AS
$BODY$  
declare result text;
declare pointText text;
BEGIN
    IF longitude = '0' THEN
        return '';
    ELSE

        pointText := 'POINT(' || longitude || ' ' || latitude || ')';

        result := (select p_code from public.parking_lot b where ST_Within (ST_GeomFromText(pointText),b.wkb_geography::GEOMETRY) limit 1);
        return result;
    END IF;

END;$BODY$
  LANGUAGE plpgsql VOLATILE STRICT
  COST 100;
ALTER FUNCTION public.returnParkingLot(character, character)
  OWNER TO mother;

访问: 我使用上面的函数使用 select 语句如下:

select public.returnParkingLot('103.84472222','1.28333333');

注意事项:想知道这个实现是否正确。

编辑:11 月 21 日

根据@jim-jones 的要求,更改下方用户输入的数据类型。

CREATE OR REPLACE FUNCTION public.returnParkingLot(
    longitude double precision,
    latitude double precision)
  RETURNS character AS
$BODY$  
declare result text;
declare pointText text;
BEGIN
    IF longitude = '0' THEN
        return '';
    ELSE

        pointText := 'POINT(' || longitude || ' ' || latitude || ')';

        result := (select p_code from public.parking_lot b where ST_Within (ST_GeomFromText(pointText),b.wkb_geography::GEOMETRY) limit 1);
        return result;
    END IF;

END;$BODY$
  LANGUAGE plpgsql VOLATILE STRICT
  COST 100;
ALTER FUNCTION public.returnParkingLot(double precision, double precision)
  OWNER TO mother;

选择语句:

select public.returnParkingLot(103.84472222, 1.28333333);

【问题讨论】:

    标签: postgresql gis postgis


    【解决方案1】:

    考虑到 a) pointText 包含有效的数字参数并且 b) wkb_geography 确实是地理类型,我们可以假设问题出在参数数据类型上。根据文档ST_Within 预计geometry。你可能想试试这个:

    SELECT p_code 
    FROM public.parking_lot b 
    WHERE ST_Within(ST_GeomFromText('POINT(2 2)'),b.wkb_geography::GEOMETRY);
    

    你的函数应该是这样的:

    CREATE OR REPLACE FUNCTION public.returnParkingLot(
      longitude NUMERIC,
      latitude NUMERIC) RETURNS character AS
    $BODY$  
    DECLARE result text;
    DECLARE pointText text;
    BEGIN
    IF longitude = '0' THEN
      RETURN '';
    ELSE
      pointText := 'POINT(' || longitude || ' ' || latitude || ')';
      result := (SELECT p_code FROM public.parking_lot b 
         WHERE ST_Within(ST_GeomFromText(pointText),b.wkb_geography::GEOMETRY) LIMIT 1);
      RETURN result;
    END IF;
    END;
    $BODY$ LANGUAGE plpgsql VOLATILE STRICT COST 100;
    

    测试:

    CREATE TABLE parking_lot (p_code INT, wkb_geography GEOMETRY);
    INSERT INTO parking_lot VALUES (1,'POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))');
    SELECT public.returnParkingLot(30, 11);
    
     returnparkinglot 
    ------------------
     1
    (1 Zeile)
    

    旁注: 您真的需要这么高的精度来定位停车场吗?有八位小数,您几乎处于显微镜领域。

    【讨论】:

    • 感谢您的解决方案。我已经编辑了 qn 以包括我对如何提供 lon、lat 功能的修改。请告知这是否是正确的实施。谢谢。
    • 我觉得没问题。我只是不太确定参数的数据类型。您将它们声明为字符,它们应该是数字。为避免异常,我建议更改这些数据类型:
    • 我尝试将输入数据类型替换为双精度,但给定输入仍然没有返回结果。但是数据存在于给定的表列中。除了 ST_Within,还有哪个函数可以用于返回给定点位于地理列中的数据行?
    • ST_Within 实际上应该完成这项工作。你能展示一下你的函数现在的样子吗?
    • 我在上面的 11 月 21 日添加了编辑。请检查一下。谢谢。很多。
    猜你喜欢
    • 2012-01-01
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 2012-03-21
    相关资源
    最近更新 更多