Thursday, 6 December 2018

polygon - How best to fix a non-noded intersection problem in PostGIS?


I'm using a PL/R function and PostGIS to generate voronoi polygons around a set of points. The function that I am using is defined here. When I use this function on a particular dataset I get the following error message:


Error : ERROR:  R interpreter expression evaluation error
DETAIL: Error in pg.spi.exec(sprintf("SELECT %3$s AS id,
st_intersection('SRID='||st_srid(%2$s)||';%4$s'::text,'%5$s')
AS polygon FROM %1$s WHERE st_intersects(%2$s::text,'SRID='||st_srid(%2$s)||';%4$s');",
:error in SQL statement : Error performing intersection: TopologyException: found non-noded
intersection between LINESTRING (571304 310990, 568465 264611) and LINESTRING (568465
264611, 594406 286813) at 568465.05533706467 264610.82749605528

CONTEXT: In R support function pg.spi.exec In PL/R function r_voronoi

From examining this part of the error message:


Error performing intersection: TopologyException: found non-noded intersection between
LINESTRING (571304 310990, 568465 264611) and LINESTRING (568465 264611, 594406 286813)
at 568465.05533706467 264610.82749605528

This is what the problem listed above looks like:


enter image description here


I initially thought that this message might be caused by the existence of identical points, and tried to solve this using the st_translate() function, used in the following way:



ST_Translate(geom, random()*20, random()*20) as geom 

This does fix the problem, but my concern is that I am now translating all points up to ~20m in the x/y direction. I also can't tell what an appropriate translation amount is need. For example, in this dataset through trial and error a 20m * random number is ok, but how can I tell if this needs to be bigger?


Based on the image above I think the problem is that the point is intersecting with the line while the algorithm is trying to intersect the point with a polygon. I'm not sure what I should be doing to ensure that the point is within a polygon, rather than intersecting with a line. The error is occurring on this line:


"SELECT 
%3$s AS id,
st_intersection(''SRID=''||st_srid(%2$s)||'';%4$s''::text,''%5$s'') AS polygon
FROM
%1$s
WHERE

st_intersects(%2$s::text,''SRID=''||st_srid(%2$s)||'';%4$s'');"

I have read through this previous question, What is a "non-noded intersection"? to try to better understand this problem, and would appreciate any advice on how best to solve it.



Answer



Through a lot of trial and error I eventually realized that the non-noded intersection resulted from a self-intersection problem. I found a thread that suggested using ST_buffer(geom, 0) can be used to fix the problem (though it does make it a lot slower overall). I then tried to use ST_MakeValid() and when applied directly to the geometry before any other function. This seems to fix the problem robustly.


ipoint <- pg.spi.exec(
sprintf(
"SELECT
%3$s AS id,
st_intersection(ST_MakeValid(''SRID=''||st_srid(%2$s)||'';%4$s''::text), ST_MakeValid(''%5$s'', 0)) AS polygon

FROM %1$s
WHERE
ST_Intersects(ST_MakeValid(%2$s::text),ST_MakeValid(''SRID=''||st_srid(%2$s)||'';%4$s''));",
arg1,
arg2,
arg3,
curpoly,
buffer_set$ewkb[1]
)
)




I've marked this as the answer as it seems to be the only approach that fixes my problem.


No comments:

Post a Comment