Vergrößern einer PostGIS-Geometrie um einen Prozentsatz

10

Ich suche nach einer Möglichkeit, einen Puffer um eine PostGIS-Geometrie hinzuzufügen, aber die Größe des Puffers sollte von der Größe der Geometrie abhängen. Das heißt, ich möchte, dass jede Geometrie um beispielsweise 5% vergrößert wird.

Die Idee ist, dass ich nach sich überschneidenden Geometrien suche, aber es könnte einen Fehler von bis zu 5% geben, der mit jeder verbunden ist, die ich berücksichtigen möchte.

Kennt jemand den besten Weg, dies zu tun?

Die Datenbank hat fast eine Million Zeilen, daher würde ich es vorziehen, wenn sie ziemlich schnell ist.

James Baker
quelle
2
5% von was? Angenommen, Sie verwenden Polygone, sind es 5% der größten Breite, der engsten Breite, des Begrenzungsrahmens, des Abstands eines Scheitelpunkts vom Schwerpunkt ...? Wenn Sie über Punkte oder Linien sprechen, ist dies noch weniger sinnvoll!
MerseyViking
Ich denke, der Scheitelpunkt-Schwerpunkt-Abstand - oder möglicherweise eine Flächenvergrößerung von 5% wäre auch in Ordnung. Das Erhöhen des Begrenzungsrahmens ist in Ordnung, wenn die Geometrie so skaliert wird, dass dieser Begrenzungsrahmen ausgefüllt wird. Alle Geometrien sind geschlossene Polygone (die überwiegende Mehrheit sind Vierecke).
James Baker

Antworten:

8

Die Kommentare legen nahe, dass die 5% nicht mit hoher Genauigkeit erreicht werden müssen. (Wenn ja, wird es eine dauern lange Zeit eine Million Polygone zu puffern!) Wir können daher rufen Sie das Pizza - Prinzip : linear rescaling ein 2D - Feature um einen Faktor ein rescales seiner Fläche von einem ^ 2.

So lautet die Argumentation:

  • Wenn die Form nicht zu kompliziert ist - insbesondere wenn sie konvex ist -, führt die Pufferung zu einem Ergebnis, das mit der Neuskalierung der Form um einen zentralen Punkt vergleichbar ist. (Es ist wichtig zu verstehen, obwohl, dass Pufferung ist nicht auf eine Neuskalierung für alle anderen Formen als Platten immer gleich. Bei einigen konkaven Formen, ein „Puffer“ berechnet über rescaling könnte tatsächlich nicht enthalten Teile der ursprünglichen Form selbst! Daher letztlich Wir werden einen echten Puffer der Form berechnen, verwenden diese ungefähre Äquivalenz jedoch nur als Heuristik, um abzuschätzen, um wie viel gepuffert werden soll.)

  • Wenn der gepufferte Bereich 5% größer sein soll, sollte der Umfang der Neuskalierung daher sqrt (1 + 5/100) betragen, was nahe bei 1,025 liegt. Das heißt, wir sollten die Form um 2,5% in alle Richtungen erweitern wollen .

  • Wenn wir uns vorstellen, dass die Form einen "Durchmesser" hat (der einem typischen Abstand entspricht), sollte ihr Radius um 2,5% zunehmen. Das entspricht 2,5% / 2 = 1,25% des Durchmessers.

  • Wir können einen typischen Durchmesser aus dem Begrenzungsrahmen der Form abschätzen. Verwenden Sie beispielsweise ein arithmetisches oder geometrisches Mittel der Seitenlängen der Box.

Dies legt den folgenden Workflow nahe:

  1. Erhalten Sie den Begrenzungsrahmen der Form.

  2. Sei e der Durchschnitt der Seitenlängen der Box.

  3. Puffer die Form um 1,25% von e ; das heißt, durch (5/100) / 4 * e .

