[postgis-users] Reducing the number of points in a GPS track

Alexandre Saunier alexandre.saunier at camptocamp.com
Fri Nov 9 06:44:44 PST 2012


Hi Birgit and Olivier,

thank you so much for your code and tips!

Birgit, your function works fine. I have made some small changes
though. For instance, I have added a "step" argument that allows to
easily adapt the value of the tolerance increment and avoid doing too
many iterations because of a too small step (in my project, using
"meter" as unit, 0.001 is a little too small, I have used a value of
1). Here is the function:

CREATE OR REPLACE FUNCTION simplify_npoints(inGeom geometry, maxPoints
integer, step float)
  RETURNS geometry AS
$BODY$

DECLARE
  tolerance float;
  outGeom geometry;

BEGIN

  outGeom := inGeom;
  tolerance := step;

  WHILE ST_NPoints(outGeom) > maxPoints LOOP
    tolerance := tolerance + step;
    outGeom := ST_Simplify(inGeom, tolerance);
  END LOOP;

  RETURN outGeom;

END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;

> A way could be to :
>  - Compute length of your road with ST_Length
>  - Use ST_Line_Interpolate_Point to compute each point on your line
>  - Aggregate all points computed in a new simplified line with ST_MakeLine

Is it really necessary to compute the length of the road?
ST_Line_Interpolate_Point takes as second argument a float between 0
and 1 (percentage of the line length).
I have written a small function that picks a given number of
equidistant points on the line and then recreates a new line linking
those points:

CREATE OR REPLACE FUNCTION simplify_npoints(inGeom geometry, maxPoints
integer) RETURNS geometry AS $$

DECLARE
  nPoints integer;
  outGeom geometry;
  fraction float;
  points geometry[];
BEGIN

  nPoints := ST_NPoints(inGeom);
  outGeom := inGeom;

  IF nPoints > maxPoints THEN
    fraction := 1 / (maxPoints - 1);
    FOR i IN 1..maxPoints LOOP
      points := array_append(points, ST_Line_Interpolate_Point(inGeom,
(i - 1)*fraction));
    END LOOP;

    outGeom := ST_MakeLine(points);
  END IF;

  RETURN outGeom;

END;
$$ LANGUAGE plpgsql IMMUTABLE;

I have not really been able to test it because my version of PostGIS
is too old (1.3) and does not support arrays of geometry as argument
of ST_MakeLine.

Thanks again!
Alexandre


2012/10/25 Olivier Courtin <olivier.courtin at oslandia.com>:
>
> On Oct 24, 2012, at 2:29 PM, Alexandre Saunier wrote:
>
> Hi Alex,
>
>> A bit like the "simplify,count=<...>" filter in GPSBabel:
>> http://www.gpsbabel.org/htmldoc-development/filter_simplify.html
>>
>> Is there a way to do that kind of simplification with PostGIS?
>
> A way could be to :
>  - Compute length of your road with ST_Length
>  - Use ST_Line_Interpolate_Point to compute each point on your line
>  - Aggregate all points computed in a new simplified line with ST_MakeLine
>
> HTH,
>
> O.
>
> _______________________________________________
> postgis-users mailing list
> postgis-users at postgis.refractions.net
> http://postgis.refractions.net/mailman/listinfo/postgis-users


More information about the postgis-users mailing list