PageRenderTime 33ms CodeModel.GetById 18ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/django/contrib/gis/gdal/envelope.py

https://code.google.com/p/mango-py/
Python | 175 lines | 112 code | 17 blank | 46 comment | 21 complexity | db1ffab7f93e687f86f2c9937bddaa32 MD5 | raw file
  1"""
  2 The GDAL/OGR library uses an Envelope structure to hold the bounding
  3 box information for a geometry.  The envelope (bounding box) contains
  4 two pairs of coordinates, one for the lower left coordinate and one
  5 for the upper right coordinate:
  6
  7                           +----------o Upper right; (max_x, max_y)
  8                           |          |
  9                           |          |
 10                           |          |
 11 Lower left (min_x, min_y) o----------+
 12"""
 13from ctypes import Structure, c_double
 14from django.contrib.gis.gdal.error import OGRException
 15
 16# The OGR definition of an Envelope is a C structure containing four doubles.
 17#  See the 'ogr_core.h' source file for more information:
 18#   http://www.gdal.org/ogr/ogr__core_8h-source.html
 19class OGREnvelope(Structure):
 20    "Represents the OGREnvelope C Structure."
 21    _fields_ = [("MinX", c_double),
 22                ("MaxX", c_double),
 23                ("MinY", c_double),
 24                ("MaxY", c_double),
 25                ]
 26
 27class Envelope(object):
 28    """
 29    The Envelope object is a C structure that contains the minimum and
 30    maximum X, Y coordinates for a rectangle bounding box.  The naming
 31    of the variables is compatible with the OGR Envelope structure.
 32    """
 33
 34    def __init__(self, *args):
 35        """
 36        The initialization function may take an OGREnvelope structure, 4-element
 37        tuple or list, or 4 individual arguments.
 38        """
 39        
 40        if len(args) == 1:
 41            if isinstance(args[0], OGREnvelope):
 42                # OGREnvelope (a ctypes Structure) was passed in.
 43                self._envelope = args[0]
 44            elif isinstance(args[0], (tuple, list)):
 45                # A tuple was passed in.
 46                if len(args[0]) != 4:
 47                    raise OGRException('Incorrect number of tuple elements (%d).' % len(args[0]))
 48                else:
 49                    self._from_sequence(args[0])
 50            else:
 51                raise TypeError('Incorrect type of argument: %s' % str(type(args[0])))
 52        elif len(args) == 4:
 53            # Individiual parameters passed in.
 54            #  Thanks to ww for the help
 55            self._from_sequence(map(float, args))
 56        else:
 57            raise OGRException('Incorrect number (%d) of arguments.' % len(args))
 58
 59        # Checking the x,y coordinates
 60        if self.min_x > self.max_x:
 61            raise OGRException('Envelope minimum X > maximum X.')
 62        if self.min_y > self.max_y:
 63            raise OGRException('Envelope minimum Y > maximum Y.')
 64
 65    def __eq__(self, other):
 66        """
 67        Returns True if the envelopes are equivalent; can compare against
 68        other Envelopes and 4-tuples.
 69        """
 70        if isinstance(other, Envelope):
 71            return (self.min_x == other.min_x) and (self.min_y == other.min_y) and \
 72                   (self.max_x == other.max_x) and (self.max_y == other.max_y)
 73        elif isinstance(other, tuple) and len(other) == 4:
 74            return (self.min_x == other[0]) and (self.min_y == other[1]) and \
 75                   (self.max_x == other[2]) and (self.max_y == other[3])
 76        else:
 77            raise OGRException('Equivalence testing only works with other Envelopes.')
 78
 79    def __str__(self):
 80        "Returns a string representation of the tuple."
 81        return str(self.tuple)
 82
 83    def _from_sequence(self, seq):
 84        "Initializes the C OGR Envelope structure from the given sequence."
 85        self._envelope = OGREnvelope()
 86        self._envelope.MinX = seq[0]
 87        self._envelope.MinY = seq[1]
 88        self._envelope.MaxX = seq[2]
 89        self._envelope.MaxY = seq[3]
 90    
 91    def expand_to_include(self, *args): 
 92        """ 
 93        Modifies the envelope to expand to include the boundaries of 
 94        the passed-in 2-tuple (a point), 4-tuple (an extent) or 
 95        envelope. 
 96        """ 
 97        # We provide a number of different signatures for this method, 
 98        # and the logic here is all about converting them into a 
 99        # 4-tuple single parameter which does the actual work of 
100        # expanding the envelope. 
101        if len(args) == 1: 
102            if isinstance(args[0], Envelope): 
103                return self.expand_to_include(args[0].tuple) 
104            elif hasattr(args[0], 'x') and hasattr(args[0], 'y'):
105                return self.expand_to_include(args[0].x, args[0].y, args[0].x, args[0].y) 
106            elif isinstance(args[0], (tuple, list)): 
107                # A tuple was passed in. 
108                if len(args[0]) == 2: 
109                    return self.expand_to_include((args[0][0], args[0][1], args[0][0], args[0][1])) 
110                elif len(args[0]) == 4: 
111                    (minx, miny, maxx, maxy) = args[0] 
112                    if minx < self._envelope.MinX: 
113                        self._envelope.MinX = minx 
114                    if miny < self._envelope.MinY: 
115                        self._envelope.MinY = miny 
116                    if maxx > self._envelope.MaxX: 
117                        self._envelope.MaxX = maxx 
118                    if maxy > self._envelope.MaxY: 
119                        self._envelope.MaxY = maxy 
120                else: 
121                    raise OGRException('Incorrect number of tuple elements (%d).' % len(args[0])) 
122            else: 
123                raise TypeError('Incorrect type of argument: %s' % str(type(args[0]))) 
124        elif len(args) == 2: 
125            # An x and an y parameter were passed in 
126                return self.expand_to_include((args[0], args[1], args[0], args[1])) 
127        elif len(args) == 4: 
128            # Individiual parameters passed in. 
129            return self.expand_to_include(args) 
130        else: 
131            raise OGRException('Incorrect number (%d) of arguments.' % len(args[0])) 
132
133    @property
134    def min_x(self):
135        "Returns the value of the minimum X coordinate."
136        return self._envelope.MinX
137
138    @property
139    def min_y(self):
140        "Returns the value of the minimum Y coordinate."
141        return self._envelope.MinY
142
143    @property
144    def max_x(self):
145        "Returns the value of the maximum X coordinate."
146        return self._envelope.MaxX
147
148    @property
149    def max_y(self):
150        "Returns the value of the maximum Y coordinate."
151        return self._envelope.MaxY
152
153    @property
154    def ur(self):
155        "Returns the upper-right coordinate."
156        return (self.max_x, self.max_y)
157
158    @property
159    def ll(self):
160        "Returns the lower-left coordinate."
161        return (self.min_x, self.min_y)
162
163    @property
164    def tuple(self):
165        "Returns a tuple representing the envelope."
166        return (self.min_x, self.min_y, self.max_x, self.max_y)
167
168    @property
169    def wkt(self):
170        "Returns WKT representing a Polygon for this envelope."
171        # TODO: Fix significant figures.
172        return 'POLYGON((%s %s,%s %s,%s %s,%s %s,%s %s))' % \
173               (self.min_x, self.min_y, self.min_x, self.max_y,
174                self.max_x, self.max_y, self.max_x, self.min_y,
175                self.min_x, self.min_y)