How can calculate the real distance between two points with GeoDjango? - python

from django.contrib.gis.geos import Point
p1 = Point(36.74851779201058, -6.429006806692149, srid=4326)
p2 = Point(37.03254161520977, -8.98366068931684, srid=4326)
p1.distance(p2)
Out: 2.5703941316759376
But what is the unit of this float number?
If you calculate this distance, this is 229.88 Km. You can get it too using geopy:
from geopy.distance import distance
distance(p1, p2)
Out: Distance(229.883275249)
distance(p1, p2).km
Out: 229.88327524944066
I have read that you can get (so so) this, if you divide the previous number for 111:
(2.5703941316759376 / 111) * 10000
Out: 231.5670388897241 # kilometers
Is there any way to get the real distance using only GeoDjango? Or should I use geopy?

Usually, all spatial calculations yield results in the same coordinate system as the input was given. In your case you should seek a calculation using the SRID 4326 which is longitude/latitude polars in degrees from the prime meridian and equator.
Consequently, GeoDjango's distance calculation - if I get it correctly - is the Euclidean distance between the two pairs of coordinates. You are searching for the big circle distance (where your division by 111 is just a rough approximation that is only close to the actual big circle distance in certain ranges of latitude).
geopy should use the big circle distance for SRID 4326 implicitly, yielding the correct result.
You now have a few different options:
A: Implement big circle on your own
Google for haversine formula, you can punch in two pairs of lat/lon coordinates and you should get a good approximation of the actual big circle distance. However, this depends on the mercator approximation that is used -- remember that Earth is not a sphere. You may run into problems near the poles with this.
B: Transform to a metric (local) coordinate system
If you transform your two locations to another coordinate system that is measured in meters, calculating the Euclidean distance will yield the correct result. However, such coordinate systems (call them planar systems) are different for various regions on the globe. There are different projections for different countries, as the approximation of the Earth's irregularly curved surface as a plane is errorneous -- especially not uniquely errorneous for any location on its surface.
This is only applicable if all points among which you wish to calculate distances are in the same geographical region.
C: Use a library for this
Use geopy or shapely or any other qualified library that can calculate the actual big circle distance based on the SRID your points are given in. Remember that all coordinates are just approximations due to Earth's irregularity.

As far as I know, GeoDjango doesn't support calculating the real distance. It just calculates the distance geometrically. Therefore, I think you should use geopy as I did in my project..
from geopy.distance import vincenty
distance = vincenty((lat1, lon1), (lat2, lon2)).kilometers
This will give the right distance as kilometers.
For further information, check the geopy documentation.
http://geopy.readthedocs.io/en/latest/

There's a solution to this online, which explains both what GeoDjango is doing originally (a distance calculation that doesn't use any standard units, essentially), but also, how to get it into a form that returns the distance in more useful units -- the code is very similar to what you're already doing, except that it makes use of a transform on each point before retrieving the distance. The link is below, hopefully it's useful to you:
https://coderwall.com/p/k1gg1a/distance-calculation-in-geodjango

Related

Converting a Plane to FiniteSet in SymPy

I am currently working with 3D geometry and I decided to use sympy.geometry to manage objects in space.
I had to solve a non-linear system of equations to find the intersection between a plane and a sphere, which yields a FiniteSet as a result (which is the correct equation of the circle, so that works). After that, I have to find the intersection between this circle and another plane, which I'm finding difficult to do as the two objects are of different type, so no direct comparison can be done.
I am asking if there is any automatic way of converting a Plane object from the module into a FiniteSet or I have to do it manually by defining a symbolic set with the coordinates of the points on the plane (which can be done as I have full description of this new plane).
Edit: By equation of the circle, I mean the following. The set is described as a collection of points (in the example, the circle is perpendicular to the z=0 plane, but this has to be done in general so few assumptions can be made to simplify the problem):
FiniteSet((70,18-sqrt(-(z-6)(z-2)),z),(70,18+sqrt(-(z-6)(z-2)),z))
Here, z is bound to be real so it is limited to the [2,4] interval.

What algorithm does GeoPandas use for calculating distances between polygons?

I'm using ArcGIS Pro and GeoPandas for spatial analysis operations. I noticed that the distance operations in ArcGIS and the GeoPandas don't align. I wonder which algorithm GeoPandas uses for its distance calculations (function distance).
In my example I selected polygons within a distance of 10 km from another polygon. One polygon is selected in ArcGIS but not in GeoPandas as the distance there is > 10 km. The data is projected to the same crs in both cases.
It's not surprising that different distance algorithms are used, I just can't find any information on which algorithm GeoPandas uses. I already checked the documentation and the code in Git.
ArcGIS uses vertex distances for polygons (ArcGIS documentation here).
Has anyone background information on the GeoPandas distance tool algorithm?
Help is greatly appreciated!
There are a lot of dependencies geopandas relies on. For the distance computation that involves point to point object, it uses shapely Euclidean distance as can be traced to this link:- https://github.com/Toblerity/Shapely/blob/master/shapely/geometry/base.py
If you have a geodataframe df5 like this
a b geometry
0 0 1 POINT (0.00000 0.00000)
1 0 2 POINT (1.00000 0.00000)
2 1 3 POINT (0.00000 2.00000)
3 5 4 POINT (1.00000 1.00000)
You can do computation check with
df5.geometry.values[0].distance( df5.geometry.values[3] )
The result will be 1.4142135623730951, which is the Euclidean distance.
There is no exact explanation for this in the shapely documentation. However, it can be estimated that
https://shapely.readthedocs.io/en/latest/manual.html#shapely.ops.nearest_points is likely to be used.
So I think it will represent the minimum distance between two polygons.
However, this is just my opinion, and I think you will have to test it yourself in the end. In my experience shapely doesn't produce the closest points other than the points shown on the polygon. (You can see this in an example where shapely calculates the minimum distance between a point and a line. The minimum distance is not the distance along the vertical tangent, but the closest point to the line's vertices.)
Since it is based only on points that already exist in polygons, I think that there may be a difference between the two values if ARCGIS finds and calculates the contact point with the minimum distance.