Da die Schritte 1 und 2 nur sehr wenig Berechnung erfordern, bietet sich dies als eine der schnellstmöglichen Lösungen an. Zur Überprüfung der Genauigkeit können Sie (natürlich) die Bereiche der gepufferten Formen berechnen und mit den ursprünglichen Bereichen vergleichen, um festzustellen, wie nahe sie der gewünschten Erhöhung um 5% kommen. Manchmal sind die gepufferten Bereiche sogar mehr als 5% größer, aber es sollte selten sein, dass sie kleiner sind, und es ist unmöglich, dass sie merklich kleiner sind.

Beispiele

Betrachten wir zur Kontrolle und Veranschaulichung einige einfache Formen.

  1. Eine Scheibe mit dem Radius r hat einen Begrenzungsrahmen mit Seiten der Länge 2 r . Unsere Formel berechnet e = (5/100) / 4 * 2 * r = r / 40. Die gepufferte Form ist offensichtlich eine konzentrische Scheibe mit dem Radius r + r / 40 = 1,025 r . Die alte Fläche war pi * r ^ 2, während die neue Fläche pi * (1,025 r ) ^ 2 = pi * 1,0506 * r ^ 2 ist, was 5,06% größer ist.

  2. Ein Rechteck mit Seiten parallel zu den Koordinatenachsen der Längen r und s ergibt e = ( r + s ) / 2. Der zusätzliche Bereich zum Puffern des Rechtecks ​​ergibt sich aus vier Rechtecken mit einer Breite (5/100) / 4 e = e / 80 = ( r + s ) / 160, die an die Seiten angrenzen, plus vier Viertelkreisen mit dem Radius e / 80 an den Ecken. Unter Vernachlässigung der Viertelkreise, die im Vergleich zu den anderen Bereichen klein sind, entspricht die gesamte neue Fläche

    2 ( r + s ) * ( r + s ) / 160 = ( r ^ 2 + s ^ 2 + 2 r * s ) / 80.

    Wenn r und s nicht zu unterschiedlich sind, können wir annehmen, dass r ^ 2 + s ^ 2 ungefähr 2 r * s ist . Diese Annäherung vereinfacht die gesamte neue Fläche wie beabsichtigt auf 4 r * s / 80 = 5% der ursprünglichen Fläche von r * s .

whuber
quelle
4

Sie möchten eine Kombination aus ST_Scale ( http://postgis.net/docs/ST_Scale.html ) und ST_Translate ( http://postgis.net/docs/ST_Translate.html ) verwenden, denke ich. Wir haben ein Beispiel dafür in PostGIS in Aktion und ähnliches in Kapitel 8. Wenn Sie das Buch nicht haben, können Sie den Code für dieses Kapitel hier herunterladen:

http://www.postgis.us/chapter_08

Ausschnitt aus dem Buch Schauen Sie sich Beispiel 8.26 an:

    -- Listing 8.26 Combining Scale and Translation to maintain centroid
    SELECT xfactor, yfactor, 
       ST_Translate(ST_Scale(hex.the_geom, xfactor, yfactor), 
       ST_X(ST_Centroid(the_geom))*(1 - xfactor), 
       ST_Y(ST_Centroid(the_geom))*(1 - yfactor) ) As scaled_geometry
    FROM 
 ( SELECT ST_GeomFromText('POLYGON((0 0,64 64,64 128,0 192,-64 128,-64 64,0 0))') As the_geom)  As hex
    CROSS JOIN (SELECT x*0.5 As xfactor 
        FROM generate_series(1,4) As x) As xf
    CROSS JOIN (SELECT y*0.5 As yfactor
        FROM generate_series(1,4) As y) As yf;
LR1234567
quelle
Funktioniert. Jetzt scheint es auch zu geben, ST_Transscaleaber irgendwie kann ich nicht herausfinden, wie das funktioniert ...
n1000
0

Dies ist sehr spät für die Party, aber ich habe kürzlich eine benutzerdefinierte PostGIS-Funktion entwickelt, die dies tut und bei Bedarf verkleinert:

ST_Dilate

wfgeo
quelle