Calculate point distance in postgis/postgresql - postgresql

I am trying to calculate the distances between points in PostgreSQL, and now I have the longitude and latitude value for each point, and I know it's from GPS(WGS84).
Because all the points are in same city, and not very far from each other, so I know that use geometry with a local cartesian projection is better, because compared with using geography, it needs less calculation.
My question is how can I find the suitable cartesian projection for my data? If I can find one, is it the SRID value which should be used in ST_Transform?
Thank you very much!

Using Postgis is not necessary just to calculate distance between points.
You can use this gist to have a simple distance computation (distances are in Km).
You can also use the earthdistance extension.

I have found the SRID I need in this page:http://help.arcgis.com/en/arcgisserver/10.0/apis/rest/pcs.html and this page:http://help.arcgis.com/en/arcgisserver/10.0/apis/rest/gcs.html , and use ST_Transform to transfer the WGS84 coordinate to local cartesian coordinate, and can get the distance result in Unit meter.
Hope this can help others :)

Related

Understanding 3D distance outputs in matlab

Being neither great at math nor coding, I am trying to understand the output I am getting when I try to calculate the linear distance between pairs of 3D points. Essentially, I have the 3D points of a bird that is moving in a confined area towards a stationary reward. I would like to calculate the distance of the animal to the reward at each point. However, when looking online for the best way to do this, I tried several options and get different results that I'm not sure how to interpret.
Example data:
reward = [[0.381605200000000,6.00214980000000,0.596942400000000]];
animal_path = = [2.08638710671220,-1.06496059617432,0.774253689976102;2.06262715454806,-1.01019576900787,0.773933446776898;2.03912411242035,-0.954888684677576,0.773408777383975;2.01583648760496,-0.898935333316342,0.772602855030873];
distance1 = sqrt(sum(([animal_path]-[reward]).^2));
distance2 = norm(animal_path - reward);
distance3 = pdist2(animal_path, reward);
Distance 1 gives 3.33919107083497 13.9693378592353 0.353216791787775
Distance 2 gives 14.3672145652704
Distance 3 gives 7.27198528565078
7.21319284516199
7.15394253573951
7.09412041863743
Why do these all yield different values (and different numbers of values)? Distance 3 seems to make the most sense for my purposes, even though the values are too large for the dimensions of the animal enclosure, which should be something like 3 or 4 meters.
Can someone please explain this in simple terms and/or point me to something less technical and jargon-y than the Matlab pages?
There are many things mathematicians call distance. What you normally associate with distance is the eucledian distance. This is what you want in this situation. The length of the line between two points. Now to your problem. The Euclidean distance distance is also called norm (or 2-norm).
For two points you can use the norm function, which means with distance2 you are already close to a solution. The problem is only, you input all your points at once. This does not calculate the distance for each point, instead it calculates the norm of the matrix. Something of no interest for you. This means you have to call norm once for each row point on the path:
k=nan(size(animal_path,1),1)
for p=1:size(animal_path,1),
k(p)=norm(animal_path(p,:) - reward);
end
Alternatively you can follow the idea you had in distance1. The only mistake you made there, you calculated the sum for each column, where the sum of each row was needed. Simple fix, you can control this using the second input argument of sum:
distance1 = sqrt(sum((animal_path-reward).^2,2))

What is the alternate to npts function of basemap in cartopy?

I want to emulate the function of ntps which is in basemap.Geod class.
Its function is described as follows:
Given a single initial point and terminus point (specified by
python floats lon1,lat1 and lon2,lat2), returns a list of
longitude/latitude pairs describing npts equally spaced
intermediate points along the geodesic between the initial and
terminus points.
I want to do the same thing in cartopy, aparantly one way is to calculate the distance needed between each pair of successive coordinate and use that distance to compute coordinates from start to end point. Is there any other way to do so?
Based on cartopy's source, https://github.com/SciTools/cartopy/tree/master/lib/cartopy/geodesic
, it is clearly that no equivalent of ntps() function is available from cartopy.
However, it is not difficult to compute locations of points along a geodesic if you know the bearing from one of the end point. Here are steps that you can follow:
Use Geodesic.inverse() with input of (long, lat) of point1 and2, and get (forward_bearing, backward_bearing, geodesic_dist) as the result.
Suppose you want to get (long, lat) of a point (say 1/4 of the whole distance) along that geodesic (in 1), use Geodesic.direct() with long1, lat1, the obtained forward_bearing and geodesic_dist/4.
A better alternative is to use pyproj and forget all the above.

