the gdalogr library uses an envelope structure to hold the bounding box information for a geometry the envelope bounding box contains two pairs of coordinates one for the lower left coordinate and one for the upper right coordinate o upper right maxx maxy lower left minx miny o the ogr definition of an envelope is a c structure containing four doubles see the ogrcore h source file for more information https gdal orgdoxygenogrcore8hsource html the envelope object is a c structure that contains the minimum and maximum x y coordinates for a rectangle bounding box the naming of the variables is compatible with the ogr envelope structure the initialization function may take an ogrenvelope structure 4element tuple or list or 4 individual arguments ogrenvelope a ctypes structure was passed in a tuple was passed in individual parameters passed in thanks to ww for the help checking the x y coordinates return true if the envelopes are equivalent can compare against other envelopes and 4tuples modify the envelope to expand to include the boundaries of the passedin 2tuple a point 4tuple an extent or envelope we provide a number of different signatures for this method and the logic here is all about converting them into a 4tuple single parameter which does the actual work of expanding the envelope a tuple was passed in an x and an y parameter were passed in individual parameters passed in todo fix significant figures the ogr definition of an envelope is a c structure containing four doubles see the ogr_core h source file for more information https gdal org doxygen ogr__core_8h_source html the envelope object is a c structure that contains the minimum and maximum x y coordinates for a rectangle bounding box the naming of the variables is compatible with the ogr envelope structure the initialization function may take an ogrenvelope structure 4 element tuple or list or 4 individual arguments ogrenvelope a ctypes structure was passed in a tuple was passed in individual parameters passed in thanks to ww for the help checking the x y coordinates return true if the envelopes are equivalent can compare against other envelopes and 4 tuples modify the envelope to expand to include the boundaries of the passed in 2 tuple a point 4 tuple an extent or envelope we provide a number of different signatures for this method and the logic here is all about converting them into a 4 tuple single parameter which does the actual work of expanding the envelope a tuple was passed in an x and an y parameter were passed in individual parameters passed in todo fix significant figures
from ctypes import Structure, c_double

from django.contrib.gis.gdal.error import GDALException





class OGREnvelope(Structure):
    "Represent the OGREnvelope C Structure."
    _fields_ = [
        ("MinX", c_double),
        ("MaxX", c_double),
        ("MinY", c_double),
        ("MaxY", c_double),
    ]


class Envelope:
    

    def __init__(self, *args):
        

        if len(args) == 1:
            if isinstance(args[0], OGREnvelope):
                
                self._envelope = args[0]
            elif isinstance(args[0], (tuple, list)):
                
                if len(args[0]) != 4:
                    raise GDALException(
                        "Incorrect number of tuple elements (%d)." % len(args[0])
                    )
                else:
                    self._from_sequence(args[0])
            else:
                raise TypeError("Incorrect type of argument: %s" % type(args[0]))
        elif len(args) == 4:
            
            
            self._from_sequence([float(a) for a in args])
        else:
            raise GDALException("Incorrect number (%d) of arguments." % len(args))

        
        if self.min_x > self.max_x:
            raise GDALException("Envelope minimum X > maximum X.")
        if self.min_y > self.max_y:
            raise GDALException("Envelope minimum Y > maximum Y.")

    def __eq__(self, other):
        
        if isinstance(other, Envelope):
            return (
                (self.min_x == other.min_x)
                and (self.min_y == other.min_y)
                and (self.max_x == other.max_x)
                and (self.max_y == other.max_y)
            )
        elif isinstance(other, tuple) and len(other) == 4:
            return (
                (self.min_x == other[0])
                and (self.min_y == other[1])
                and (self.max_x == other[2])
                and (self.max_y == other[3])
            )
        else:
            raise GDALException("Equivalence testing only works with other Envelopes.")

    def __str__(self):
        "Return a string representation of the tuple."
        return str(self.tuple)

    def _from_sequence(self, seq):
        "Initialize the C OGR Envelope structure from the given sequence."
        self._envelope = OGREnvelope()
        self._envelope.MinX = seq[0]
        self._envelope.MinY = seq[1]
        self._envelope.MaxX = seq[2]
        self._envelope.MaxY = seq[3]

    def expand_to_include(self, *args):
        
        
        
        
        
        if len(args) == 1:
            if isinstance(args[0], Envelope):
                return self.expand_to_include(args[0].tuple)
            elif hasattr(args[0], "x") and hasattr(args[0], "y"):
                return self.expand_to_include(
                    args[0].x, args[0].y, args[0].x, args[0].y
                )
            elif isinstance(args[0], (tuple, list)):
                
                if len(args[0]) == 2:
                    return self.expand_to_include(
                        (args[0][0], args[0][1], args[0][0], args[0][1])
                    )
                elif len(args[0]) == 4:
                    (minx, miny, maxx, maxy) = args[0]
                    if minx < self._envelope.MinX:
                        self._envelope.MinX = minx
                    if miny < self._envelope.MinY:
                        self._envelope.MinY = miny
                    if maxx > self._envelope.MaxX:
                        self._envelope.MaxX = maxx
                    if maxy > self._envelope.MaxY:
                        self._envelope.MaxY = maxy
                else:
                    raise GDALException(
                        "Incorrect number of tuple elements (%d)." % len(args[0])
                    )
            else:
                raise TypeError("Incorrect type of argument: %s" % type(args[0]))
        elif len(args) == 2:
            
            return self.expand_to_include((args[0], args[1], args[0], args[1]))
        elif len(args) == 4:
            
            return self.expand_to_include(args)
        else:
            raise GDALException("Incorrect number (%d) of arguments." % len(args[0]))

    @property
    def min_x(self):
        "Return the value of the minimum X coordinate."
        return self._envelope.MinX

    @property
    def min_y(self):
        "Return the value of the minimum Y coordinate."
        return self._envelope.MinY

    @property
    def max_x(self):
        "Return the value of the maximum X coordinate."
        return self._envelope.MaxX

    @property
    def max_y(self):
        "Return the value of the maximum Y coordinate."
        return self._envelope.MaxY

    @property
    def ur(self):
        "Return the upper-right coordinate."
        return (self.max_x, self.max_y)

    @property
    def ll(self):
        "Return the lower-left coordinate."
        return (self.min_x, self.min_y)

    @property
    def tuple(self):
        "Return a tuple representing the envelope."
        return (self.min_x, self.min_y, self.max_x, self.max_y)

    @property
    def wkt(self):
        "Return WKT representing a Polygon for this envelope."
        
        return "POLYGON((%s %s,%s %s,%s %s,%s %s,%s %s))" % (
            self.min_x,
            self.min_y,
            self.min_x,
            self.max_y,
            self.max_x,
            self.max_y,
            self.max_x,
            self.min_y,
            self.min_x,
            self.min_y,
        )