affecter et déplacer des centroïdes à leurs polygones

9

J'utilise QGIS 1.8 Lisboa. Après avoir calculé les centroïdes à partir d'un fichier de formes de polygones, si certains d'entre eux se trouvent en dehors des contours du polygone, je voudrais les déplacer sur le polygone dont ils sont issus. Le critère doit être univoque car je dois les utiliser pour extraire les coordonnées à utiliser comme code d'identification du polygone lui-même. Par conséquent, la procédure doit générer le même emplacement de point chaque fois qu'elle s'exécute pour le même polygone (pas une position aléatoire comme celle donnée par la fonction "points aléatoires", qui donne un nouveau résultat à chaque exécution).

umbe1987
la source
1
Cela ressemble à deux questions. Si je comprends bien, vous voulez (a) ajouter des points aléatoires à l'intérieur d'un polygone et (b) leur donner ou au polygone un ID unique basé sur cela. La chose la plus simple qui vous vient à l'esprit pour (a) est d'utiliser les capacités de points aléatoires existantes dans QGIS, puis d'intersecter ce nuage de points avec votre polygone.
lynxlynxlynx
l'utilisation de la fonction "points aléatoires" à des moments différents avec les mêmes polygones conduit à des résultats différents (à savoir, la position des points dérivés de chaque polygone est différente à chaque nouvelle utilisation de la fonction), et je veux créer une méthode qui me donnerait toujours le même point par polygone d'où je pouvais extraire les coordonnées que je veux utiliser comme code d'identification pour les polygones eux-mêmes.
umbe1987
utiliser l'outil 'true centroid' de fTools sous outils de géométrie - docs.qgis.org/html/en/docs/user_manual/plugins/…
Mapperz
cela me donne juste le centroïde, mais cela pourrait aussi se trouver à l'extérieur du poligon, ce que je dois éviter. Je dois les déplacer sur le polygone dont ils dérivent, en utilisant une fonction comme la distance minimale (mais je ne suis pas intéressé par la distance, je veux qu'elle soit déplacée). Dans un autre blog, quelqu'un m'a dit d'utiliser ST_PointOnSurface de PostGIS (mais j'utilise QGIS).
umbe1987
2
est-ce un doublon de gis.stackexchange.com/questions/50029/… maintenant?
underdark

Réponses:

7

Vous pouvez utiliser la bibliothèque Shapely python, qui fournit une fonction representative_point()qui est garantie de se trouver dans le polygone.

Voici un script Python qui peut être exécuté dans la console QGIS Python. La couche de polygones pour laquelle vous souhaitez créer l'attribut doit être sélectionnée. La fonction prend le nom de l'attribut que vous souhaitez mettre à jour. L'attribut doit déjà exister dans votre couche, il doit être de type chaîne et il doit être suffisamment long (30 caractères).

Voici un exemple des points trouvés par l'algorithme:

import shapely.wkb

def setIDPoint(attributename):
 layer = qgis.utils.iface.activeLayer()
 provider = layer.dataProvider()
 fields = provider.fields()
 provider.select(provider.attributeIndexes() )
 attributeID = provider.fieldNameIndex(attributename)
 feature = QgsFeature()
 layer.startEditing()
 while provider.nextFeature(feature):
  wkb = feature.geometry().asWkb()
  polygon = shapely.wkb.loads(wkb)
  reprPoint = ','.join([str(polygon.representative_point().x), str(polygon.representative_point().y)] )
  feature.changeAttribute(attributeID, reprPoint)
  layer.updateFeature(feature)
 layer.commitChanges()