Great Circle Distance Problems (Spherical Vincenty Case and a simplified version)

%Great Circle Distnace -- Simplified
%% 12.18993,133.45898 %% point 1 (lat/long)
%% 14.34243,65.12750 %% point 2 (lat/long)
%%VARIABLES%%
phi_1=12.18993; %lat_1
phi_2=14.34243; %lat_2
gam_1=133.45898; %long_1
gam_2=65.12750; %long_2
delt_gam = abs(gam_1 - gam_2); %absoulte difference in longitudes
R_Earth = 6371000; %mean radius of the earth in meters, change to FT to get distance accordingly
%%Unsimplified Great-Circle Equation -- Breaking it up into numerator and
%%denominator sections to avoid more problems -- Spherical Case of the
%%Vincenty Formula
Numer_sec1= ((cos(phi_2))*(sin(delt_gam))^2);
Numer_sec2=(((((cos(phi_1))*(sin(phi_2)))+((sin(phi_1))*(cos(phi_2))*(delt_gam))))^2);
Denom_1= (((sin(phi_1))*(sin(phi_2)))+((cos(phi_1))*(cos(phi_2))*delt_gam));
delt_sig2=atan((sqrt(Numer_sec1+Numer_sec2))/(Denom_1));
delt_GC2=R_Earth*delt_sig2;
disp(delt_GC2)
Hey guys, so currently I'm trying to get my distance between two Lat/Long Points hammered out with the Spherical Case of the Vincenty formula in MatLab. I've been referencing http://en.wikipedia.org/wiki/Great-circle_distance
And from that have created the above MatLab code. I tried the first equation that was given (a more simplified version, but to no avail either), so I'm going with the Vincenty case. Given the two lat/long points (decimal format) that are listed at the beginning of the code I've yet to calculate the correct distance in between the two points with my program. I can't seem to find out what's going on, so I'm asking you guys if there's any way you could help me figure this out.
Thank you very much in advance, and I'll be looking at the post frequently so that I can help you help me by answering any questions you may have about my code thus far.
Based on this website: http://williams.best.vwh.net/gccalc.htm the distance should be 7381.56km.
The first answer below has reminded me that I have the mapping toolbox, yet I'm not sure how to interpret the results that I'm getting, so please check the commment that I posted below.
[ARCLEN, AZ] = distance(LAT1,LON1,LAT2,LON2)
this does in-fact work, but I'm not sure what I do with the arc-length or the azimuth that's produced.
Thank you and Happy New Year to all.
If you just want an answer for the WGS84 without programming up the
algorithm and without paying for the Mapping Toolbox, download the
Matlab package Geodesics on an ellipsoid of revolution. This
includes an improvement in the Mapping Toolbox function,
called geoddistance. To solve your problem
format long;
geoddistance(12.18993,133.45898,14.34243,65.12750)
->
7381566.23351761
The arguments to geoddistance are in degrees and the result is in
meters. This does the calculation for the WGS84 ellipsoid. If you want
to use a difference ellipsoid specify a 5th argument [a,e] (equatorial
radius, eccentricity). (For a sphere, set e = 0; if you want to specify a prolate ellipsoid, set e to a pure imaginary. Accurate answers are returned for |e| < 0.2.)
Incidentally many of the pictures of geodesics shown in the
Wikipedia article on ellipsoidal geodesics are drawn with this
package.
The default units for trigonometric functions in MATLAB are radians. You appear to be specifying your latitudes and longitudes in degrees. Either translate to radians or else use the sind() and cosd() functions.
Or, if you happen to have the mapping toolbox installed (Mathworks does charge extra for it, however), you can just use the distance() function. The distance() function should in principle actually be the superior way, if it is available to you, because it can accept an ellipsoidal Earth model.

Matlab Finding All Possible Triangles

I have several datasets and smallest have around 1000 points and largest have around 1,000,000 points. These points are consist of Longitude and Latitude information.
I would like to create triangles for all possible combinations of these points. I am planning to use Matlab. I will appreciate any answer about how to create triplets of points from these datasets by using Matlab.
One other problem is as you can see there are huge number of points in my dataset so how can I find a fast way to do this. Thanks for any help.
You can call combnk( points, k);
http://www.mathworks.in/help/stats/combnk.html

