J'ai un fichier de formes et je veux savoir pour chaque polygone ce que d'autres polygones le touchent. À cette fin, j'ai ce code:Calculer la longueur des limites partagées entre plusieurs polygones
require("rgdal")
require("rgeos")
download.file("https://www.dropbox.com/s/vbxx9dic34qwz63/Polygons.zip?dl=1", "Polygons.zip")
Shapefile <- readOGR(".","Polygons")
Touching_List <- gTouches(Shapefile, byid = TRUE, returnDense=FALSE)
Touching_DF <- setNames(stack(lapply(Touching_List, as.character)), c("TOUCHING", "ORIGIN"))
Je veux maintenant aller plus loin et comprendre la mesure dans laquelle chaque touche de polygone d'autres polygones. Ce que je suis après pour chaque ligne dans Touching_DF
est une longueur totale/périmètre pour chaque polygone ORIGIN
et la longueur totale que chaque polygone TOUCHING
est en contact avec le polygone d'origine. Cela permettra ensuite de calculer le pourcentage de la limite partagée. Je peux imaginer la sortie de ce serait 3 nouvelles colonnes dans Touching_DF
(par exemple pour la première rangée, il pourrait être quelque chose comme le paramètre d'origine 1000m, toucher la longueur 500m, frontière partagée 50%). Merci.
EDIT 1
J'ai appliqué @ réponse de StatnMap à mon vrai jeu de données. Il semble que gTouches
renvoie des résultats si un polygone partage à la fois une arête et un point. Ces points causent des problèmes parce qu'ils n'ont pas de longueur. J'ai modifié la portion de code de StatnMap pour y faire face, mais quand il s'agit de créer la trame de données à la fin, il y a un décalage entre le nombre d'arêtes/sommets partagés renvoyés par gTouches et le nombre d'arêtes ayant des longueurs.
Voici un code pour démontrer le problème en utilisant un échantillon de mon jeu de données réelles:
library(rgdal)
library(rgeos)
library(sp)
library(raster)
download.file("https://www.dropbox.com/s/hsnrdfthut6klqn/Sample.zip?dl=1", "Sample.zip")
unzip("Sample.zip")
Shapefile <- readOGR(".","Sample")
Touching_List <- gTouches(Shapefile, byid = TRUE, returnDense=FALSE)
# ---- Calculate perimeters of all polygons ----
perimeters <- sp::SpatialLinesLengths(as(Shapefile, "SpatialLines"))
# ---- All in a lapply loop ----
all.length.list <- lapply(1:length(Touching_List), function(from) {
lines <- rgeos::gIntersection(Shapefile[from,], Shapefile[Touching_List[[from]],], byid = TRUE)
if(class(lines) != "SpatialLines"){lines <- [email protected]}
l_lines <- sp::SpatialLinesLengths(lines, longlat=FALSE)
results <- data.frame(origin = from,
perimeter = perimeters[from],
touching = Touching_List[[from]],
t.length = l_lines,
t.pc = 100*l_lines/perimeters[from])
results
})
Cela montre spécifiquement la question pour l'un des polygones:
from <- 4
lines <- rgeos::gIntersection(Shapefile[from,], Shapefile[Touching_List[[from]],], byid = TRUE)
if(class(lines) != "SpatialLines"){lines <- [email protected]}
l_lines <- sp::SpatialLinesLengths(lines, longlat=FALSE)
plot(Shapefile[c(from, Touching_List[[from]]),])
plot(lines, add = TRUE, col = 1 + 1:length(Touching_List[[from]]), lwd = 2)
Les deux solutions possibles I voir sont 1. obtenir gTouches pour retourner seulement les bords partagés avec une longueur supérieure à zéro ou 2. renvoyant une longueur de zéro (plutôt que d'erreur) quand un point plutôt qu'un bord est rencontré. Jusqu'à présent, je ne trouve rien qui puisse faire l'une ou l'autre de ces choses.
EDIT 2
@ solution révisée de StatnMap fonctionne très bien. Toutefois, si un polygone ne partage pas un boarder Snapped avec son polygone (il va à un point et crée alors un polygone de Slither de l'île), il arrive avec cette erreur après lines <- rgeos::gIntersection(Shapefile[from,], Shapefile[Touching_List[[from]],], byid = TRUE)
Error in RGEOSBinTopoFunc(spgeom1, spgeom2, byid, id, drop_lower_td, unaryUnion_if_byid_false, :
Geometry collections may not contain other geometry collections
Je suis voisin à la recherche pour une solution qui est capable d'identifier les polygones avec des bordures mal dessinées et de ne pas effectuer de calculs et de retourner 'NA' dans res
(afin qu'ils puissent être identifiés plus tard). Cependant, j'ai été incapable de trouver une commande qui distingue ces polygones problématiques des polygones 'normaux'.
Exécution @ solution révisée de StatnMap avec ces 8 polygones démontre la question:
download.file("https://www.dropbox.com/s/ttg2mi2nq1gbbrq/Bad_Polygon.zip?dl=1", "Bad_Polygon.zip")
unzip("Bad_Polygon.zip")
Shapefile <- readOGR(".","Bad_Polygon")
Merci pour votre inscription. Basé sur mes données d'échantillon, il fait exactement ce que je suis après. Cependant, j'ai appliqué votre solution à mon jeu de données «réel» et j'ai rencontré quelques problèmes. J'ai édité ma question pour montrer ce que je veux dire. – Chris
J'ai édité ma réponse pour rendre compte de cette affaire. –
Merci. Votre code fonctionne parfaitement. Le seul problème que j'ai maintenant est avec certains de mes polygones d'entrée étant mal dessinés. Je ne peux rien faire à ce sujet, j'ai donc besoin de trouver une solution qui ignore les polygones douteux (c'est-à-dire renvoie NA dans res) ou peut gérer les polygones d'îlots glissants. La première option me semble être une meilleure solution, je ne trouve pas d'instruction if avant 'rgeos :: gIntersection (Shapefile [n,], Shapefile [Touching_List [[n]],], byid = TRUE)' être capable d'identifier les polygones problématiques. J'ai ajouté un petit ensemble de 8 polygones à ma question pour montrer ce que je veux dire. – Chris