I have generated a Voronoi tessellation for N number of points in 2D space using the deldir R package.
Now I want to divide each Voronoi cell into three Voronoi cells according to given azimuth described as below:
Azimuth is given as an input. E.g.: azimuth = 0 means an area should be separated by 2 lines at angle = 0 to angle = 120. Next area by angle = 120 to angle = 240 and last area is the remainder.
Azimuth is the starting angle from north for this separation and always it spans 120 degrees. In more detail, from each point Voronoi is generated exactly three lines are drawn dividing previous Voronoi cell into three Voronoi cells.
Can this be achieved using the deldir package? if not can anyone suggest a extension for this?
I don't know any easy/implemented way of doing this. However, you could try creating those lines manually.
I would try something along the lines of:
Access the coordinates of the edges of a voronoi polygon using deldir()
Convert the coordinates into line objects using the sp package
Create line objects that reach from the "center"-point to the border of the plot (calculating the end points based on your azimuth)
Find intersections of the lines created in 3 with the lines created in 2 (check How to get the intersection point of two vector?)
Create new (shorter) lines starting from your original point and ending at the intersection point retrieved from step 4.
Plot the lines created in 5.
Loop for every polygon
This may well be a very clumsy solution, but it is the only workaround I could come up with ;)
Related
I am trying to generate randomly distributed points in a rectangle.
To create 50 random points in a rectangle, I used
i=50
pp<-runifpoint(i, win=owin(c(0,19.5),c(0,3.12))
If I were to add conditions on the coordinates before randomly generating points,
e.g. 0.24 <x<19.26 ,0.24<y<2.64 ,
then generate random points, what code can I imply?
The ultimate goal is to generate points in the rectangle except for the grey shaded area, in the below image
This is a question about the R package spatstat.
The argument win specifies the spatial region in which the points will be generated. In your example you have specified this region to be a rectangle. You just need to replace this rectangle by the region in which you want the points to be generated.
You can construct spatial regions (objects of class owin) in many ways. See help(owin), or help(spatstat) for an overview.
In your example, you could build up the shape by forming the union of several rectangles. For example to make a simple cross shape, I could just write
require(spatstat)
A <- owin(c(-1,1), c(-4, 4))
B <- owin(c(-4,4), c(-1,1))
U <- union.owin(A, B)
plot(U)
Another way would be to specify the corners of the polygon shape and use W <- owin(poly=p) where p = list(x, y) contains the coordinates of the corners, listed in anticlockwise order without repetition. See help(owin).
This is also covered in Section 3.5 of the spatstat book. You can download Chapter 3 for free.
I would like to generate vector arrows that conform to the topography/slope of a raster dataset of a river catchment area.
I have created a Fishnet grid of points in ArcGIS and I would like to create a single arrow for each point of a set length that will follow the shape of the slope i.e. follow the path of least resistance, the line will follow progressively small numbers in a 3 x 3 grid.
I think I can generate the vector arrows using vector plot. Is it possible to achieve the lines conforming to the raster?
UPDATE: I have ~200,000 lines that I generated from a grid of points. I am going to turn these into a raster using R and set it to the same resolution as my slope raster.
Any ideas on how to layer the raster lines on the slope so I can get the lines to follow the lowest values of the slope?
This is for display/mapping purposes only? Use a DEM or TIN and display your arrow lines in ArcScene.
EDIT: given your update about your data and software not working-
Try this:
1) Make a raster surface covering the extent of your data with a cell size of 100m (or smaller or larger if that doesn't suit)
2) Convert that raster to a polygon layer e.g. 'area_grid100m'
3) Do a spatial join and assign all points a polygon cell id from one of the unique id fields in 'area_grid100m'
4) Use Summarize to get the mean lat/long of the start points and mean lat/long of the end points for each polygon. Summarize on the polygon id field and get select mean for both the lat and long fields
5) Add summary table to ArcMap, right click and select Display XY Data (set X Field as longitude and y Field as latitude). Right right the result and select Data > Export Data to make it permanent. You will now have two points per 'area_grid100m' cell.
5) Recreate your lines using this new file, which will give you one line per cell
If the res is not small enough, make the 'area_grid' cells smaller.
Suppose we have a polygon with five vertices. The two coordinates of the vertices are-
>x=c(1,4,6,3,-2)
>y=c(1,1,5,9,4)
We define the centre of the polygon as the point (mean(x),mean(y)).
I am struggling to draw spokes from the centre of the polygon to the boundary of the polygon such that the spokes creates same angle in the centre (i.e., two neighbouring spokes create equal angle in the centre). I also want to have the all the points on the boundary of the polygon (red circle in the following plot) in orderly manner.
Here is a rough sample plot (convex) which I want to have:
Note: The polygon I am dealing with not necessarily convex.
Sample plot (non-convex)
The output I want: 1) The coordinates of the line (i.e., the intersection points of the line through the origin and boundary segments of the polygon).
2) For each equispaced angle (theta in fig.2) I want a to draw a spoke corresponding to each theta (as in figure 2). Note that, angle lies between 0 to 360 degree.
3) In case of my second polygon (non-convex) where the same line go through two boundary segments (creating three intersecting points), I want to have three coordinates corresponding to the same angle (theta).
Could anyone help me in doing that using R? Thanks in advance.
Here you go. You need the sp and rgeos packages:
spokey <- function(xy,n=20){
xcent = mean(xy[,1])
ycent = mean(xy[,2])
cent = sp::SpatialPoints(cbind(xcent, ycent))
pts = sp::SpatialPoints(xy)
## take the furthest distance from centre to vertex, times two!
r = 2 * max(sp::spDistsN1(pts, cent))
theta=seq(0,2*pi,length=n+1)[-(n+1)]
## construct a big wheel of spoke lines
sl = sp::SpatialLines(
lapply(1:length(theta),function(id){
t = theta[id]
sp::Lines(
list(
sp::Line(
rbind(
c(xcent, ycent),
c(xcent + r * cos(t),ycent + r * sin(t))
)
)
),ID=id)
}))
## construct the polygon as a SpatialPolygons object:
pol = sp::SpatialPolygons(list(sp::Polygons(list(sp::Polygon(rbind(xy,xy[1,]))),ID=1)))
## overlay spokes on polygon as "SpatialLines" so we do line-on-line
## intersect which gets us points
spokes = rgeos::gIntersection(sl, as(pol,"SpatialLines"), byid=TRUE)
spokes
}
It takes a matrix of coordinates where the first point is not the last point:
xy1 = structure(c(4.49425847117117, 4.9161781929536, 7.95751618746858,
7.92235621065338, 9.76825499345149, 9.9616348659351, 8.04541612950659,
7.83445626861537, 6.42805719600729, 0.644241009906543, 2.40223985066665,
1.24196061576498, 2.13854002455263, 7.935927470861, 9.41043173309254,
9.33179150577352, 6.50074332228897, 7.34612576596839, 2.76533252463575,
1.07456763727692, 3.88595576393172, 1.17286792142569, 2.745672467806,
5.20317957152522, 5.81264133324759, 8.21116826647756), .Dim = c(13L,
2L))
and then:
> plot(xy1,asp=1)
> polygon(xy1)
> spokes = spokey(xy1,20) # second arg is number of spokes
> points(spokes,pch=19,col="red")
gets you:
If you don't believe it, draw the segments from the centre to the points :)
segments(mean(xy1[,1]),mean(xy1[,2]), coordinates(spokes)[,1], coordinates(spokes)[,2])
The function coordinates(spokes) will get you a two-column matrix of the spoke points - its returned as a SpatialPoints object at present.
I modified this to handle the convex case illustrated.
You will have to write code that computes the intersection of a spoke from the center to each edge line segment. Not that hard, really, but have never seen it in R. Then you will have to loop over the angles that you are interested in drawing, loop over the segments, find the ones it intersects, sort those values, and then draw the line to the intersection you are interested in.
You would then to the furthest, or some combination (maybe a dotted line between the closest and the furthest).
In pseudo-code:
for each spoke you want to draw
calculate the spoke-line from the center to some point far outside
initialize edge intersection-point list to empty
for each edge-segment
calculate the intersection-point of spoke-line and edge-segment
if the intersection-point exists
add it to the intersection list
now go through the intersections and find the furthest
draw the spoke from the center to the furthest intersection point
continue with the next spoke
This would probably take several hours to research and write, unless you write this kind of graphics code constantly.
I have the vertices of a non-self-intersecting polygon in 2-D where the x-coordinate is centred longitude and y-coordinate is centred latitude. I want to find the edges of the polygon.
I can plot the vertices and see which vertices are neighbouring and see the edges. But my question is how can I get these edges.
For example, I am considering the sample data:
> data1
vertices lon lat
5 1.133179 1.027886
4 1.094459 1.013952
2 1.055672 1.000000
1 1.000000 1.028578
3 1.038712 1.042541
6 1.116241 1.070438
Sample Plot of the points is
I want to have an array like this
>edges
ind1 ind2
[1,] 5 6
[2,] 1 3
[3,] 3 6
[4,] 1 2
[5,] 2 4
[6,] 4 5
I am interested about this kind of shape of the polygon (with minimum area)
I got this array by using a function ashape of the R-package alphahull. But in this function Euclidean distance is used to find distance between points, which not applicable in my case (since I am considering data on (lon, lat), we can use distHaversine distance function in the package geosphere). And this function giving unsatisfactory result in case if the polygon has large number vertices and have complex shape. This polygon may or may not be convex.
Now all I want is to build an algorithm to find the edges of the non-intersecting polygon with minimum area.
Any help in this direction will be gratefully appreciated.
Algorithm for finding all possible polygons:
generate the convex hull .
Note that any non intersecting polygon must traverse its convex hull in order.
Start with any point on the convex hull
Generate a list of paths from that point to each interior point, and to the next adjacent point on the convex hull
recursively extend each path to each remaining interior point as well as to that first free point on the convex hull
for each segment added to a path reject the path if it self intersects
I'm not going to post the code, but here are all 67 possible polygons for a random set of 8 points.
As one can imagine the set of results blows up quickly with the number of points (eg. n=12 -> ~10000 polygons.. )
here are the polygons with min and max perimeters.
convert points from lon,lat to Cartesian x,y or x,y,z
use spherical or ellipsoidal surface
if the size is small enough you can project (x,y,z) to local surface plane to avoid 3D computing
you can also use lon,lat as x,y but make sure there is no zero crossing (if is then offset that axis by some value until it isn't)
now there are many possible strategies
you did not provide any rule for the shape
so I assume 'minimal' perimeter/size/area and generic concave polygon
you can not go directly to edge lines before you know where is inside and where is outside
I would do this task like this: find polygon based on find holes in 2D point set
modification 1
as you already have all the edge points (at least that is my impression)
so you can make flag for each point from the above algorithm
that will tell you where is inside or outside of polygon
for example take 8 directions (N,NE,E,...) and encode which way is filled and which empty
then on each edge start in the middle of empty direction
and find 2 closest lines to it (in angular terms) that are not intersecting any previous line
and if more available use the smallest ones
gray means inside polygon
make list of all such possible lines (2 per point)
then search for connected loops
beware this modification is not 100% error prone (I do not think that is for concave polygon even possible)
modification 2
use complete polygon from bullet 2
and try to match its edge points to your input edge points
then use the edge lines as in original polygon but with your new points
if some points are skipped then find closest edge line to it and divide it by this point
this should be more safe and accurate then bullet 3.
simple approach
if the above is too much for you then
create list of all possible lines
sort them by size ascending
remove all 'long' lines that are intersecting any 'short' line
what is short or long depends on you
for example first third of lines can be the short ones and the last third the long ones
or make average size and what is < 0.6*avg_size or > 1.2*avg_size ...
or if you have N points then first 2N lines are short the rest is long (2 lines per point)
test all and select the best option for you ...
try to find joined lines
find only lines that are connected once (no more then 2 lines per point)
remove them from list into the final solution list
after this you will have list of possible lines and list of found lines
remove all lines from possible lines that intersect any line in found lines
this should remove any non relevant lines
try to find connections again
take first possible line if found connection move it to the solution list
and go to bullet 5.
if none found continue with next line ...
stop if none line left or none connection found.
How do you draw the curve representing the shortest distance between 2 points on a flat map of the Earth?
Of course, the line would not be a straight line because the Earth is curved. (For example, the shortest distance between 2 airports is curved.)
EDIT: THanks for all the answers guys - sorry I was slow to choose solution :/
I get this sort of information from the Aviation Formulary.
In this case:
Distance between points
The great circle distance d between
two points with coordinates
{lat1,lon1} and {lat2,lon2} is given
by:
d=acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2))
A mathematically equivalent formula,
which is less subject to rounding
error for short distances is:
d=2*asin(sqrt((sin((lat1-lat2)/2))^2 +
cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2))
And
Intermediate points on a great circle
In previous sections we have found
intermediate points on a great circle
given either the crossing latitude or
longitude. Here we find points
(lat,lon) a given fraction of the
distance (d) between them. Suppose the
starting point is (lat1,lon1) and the
final point (lat2,lon2) and we want
the point a fraction f along the great
circle route. f=0 is point 1. f=1 is
point 2. The two points cannot be
antipodal ( i.e. lat1+lat2=0 and
abs(lon1-lon2)=pi) because then the
route is undefined. The intermediate
latitude and longitude is then given
by:
A=sin((1-f)*d)/sin(d)
B=sin(f*d)/sin(d)
x = A*cos(lat1)*cos(lon1) + B*cos(lat2)*cos(lon2)
y = A*cos(lat1)*sin(lon1) + B*cos(lat2)*sin(lon2)
z = A*sin(lat1) + B*sin(lat2)
lat=atan2(z,sqrt(x^2+y^2))
lon=atan2(y,x)
To draw the 3D shortest path between two points on Earth's surface onto a 2D map of Earth's surface, you have to know how the 3D surface of Earth was projected onto the 2D map in question. If you know the projection used, you just need to apply it to the 3D shortest path to project it onto the 2D map. If you don't know the exact projection used, but have access to it through some sort of interface (ie. input 3D surface coords -> output 2D map coords), you could sample points along the 3D surface path, generate their corresponding map points through said interface, and then approximate the projected path with line segments/bezier curves/etc. through the projected sample points.