I am trying to split a concave polygon into convex polygons using r.
I am trying to figure out how to successfully accomplish this for one polygon with the hopes of implementing this on a large number of polygons in an automated way.
The only way I could think of so far was to use triangulation to break this shape into several smaller shapes, then group those into some minimized number convex polygons.
library(sp)
library(rgdal)
library(sf)
files <- list.files("~/Cluster polygons 2020",pattern=".shp", full.names=TRUE)
cluster=readOGR(files[1])
spatstat::is.convex(maptools::as.owin.SpatialPolygons(cluster[1,])) #CHECK IF CONVEX
[1] FALSE
plygn=sfdct::ct_triangulate(sf::st_as_sf(cluster[1,]),D=TRUE)
plygn=st_collection_extract(plygn, "POLYGON")
plygn=as_Spatial(plygn)
length(plygn) #HOW MANY TRIANGLES GENERATED?
[1] 58
This is as far as I have gotten. Is there a clever/principled way group the triangles into the smallest number of groups and then merge them so the final product is a set of convex polygons? Or is there an entirely better approach to this problem?
I appreciate the help. Here is a link to the shapefile
Related
I want to return the dimensions of some gridded polygons. I know the overall area of the polygons, but I would like to have the height and width as well for some calculations. The polygons are sf objects and I wanted to convert them into multiline objects and then just take the length of each line. I can't figure out how to do this, but assume there is a built in function in the sf package for this.
For some sample code:
library(sf)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
poly <- nc[5,] # object five chosen at random for testing
Now I just want poly to be converted to a series of lines, and then be able to take the length of those lines.
Any help is appreciated.
I'm still somewhat new to R and the sf package...
I have two sets of multipolygon data that I am trying to analyze. My first set of polygons (fires) contains hundreds of wildfire perimeters. The second set (towns) contains hundreds of urban areas boundaries.
For each fire, I would like to calculate the distance to the closest town (fire polygon edge to closest town polygon edge), and add that as a field to each fire.
So far I have mostly been using the sf package for spatial data. In my searches, I can only find minimum distance methods for polygons to points, points to points, lines to points, etc. but cannot seem to find polygon to polygon examples. Any help to send me in the right direction would be much appreciated! Thank you.
#TimSalabim Thank you for sending me in the right direction. I was able to accomplish what I was after. Maybe not the most elegant solution, but it worked.
# create an index of the nearest feature
index <- st_nearest_feature(x = poly1, y = poly2)
# slice based on the index
poly2 <- poly2 %>% slice(index)
# calculate distance between polygons
poly_dist <- st_distance(x = poly1, y= poly2, by_element = TRUE)
# add the distance calculations to the fire polygons
poly1$distance <- poly_dist
I am working with dataframe which has lat and long coordinates. I want to cluster those coordinates based on their location closeness in R and then plot it on some map.
I am able to plot the points on map with leaflet package,which gives me nice map layout and lat and long coordinates. Just don't know how to cluster those points lets say in 3 clusters. Will k-means clustering appropriate for this kind of problems? Or do I have to apply some distance metrics and then use clustering algorithm. I am bit confused with online literature available on clustering of geographic data.
Here is what I am doing in R
map <- leaflet() %>%
addTiles() %>% # Add default OpenStreetMap map tiles
addMarkers(lng=df_final$order_long, lat=df_final$order_lat)
map
Please help.
Can you help clarify your question: Do you already know the lon/lat coordinates about which you would like to cluster your data or are you trying to determine the ideal centroids based on your data?
If you know the coordinates of each centroid, then you could just run your data through the kmeans algorithm with a max iteration of one. The following would do that:
set.seed(1)
centroids <- data.frame(lat=1:3, lon=4:6) # Input the coordinates for your centroids here
locations <- data.frame(lat=runif(50,1,3), lon=runif(50,4,6))
kmeans(locations, centroids, iter.max=1) # Set your initial centroids and then iter once
If you do not know the coordinates and want kmeans to find them for you, then just increase iter.max or leave it as default (10).
This question has been asked several times here, please use search.
k-means is a bad choice for such data:
how do you find k?
k-means uses squared-Euclidean but you want a spherical geo-distance
k-means is sensitive to outliers
If you google a little bit, you will find examples why this does not work well. Instead, have a look at OPTICS for example.
I have a shapefile with 50+ different polygonal shapes (representing 50+ different regions) and 10,000+ data points that are supposed to be present in one of the regions. The thing is, the 10,000+ points are already coded with a region they are supposed to be in, and I want to figure out how far they are from this coded region in geo-spatial distance.
My current approach (code below), which involves converting shapefiles to owin objects from the sp library and using distfun gets me distances in lat,long euclidean space. But I would like to get geo-spatial distances (eventually to convert to km). Where should I go next?
#basically cribbed from http://cran.r-project.org/web/packages/spatstat/vignettes/shapefiles.pdf (page 9)
shp <- readShapeSpatial("myShapeFile.shp", proj4string=CRS("+proj=longlat +datum=WGS84"))
regions <- lapply(slot(shp, "polygons"), function(x) SpatialPolygons(list(x)))
windows <- lapply(regions, as.owin)
# need to convert this to geo distance
distance_from_region <- function(regionData, regionName) {
w <- windows[[regionName]]
regionData$dists <- distfun(w)(regionData$lat, regionData$long)
regionData
}
I'd project the data to a euclidean (or near euclidean) coordinate system - unless you are spanning a large chunk of the globe then this is feasible. Use spTransform from maptools or sp or rgdal (I forget which) and convert to a UTM zone near your data.
You also might do better with package rgeos and the gDistance function:
gDistance by default returns the cartesian minimum distance
between the two geometries in the units of the current projection.
If your data is over a large chunk of globe then... tricky... 42...
Barry
I am working with shapefiles in R, one is point.shp the other is a polygon.shp.
Now, I would like to intersect the points with the polygon, meaning that all the values from the polygon should be attached to the table of the point.shp.
I tried overlay() and spRbind in package sp, but nothing did what I expected them to do.
Could anyone give me a hint?
With the new sf package this is now fast and easy:
library(sf)
out <- st_intersection(points, poly)
Additional options
If you do not want all fields from the polygon added to the point feature, just call dplyr::select() on the polygon feature before:
library(magrittr)
library(dplyr)
library(sf)
poly %>%
select(column-name1, column-name2, etc.) -> poly
out <- st_intersection(points, poly)
If you encounter issues, make sure that your polygon is valid:
st_is_valid(poly)
If you see some FALSE outputs here, try to make it valid:
poly <- st_make_valid(poly)
Note that these 'valid' functions depend on a sf installation compiled with liblwgeom.
If you do overlay(pts, polys) where pts is a SpatialPointsDataFrame object and polys is a SpatialPolygonsDataFrame object then you get back a vector the same length as the points giving the row of the polygons data frame. So all you then need to do to combine the polygon data onto the points data frame is:
o = overlay(pts, polys)
pts#data = cbind(pts#data, polys[o,])
HOWEVER! If any of your points fall outside all your polygons, then overlay returns an NA, which will cause polys[o,] to fail, so either make sure all your points are inside polygons or you'll have to think of another way to assign values for points outside the polygon...
You do this in one line with point.in.poly fom spatialEco package.
library(spatialEco)
new_shape <- point.in.poly(pts, polys)
from the documentation: point.in.poly "intersects point and polygon feature classes and adds polygon attributes to points".