Agrandir une géométrie PostGIS en pourcentage

10

Je cherche un moyen d'ajouter un tampon autour d'une géométrie PostGIS, mais la taille du tampon devrait dépendre de la taille de la géométrie. Autrement dit, je veux que chaque géométrie soit agrandie, disons, de 5%.

L'idée est que je recherche des géométries entrecroisées, mais il pourrait y avoir une erreur jusqu'à 5% associée à chacune que je veux prendre en compte.

Quelqu'un connaît la meilleure façon de procéder?

La base de données compte environ un million de lignes, je préférerais donc qu'elle soit assez rapide.

James Baker
la source
2
5% de quoi? En supposant que vous utilisez des polygones, s'agit-il de 5% de la plus grande largeur, de la largeur la plus étroite, du cadre de délimitation, de la distance d'un sommet par rapport au centroïde ...? Si vous parlez de points ou de lignes, cela a encore moins de sens!
MerseyViking
Je suppose que la distance vertex-centroïde - ou peut-être une augmentation de 5% de la surface serait également acceptable. L'augmentation de la zone de délimitation est correcte si la géométrie est mise à l'échelle pour remplir cette zone de délimitation. Toutes les géométries sont des polygones fermés (la grande majorité étant des quadrilatères).
James Baker

Réponses:

8

Les commentaires suggèrent que les 5% n'ont pas besoin d'être atteints avec une grande précision. (Si c'est le cas, il faudra beaucoup de temps pour tamponner un million de polygones!) Nous pouvons donc invoquer le principe de la pizza : redimensionner linéairement une entité 2D d'un facteur a redimensionne sa zone d' un ^ 2.

Voici comment se déroule le raisonnement:

  • Lorsque la forme n'est pas trop alambiquée - surtout si elle est convexe -, la mise en mémoire tampon produit un résultat comparable à un redimensionnement de la forme autour d'un point central. (Il est important de comprendre, cependant, que le buffering est pas toujours équivalente à une renormalisation pour toutes les formes autres que les disques. Pour certaines formes concaves, un « tampon » calculée par l' intermédiaire redimensionnant pourrait effectivement pas inclure des parties de la forme originale elle - même! Par conséquent , en fin de compte nous allons calculer un véritable tampon de la forme, mais nous utilisons uniquement cette équivalence approximative comme une heuristique pour estimer la quantité de tampon par.)

  • Si la zone tamponnée doit être supérieure de 5%, la quantité de redimensionnement doit donc être sqrt (1 + 5/100), ce qui est proche de 1,025: c'est-à-dire que nous devrions vouloir étendre la forme de 2,5% dans toutes les directions. .

  • De même, si nous considérons la forme comme ayant un "diamètre" (égal à une distance typique à travers), son rayon devrait augmenter de 2,5%. Cela équivaut à 2,5% / 2 = 1,25% du diamètre.

  • Nous pouvons estimer un diamètre typique à partir du cadre de délimitation de la forme. Utilisez, par exemple, une moyenne arithmétique ou géométrique des longueurs des côtés de la boîte.

Cela suggère le flux de travail suivant:

  1. Obtenez la boîte englobante de la forme.

  2. Soit e la moyenne des longueurs latérales de la boîte.

  3. Tamponner la forme de 1,25% de e ; c'est-à-dire par (5/100) / 4 * e .

Étant donné que les étapes 1 et 2 nécessitent très peu de calculs, cela se présente comme l'une des solutions les plus rapides possibles. Pour vérifier la précision, vous pouvez (bien sûr) calculer les zones des formes tamponnées et les comparer aux zones d'origine pour voir à quel point elles se rapprochent de l'augmentation souhaitée de 5%. Parfois, les zones tamponnées seront même supérieures de plus de 5%, mais il devrait être rare qu'elles soient moindres, et il est impossible qu'elles soient sensiblement inférieures.

Exemples

À titre de vérification et d'illustration, considérons quelques formes simples.

  1. Un disque de rayon r a une boîte englobante avec des côtés de longueur 2 r . Notre formule calcule e = (5/100) / 4 * 2 * r = r / 40. La forme tamponnée est évidemment un disque concentrique de rayon r + r / 40 = 1,025 r . L'ancienne zone était pi * r ^ 2 tandis que la nouvelle zone était pi * (1.025 r ) ^ 2 = pi * 1.0506 * r ^ 2, soit 5,06% de plus.

  2. Un rectangle avec des côtés parallèles aux axes de coordonnées des longueurs r et s donne e = ( r + s ) / 2. La zone supplémentaire de mise en mémoire tampon du rectangle provient de quatre rectangles de largeur (5/100) / 4 e = e / 80 = ( r + s ) / 160 bordant les côtés plus quatre quart de cercles de rayon e / 80 aux coins. Négliger les quart de cercles, qui seront petits par rapport aux autres zones, La nouvelle zone totale est égale à

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

    Lorsque r et s ne sont pas trop différents, on peut penser que r ^ 2 + s ^ 2 est environ 2 r * s . Cette approximation simplifie la nouvelle zone totale à 4 r * s / 80 = 5% de la zone d'origine de r * s , comme prévu.

whuber
la source
4

Vous voulez utiliser une combinaison de ST_Scale ( http://postgis.net/docs/ST_Scale.html ) et ST_Translate ( http://postgis.net/docs/ST_Translate.html ) je pense. Nous en avons un exemple dans PostGIS in Action et similaire au chapitre 8. Si vous n'avez pas le livre, vous pouvez télécharger le code de ce chapitre ici:

http://www.postgis.us/chapter_08

Extrait d'un livre Regardez l'exemple 8.26:

    -- 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
la source
Travaux. Maintenant, il semble y en avoir aussi, ST_Transscalemais je ne sais pas comment faire fonctionner ça ...
n1000
0

C'est très tard pour la fête mais j'ai récemment développé une fonction PostGIS personnalisée qui fait cela, ainsi que la réduire si nécessaire:

ST_Dilate

wfgeo
la source