3

I get latitude, longitude and altitude using android.location.Location, after that I send this data on the server, and save it using:

update users set location = ST_SetSRID(ST_MakePoint(-40, 40, 40), 4326) where id = 1;

users.location column was created using:

SELECT AddGeometryColumn ('users', 'location', 4326, 'POINT', 3);

I already saw an answers about 2D points, or answers in which you need to translate one SRID into another, and this is confused me. I want to know correct way from the Android to the postgis.

So, how can I calculate distance between user with id 1 and user with id 2 in kilometers using postgis?

UPD:

SELECT AddGeometryColumn ('users', 'location', 4326, 'POINT', 2);

update users set location = ST_SetSRID(ST_MakePoint(-118.4079, 33.9434), 4326) where id = 1;

update users set location = ST_SetSRID(ST_MakePoint(2.5559, 49.0083), 4326) where id = 2;

SELECT ST_Distance(a.location, b.location)/1000 as Dist_deg from users a, users b where a.id=1 AND b.id=2;

Output:

 0.121898285970107

This is wrong(since these are degrees), so I tried this:

SELECT ST_Distance(ST_Transform(a.location, 2163), ST_Transform(b.location, 2163))/1000 as Dist_deg from users a, users b where a.id=1 AND b.id=2;

Output:

 8731.12032614592

So, this is wrong too.

  • ST_3DDistance is what you are looking for. careful, it returns distance in CRS units, so in (useless) degrees for EPSG:4326. you need to find a local projection for your area of interest, suitable for distance measurements and units in meter. – geozelot Apr 01 '18 at 09:39

2 Answers2

3

For the distance between the 3D points, you should create the 3d geometry for these points, then transform the points on an SRID (depends on the location of the points). After that, you can use (ST_3DDISTANCE), which is the only way.

You can find this ANSWER for a similar problem as yours.

If you want to drop the Z-Index, you can calculate the distance between the two 2D points, but be careful that the calculated distance (in degrees which is nonsense number) because the units for spatial reference 4326 are degrees.

 SELECT ST_Distance(
      ST_GeometryFromText('POINT(-118.4079 33.9434)', 4326), -- Los Angeles (LAX)
      ST_GeometryFromText('POINT(2.5559 49.0083)', 4326)     -- Paris (CDG)
      ) as Dist_deg;

In order to calculate the distance (in meter or Km), we must treat geographic coordinates not as approximate Cartesian coordinates but rather as true spherical coordinates. We must measure the distances between points as true paths over a sphere – a portion of a great circle [1].

So in this case, we will use (ST_Geography) as follows

 SELECT ST_Distance(
  ST_GeographyFromText('POINT(-118.4079 33.9434)'), -- Los Angeles (LAX)
  ST_GeographyFromText('POINT(2.5559 49.0083)')     -- Paris (CDG)
  )/1000 as Dist_KM;

And the result is about 9124.665 Km

For your case e.g (Location between 2D point1 & 2D point2):

SELECT ST_Distance(a.location, b.location)/1000 as Dist_deg from users a, users b where a.id=1 AND b.id=2;

For more information [please find this helpful tutorial]

Finally, let's have a small comparison as an example between the 3D & 2D distance[2].

SELECT ST_3DDistance(
            ST_Transform(ST_GeomFromEWKT('SRID=4326;POINT(-72.1235 42.3521 4)'),2163),
            ST_Transform(ST_GeomFromEWKT('SRID=4326;LINESTRING(-72.1260 42.45 15, -72.123 42.1546 20)'),2163)
        ) As dist_3d,
        ST_Distance(
            ST_Transform(ST_GeomFromText('POINT(-72.1235 42.3521)',4326),2163),
            ST_Transform(ST_GeomFromText('LINESTRING(-72.1260 42.45, -72.123 42.1546)', 4326),2163)
        ) As dist_2d;

And the results are (3D Distance=127.295059324629, 2D Distance=126.66425605671)

Moh
  • 1,588
  • 1
  • 9
  • 17
  • 1
    Thanks for your answer, but I have some misunderstandings: 1. You didn't use altitude, so how important is this parameter in measuring the approximate distance between two users(in kilometers)? 2. You said "then transform the points on an SRID (depends on the location of the points)", what did you mean? Because I see only SRID 4326, when we talk about geography. When should I use something other than 4326 when I need to calculate a distance between two people? – konstantin_doncov Apr 02 '18 at 22:46
  • Please, change your example with Paris and LA coords on the already inserted points in the table, this will correspond to the my question and will help other users.
  • – konstantin_doncov Apr 02 '18 at 22:47
  • 1
    @don-prog 3. I updated the answer to include a small example of how to get the distance between two locations (1,2) in case of this points stored as 2D points. 2. In simple words, in the SRID 4326, the distance will be in degrees. to get the distances in metric units, we need a projection SRID, so in this case, the projection is different depends on the area covered on the earth (SELECT srtext FROM spatial_ref_sys). – Moh Apr 02 '18 at 23:45
  • 1
    @don-prog 1. the answer it depends on the point 2 (SRID and projection) but in general, it's a small difference. – Moh Apr 02 '18 at 23:53
  • "...so in this case, the projection is different depends on the area covered on the earth (SELECT srtext FROM spatial_ref_sys)", sorry, it is a little complicated, as for a person who is not very versed in gis at all :( Do I have to manually select the SRID each time, depending on the user's coordinates?
  • Also, I tried your code, but got wrong output, please, check the UPD section in the my question.
  • – konstantin_doncov Apr 03 '18 at 05:49
  • In your (UPD), the first result in degrees is true (you get 0.121, just remove /1000 from the query and you will get the right result in degrees). For the second result, it's also true which is the 2d distance projected between the two coordinates in the SRID 2163. (I did 2163 just as an example but not for the same coordinates) – Moh Apr 03 '18 at 10:26
  • Ok, but now my first question in the my previous comment even more important. ...Do I have to manually select the SRID each time, depending on the user's coordinates? Can I automate this or use only one SRID everytime? What workaround is needed here? It's really a big difference between 8731 km and 9124 km. – konstantin_doncov Apr 04 '18 at 04:12
  • @don-prog Actually I am not sure, maybe someone has created something similar or if you would ask here so someone maybe has an idea about that. – Moh Apr 04 '18 at 10:41
  • Sorry for the delay. And what about ST_DistanceSphere(a.location, b.location)/1000? I found this function very useful, simple and quite accurate. Can I just create 2D point and use this function for distance calculations? Anyway, I still don't know what to do with altitude, maybe the difference between 2D and 3D is really not so big(as you said), and I just can use 2D points with ST_DistanceSphere()? – konstantin_doncov Apr 14 '18 at 07:43
  • 1
    ST_DistanceSphere it's a good option also. Regarding the difference, try to take two points from your measurements, and apply both 3d and 2d and see the difference. – Moh Apr 14 '18 at 14:08
  • I marked your answer as accepted, but it will be useful for other users if you add ST_DistanceSphere() to your answer. – konstantin_doncov Apr 14 '18 at 21:14