How to find the nearest points to given coordinates with MATLAB?

I need to solve a minimization problem with Matlab and I'm wondering which is the easiest solution. All the potential solutions that I've been thinking in require lot of programming effort.
Suppose that I have a lat/long coordinate point (A,B), what I need is to search for the nearest point to this one in a map of lat/lon coordinates.
In particular, the latitude and longitude arrays are two matrices of 2030x1354 elements (1km distance) and the idea is to find the unique indexes in those matrices that minimize the distance to the coordinates (A,B), i.e., to find the closest values to the given coordinates (A,B).
Any help would be very appreciated.
Thanks!
This is always a fun one :)
First off: Mohsen Nosratinia's answer is OK, as long as
you don't need to know the actual distance
you can guarantee with absolute certainty that you will never go near the polar regions
and will never go near the ±180° meridian
For a given latitude, -180° and +180° longitude are actually the same point, so simply looking at differences between angles is not sufficient. This will be more of a problem in the polar regions, since large longitude differences there will have less of an impact on the actual distance.
Spherical coordinates are very useful and practical for purposes of navigation, mapping, and that sort of thing. For spatial computations however, like the on-surface distances you are trying to compute, spherical coordinates are actually pretty cumbersome to work with.
Although it is possible to do such calculations using the angles directly, I personally don't consider it very practical: you often have to have a strong background in spherical trigonometry, and considerable experience to know its many pitfalls -- very often there are instabilities or "special points" you need to work around (the poles, for example), quadrant ambiguities you need to consider because of trig functions you've introduced, etc.
I've learned to do all this in university, but I also learned that the spherical trig approach often introduces complexity that mathematically speaking is not strictly required, in other words, the spherical trig is not the simplest representation of the underlying problem.
For example, your distance problem is pretty trivial if you convert your latitudes and longitudes to 3D Cartesian X,Y,Z coordinates, and then find the distances through the simple formula
distance (a, b) = R · arccos( a/|a| · b/|b| )
where a and b are two such Cartesian vectors on the sphere. Note that |a| = |b| = R, with R = 6371 the radius of Earth.
In MATLAB code:
% Some example coordinates (degrees are assumed)
lon = 360*rand(2030, 1354);
lat = 180*rand(2030, 1354) - 90;
% Your point of interest
P = [4, 54];
% Radius of Earth
RE = 6371;
% Convert the array of lat/lon coordinates to Cartesian vectors
% NOTE: sph2cart expects radians
% NOTE: use radius 1, so we don't have to normalize the vectors
[X,Y,Z] = sph2cart( lon*pi/180, lat*pi/180, 1);
% Same for your point of interest
[xP,yP,zP] = sph2cart(P(1)*pi/180, P(2)*pi/180, 1);
% The minimum distance, and the linear index where that distance was found
% NOTE: force the dot product into the interval [-1 +1]. This prevents
% slight overshoots due to numerical artifacts
dotProd = xP*X(:) + yP*Y(:) + zP*Z(:);
[minDist, index] = min( RE*acos( min(max(-1,dotProd),1) ) );
% Convert that linear index to 2D subscripts
[ii,jj] = ind2sub(size(lon), index)
If you insist on skipping the conversion to Cartesian and use lat/lon directly, you'll have to use the Haversine formula, as outlined on this website for example, which is also the method used by distance() from the mapping toolbox.
Now, all of this is valid for the whole Earth, provided you find the smooth spherical Earth accurate enough an approximation. If you want to include the Earth's oblateness or some higher order shape model (or God forbid, distances including terrain), you need to do far more complicated stuff. But I don't think that is your goal here :)
PS - I wouldn't be surprised that if you would write everything out that I did, you'll probably re-discover the Haversine formula. I just prefer to be able to calculate something as simple as distances along the sphere from first principles alone, rather than from some black box formula you had implanted in your head sometime long ago :)
Let Lat and Long denote latitude and longitude matrices, then
dist2=sum(bsxfun(#minus, cat(3,A,B), cat(3,Lat,Long)).^2,3);
[I,J]=find(dist2==min(dist2(:)));
I and J contain the indices in A and B that correspond to nearest point. Note that if there are multiple answers, I and J will not be scalar values, but vectors.