[GIS] GeoDjango – faster way to use polygon.crosses

djangogeodjangopython

I have a polygon and a line segment. I want to know if the line segment is both inside and outsize the polygon. Using "prepared" has helped but it's still no where near fast enough. how can i speed up this process? I really want to use geoDjango but I'm all ears if there is something else out there (still in python).

myPolygon = Polygon(....)
myPreparedPolygon = myPolygon.prepared
myPreparedPolygon.crosses(lineAB)

:::EDIT::: I'm using "myPreparedPolygon.crosses(line)" because it's a prepared polygon. Using "line.crossed(myPreparedPolygon)" with not work.

Does segment AB cross the polygon?

Best Answer

GeoDjango is based on the GEOS library as Shapely. If you don't use Django it is more interesting to work with this module (many examples in GIS SE)

Following the explanations of GEOS: Prepared Geometries, a Prepared Geometry is a spatial predicate (only True or False). Geometries are "prepared" ala SQL for efficient batch operations (Efficient batch operations for Shapely)

myPolygon.intersects(lineAB) 
lineAB.intersects(myPolygon) 
myPreparedPolygont.intersects(lineAB)

With Shapely

from shapely.prepared import prep
myPolygon.intersects(lineAB) 
lineAB.intersects(myPolygon) 
prep(myPolygon).intersects(line)

give the same result, True.

The only difference is the speed if you work with many objects (see Efficient batch operations for Shapely) as a Spatial Index (More Efficient Spatial join in Python without QGIS, ArcGIS, PostGIS, etc).

The performance gains from using PreparedGeometry in real-world situations can be dramatic - up to 40 times improvement in speed (PreparedGeometry - efficient batch spatial operations for JTS )

With GeoDjango or Shapely

res = [line for line in lines if myPolygon.intersects(line)]
# and
res = [line for line in lines if myPreparedPolygont.intersects(line)]

In your example, the only solution (or use a Spatial Index) is the result of

With GeoDjango or Shapely

 len(lineAB.intersection(myPolygon))
 2 # -> MultiLineString

enter image description here

Compare with the upper line (green) where thelen = 1 (simple LineString)

Or the inverse with

lineAB.difference(myPolygon)

enter image description here

Related Question