detect point on a curve boundary

I have boundaries of semi-circle or ellipse shaped objects. Example image is
The boundary can be slightly jagged (when you zoom in). I am looking to detect a point of interest (location x and y) on these curves, where we see a definite change in the shape, such as
There can be two outputs:
No point of interest: we cannot find specific features
Point of interest with x and y location
Currently, I am using Python and OpenCV. I cannot think of a efficient and effective way to solve this problem. Any help will be really appreciated.
Nothing says that others will agree with my closure vote, so ...
I suggest two steps:
Fit an ellipse to the given points. I'm sure you've already found curve-fitting algorithms (and perhaps software packages) by now -- and asking for those is specifically proscribed on Stack Overflow.
Code a small anomaly detector, which works on the difference between the fitted curve and the actual data points.
Step 2 depends heavily on your definition of "point of interest". What are the criteria? I notice that your second point of interest actually lies very close to the fitted curve; it's the region on either side the deviates inward.
I suggest that you do your fitting in polar coordinates, and then consider the result in terms of theta and radius. Think of "flattening" the two curves as a single unit, so that the central angle (theta) is the new x-coordinate, and the distance from the center is the new y-coordinate.
Now, subtract the two curves and plot the difference (or just store this new curve as an array of points). Look for appropriate anomalies in these differences. This is where you have to decide what you need. Perhaps a sufficient deviation in the "r" value (radius, distance from center"); perhaps a change in the gradient (find a peak/valley, but not a gently sloping bulge). Do you want absolute difference, or an integral of deviation (area between the fit and the anomaly). Do you want it linear or squared ... or some other function? Does the width of the anomaly figure into your criteria?
That's what you need to decide. Does this get you moving?

Finding euclidean distance between coordinates in python

I have a problem with pdist function in python. I have coordinates of points that I want to find the distance between them but it does not consider them as coordinates and find distance between two points rather than coordinate (it consider coordinates as decimal numbers rather than coordinates). I could not find anything so far of how to fix this problem. Any help is appreciated. In other words, should I do any transformation on my coordinates? Here is a sample code:
p1=[39.1653, -86.5264]
p2=[39.704166670000049, -86.399444439999826]
X=[p1[0],p2[0]]
Y=[p1[1],p2[1]]
spdist.pdist(zip(X,Y), 'euclidean')
The result it gives me is 0.55361991 miles but when I put the coordinates in google map, it give me 42 miles.
Thanks
You can calculate distance from decimal coordinates if you know the formula that's involved. There's one for rectangular coordinate systems; another for spherical coordinate systems.
If the Python built in function takes in point parameters, why not wrap your decimal values as points before calling the function?

How do you calculate the area of a series of random points?

So I'm working on a piece of code to take positional data for a RC Plane Crop Duster and compute the total surface area transversed (without double counting any area). I cannot figure out how to calculate the area for a given period of operation.
Given the following Table Calculate the area the points cover.
x,y
1,2
1,5
4,3
6,6
3,4
3,1
Any Ideas? I've browsed Greens Theorem and I'm left without a practical concept in which to code.
Thanks for any advise
Build the convex hull from the given points
Algorithms are described here
See a very nice python demo + src
Calculate its area
Python code is here
Someone mathier than me may have to verify the information here. But it looks legit: http://www.wikihow.com/Calculate-the-Area-of-a-Polygon and fairly easy to apply in code.
I'm not entirely sure that you're looking for "Surface area" as much as you're looking for Distance. It seems like you want to calculate the distance between one point and the next for that list. If that's the case, simply use the Distance Formula.
If the plane drops a constant width of dust while flying between those points, then the area is simply the distance between those points times the width of the spray.
If your points are guaranteed to be on an integer grid - as they are in your example - (and you really are looking for enclosed area) would Pick's Theorem help?
You will have to divide the complex polygon approximately into standard polygons (triangles, rectangles etc) and then find area of all of them. This is just like regular integration (only difference is that you are yet to find a formula to approximate your data).
The above points are when you assume that you are forming a closed polygon with your data.
Use to QHull to triangulate the region, then sum the areas of the resulting triangles.
Python now conveniently has a library that implements the method Lior provided. https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.ConvexHull.html will calculate the convex hull for any N dimensional space and calculate the area/volume for you as well. See the example and return value attributes towards the bottom of the page for details.

Categories