Location calculation- is UTM appropriate? - r

I'm wanting to calculate the location of point D, based on the location of point A B and C where I know the angle of point A relative to D and D relative to B and c relative to D.
In real terms, points A B and C are 3 locations i have marked with my GPS and point D is the location of a radiocollared animal I'm attempting to get a GPS location on. The angles I gain by knowing in which direction the radio collared animal is relative to north.
I've written the algorithm, but I know I can't put GPS co-ordinates straight into it and will have to convert them in and then out again. I've been googling, and I'm a bit confused, is the usage of cartesian or UTM more appropriate for this?
How do I go about converting GPS to UTM? I've searched and I'm a bit confused. Some conversions talk of degrees minutes adn seconds, my GPS appears to give me an additional number to this, so its N 68.21.446 and `w 12.14.284
Incase its relevant, I've assumed that the area is 2d in my calculations to make things a bit simpler.
Here is the code though I'm not sure it's needed:
#10/09/2013
#Enter your points for locations A B and C
#AN and AW is your first GPS points AA is the angle
AN<-10
AW<-0
AA<-45
#BN and BW are your second
BN<-10
BW<-0
BA<-0
#CN and CW are your third
CN<-0
CW<-10
CA<-90
#Convert these to ?
#work out distance
#For each co ordinate and angle, you need to calculate y=mx+c to make a line
#From these 3 lines, you can work out where they intersect
#If the angle is 0 it wont work, so make it very close to 0.
if(AA==0) {AA<-0.00001}
if(BA==0) {BA<-0.00001}
if(CA==0) {CA<-0.00001}
#Convert all angles to radians
AAr<-(AA*pi)/180
BAr<-(BA*pi)/180
CAr<-(CA*pi)/180
#Calculate M which is 1/tan(b)
AM<-1/tan(AAr)
BM<-1/tan(BAr)
CM<-1/tan(CAr)
#Calculate C the equation constant
#c=y-m*x
AC<-AW-AM*AN
BC<-BW-BM*BN
CC<-CW-CM*CN
#Caclulate intersections
#A and B
XAB<-(AC-BC)/(BM-AM)
YAB<-(AM*XAB+AC)
#B and C
XBC<-(BC-CC)/(CM-BM)
YBC<-(BM*XBC+BC)
#C and A
XAC<-(CC-AC)/(AM-CM)
YAC<-(CM*XAC+CC)
#Work out average of these 3 points
(XofABC<-(XAB+XBC+XAC)/(3))
(YofABC<-(YAB+YBC+YAC)/(3))
#Convert this back into GPS coordinate
`

UTMs are handy for this sort of operation as they're based on a square mapping datum and are flat 2D x-y cartesian system.
But beware of their limitations especially towards higher latitudes. And be careful that the system you choose is relevant to your location – some datum systems will be very warped if you use the wrong one.
Not sure why this is tagged in R?
Code looks like it should be fine.

Coordinate system transformations are done using the spTransform function in the rgdal package. You'll need to convert your coordinates to decimal degrees before you can convert them to UTM coords.
So, what is your "N 68.21.446" in decimal degrees? Well I'm not sure. Its 68 + (21/60) but you need to find out what the last number is. It might be a) thousandths of a minute (and if the first digit of it is ever 6 or more then that would seem likely) or b) two digits for seconds and then tenths of seconds.
For a) N 68.21.446 is then 68 + (21/60) + (446/1000)/60 decimal degrees.
For b) N 68.21.446 is then 68 + (21/60) + (44/3600) + (6/36000) decimal degrees.
You'll have to use some string matching functions to split it up.
Once you've got decimal degrees, create a spatial points dataframe with those numbers, set its CRS to your GPS coordinate system (probably EPSG code 4326) and then use spTransform to convert to your UTM code - use the one appropriate for your longitude.
Unless its polar bears or emperor penguins and the distances are not tens of km then the UTM coordinates should be a good approximation to a regular square grid. The bigger source of error is going to be your angular measurements!
On that subject, I did start writing an R package for doing location finding from radio direction finding equipment, implementing some of the statistical methods in the literature. You'll find that here: https://github.com/barryrowlingson/telemetr
If you have any comments on that package, address them to me via that github site, and not here on StackOverflow.

Related

Calculate Distance Between 3D (NED) Geographic Coordinates (Lat, Long, Depth)

