1

I am trying to calculate the distance between two locations in miles however the result that I am getting is incorrect.

The reason I think its incorrect is because I put locations (latitude and longitude) on this website and I get the distance in miles as 0.055. Here are the details from my code

PointField A : (-122.1772784, 47.7001663)
PointField B : (-122.1761632, 47.700408)
Distance : 0.001141091551967795

However, according to the website, the distance should be

Distance: 0.055 miles

Here is how I am calculating the distance.

This is my model

class modelEmp(models.Model):
       user                = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
       location            = models.PointField(srid=4326,max_length=40, blank=True, null=True)  
       objects             = GeoManager() 

and this is how I calculate the distance

 result = modelEmpInstance.location.distance(PointFieldBLocation)
   where result = 0.001141091551967795

Any suggestions on what I might be doing wrong here and why my result is different from the website?

John Moutafis
  • 22,254
  • 11
  • 68
  • 112
MistyD
  • 16,373
  • 40
  • 138
  • 240
  • FWIW I just entered your points in Google Earth and measured direct distance between as 282 feet or 0.0534091 miles – Slumdog Sep 27 '18 at 02:47
  • so that means the other website is correct and for some reason my calculations in code are wrong – MistyD Sep 27 '18 at 02:52
  • 1
    Where are the variables `modelEmpInstance` and `PointFieldBLocation` coming from? (Side note - your code will be much more readable to others if you use [PEP8 conventions](https://www.python.org/dev/peps/pep-0008/?) - using camelcase for variables is frowned apon). – solarissmoke Sep 27 '18 at 04:13
  • 1
    The answer is right - just in degrees! I don't know enough about GeoDjango to give an answer, but to get a result in metres from PostGIS you either need an SRID in metres, use geography rather than geometry type, or use st_distance_sphere. As your distances are quite small your most accurate option might be to use a local projection. – mlinth Sep 27 '18 at 12:11
  • 1
    Possible duplicate of [How to calculate distance between two PointField?](https://stackoverflow.com/questions/36020805/how-to-calculate-distance-between-two-pointfield) – JGH Sep 27 '18 at 12:14

1 Answers1

3

Your calculation is not wrong but the result is in the EPSG:4326's units, which are degrees. In order to calculate the distance in the wanted unit, we need to do the following:

  1. Transform the points into an EPSG with meter units.

    • If you don't care much about the accuracy of the calculations, you can use the EPSG:3857 (but the result will be 0.08104046068988752mi).
    • If you do care about the accuracy of your calculation though, you need to find an EPSG with meter units that are appropriate for your location. Since your points are located around the Seattle area, the appropriate EPSG is 32148.
  2. Create a Distance object with the distance calculation in meters

  3. Finally, convert it to miles:

    from django.contrib.gis.measure import Distance
    
    result = Distance(
        m = modelEmpInstance.location.transform(
            32148, clone=True
        ).distance(PointFieldBLocation.transform(32148, clone=True)
    )
    print(
        'Raw calculation: {}\nRounded calculation: {}'
        .format(result.mi, round(result.mi, 2)
    )
    

    This will print:

    Raw calculation: 0.0546237743898667 
    Rounded calculation: 0.055
    
John Moutafis
  • 22,254
  • 11
  • 68
  • 112
  • Thanks for clearing this up. I am new to this. Is there a service out there that would tell me what the EPSG is based on longitude latitude ? or is there a standard EPSG I can use ? – MistyD Sep 28 '18 at 11:53
  • I don't know of a site that you can add a point and get the appropriate EPSGs for that place. What you can do though is search where your point is on the map and then google something like "Seattle EPSG". From there I trust http://www.spatialreference.org and http://www.epsg.io. – John Moutafis Sep 28 '18 at 12:08
  • I have been reading a bit about EPSG. But I had a question. You mentioned that my initial result was correct but was in degrees. Is there a way to convert it into a unit of length ? I am not looking for a super accurate result but something +-15 miles would be great – MistyD Sep 28 '18 at 12:13
  • @MistyD There is not a standard way of doing that. If you don't care about accuracy, you can use the `EPSG:3857`. – John Moutafis Sep 28 '18 at 12:15
  • Ok thanks if I use EPSG:3857 will I need to change the SRID of the model as well ? – MistyD Sep 28 '18 at 12:18
  • @MistyD You can keep your model's EPSG as it is and only transform it at the time of the calculation. – John Moutafis Sep 28 '18 at 12:36
  • did you mean keep the SRID as it is and use the EPSG:3857 during calculation ? – MistyD Sep 28 '18 at 12:37
  • @MistyD Yes. (EPSG is the authority that produces reference systems and SRID is the corresponding code. So EPSG:4326 is produced from EPSG and has the SRID of 4326.) – John Moutafis Sep 28 '18 at 12:39
  • @MistyD No problem :) – John Moutafis Sep 28 '18 at 12:41
  • 1
    I am going to give this a try later today and mark it – MistyD Sep 28 '18 at 12:41
  • So I have been trying this out for a while now and I am getting the error 'Point' object has no attribute 'tranform' . Any suggestions ? Am I missing something here ? – MistyD Oct 01 '18 at 02:39
  • Suspect "tranform" is a typo and should be "transform". Also, possibly "format" and not "fromat". – mlinth Oct 01 '18 at 09:39
  • @MistyD That is correct and that is also the reason why one should not just copy paste directly from StackOverflow :D – John Moutafis Oct 01 '18 at 11:04
  • Nope I am using transform. Seems like I need to do this instead ```employerLocation = GEOSGeometry(loggedInEmployer.location).tranform(32148, clone=True)``` – MistyD Oct 01 '18 at 11:05
  • Seems like there is no transform method in the location. I am currently experimenting with ```GEOSGeometry(loggedInEmployer.location).tranform(32148, clone=True)``` – MistyD Oct 01 '18 at 11:05
  • @MistyD There is definitely a `transform` method on a `model.PointField`. – John Moutafis Oct 01 '18 at 11:10
  • Let me confirm this - I dont know why its failing in my code – MistyD Oct 01 '18 at 11:11
  • @MistyD Don't mention it :D – John Moutafis Oct 01 '18 at 11:37