How to have Shapely polygon understand Earth projection? - python

I am interested in having my Shapely polygon understand the crossover from a longitude of 179 degrees to -179 degrees. As can be seen with the plot below, this Polygon is understandably viewed as spanning from -179 to +179. Is there anyway around this (to get it to view it as spanning from +179 to -179 and thus having an area of 2? Thank you!
import geopandas
from shapely.geometry import Polygon
p = Polygon([[179,5],[179,6],[-179,6],[-179,5],[179,5]])
p_gs = geopandas.GeoSeries(p,crs= "EPSG:4326")
p_gs.plot()

I see what you mean.
But a map is not a globe.
(After opening the OSM map in QGIS, etc., keep moving to the right. There is only a blank space.)
epsg 4326 i.e. the longitude and latitude coordinate system ends at 180 on both sides. It represents only 180 from the reference point.
Therefore, to do the work you want, you need to select a coordinate system that can represent the part and then draw again.
Choose a coordinate system that allows for meter-based calculations(area or Euclidean distances must use the TM coordinate system) and the reference point represents the desired area.
After that, it seems to be necessary to draw a picture by changing the longitude and latitude to the coordinates that fit the CRS.

Related

Given a surface area, longitude and latitude, is there a formula for determining the best resolution to use with Google Tiles to map the area?

I'm trying to create a series of maps showing general geographic features (e.g. major roads and town names) using Cartopy and Matplotlib, but have been stumped trying to write a function to calculate the right resolution when adding the Google Tiles.
I've tried looking into how the resolution and tiles work but it's all getting a bit confusing. I was able to compute the meters per pixel given the latitude and resolution but nothing that connects to the square area that I'm shown, so I'm wondering if there is an easier way to estimate the best resolution to plot a rectangular area given:
latitude and longitude of the centroid
surface area of the rectangular area (in sq km)
Specifically, I want to be able to choose a resolution that looks best and shows the general landscape given the surface area being mapped and its geocoordinates.

Python package/function to get percentage area covered by one polygon in another polygon using geo coordinates

I am looking for a solution to find the percentage area covered by a polygon inside another polygon, from geo coordinates using python.
The polygon can be either fully reside inside the other one or a portion of the second polygon.
Is there a solution to this.
Please advice.
Percentage is just area of intersection over area of the (other) polygon:
area(intersection)/area(polygon2).
Basically any of geometry packages should be able to compute this, as they all support area and intersection functions: I think Geopandas, SymPy, Shapely (and others I missed) should be able to do this. There might be differences in supported formats.
You did not specify what Geo coordinates you use though. I think Geopandas and SymPy support only 2D maps (flat map) - meaning you need to use appropriate projection to get exact result, and Shapely works with spherical Earth model.

How to determine the projection or coordinate reference system given spatial points

I am just a starter to Spatial Analysis and am stuck at a point.
I have a crime data set where the points are given in latitude and longitude. I have another dataset (a shape file of Chicago) and I would like to plot all the lat-long points on top of map plot using the polygons from the shape file.
The problem is that the shape file contains polygon information in a different format which I am unaware of. I retrieve the shape file from
https://data.cityofchicago.org/Facilities-Geographic-Boundaries/Boundaries-Neighborhoods/9wp7-iasj
From the above download I use the Neighborhoods_2012b.shp file
Latitude Longitude from crime data:
POINT (-87.680162979 41.998718085)
POINT (-87.746717696 41.934629749)
Polygon shapes in the Chicago Shapefile: (All are positive values)
POLYGON ((1182322.0429 1876674.730700001, 1182...
POLYGON ((1176452.803199999 1897600.927599996,...
I tried transforming the Latitude and Longitude information into different projection (Mercator) such as (epsg:3857, epsg:3395), but these projection give me both positive and Negative values
epsg:3857:
POINT (-9760511.095493518 5160787.421333898)
POINT (-9767919.932699846 5151192.321624438)
I even tried transforming all Lat-Long into UTM (using the python UTM library), which hopefully gives me all positive value but still it doesn't seem the right format as the plots are at very different scale.
Using UTM python Library (utm.from_latlon)
POINT (4649857.621612935 443669.2483944244)
POINT (4642787.870839979 438095.1726599361)
I am not sure how to handle this situation, Is there a way to know what type of projection is used given the spatial points?
I'd be glad for any help.
The prj file says:
PROJCS["NAD_1983_StatePlane_Illinois_East_FIPS_1201_Feet",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",984250.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-88.33333333333333],PARAMETER["Scale_Factor",0.999975],PARAMETER["Latitude_Of_Origin",36.66666666666666],UNIT["Foot_US",0.3048006096012192]]
I opened the layer with QGIS and it did not use the prj file directly. However, with the information of the prj file, you can use the CRS selector to retrieve it. Search parameters are : NAD83 Illinois East here. Choose the one that is in Feet as suggested by the prj file. EPSG = 6455 is a good one for instance. I think you now have enough information to continue...

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

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

python: scipy.spatial: draw a convex polygon and calculate the area

I am using python. Now I have some coordinates (earth plane coordinates) and I want to draw a convex polygon based on these coordinates. Besides, I need to save the polygon into a GeoJSON format and calculate the polygon area.
I heard that scipy.spatial can do this but I have no idea how to do that, besides, how to extract the polygon coordinates and calculate the area on earth?
Thanks
As far as I know, scipy.spatial does not include the functions you need.
GeoPandas would be suitable for this task. See for instance this example for calculating areas of a polynomial. It also allows to convert between different coordinates system and support output to GeoJSON format.

Categories