Cómo convertir en PostGIS líneas no simples a simples (How to convert non-simple to simple lines in PostGIS)

Las líneas no simples son aquellas que pasan por un mismo punto dos veces, es decir, se autointersecan.

A los que trabajamos con cartografía esto no nos gusta nada, ya que puede originar comportamientos no deseados en análisis espaciales futuros.

PostGIS con ST_IsSimple permite saber si una línea contiene autointersecciones pero no permite eliminarlas.

El comando ST_Node calcula nuevas intersecciones convirtiendo una linestring en una multilinestring con 3 subelementos (en el ejemplo inferior), pero !sorpresa! esa nueva multilinestring sigue siendo no simple (* razón en la figura).

La sencilla función STX_NodeSimple que hemos desarrollado en plpgsql partirá dicho elemento cerrado de forma que la multilinestring resultante sea simple.

Non-simple lines are those that pass through the same point twice, that is, they are self-intersecting.

Those of us who work with cartography do not like this at all, since it can cause unwanted behavior in future spatial analysis.

PostGIS with ST_Issimple allows to know if a line contains self-intersections but does not allow to eliminate them.

The ST_Node command calculates new intersections by converting a linestring into a multilinestring with 3 subelements (in the example), but what a surprise to know that the new multilinestring is still not simple (* reason).

The STX_NodeSimple  in plpgsql will split said closed element so that the resulting multilinestring is simple.

nodesimple_code1

nodeexample

s1=# select st_astext(geom), st_issimple(geom),       st_numgeometries(geom),st_length(geom) from
(select st_node ('LINESTRING (6 3, 15 12, 26 16, 36 17, 26 7, 19 18, 22 22)'::geometry)) as foo(geom);

-[ RECORD 1 ]----+-------------------------------------------------------
st_astext | MULTILINESTRING((6 3,15 12,21.3489932885906 14.3087248322148),(21.3489932885906 14.3087248322148,26 16,36 17,26 7,21.3489932885906 14.3087248322148),(21.3489932885906 14.3087248322148,19 18,22 22))
st_issimple | f
st_numgeometries | 3
st_length | 66.6630380273346

s1=# select st_astext(geom), st_issimple(geom), st_numgeometries(geom),st_length(geom) from
(select stx_nodesimple ('LINESTRING (6 3, 15 12, 26 16, 36 17, 26 7, 19 18, 22 22)'::geometry)) as foo(geom);

-[ RECORD 1 ]----+-------------------------------------------------------
st_astext | MULTILINESTRING((6 3,15 12,21.3489932885906 14.3087248322148),(21.3489932885906 14.3087248322148,26 16),(26 16,36 17,26 7,21.3489932885906 14.3087248322148),(21.3489932885906 14.3087248322148,19 18,22 22))
st_issimple | t
st_numgeometries | 4
st_length | 66.6630380273346