It is well known that the Haversine formula is a useful mechanism in which to calculate distances between geographic coordinates. Obviously, there are certain packages in R which provider further refinements; accounting for the ellipsoidal nature of the earth.
What I cannot find, however, is any method for finding the straight-line distance between NED coordinates: that is, latitude, longitude and depth.
This type of distance calculation is essential for research on events which occur deep under oceans, or under the earth's crust in general.
Is anyone aware of a method to assist with this type of distance calculation on a sphere? On the earth? If not, does anyone have any ideas what the best trigonometric approach to this problem would be?
Linear distances are much easier to compute in a Cartesian coordinate system, so the first step is to convert your NED coordinates (i.e. long-lat-height) coordinates to some such system. In the open source world, PROJ4's "geocent" projection, which gives locations in meters in an orthogonal x-y-z coordinate system, is a good choice.
Simon Urbanek's proj4 package provides a good lightweight means of accomplishing that conversion. To demonstrate it's use, I'll write a little wrapper function that takes two points in NED coordinates and computes their separation in meters. (The one complication is that the ptransform() expects its latitude and longitude coordinate in radians; hence the divisions by 180/pi in the function's first and second lines.)
library(proj4)
findDist <- function(x=c(0,0,0), y=c(0,0,0)) {
x <- matrix(x/c(180/pi, 180/pi, 1), ncol=3)
y <- matrix(y/c(180/pi, 180/pi, 1), ncol=3)
xx <- ptransform(x, src.proj="+proj=longlat +ellps=WGS84",
dst.proj="+proj=geocent +ellps=WGS84")
yy <- ptransform(y, src.proj="+proj=longlat +ellps=WGS84",
dst.proj="+proj=geocent +ellps=WGS84")
sqrt(sum((yy-xx)^2))
}
## A sanity check. (Find distance between two points at 0°N 0°E, one on the
## surface and one 100m below the surface (i.e. at a height of -100m).)
findDist(c(0,0,0), c(0,0,-100))
## [1] 100
## Distance from North to South Pole
findDist(c(0,90,0), c(0,-90,0))
## [1] 12713505
## Diameter of the earth at its equator
findDist(c(0,0,0), c(180,0,0))
## [1] 12756274
You can use Matlab function ecefOffset to compute distance between two geographical locations in 3D.
https://www.mathworks.com/help/map/ref/ecefoffset.html

Trying to find lat lon given original lat lon + 3 meters

I have this problem I have to solve.
I am given a coordinate lat/lon, and I need to find a random point within 3 meters of this original point. Approximations are good, but all I could find was this https://gis.stackexchange.com/questions/2951/algorithm-for-offsetting-a-latitude-longitude-by-some-amount-of-meters that has a 10 meter error. Thank you.
Not sure what "find" and "random" mean in this question.
The earth is about 10 million meters from equator to either pole (that's actually how they defined the size of the meter, at first; it's been modified slightly since). The width of latitude lines doesn't vary, so one meter north or south is always is one ten-millionth of 90 degrees, or 9e-6 degrees, so just multiply that by the north-south displacement in meters of your desired point from the initial point and you'll get the number to add to the initial point in degrees: delta_lat = y_meters * 9e-6.
The width of longitude lines does vary, but it works out as simply east-west displacement in meters * 9e-6 = delta_lon * cos(lat), which means you can use the distance from your initial point to figure the east-west difference in degrees: delta_lon = x_meters * 9e-6/cos(lat).
You'll have to be careful with that last part around the poles, because cos(lat) will approach zero. Navigational systems use quaternions to do these things because they don't have singularities in spherical coordinates.

GIS: Tunnel to geographical distance approximation

This question is more about math than programming. I am programming a function which takes a square of geographical distance between 2 points with known latitude and longitude as an argument. There's a straightforward way to compute it: calculate dot-product, then take arccos, and multiply by Earth radius. Then square the result and you get the square of geographical distance assuming Earth is a sphere (which is acceptable approximation in my case).
However I would like, if possible, to avoid an expensive arccos() call, especially given that I can easily obtain the square of the tunnel distance (by either Pythagorean theorem or the dot product).
I also read here http://en.wikipedia.org/wiki/Geographical_distance#Tunnel_distance about underestimation formula which I can use to get tunnel distance from geographical distance. In my case however, I need the opposite (tunnel to geographical), and for the square. I played with Taylor series and got a rough approximation:
G square = T2 / (1 - (T2/R2)/12.0) // here G2 is square of geographical distance, T2-square of tunnel, R2-square of Earth radius. I also was able to get a more accurate formula:
G square = T2 / (1 - (T2/R2)/12.0 - ((T2/R2)^2)/240.0).
This last formula gives error of only 3.8mm for G=1000 km, and less than 50cm for G=2000 km.
However, I still cannot mathematically prove this formula, at least when using Taylor series. Wonder if it's possible to get the mathematical proof and also expansion of this formula for larger values of G/T. Thanks!
Why tunnel distance from geo distance?. There is no geo distance. There are many possibilities to calculate a distance between two points on earth.
Just take the two lat/lon cooridnates, and then calculate the distance between them using a simmple cyclindrical projection.
This needs only a cos(centerLatitude), and a multiplication with a factor. (meters_per_degree)
See also Cyclindrical equi distant projection. Up to some kilomters (abou 10 to 100) this gives sufficient accuracy.

Calculating angle from latitude and longitude