Jake
la source
J'essaye de le tester, semble exactement ce que je cherchais. Je vous ferai savoir dès que je l'exécuterai!
umbe1987
une chose que je n'ai pas compris, c'est ce que tu veux dire par "ça doit être du type chaîne, et ça devrait être assez long (30 caractères)". Cette bibliothèque fonctionne-t-elle directement sur les fichiers shp polygonaux? Si oui, suis-je censé créer un nouveau champ de type de chaîne dans l'onglet Att avec au moins 30 caractères, et ce serait celui à mettre à jour?
umbe1987
@ user9518: Oui, la façon dont la fonction est écrite au moment où vous devez créer l'attribut dans la table vous-même, puis transmettre uniquement le nom du champ à la fonction. Le script pourrait également être facilement adapté pour créer le champ requis lui-même, si c'est ce qui est nécessaire.
Jake
Je manque juste une chose. Il semble maintenant que je définis une fonction (ou une classe) en tapant "def", mais quand je termine en écrivant le script, il ne se passe rien. Comment puis-je enfin avoir le résultat dans ma table?
umbe1987
1
Cela a parfaitement fonctionné !!! J'imagine que les coordonnées sont écrites selon le système de coordonnées de la couche et que si je veux avoir les points dont j'ai besoin pour créer un shp avec ces coordonnées, non? Si vous étiez ici je vous offrirais au moins 3 bières! Merci beaucoup pour vos efforts !!!
umbe1987
5

L'outil ftools centroid peut placer le centroïde en dehors du polygone s'il est concave.

ST_PointOnSurfacefera certainement ce que vous voulez. Vous pouvez utiliser la commande à partir de QGIS si vous l'avez installé en utilisant SPIT pour obtenir votre fichier de formes dans PostGIS, puis utiliser le plugin PgQuery pour exécuter la requête.

Alternativement, si l'installation de PostGIS est un peu trop pour une utilisation ponctuelle, vous pouvez utiliser Spatialite à partir de QGIS. Vous pouvez ensuite utiliser le plugin QSpatiaLite pour importer vos données dans SpatiaLite et exécuter la requête (SpatialLite honors ST_PointOnSurface).

MappaGnosis
la source
2

quand je vous comprends bien, utilisez: Vector-> Research Tools_> Random Points. Sélectionnez maintenant sous "Plan d'échantillonnage stratifié (polygones individuels)" utilisez la valeur du champ de saisie et utilisez le champ approprié, qui donne la valeur numérique des points, qui doit être générée pour chaque polygone différent

Kurt
la source
que voulez-vous dire par «champ approprié»? Je pensais utiliser le centroïde, puis le lier à la partie la plus proche du polygone auquel il se réfère, s'il se trouve en dehors du contour, en calculant (par exemple) la distance minimale de ce point à son polygone le plus proche. Le but est alors d'extraire ces coordonnées de point afin de les utiliser comme code d'identification spécifique unique du polygone.
umbe1987
Fondamentalement, ce que j'essaie de faire est d'attribuer chaque centroïde à son polygone relatif et de le déplacer pour qu'il se trouve à l'intérieur de son polygone (ou au moins pour toucher sa limite).
umbe1987
@ user9518: désolé, j'ai mal compris votre question. Je pensais que vous vouliez un nombre spécifique de points aléatoires dans chaque poly, par exemple 2 points fpr poly 1, 10 points dans poly2, etc. donc le terme "champ approprié". bien sûr, vous pouvez sélectionner 1 pour "utiliser ce nombre de points" pour générer un seul point pour chaque poly. ce point est à l'intérieur du poly ou touche au moins sa limite. mais ce point est toujours trouvé par hasard, donc lorsque vous refaites la procédure, vous obtenez d'autres points :-(
Kurt
1

Le plugin realcentroids, disponible à installer via Plugins> Gérer et installer les plugins a fonctionné pour moi dans QGIS 2.2 pour générer des points centroïdes, forcés à l'intérieur de chaque polygone s'il est concave (le point se trouvera très près du bord). J'ai essayé l'outil de points aléatoires comme suggéré par Kurt, et bien que j'aie spécifié 1 point par polygone, il en génère deux à la place. Un inconvénient supplémentaire est que dans la plupart des cas, les points ne représentent pas le centroïde car ils sont aléatoires.

http://www.agt.bme.hu/gis/qgis/realcentroid/

Alexandra Mates
la source