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.

point.py 4.3 KiB

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