I have a set of latitudes and longitudes , so this is the data for an animal as it moves in time. what i want to do is to calculate turning angle, that is by what angle it turns between every movement. so say i have point 1, point 2 and point 3 with latitude and longitude value corresponding to each point(animal moves from point 1 to point 2 to point 3 and so on) and i want to calculate the angle between these 3 points, point 2 being the middle point. what should i do? my OS is windows and i am using R for analysis.
so here is my sample data:
longitude latitude
36.89379547 0.290166977
36.89384037 0.290194109
36.88999724 0.286821044
36.88708721 0.288339411
36.88650313 0.29010232
36.88563203 0.289939416
36.88545224 0.290924863
they are in decimal degrees
Using the function trackAzimuth in maptools:
library(maptools)
trackAngle <- function(xy) {
angles <- abs(c(trackAzimuth(xy), 0) -
c(0, rev(trackAzimuth(xy[nrow(xy):1, ]))))
angles <- ifelse(angles > 180, 360 - angles, angles)
angles[is.na(angles)] <- 180
angles[-c(1, length(angles))]
}
The trackAzimuth function is a simple loop wrapper around gzAzimuth. See ?gzAzimuth for references on calculating directions on the sphere.
Using your data:
x <- read.table(text = "longitude latitude
36.89379547 0.290166977
36.89384037 0.290194109
36.88999724 0.286821044
36.88708721 0.288339411
36.88650313 0.29010232
36.88563203 0.289939416
36.88545224 0.290924863", header = TRUE)
trackAngle(as.matrix(x))
[1] 10.12946 111.17211 135.88514 97.73801 89.74684
EDIT: I had to remove first/last angles from the function, something I was doing after the fact with this function elsewhere. Should be right now. :)
Also, the packages adehabitatLT and argosfilter contain functions to calculate track directions and angles.
Your data points vary over only a small range. We can look at one small patch of Earth's surface and pretend it's flat, two dimensional. You have to figure out the scale of how many km, meters, miles, whatever your favorite unit is, corresponds to one degree of latitude, and for one degree of longitude. The latter depends on latitude - it'll be the same as the scale for latitude when near the equator, but if you are standing within arm's length of the north pole, one step will take you through fifty degrees. Set up x,y coordinates where x=0 is at longitude 36.88000, and y=0 is latitude 0.29000.
So, now you have a series of (x,y) points. Take the differences from each point to the next: P2-P1, P3-P2, etc. These could be called "displacement vectors" but other terms may be used in other fields than where i'm from. Call them V1, V2, etc. Use dot products and norms: dot(V1,V2) = magnitude(V1)*magnitude(V2)*cos(a) where a is the angle by which V2 deviates from the direction of V1. Repeat for V3 and V2, and so on.
R has all the tools to do this, but I don't know enough syntax of R to give examples.

Zip Code Radius Search

I'm wondering if it's possible to find all points by longitude and latitude within X radius of one point?
So, if I provide a latitude/longitude of -76.0000, 38.0000, is it possible to simply find all the possible coordinates within (for example) a 10 mile radius of that?
I know that there's a way to calculate the distance between two points, which is why I'm not clear as to whether this is possible. Because, it seems like you need to know the center coordinates (-76 and 38 in this case) as well as the coordinates of every other point in order to determine whether it falls within the specified radius. Is that right?
#David's strategy is correct, his implementation is seriously flawed. I suggest that before you perform the calculations you transform your lat,long pair to UTM coordinates and work in distance, not angular, measurements. If you are not familiar with Universal Transverse Mercator, hit Google or Wikipedia.
I reckon that your point (-76,38) is at UTM 37C 472995 (Easting) 1564346 (Northing). So you want to do your calculations of distance from that point. You'll find it easier, working with UTM, to work in metres, so your distance is (if you are using statute miles of 5280 feet) 16040 metres.
Incidentally, (-76,38) is well outside the contintental US -- does the US Post Office define zip codes for Antarctica ?
If you accept that the Earth is a perfect sphere, you can obtain the spatial coordinates of a point by
x = R.cos(Lat).cos(Long)
y = R.cos(Lat).sin(Long)
z = R.sin(Lat)
Now, take two points and compute the angle they form with the center of the Earth (using a dot product):
cos(Phi) = (x'.x" + y'.y" + z'.z") / R²
(the value of R gets simplified).
In your case, the angular distance, Phi, equals 2Pi.D/R. (R=6 378.1 km).
A point P" is inside the ground distance (D) of P' when the dot product is larger than cos(Phi).
CAUTION: all angles must be in radians.
Depending on the precision, the data set of points within a certain distance may be extremely large or even infinite (impossible). In a given area of a circle with a positive radius you will have infinitely many points. Thus, it is trivial to determine if a point falls within a circle, however to enumerate over all the points is impossible.
If you do set a fixed precision (such as a single digit), you can loop over all possible latitude and longitude combinations and perform the distance test.
Kevin is correct. There is no reason to calculate every possible coordinate-pair in the radius.
If you start at the centerpoint pC = Point(-76.0000, 38.0000) and are testing to find out if arbitrary point pA = Point(Ax, Ay) is within a 10 mile radius... use the Pythagorean theorem:
xDist = abs( pCx - Ax )
yDist = abs ( pCy - Ay )
r^2 = (xDist)^2 + (yDist)^2
A reasonable approximation is to only query the points where
pAx >= (-76.0000 - 10.0000) && pAx <= (-76.0000 + 10.0000)
pAy >= ( 38.0000 - 10.0000) && pAy <= ( 38.0000 + 10.0000)
then perform the more intensive calculation above.

Resources