|
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 |
|
6 class Point(GEOSGeometry): |
|
7 _minlength = 2 |
|
8 _maxlength = 3 |
|
9 |
|
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 |
|
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, (int, float, long)) and isinstance(y, (int, float, long)): |
|
24 # Here X, Y, and (optionally) Z were passed in individually, as parameters. |
|
25 if isinstance(z, (int, float, long)): |
|
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 |
|
34 point = self._create_point(ndim, coords) |
|
35 |
|
36 # Initializing using the address returned from the GEOS |
|
37 # createPoint factory. |
|
38 super(Point, self).__init__(point, srid=srid) |
|
39 |
|
40 def _create_point(self, ndim, coords): |
|
41 """ |
|
42 Create a coordinate sequence, set X, Y, [Z], and create point |
|
43 """ |
|
44 if ndim < 2 or ndim > 3: |
|
45 raise TypeError('Invalid point dimension: %s' % str(ndim)) |
|
46 |
|
47 cs = capi.create_cs(c_uint(1), c_uint(ndim)) |
|
48 i = iter(coords) |
|
49 capi.cs_setx(cs, 0, i.next()) |
|
50 capi.cs_sety(cs, 0, i.next()) |
|
51 if ndim == 3: capi.cs_setz(cs, 0, i.next()) |
|
52 |
|
53 return capi.create_point(cs) |
|
54 |
|
55 def _set_list(self, length, items): |
|
56 ptr = self._create_point(length, items) |
|
57 if ptr: |
|
58 capi.destroy_geom(self.ptr) |
|
59 self._ptr = ptr |
|
60 self._set_cs() |
|
61 else: |
|
62 # can this happen? |
|
63 raise GEOSException('Geometry resulting from slice deletion was invalid.') |
|
64 |
|
65 def _set_single(self, index, value): |
|
66 self._cs.setOrdinate(index, 0, value) |
|
67 |
|
68 def __iter__(self): |
|
69 "Allows iteration over coordinates of this Point." |
|
70 for i in xrange(len(self)): |
|
71 yield self[i] |
|
72 |
|
73 def __len__(self): |
|
74 "Returns the number of dimensions for this Point (either 0, 2 or 3)." |
|
75 if self.empty: return 0 |
|
76 if self.hasz: return 3 |
|
77 else: return 2 |
|
78 |
|
79 def _get_single_external(self, index): |
|
80 if index == 0: |
|
81 return self.x |
|
82 elif index == 1: |
|
83 return self.y |
|
84 elif index == 2: |
|
85 return self.z |
|
86 |
|
87 _get_single_internal = _get_single_external |
|
88 |
|
89 def get_x(self): |
|
90 "Returns the X component of the Point." |
|
91 return self._cs.getOrdinate(0, 0) |
|
92 |
|
93 def set_x(self, value): |
|
94 "Sets the X component of the Point." |
|
95 self._cs.setOrdinate(0, 0, value) |
|
96 |
|
97 def get_y(self): |
|
98 "Returns the Y component of the Point." |
|
99 return self._cs.getOrdinate(1, 0) |
|
100 |
|
101 def set_y(self, value): |
|
102 "Sets the Y component of the Point." |
|
103 self._cs.setOrdinate(1, 0, value) |
|
104 |
|
105 def get_z(self): |
|
106 "Returns the Z component of the Point." |
|
107 if self.hasz: |
|
108 return self._cs.getOrdinate(2, 0) |
|
109 else: |
|
110 return None |
|
111 |
|
112 def set_z(self, value): |
|
113 "Sets the Z component of the Point." |
|
114 if self.hasz: |
|
115 self._cs.setOrdinate(2, 0, value) |
|
116 else: |
|
117 raise GEOSException('Cannot set Z on 2D Point.') |
|
118 |
|
119 # X, Y, Z properties |
|
120 x = property(get_x, set_x) |
|
121 y = property(get_y, set_y) |
|
122 z = property(get_z, set_z) |
|
123 |
|
124 ### Tuple setting and retrieval routines. ### |
|
125 def get_coords(self): |
|
126 "Returns a tuple of the point." |
|
127 return self._cs.tuple |
|
128 |
|
129 def set_coords(self, tup): |
|
130 "Sets the coordinates of the point with the given tuple." |
|
131 self._cs[0] = tup |
|
132 |
|
133 # The tuple and coords properties |
|
134 tuple = property(get_coords, set_coords) |
|
135 coords = tuple |