Ich benutze eine PL/R
Funktion und PostGIS
generiere Voronoi-Polygone um eine Menge von Punkten. Die Funktion, die ich benutze, wird hier definiert . Wenn ich diese Funktion für einen bestimmten Datensatz verwende, wird folgende Fehlermeldung angezeigt:
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
Nach Prüfung dieses Teils der Fehlermeldung:
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
So sieht das oben aufgeführte Problem aus:
Ich dachte anfangs, dass diese Nachricht durch die Existenz identischer Punkte verursacht werden könnte, und versuchte dies mithilfe der st_translate()
Funktion zu lösen , die folgendermaßen verwendet wurde:
ST_Translate(geom, random()*20, random()*20) as geom
Dies behebt das Problem, aber meine Sorge ist, dass ich jetzt alle Punkte bis zu ~ 20 m in x / y-Richtung übersetze. Ich kann auch nicht sagen, welcher Übersetzungsbetrag angemessen ist. Zum Beispiel ist in diesem Datensatz durch Ausprobieren a 20m * random number
in Ordnung, aber wie kann ich feststellen, ob dies größer sein muss?
Basierend auf dem obigen Bild denke ich, dass das Problem darin besteht, dass sich der Punkt mit der Linie schneidet, während der Algorithmus versucht, den Punkt mit einem Polygon zu schneiden. Ich bin nicht sicher, was ich tun soll, um sicherzustellen, dass sich der Punkt innerhalb eines Polygons befindet, anstatt sich mit einer Linie zu schneiden. Der Fehler tritt in dieser Zeile auf:
"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'');"
Ich habe diese vorherige Frage gelesen: Was ist eine "nicht geknotete Kreuzung"? Um zu versuchen, dieses Problem besser zu verstehen, und um Ratschläge zu erhalten, wie es am besten gelöst werden kann.
WHERE ST_IsValid(p.geom)
, um die Punkte anfangs zu filtern.Antworten:
Nach meiner Erfahrung wird dieses Problem fast immer verursacht durch:
Mit dem "Nudge" -Ansatz der
ST_Buffer
Lösungen kommen Sie mit Nummer 2 klar, aber alles, was Sie tun können, um diese zugrunde liegenden Ursachen zu beheben, z. Die gepufferten Geometrien eignen sich normalerweise gut für Zwischenberechnungen wie Überlappungsbereiche. Sie sollten jedoch darauf achten, sie beizubehalten, da sie auf lange Sicht Ihre Nah-aber-nicht-ganz-Probleme verschlimmern können.Mit der Ausnahmebehandlungsfunktion von PostgreSQL können Sie Wrapper-Funktionen schreiben, um diese Sonderfälle zu behandeln und nur bei Bedarf zu puffern. Hier ist ein Beispiel für
ST_Intersection
; Ich benutze eine ähnliche Funktion fürST_Difference
. Sie müssen entscheiden, ob die Pufferung und die potenzielle Rückgabe eines leeren Polygons in Ihrer Situation akzeptabel sind.Ein weiterer Vorteil dieses Ansatzes besteht darin, dass Sie die Geometrien genau bestimmen können, die Ihre Probleme verursachen. Fügen Sie einfach einige
RAISE NOTICE
Anweisungen in denEXCEPTION
Block ein, um WKT oder etwas anderes auszugeben, mit dessen Hilfe Sie das Problem aufspüren können.quelle
Durch viele Versuche und Irrtümer wurde mir schließlich klar, dass das
non-noded intersection
Ergebnis eines Selbstüberschneidungsproblems war. Ich habe einen Thread gefunden, dessen Verwendung empfohlenST_buffer(geom, 0)
wird, um das Problem zu beheben (obwohl es insgesamt sehr viel langsamer ist). Ich habe dann versucht,ST_MakeValid()
und wenn direkt auf die Geometrie angewendet, vor jeder anderen Funktion. Dies scheint das Problem robust zu beheben.Ich habe dies als Antwort markiert, da dies der einzige Ansatz zu sein scheint, der mein Problem behebt.
quelle
Ich bin auf dasselbe Problem gestoßen (Postgres 9.1.4, PostGIS 2.1.1), und das einzige, was für mich funktionierte, war, die Geometrie mit einem sehr kleinen Puffer zu umschließen.
ST_MakeValid
hat bei mir nicht funktioniert, auch die Kombination vonST_Node
und nichtST_Dump
. Der Puffer schien keine Verschlechterung der Leistung zu bewirken, aber wenn ich ihn verkleinerte, erhielt ich immer noch einen nicht geknoteten Kreuzungsfehler.Hässlich, aber es funktioniert.
Aktualisieren:
Die ST_Buffer-Strategie scheint gut zu funktionieren, aber ich bin auf ein Problem gestoßen, bei dem beim Umwandeln der Geometrie in die Geografie Fehler aufgetreten sind. Wenn sich ein Punkt ursprünglich bei -90,0 befindet und von 0,0000001 gepuffert wird, befindet er sich jetzt bei -90,0000001, was eine ungültige Geografie ist.
Dies bedeutet , dass , obwohl
ST_IsValid(geom)
wart
,ST_Area(geom::geography)
kehrteNaN
für viele Funktionen.Um das nicht-knotige Kreuzung Problem zu vermeiden, während gültige Geographie beibehalten, landete ich mit bis
ST_SnapToGrid
wie soquelle
In postgis sollte ST_Node eine Reihe von Linien an Kreuzungen brechen, wodurch das Problem der nicht geknoteten Kreuzungen gelöst werden sollte. Wenn Sie dies in ST_Dump einschließen, wird das zusammengesetzte Array der unterbrochenen Linien generiert.
Etwas verwandt gibt es eine großartige Präsentation von PostGIS: Tips for Power Users, die diese Art von Problemen und Lösungen klar umreißt.
quelle
ST_Node
und verwendenST_Dump
? Ich stelle mir vor, ich müsste sie in der Nähe dieses Teils der Funktion verwenden, bin mir aber nicht sicher:st_intersection(''SRID=''||st_srid(%2$s)||'';%4$s''::text,''%5$s'')
inst_node
hier benutze - kann ich es vorher benutzenst_intersection
?Nach meiner Erfahrung habe ich meinen
non-noded intersection
Fehler mit der Funktion St_SnapToGrid behoben, die das Problem der hohen Genauigkeit der Koordinaten des Scheitelpunkts der Polygone behebt .quelle