13

I have (multi)linestrings containing upwards of 5000 points and I want to perform two simplifications possibly using Ramer Douglas Peucker or alternative methods in PostGIS. The (multi)linestrings consist of straight lines, 90 degree curves, 180 degree curves and loops (circles).

I understand that ST_simplify may remove the loops and possibly some of the bends depending on the tolerance set. I need to have a zoomed out version which can probably be done satisfactorily done with ST_simplify. However, on the zoomed in version, it is important to keep the loops, and curve points.

I would like to remove all the points from the straight segments (within a tolerance) which constitute 90% of the (multi)linestring and keep the points on the curve section.

How can I achieve this in PostGIS?

7
  • 2
    one solution is dump all linestrings , then calculate azimuth between start and n+1 points on line. When azimuth between start to 1, and start to x go over tolerance ,store line_id ,start ,x-1 point and repeat process from using x-1 as start to x-1. solution will be slow in db or in code if implementation dosen't manage linestrings as set (so no for loop over over linestring). Probably not smartest way to do it Commented Feb 24, 2014 at 10:45
  • 6
    Are you certain that ST_Simplify won't do what you want? With a tight tolerance, it'll strip out the redundant points in the straight parts while leaving the curvey parts untouched. The only time you'd have to worry about losing the curvey parts is if they are actually smaller than your tolerance, which is hard to picture. Commented Feb 25, 2014 at 4:17
  • 1
    It appears this question was abandoned after Paul's comment. It is also a bit broad without clear evidence of code.
    – kttii
    Commented Oct 17, 2016 at 15:46
  • @PaulRamsey ST_Simplify won't solve this, because every single LineString of a MultiLineString is considered its own entity when it comes to simplification. So if 2 adjacent LineStrings form another straight line, the midpoint won't be removed as that would in essence create an invalid line (with 1 point)
    – U2ros
    Commented Feb 22, 2017 at 7:28
  • Run an ST_LineMerge on them first maybe? Commented Feb 22, 2017 at 13:37

2 Answers 2

2

Use ST_SetEffectiveArea in conjunction with ST_FilterByM on the result of ST_LineMerge, e.g.:

SELECT  ST_AsText(
            ST_FilterByM(
                ST_SetEffectiveArea(
                    ST_LineMerge('MULTILINESTRING((0 0, 0 1), (0 1, 0 2), (0 2, 0 3), (0 3, 0 4), (0 4, 1 4), (1 4, 2 4), (2 4, 3 4))'::GEOMETRY)
                ),
                0.0001
            )
        )
;

SELECT  ST_AsText(
            ST_FilterByM(
                ST_SetEffectiveArea(
                    ST_Buffer('POINT(0 0)'::GEOMETRY, 0.1)
                ),
                0.0001
            )
        )
;
1
  • Not really sure how I ended up on this age old post...but since I was at it I thought I might just as well leave a solid solution...
    – geozelot
    Commented Nov 27, 2019 at 13:23
2

This is easily achievable by using ST_SimplifyVW which is available in PostGIS from version 2.2.0 If you chose small tolerance, then points forming straight (or nearly straight) lines will be removed. As a side-effect, it will remove also points forming small triangles, if their area will be within a specified tolerance, so be aware of it...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.