point.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. from ctypes import c_uint
  2. from django.contrib.gis.geos.error import GEOSException
  3. from django.contrib.gis.geos.geometry import GEOSGeometry
  4. from django.contrib.gis.geos import prototypes as capi
  5. from django.utils import six
  6. from django.utils.six.moves import xrange
  7. class Point(GEOSGeometry):
  8. _minlength = 2
  9. _maxlength = 3
  10. def __init__(self, x, y=None, z=None, srid=None):
  11. """
  12. The Point object may be initialized with either a tuple, or individual
  13. parameters.
  14. For Example:
  15. >>> p = Point((5, 23)) # 2D point, passed in as a tuple
  16. >>> p = Point(5, 23, 8) # 3D point, passed in with individual parameters
  17. """
  18. if isinstance(x, (tuple, list)):
  19. # Here a tuple or list was passed in under the `x` parameter.
  20. ndim = len(x)
  21. coords = x
  22. elif isinstance(x, six.integer_types + (float,)) and isinstance(y, six.integer_types + (float,)):
  23. # Here X, Y, and (optionally) Z were passed in individually, as parameters.
  24. if isinstance(z, six.integer_types + (float,)):
  25. ndim = 3
  26. coords = [x, y, z]
  27. else:
  28. ndim = 2
  29. coords = [x, y]
  30. else:
  31. raise TypeError('Invalid parameters given for Point initialization.')
  32. point = self._create_point(ndim, coords)
  33. # Initializing using the address returned from the GEOS
  34. # createPoint factory.
  35. super(Point, self).__init__(point, srid=srid)
  36. def _create_point(self, ndim, coords):
  37. """
  38. Create a coordinate sequence, set X, Y, [Z], and create point
  39. """
  40. if ndim < 2 or ndim > 3:
  41. raise TypeError('Invalid point dimension: %s' % str(ndim))
  42. cs = capi.create_cs(c_uint(1), c_uint(ndim))
  43. i = iter(coords)
  44. capi.cs_setx(cs, 0, next(i))
  45. capi.cs_sety(cs, 0, next(i))
  46. if ndim == 3:
  47. capi.cs_setz(cs, 0, next(i))
  48. return capi.create_point(cs)
  49. def _set_list(self, length, items):
  50. ptr = self._create_point(length, items)
  51. if ptr:
  52. capi.destroy_geom(self.ptr)
  53. self._ptr = ptr
  54. self._set_cs()
  55. else:
  56. # can this happen?
  57. raise GEOSException('Geometry resulting from slice deletion was invalid.')
  58. def _set_single(self, index, value):
  59. self._cs.setOrdinate(index, 0, value)
  60. def __iter__(self):
  61. "Allows iteration over coordinates of this Point."
  62. for i in xrange(len(self)):
  63. yield self[i]
  64. def __len__(self):
  65. "Returns the number of dimensions for this Point (either 0, 2 or 3)."
  66. if self.empty:
  67. return 0
  68. if self.hasz:
  69. return 3
  70. else:
  71. return 2
  72. def _get_single_external(self, index):
  73. if index == 0:
  74. return self.x
  75. elif index == 1:
  76. return self.y
  77. elif index == 2:
  78. return self.z
  79. _get_single_internal = _get_single_external
  80. def get_x(self):
  81. "Returns the X component of the Point."
  82. return self._cs.getOrdinate(0, 0)
  83. def set_x(self, value):
  84. "Sets the X component of the Point."
  85. self._cs.setOrdinate(0, 0, value)
  86. def get_y(self):
  87. "Returns the Y component of the Point."
  88. return self._cs.getOrdinate(1, 0)
  89. def set_y(self, value):
  90. "Sets the Y component of the Point."
  91. self._cs.setOrdinate(1, 0, value)
  92. def get_z(self):
  93. "Returns the Z component of the Point."
  94. if self.hasz:
  95. return self._cs.getOrdinate(2, 0)
  96. else:
  97. return None
  98. def set_z(self, value):
  99. "Sets the Z component of the Point."
  100. if self.hasz:
  101. self._cs.setOrdinate(2, 0, value)
  102. else:
  103. raise GEOSException('Cannot set Z on 2D Point.')
  104. # X, Y, Z properties
  105. x = property(get_x, set_x)
  106. y = property(get_y, set_y)
  107. z = property(get_z, set_z)
  108. ### Tuple setting and retrieval routines. ###
  109. def get_coords(self):
  110. "Returns a tuple of the point."
  111. return self._cs.tuple
  112. def set_coords(self, tup):
  113. "Sets the coordinates of the point with the given tuple."
  114. self._cs[0] = tup
  115. # The tuple and coords properties
  116. tuple = property(get_coords, set_coords)
  117. coords = tuple