web/lib/django/contrib/gis/measure.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
    25 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    25 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    27 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    27 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    28 #
    28 #
    29 """
    29 """
    30 Distance and Area objects to allow for sensible and convienient calculation 
    30 Distance and Area objects to allow for sensible and convienient calculation
    31 and conversions.
    31 and conversions.
    32 
    32 
    33 Authors: Robert Coup, Justin Bronn
    33 Authors: Robert Coup, Justin Bronn
    34 
    34 
    35 Inspired by GeoPy (http://exogen.case.edu/projects/geopy/)
    35 Inspired by GeoPy (http://exogen.case.edu/projects/geopy/)
    68         return val, default_unit
    68         return val, default_unit
    69 
    69 
    70     @classmethod
    70     @classmethod
    71     def unit_attname(cls, unit_str):
    71     def unit_attname(cls, unit_str):
    72         """
    72         """
    73         Retrieves the unit attribute name for the given unit string.  
    73         Retrieves the unit attribute name for the given unit string.
    74         For example, if the given unit string is 'metre', 'm' would be returned.
    74         For example, if the given unit string is 'metre', 'm' would be returned.
    75         An exception is raised if an attribute cannot be found.
    75         An exception is raised if an attribute cannot be found.
    76         """
    76         """
    77         lower = unit_str.lower()
    77         lower = unit_str.lower()
    78         if unit_str in cls.UNITS:
    78         if unit_str in cls.UNITS:
   163     def __init__(self, default_unit=None, **kwargs):
   163     def __init__(self, default_unit=None, **kwargs):
   164         # The base unit is in meters.
   164         # The base unit is in meters.
   165         self.m, self._default_unit = self.default_units(kwargs)
   165         self.m, self._default_unit = self.default_units(kwargs)
   166         if default_unit and isinstance(default_unit, str):
   166         if default_unit and isinstance(default_unit, str):
   167             self._default_unit = default_unit
   167             self._default_unit = default_unit
   168     
   168 
   169     def __getattr__(self, name):
   169     def __getattr__(self, name):
   170         if name in self.UNITS:
   170         if name in self.UNITS:
   171             return self.m / self.UNITS[name]
   171             return self.m / self.UNITS[name]
   172         else:
   172         else:
   173             raise AttributeError('Unknown unit type: %s' % name)
   173             raise AttributeError('Unknown unit type: %s' % name)
   174     
   174 
   175     def __repr__(self):
   175     def __repr__(self):
   176         return 'Distance(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
   176         return 'Distance(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
   177 
   177 
   178     def __str__(self):
   178     def __str__(self):
   179         return '%s %s' % (getattr(self, self._default_unit), self._default_unit)
   179         return '%s %s' % (getattr(self, self._default_unit), self._default_unit)
   180         
   180 
   181     def __cmp__(self, other):
   181     def __cmp__(self, other):
   182         if isinstance(other, Distance):
   182         if isinstance(other, Distance):
   183             return cmp(self.m, other.m)
   183             return cmp(self.m, other.m)
   184         else:
   184         else:
   185             return NotImplemented
   185             return NotImplemented
   186         
   186 
   187     def __add__(self, other):
   187     def __add__(self, other):
   188         if isinstance(other, Distance):
   188         if isinstance(other, Distance):
   189             return Distance(default_unit=self._default_unit, m=(self.m + other.m))
   189             return Distance(default_unit=self._default_unit, m=(self.m + other.m))
   190         else:
   190         else:
   191             raise TypeError('Distance must be added with Distance')
   191             raise TypeError('Distance must be added with Distance')
   192     
   192 
   193     def __iadd__(self, other):
   193     def __iadd__(self, other):
   194         if isinstance(other, Distance):
   194         if isinstance(other, Distance):
   195             self.m += other.m
   195             self.m += other.m
   196             return self
   196             return self
   197         else:
   197         else:
   198             raise TypeError('Distance must be added with Distance')
   198             raise TypeError('Distance must be added with Distance')
   199     
   199 
   200     def __sub__(self, other):
   200     def __sub__(self, other):
   201         if isinstance(other, Distance):
   201         if isinstance(other, Distance):
   202             return Distance(default_unit=self._default_unit, m=(self.m - other.m))
   202             return Distance(default_unit=self._default_unit, m=(self.m - other.m))
   203         else:
   203         else:
   204             raise TypeError('Distance must be subtracted from Distance')
   204             raise TypeError('Distance must be subtracted from Distance')
   205     
   205 
   206     def __isub__(self, other):
   206     def __isub__(self, other):
   207         if isinstance(other, Distance):
   207         if isinstance(other, Distance):
   208             self.m -= other.m
   208             self.m -= other.m
   209             return self
   209             return self
   210         else:
   210         else:
   211             raise TypeError('Distance must be subtracted from Distance')
   211             raise TypeError('Distance must be subtracted from Distance')
   212     
   212 
   213     def __mul__(self, other):
   213     def __mul__(self, other):
   214         if isinstance(other, (int, float, long, Decimal)):
   214         if isinstance(other, (int, float, long, Decimal)):
   215             return Distance(default_unit=self._default_unit, m=(self.m * float(other)))
   215             return Distance(default_unit=self._default_unit, m=(self.m * float(other)))
   216         elif isinstance(other, Distance):
   216         elif isinstance(other, Distance):
   217             return Area(default_unit='sq_' + self._default_unit, sq_m=(self.m * other.m))
   217             return Area(default_unit='sq_' + self._default_unit, sq_m=(self.m * other.m))
   218         else:
   218         else:
   219             raise TypeError('Distance must be multiplied with number or Distance')
   219             raise TypeError('Distance must be multiplied with number or Distance')
   220     
   220 
   221     def __imul__(self, other):
   221     def __imul__(self, other):
   222         if isinstance(other, (int, float, long, Decimal)):
   222         if isinstance(other, (int, float, long, Decimal)):
   223             self.m *= float(other)
   223             self.m *= float(other)
   224             return self
   224             return self
   225         else:
   225         else:
   226             raise TypeError('Distance must be multiplied with number')
   226             raise TypeError('Distance must be multiplied with number')
   227     
   227 
       
   228     def __rmul__(self, other):
       
   229         return self * other
       
   230 
   228     def __div__(self, other):
   231     def __div__(self, other):
   229         if isinstance(other, (int, float, long, Decimal)):
   232         if isinstance(other, (int, float, long, Decimal)):
   230             return Distance(default_unit=self._default_unit, m=(self.m / float(other)))
   233             return Distance(default_unit=self._default_unit, m=(self.m / float(other)))
   231         else:
   234         else:
   232             raise TypeError('Distance must be divided with number')
   235             raise TypeError('Distance must be divided with number')
   249 
   252 
   250     def __init__(self, default_unit=None, **kwargs):
   253     def __init__(self, default_unit=None, **kwargs):
   251         self.sq_m, self._default_unit = self.default_units(kwargs)
   254         self.sq_m, self._default_unit = self.default_units(kwargs)
   252         if default_unit and isinstance(default_unit, str):
   255         if default_unit and isinstance(default_unit, str):
   253             self._default_unit = default_unit
   256             self._default_unit = default_unit
   254     
   257 
   255     def __getattr__(self, name):
   258     def __getattr__(self, name):
   256         if name in self.UNITS:
   259         if name in self.UNITS:
   257             return self.sq_m / self.UNITS[name]
   260             return self.sq_m / self.UNITS[name]
   258         else:
   261         else:
   259             raise AttributeError('Unknown unit type: ' + name)
   262             raise AttributeError('Unknown unit type: ' + name)
   260     
   263 
   261     def __repr__(self):
   264     def __repr__(self):
   262         return 'Area(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
   265         return 'Area(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
   263 
   266 
   264     def __str__(self):
   267     def __str__(self):
   265         return '%s %s' % (getattr(self, self._default_unit), self._default_unit)
   268         return '%s %s' % (getattr(self, self._default_unit), self._default_unit)
   267     def __cmp__(self, other):
   270     def __cmp__(self, other):
   268         if isinstance(other, Area):
   271         if isinstance(other, Area):
   269             return cmp(self.sq_m, other.sq_m)
   272             return cmp(self.sq_m, other.sq_m)
   270         else:
   273         else:
   271             return NotImplemented
   274             return NotImplemented
   272         
   275 
   273     def __add__(self, other):
   276     def __add__(self, other):
   274         if isinstance(other, Area):
   277         if isinstance(other, Area):
   275             return Area(default_unit=self._default_unit, sq_m=(self.sq_m + other.sq_m))
   278             return Area(default_unit=self._default_unit, sq_m=(self.sq_m + other.sq_m))
   276         else:
   279         else:
   277             raise TypeError('Area must be added with Area')
   280             raise TypeError('Area must be added with Area')
   278     
   281 
   279     def __iadd__(self, other):
   282     def __iadd__(self, other):
   280         if isinstance(other, Area):
   283         if isinstance(other, Area):
   281             self.sq_m += other.sq_m
   284             self.sq_m += other.sq_m
   282             return self
   285             return self
   283         else:
   286         else:
   284             raise TypeError('Area must be added with Area')
   287             raise TypeError('Area must be added with Area')
   285     
   288 
   286     def __sub__(self, other):
   289     def __sub__(self, other):
   287         if isinstance(other, Area):
   290         if isinstance(other, Area):
   288             return Area(default_unit=self._default_unit, sq_m=(self.sq_m - other.sq_m))
   291             return Area(default_unit=self._default_unit, sq_m=(self.sq_m - other.sq_m))
   289         else:
   292         else:
   290             raise TypeError('Area must be subtracted from Area')
   293             raise TypeError('Area must be subtracted from Area')
   291     
   294 
   292     def __isub__(self, other):
   295     def __isub__(self, other):
   293         if isinstance(other, Area):
   296         if isinstance(other, Area):
   294             self.sq_m -= other.sq_m
   297             self.sq_m -= other.sq_m
   295             return self
   298             return self
   296         else:
   299         else:
   297             raise TypeError('Area must be subtracted from Area')
   300             raise TypeError('Area must be subtracted from Area')
   298     
   301 
   299     def __mul__(self, other):
   302     def __mul__(self, other):
   300         if isinstance(other, (int, float, long, Decimal)):
   303         if isinstance(other, (int, float, long, Decimal)):
   301             return Area(default_unit=self._default_unit, sq_m=(self.sq_m * float(other)))
   304             return Area(default_unit=self._default_unit, sq_m=(self.sq_m * float(other)))
   302         else:
   305         else:
   303             raise TypeError('Area must be multiplied with number')
   306             raise TypeError('Area must be multiplied with number')
   304     
   307 
   305     def __imul__(self, other):
   308     def __imul__(self, other):
   306         if isinstance(other, (int, float, long, Decimal)):
   309         if isinstance(other, (int, float, long, Decimal)):
   307             self.sq_m *= float(other)
   310             self.sq_m *= float(other)
   308             return self
   311             return self
   309         else:
   312         else:
   310             raise TypeError('Area must be multiplied with number')
   313             raise TypeError('Area must be multiplied with number')
   311     
   314 
       
   315     def __rmul__(self, other):
       
   316         return self * other
       
   317 
   312     def __div__(self, other):
   318     def __div__(self, other):
   313         if isinstance(other, (int, float, long, Decimal)):
   319         if isinstance(other, (int, float, long, Decimal)):
   314             return Area(default_unit=self._default_unit, sq_m=(self.sq_m / float(other)))
   320             return Area(default_unit=self._default_unit, sq_m=(self.sq_m / float(other)))
   315         else:
   321         else:
   316             raise TypeError('Area must be divided with number')
   322             raise TypeError('Area must be divided with number')
   322         else:
   328         else:
   323             raise TypeError('Area must be divided with number')
   329             raise TypeError('Area must be divided with number')
   324 
   330 
   325     def __nonzero__(self):
   331     def __nonzero__(self):
   326         return bool(self.sq_m)
   332         return bool(self.sq_m)
   327         
   333 
   328 # Shortcuts
   334 # Shortcuts
   329 D = Distance
   335 D = Distance
   330 A = Area
   336 A = Area