r alphahull post-processing/ avoid two hulls - r

I have got a table with coordinates of points and want to get the smalest polygon around them. I tried different functions and so far alphahull works best for my purposes. My major interest is in the area of the hull. I have got approximately 3500 datasets, so I have to find a reliable method for my analysis.
I analysed some datasets and realised that in some cases I get a hull in a hull and areahull() is not able to return an area. A higher alpha-value would avoid this but would overestimate my area by far.
Is there a possibility to post-process my alpha-hull to remove the second hull? Or a better method to get the size of the area?
library(alphahull)
tmp <- ahull(path.points.1$x, path.points.1$y, alpha = 50)
plot(tmp, wpoints = F)
lin to example dataset

I found a solution which seems to work for my purposes: the function ahull_track() returns only the boundary as a geom_path()-object. the coordinates of the single boundary segments are stored in a list. unfortunately they are not in the correct order, so it is no straight-forward solution. I had to write a function which rearranges the segments into the correct order and generates a polygon.

Related

Road Length within Polygons in R

I have a shape file of a road network and another shape-file containing area boundaries. Is there any better code that I can use to get length of roads that lies inside each polygon?
This Question was asked earlier with the difference that I want to use R instead of QGIS.
I tried:
intersec=intersect(roads,Polygon)
road_length=tapply(intersec$length, intersec$polygon, sum)
This works, but the problem is that the intersection does not divide the length of the roads, that cross to Polygons, but doubles them in the intersec file and assigns the full length of those roads to both Polygons.
How I found out about that Problem: There is no error message, but the following proove tells me that something is wrong:
a=sum(roads$length) and b=sum(intersec$length)
a and b do not have same length -> a is smaller than b.
I actually did this for a project about 8 months ago.
I had been getting into the sf way of dealing with spatial data, and so my solution uses Classes, Methods, and functions from that package.
First, I made sure both my roads and shapes had the same coordinate-reference-system (CRS) by using sf::st_transform on one of them. Then I used sf::st_intersection() to find the intersections, and used sf::st_length() on the result to get the lengths. You may need to aggregate the lengths at this point, depending on whether your roads were combined into one super-multi-line or if each road is its own object. The following gives the gist of what I think ought to work:
sf::st_intersection(road, shape) %>% # Find the intersections, which should all be points or multilines
dplyr::mutate(len_m = sf::st_length(geom)) %>% # Find the length of each line
dplyr::group_by(SHAPE_COLUMNS) %>% # Here you need to insert all the columns from your shapes
dplyr::summarize(len_m = sum(len_m))

R: Find a shape from a point cloud

