You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

adapter.py 1.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. from cx_Oracle import CLOB
  2. from django.contrib.gis.db.backends.base.adapter import WKTAdapter
  3. from django.contrib.gis.geos import GeometryCollection, Polygon
  4. class OracleSpatialAdapter(WKTAdapter):
  5. input_size = CLOB
  6. def __init__(self, geom):
  7. """
  8. Oracle requires that polygon rings are in proper orientation. This
  9. affects spatial operations and an invalid orientation may cause
  10. failures. Correct orientations are:
  11. * Outer ring - counter clockwise
  12. * Inner ring(s) - clockwise
  13. """
  14. if isinstance(geom, Polygon):
  15. self._fix_polygon(geom)
  16. elif isinstance(geom, GeometryCollection):
  17. self._fix_geometry_collection(geom)
  18. self.wkt = geom.wkt
  19. self.srid = geom.srid
  20. def _fix_polygon(self, poly):
  21. """Fix single polygon orientation as described in __init__()."""
  22. if self._isClockwise(poly.exterior_ring):
  23. poly.exterior_ring = list(reversed(poly.exterior_ring))
  24. for i in range(1, len(poly)):
  25. if not self._isClockwise(poly[i]):
  26. poly[i] = list(reversed(poly[i]))
  27. return poly
  28. def _fix_geometry_collection(self, coll):
  29. """
  30. Fix polygon orientations in geometry collections as described in
  31. __init__().
  32. """
  33. for i, geom in enumerate(coll):
  34. if isinstance(geom, Polygon):
  35. coll[i] = self._fix_polygon(geom)
  36. def _isClockwise(self, coords):
  37. """
  38. A modified shoelace algorithm to determine polygon orientation.
  39. See https://en.wikipedia.org/wiki/Shoelace_formula.
  40. """
  41. n = len(coords)
  42. area = 0.0
  43. for i in range(n):
  44. j = (i + 1) % n
  45. area += coords[i][0] * coords[j][1]
  46. area -= coords[j][0] * coords[i][1]
  47. return area < 0.0