web/lib/django/contrib/gis/gdal/envelope.py
changeset 0 0d40e90630ef
equal deleted inserted replaced
-1:000000000000 0:0d40e90630ef
       
     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 """
       
    13 from ctypes import Structure, c_double
       
    14 from 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
       
    19 class 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 
       
    27 class 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)