I have a point cloud like such below
df <- data.frame(x=c(2,3,3,5,6,2,6,7,7,4,3,8,9,10,10,12,11,12,14,15),
y=c(6,5,4,4,4,4,3,3,2,3,7,3,2,3,4,6,5,5,4,6))
plot(df,xlab="",ylab="",pch=20)
Think of them as gps coordinates of movement by an animal. I would like to find the spatial area covered by the points (animal). The most obvious solution is a convex hull which produces this:
df1 <- df[chull(x = df$x,y=df$y),]
polygon(x = df1$x,df1$y)
But this is not the result I am looking for. The movement area is not a closed geometric shape, but rather a boomerang kind of shape. The convex hull covers a lot of area not covered by the animal thereby overestimating the area. I am looking for something like this:
Of course, this is a mock dataset to give an idea. The original datasets have lot more points and varying geometries in point cloud. I was thinking along the lines of DBSCAN or minimum spanning networks, but they don't quite work.
I am not sure how to describe this geometrically or mathematically. If anyone has any ideas on how to approach this (even if it's not a full solution), I would very much appreciate that. If anyone has a better title for this question, that would be nice too :-)
Thanks.
Update ----------------------------------------------------------------
Plot of (minimum spanning tree) MST. I think this might be in the right direction.
library(ape)
d <- dist(df)
mstree <-mst(d)
plot(mstree, x1 = df$x, x2 = df$y)
Try alphahull
library(alphahull)
p <- ahull(df$x, df$y, alpha = 2.5)
plot(p)
Still, purely geometric tricks like this are rarely helpful for animal tracking data. It's too ad hoc to be applicable for other cases, doesn't have anything for the temporal component or information about the environment or the uncertainty of the locations or the relationship between the point samples and the real track etc etc.
library(geometry)
polyarea(df$x, df$y)
[1] 18.5
This requires the right order though.
You might want to consider an approach based on TSP heuristics. Such approaches are near ideal when all points are relevant.
Below is a simple approach extended from the insertion heuristic for TSP that might be workable, but it's O(N^2) or worst unless you rather careful with the data structure. The link gives the following for the heuristic description of the convex hull method.
Convex Hull, O(n^2*log^2(n))
Find the convex hull of our set of cities, and make it our initial subtour.
For each city not in the subtour, find its cheapest insertion (as in step 3 of Nearest Insertion). Then chose the city with the least
cost/increase ratio, and insert it.
Repeat step 2 until no more cities remain.
In this case, the cities are the data points, and since the goal isn't to connect to all of the data points but rather get the general shape, an extra step is needed to determine when a data point either shouldn't be added or is no longer needed and can be removed. The issue though is that it's not clear what what points would be considered irrelevant.
This TSP Test Data site should give you an idea of what the results of that heuristic will be, and how you want to go about removing points form the resulting "tour", which you consider irrelevant.
Although possibility solution is to keep track of the original convex hull, and limit the increase in distance between two adjacent hull points to some (relatively small) multiple of the original distance between the hull points, which is similar to how alpha hulls work. This would prevent shapes such as the one at the bottom of this, TSP Test Case BCL380, by limiting the distance that can be traveled between two hull points.

R: Determining whether a point lies inside a region made up of separate polygons generated from contourLines()

I am using the function contourLines() in R to record the vertices of a contour based on a probability density estimation. Then I test to see whether a point lies inside the contour region. I can do this test easily when there is only one region (polygon) created from contourLines, but sometimes the there are multiple polygons created. I am trying to come up with a way to determine whether a point lies inside the multiple polygon contour.
My idea so far is to calculate the number of polygons generated and treat each one separately. I was thinking I could use graph theory to determine the number of polygons generated because there will not be a path between points on 2 separate polygons.
Probably there is an easier way. Any suggestions?
Thanks in advance,
HS

Finding the image boundary

While I use R quite a bit, just started an image analysis project and I am using the EBImage package. I need to collect a lot of data from circular/elliptical images. The built-in function computeFeatures gives the maximum and minimum radius. But I need all of the radii it computes.
Here is the code. I have read the image, thresholded and filled.
actual.image = readImage("xxxx")
image = actual.image[,2070:4000]
image1 = thresh(image)
image1 = fillHull(image1)
As there are several objects in the image, I used the following to label
image1 = bwlabel(image1)
I generated features using the built in function
features = data.frame(computeFeatures(image1,image))
Now, computeFeatures gives max radius and min radius. I need all the radii of all the objects it has computed for my analysis. At least if I get the coordinates of boundaries of all objects, I can compute the radii through some other code.
I know images are stored as matrices and can come up with a convoluted way to find the boundaries and then compute radii. But, was wondering if there a more elegant method?
You could try extracting each object + some padding, and plotting the x and y axis intensity profiles for each object. The intensity profiles is simply the sum of rows / columns which can be computed using rowSums and colSums in R
Then you could find where it dropps by splitting each intensity profiles in half and computing the nearest minimum value.
Maybe an example would help clear things up:
Hopefully this makes sense

Dissolve holes in polygon in R

I am running some geoprocessing tasks in R, in which I am trying to create some polygons for clipping rasters of environmental information. I am buffering somewhat complex polygons, and this leaves small subgeometries that I would like to get rid of. In ArcGIS, I think this would involve converting my polygon from multipart to singlepart (or something along those lines) and then dissolving, but I don't know how to do this in R.
Here's an example that illustrates the problem:
require(maptools)
require(rgeos)
data(wrld_simpl)
wrld_simpl[which(wrld_simpl#data$NAME=='Greece'),]->greece
proj4string(greece)<-CRS('+proj=lonlat +datum=WGS84')
gBuffer(greece,width=0.5)->buf
plot(buf)
What I really want is the outer boundary of the polygon, with nothing else inside. Any ideas?
If you just want to get the one ring that forms the boundary of your buffer, then this:
plot(SpatialPolygons(list(Polygons(list(buf#polygons[[1]]#Polygons[[1]]),ID=1))),lwd=2)
is a very ad-hoc way of doing it (and plotting it) for your case.
What you really really want is to get all the rings with ringDir=1, since the rest will be holes. You need all the rings because your buffer might still be two disconnected islands.
outerRings = Filter(function(f){f#ringDir==1},buf#polygons[[1]]#Polygons)
outerBounds = SpatialPolygons(list(Polygons(outerRings,ID=1)))
plot(outerBounds)
might do the trick... Try it with width=0.1 and you'll see it work with multiple islands, but still removing a hole.
If you want the convex hull that will fit Greece, you can use the gConvexHull function in the rgeos package. Note that this is not necessarily the approach to take if you are dealing with polygons with holes in them, as I thought was the case from the question's title. However, from your example, it looks like the below approach will get you where you want.
myCH <- gConvexHull(greece)
plot(myCH)
which will produce something like
And to check that everything fits,
plot(myCH)
plot(greece,add=TRUE)

Resources