~ubuntu-branches/ubuntu/quantal/python-django/quantal

« back to all changes in this revision

Viewing changes to django/contrib/gis/geos/linestring.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2009-07-29 11:26:28 UTC
  • mfrom: (1.1.8 upstream) (4.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20090729112628-pg09ino8sz0sj21t
Tags: 1.1-1
* New upstream release.
* Merge from experimental:
  - Ship FastCGI initscript and /etc/default file in python-django's examples
    directory (Closes: #538863)
  - Drop "05_10539-sphinx06-compatibility.diff"; it has been applied
    upstream.
  - Bump Standards-Version to 3.8.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from django.contrib.gis.geos.base import numpy
 
2
from django.contrib.gis.geos.coordseq import GEOSCoordSeq
 
3
from django.contrib.gis.geos.error import GEOSException
 
4
from django.contrib.gis.geos.geometry import GEOSGeometry
 
5
from django.contrib.gis.geos.point import Point
 
6
from django.contrib.gis.geos import prototypes as capi
 
7
 
 
8
class LineString(GEOSGeometry):
 
9
    _init_func = capi.create_linestring
 
10
    _minlength = 2
 
11
 
 
12
    #### Python 'magic' routines ####
 
13
    def __init__(self, *args, **kwargs):
 
14
        """
 
15
        Initializes on the given sequence -- may take lists, tuples, NumPy arrays
 
16
        of X,Y pairs, or Point objects.  If Point objects are used, ownership is
 
17
        _not_ transferred to the LineString object.
 
18
 
 
19
        Examples:
 
20
         ls = LineString((1, 1), (2, 2))
 
21
         ls = LineString([(1, 1), (2, 2)])
 
22
         ls = LineString(array([(1, 1), (2, 2)]))
 
23
         ls = LineString(Point(1, 1), Point(2, 2))
 
24
        """
 
25
        # If only one argument provided, set the coords array appropriately
 
26
        if len(args) == 1: coords = args[0]
 
27
        else: coords = args
 
28
 
 
29
        if isinstance(coords, (tuple, list)):
 
30
            # Getting the number of coords and the number of dimensions -- which
 
31
            #  must stay the same, e.g., no LineString((1, 2), (1, 2, 3)).
 
32
            ncoords = len(coords)
 
33
            if coords: ndim = len(coords[0])
 
34
            else: raise TypeError('Cannot initialize on empty sequence.')
 
35
            self._checkdim(ndim)
 
36
            # Incrementing through each of the coordinates and verifying
 
37
            for i in xrange(1, ncoords):
 
38
                if not isinstance(coords[i], (tuple, list, Point)):
 
39
                    raise TypeError('each coordinate should be a sequence (list or tuple)')
 
40
                if len(coords[i]) != ndim: raise TypeError('Dimension mismatch.')
 
41
            numpy_coords = False
 
42
        elif numpy and isinstance(coords, numpy.ndarray):
 
43
            shape = coords.shape # Using numpy's shape.
 
44
            if len(shape) != 2: raise TypeError('Too many dimensions.')
 
45
            self._checkdim(shape[1])
 
46
            ncoords = shape[0]
 
47
            ndim = shape[1]
 
48
            numpy_coords = True
 
49
        else:
 
50
            raise TypeError('Invalid initialization input for LineStrings.')
 
51
 
 
52
        # Creating a coordinate sequence object because it is easier to
 
53
        # set the points using GEOSCoordSeq.__setitem__().
 
54
        cs = GEOSCoordSeq(capi.create_cs(ncoords, ndim), z=bool(ndim==3))
 
55
 
 
56
        for i in xrange(ncoords):
 
57
            if numpy_coords: cs[i] = coords[i,:]
 
58
            elif isinstance(coords[i], Point): cs[i] = coords[i].tuple
 
59
            else: cs[i] = coords[i]
 
60
 
 
61
        # If SRID was passed in with the keyword arguments
 
62
        srid = kwargs.get('srid', None)
 
63
 
 
64
        # Calling the base geometry initialization with the returned pointer
 
65
        #  from the function.
 
66
        super(LineString, self).__init__(self._init_func(cs.ptr), srid=srid)
 
67
 
 
68
    def __iter__(self):
 
69
        "Allows iteration over this LineString."
 
70
        for i in xrange(len(self)):
 
71
            yield self[i]
 
72
 
 
73
    def __len__(self):
 
74
        "Returns the number of points in this LineString."
 
75
        return len(self._cs)
 
76
 
 
77
    def _get_single_external(self, index):
 
78
        return self._cs[index]
 
79
 
 
80
    _get_single_internal = _get_single_external
 
81
 
 
82
    def _set_list(self, length, items):
 
83
        ndim = self._cs.dims #
 
84
        hasz = self._cs.hasz # I don't understand why these are different
 
85
 
 
86
        # create a new coordinate sequence and populate accordingly
 
87
        cs = GEOSCoordSeq(capi.create_cs(length, ndim), z=hasz)
 
88
        for i, c in enumerate(items):
 
89
            cs[i] = c
 
90
 
 
91
        ptr = self._init_func(cs.ptr)
 
92
        if ptr:
 
93
            capi.destroy_geom(self.ptr)
 
94
            self.ptr = ptr
 
95
            self._post_init(self.srid)
 
96
        else:
 
97
            # can this happen?
 
98
            raise GEOSException('Geometry resulting from slice deletion was invalid.')
 
99
 
 
100
    def _set_single(self, index, value):
 
101
        self._checkindex(index)
 
102
        self._cs[index] = value
 
103
 
 
104
    def _checkdim(self, dim):
 
105
        if dim not in (2, 3): raise TypeError('Dimension mismatch.')
 
106
 
 
107
    #### Sequence Properties ####
 
108
    @property
 
109
    def tuple(self):
 
110
        "Returns a tuple version of the geometry from the coordinate sequence."
 
111
        return self._cs.tuple
 
112
    coords = tuple
 
113
 
 
114
    def _listarr(self, func):
 
115
        """
 
116
        Internal routine that returns a sequence (list) corresponding with
 
117
        the given function.  Will return a numpy array if possible.
 
118
        """
 
119
        lst = [func(i) for i in xrange(len(self))]
 
120
        if numpy: return numpy.array(lst) # ARRRR!
 
121
        else: return lst
 
122
 
 
123
    @property
 
124
    def array(self):
 
125
        "Returns a numpy array for the LineString."
 
126
        return self._listarr(self._cs.__getitem__)
 
127
 
 
128
    @property
 
129
    def merged(self):
 
130
        "Returns the line merge of this LineString."
 
131
        return self._topology(capi.geos_linemerge(self.ptr))   
 
132
 
 
133
    @property
 
134
    def x(self):
 
135
        "Returns a list or numpy array of the X variable."
 
136
        return self._listarr(self._cs.getX)
 
137
 
 
138
    @property
 
139
    def y(self):
 
140
        "Returns a list or numpy array of the Y variable."
 
141
        return self._listarr(self._cs.getY)
 
142
 
 
143
    @property
 
144
    def z(self):
 
145
        "Returns a list or numpy array of the Z variable."
 
146
        if not self.hasz: return None
 
147
        else: return self._listarr(self._cs.getZ)
 
148
 
 
149
# LinearRings are LineStrings used within Polygons.
 
150
class LinearRing(LineString):
 
151
    _minLength = 4
 
152
    _init_func = capi.create_linearring