Detecting spikes in geometries using angle threshold

Hi there,

We all know that search for errors in geometries can be quite a journey. One of the errors we need to fix is the presence of spikes in our geometries. One way to determine the location of those spikes is to determine the angles and check if them are smaller than a predefined threshold.

Ok them, one way to tackle this problem is to load your data into a PostGIS layer and use the available ST functions.

In this post I’ll show you guys a SQL query to solve this.

Let’s suppose we have geometries with problems like these here:

angle_before

To solve this problems we will use the following ST PostGIS functions:

  • ST_Azimuth
  • ST_PointN
  • ST_NPoints
  • ST_Boundary
  • ST_Dump
  • ST_ForceRHR

For more information about these functions check this: http://postgis.net/docs/manual-1.3/ch06.html

The following query can show us where the problems are located, let’s use a limit of 10 degrees here to determine the spikes:

WITH result AS (SELECT points.id, points.anchor, (degrees
                            (
                                ST_Azimuth(points.anchor, points.pt1) - ST_Azimuth(points.anchor, points.pt2)
                            )::decimal + 360) % 360 as angle
            FROM
            (SELECT
                  ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1)) as pt1,
                  ST_PointN(geom, generate_series(1, ST_NPoints(geom)-1) %  (ST_NPoints(geom)-1)+1) as anchor,
                  ST_PointN(geom, generate_series(2, ST_NPoints(geom)) %  (ST_NPoints(geom)-1)+1) as pt2,
                  linestrings.id as id
                FROM
                  (SELECT id as id, ST_Boundary((ST_Dump(ST_ForceRHR(geom))).geom) as geom
                   FROM only my schema.mylayer -- enter your layer name here
                   ) AS linestrings WHERE ST_NPoints(linestrings.geom) > 2 ) as points)
select distinct id, anchor, angle from result where (result.angle % 360) < 10 or result.angle > (360.0 - (10 % 360.0)) -- the 10 here is our threshold

With the results from this query we can locate our spikes using the “anchor” value returned in the query. Something like this:

angle_later

Very nice right?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s