[postgis-devel] ST_Reverse issues

Sandro Santilli strk at kbt.io
Thu Jun 24 07:53:14 PDT 2021


I'm facing dragons with this query:


  WITH inp AS (
    SELECT 'LINESTRING(0 0,10 0,5 5,0 0)'::geometry g
    UNION ALL
    SELECT 'LINESTRING(-1.8 -6,-1.8 -7,-1.2 -7,-1.2 -6,-1.8
  -6)'::geometry
  )
  SELECT
    -- We expect both fields being true
    ST_AsText(g) straight,
    ST_AsText(ST_Reverse(g)) reverse,
    ST_IsPolygonCW(ST_MakePolygon(ST_Normalize(g))) cw,
    ST_IsPolygonCW(ST_MakePolygon(ST_Normalize(ST_Reverse(g)))) cw_when_reverted
  FROM inp;


The result I'm getting:

    -[ RECORD 1 ]----+----------------------------------------------------
    straight         | LINESTRING(0 0,10 0,5 5,0 0)
    reverse          | LINESTRING(0 0,5 5,10 0,0 0)
    cw               | t
    cw_when_reverted | t
    -[ RECORD 2 ]----+----------------------------------------------------
    straight         | LINESTRING(-1.8 -6,-1.8 -7,-1.2 -7,-1.2 -6,-1.8 -6)
    reverse          | LINESTRING(-1.8 -6,-1.2 -6,-1.2 -7,-1.8 -7,-1.8 -6)
    cw               | f
    cw_when_reverted | f

Note how  "cw" and "cw_when_reverted" have the same value.
If writing the query in a different way I get correct results:

    WITH inp AS (
      SELECT 't1' lbl, 'LINESTRING(0 0,10 0,5 5,0 0)'::geometry g
      UNION ALL
      SELECT 't2', 'LINESTRING(-1.8 -6,-1.8 -7,-1.2 -7,-1.2 -6,-1.8 -6)'::geometry
    ),
    back_and_forw AS (
      SELECT lbl, g, st_reverse(g) rg from inp
    )
    SELECT
      -- We expect both fields being true
      lbl,
        ST_AsText(g) forw,
        ST_AsText(rg) back,
        ST_IsPolygonCW(ST_MakePolygon(g)) forw_cw,
        ST_IsPolygonCW(ST_MakePolygon(rg)) back_cw
    FROM back_and_forw;

    -[ RECORD 1 ]------------------------------------------------
    lbl     | t1
    forw    | LINESTRING(0 0,10 0,5 5,0 0)
    back    | LINESTRING(0 0,5 5,10 0,0 0)
    forw_cw | f
    back_cw | t
    -[ RECORD 2 ]------------------------------------------------
    lbl     | t2
    forw    | LINESTRING(-1.8 -6,-1.8 -7,-1.2 -7,-1.2 -6,-1.8 -6)
    back    | LINESTRING(-1.8 -6,-1.2 -6,-1.2 -7,-1.8 -7,-1.8 -6)
    forw_cw | f
    back_cw | t


Can you imagine reasons for this ? The only thing that comes to my
mind is we're doing reverse in-place w/out first taking a copy of the
parameter, thus changing also the input passed to ST_Reverse().

This is happening with

  POSTGIS="3.1.2dev 3.1.1-38-gb02ee9513" [EXTENSION] PGSQL="120" GEOS="3.8.2dev-CAPI-1.13.4" 

--strk; 

  ()   Free GIS & Flash consultant/developer
  /\   https://strk.kbt.io/services.html


More information about the postgis-devel mailing list