PLPGSQL Function to Calculate Bearing

。_饼干妹妹 提交于 2019-12-09 03:48:08

问题


Basically I can't get my head around the syntax of plpgsql and would appreciate some help with the following efforts. I have a table containing 1000's of wgs84 points. The following SQL will retrieve a set of points within a bounding box on this table:

SELECT id, ST_X(wgs_geom), ST_Y(wgs_geom), ST_Z(wgs_geom) 
  FROM points_table 
  INNER JOIN 
   (SELECT ST_Transform(ST_GeomFromText('POLYGON((-1.73576102027 1.5059743629,
     -1.73591122397 51.5061067655,-1.73548743495 51.5062838333,-1.73533186682 
      1.5061514313,-1.73576102027 51.5059743629))', 4326, 27700)
   ) AS bgeom
  ) AS t2 
ON ST_Within(local_geom, t2.bgeom)

What I need to do is add a bearing/azimuth column to the results that describes the bearing at each point in the returned data set. So the approach I'm trying to implement is to build a plpgsql function that can select the data as per above and calculate the bearing between each set of points in a loop. However my efforts at understanding basic data access and handling within a plpgsql function are failing miserably.

An example of the current version of the function I'm trying to create is as follows:

CREATE TYPE bearing_type AS (x numeric, y numeric, z numeric, bearing numeric);

--DROP FUNCTION IF EXISTS get_bearings_from_points();

CREATE OR REPLACE FUNCTION get_bearings_from_points()
   RETURNS SETOF bearing_type AS

$BODY$

DECLARE
    rowdata points_table%rowtype;
    returndata bearing_type;

BEGIN
    FOR rowdata IN
        SELECT nav_id, wgs_geom 
          FROM points_table INNER JOIN 
             (SELECT ST_Transform(ST_GeomFromText('POLYGON((-1.73576102027
                3.5059743629,-1.73591122397 53.5061067655,-1.73548743495 
                53.5062838333,-1.73533186682 53.5061514313,-1.73576102027 
                53.5059743629))', 4326), 27700) 
             AS bgeom) 
          AS t2 ON ST_Within(local_geom, t2.bgeom)
    LOOP
        returndata.x := ST_X(rowdata.wgs_geom);
        returndata.y := ST_Y(rowdata.wgs_geom);
        returndata.z := ST_Z(rowdata.wgs_geom);
        returndata.bearing := ST_Azimuth(<current_point> , <next_point>)
    RETURN NEXT returndata;
    END LOOP;
    RETURN;
END

$BODY$
LANGUAGE plpgsql;

I would like to just call this function as follows:

SELECT get_bearings_from_points();

and get the desired result. Basically the problems are understanding how to access the rowdata properly such that I can read the current and next points.

In the above example I've had various problems from how to call the ST_X etc SQL functions and have tried EXECUTE select statements with errors re geometry data types.

Any insights/help would be much appreciated.


回答1:


In PL/pgSQL it's most effective to do as much as is elegantly possible in basic SQL queries at once. You can largely simplify.

I didn't get a definition of the sort order out of your question and left ??? to fill in for you:

CREATE OR REPLACE FUNCTION get_bearings_from_points(_bgeom geometry)
  RETURNS TABLE (x numeric, y numeric, z numeric, bearing numeric) AS
$func$
BEGIN
   FOR x, y, z, bearing IN
      SELECT ST_X(t.wgs_geom), ST_Y(t.wgs_geom), ST_Z(t.wgs_geom)
           , ST_Azimuth(t.wgs_geom, lead(t.wgs_geom) OVER (ORDER BY ???))
      FROM   points_table t
      WHERE  ST_Within(t.local_geom, _bgeom)
      ORDER  BY ???
   LOOP
      RETURN NEXT;
   END LOOP;
END
$func$ LANGUAGE plpgsql;

The window function lead() references a column from the next row according to sort order.

This can be simplified further to a single SQL query - possibly wrapped into an SQL function:

CREATE OR REPLACE FUNCTION get_bearings_from_points(_bgeom geometry)
  RETURNS TABLE (x numeric, y numeric, z numeric, bearing numeric) AS
$func$
   SELECT ST_X(t.wgs_geom), ST_Y(t.wgs_geom), ST_Z(t.wgs_geom)
        , ST_Azimuth(t.wgs_geom, lead(t.wgs_geom) OVER (ORDER BY ???))
   FROM   points_table t
   WHERE  ST_Within(t.local_geom, $1)  -- use numbers in pg 9.1 or older
   ORDER  BY ???
$func$ LANGUAGE sql;

Parameter names can be referenced in pg 9.2 or later. Per release notes of pg 9.2:

Allow SQL-language functions to reference parameters by name (Matthew Draper)



来源:https://stackoverflow.com/questions/27110599/plpgsql-function-to-calculate-bearing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!