Django

Code

Changeset 6865

Show
Ignore:
Timestamp:
12/03/07 12:15:57 (7 months ago)
Author:
jbronn
Message:

gis: added additional units (including WKT aliases) and the unit_attname class method to Distance.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis/django/contrib/gis/measure.py

    r5772 r6865  
    4040class Distance(object): 
    4141    UNITS = { 
     42        'chain' : 20.1168, 
     43        'chain_benoit' : 20.116782, 
     44        'chain_sears' : 20.1167645, 
     45        'british_chain_benoit' : 20.1167824944, 
     46        'british_chain_sears' : 20.1167651216, 
     47        'british_chain_sears_truncated' : 20.116756, 
     48        'cm' : 0.01, 
     49        'british_ft' : 0.304799471539, 
     50        'british_yd' : 0.914398414616, 
     51        'degree' : 0.0174532925199, 
     52        'clarke_ft' : 0.3047972654, 
     53        'clarke_link' : 0.201166195164, 
     54        'fathom' :  1.8288, 
     55        'ft': 0.3048, 
     56        'german_m' : 1.0000135965, 
     57        'grad' : 0.0157079632679, 
     58        'gold_coast_ft' : 0.304799710181508, 
     59        'indian_yd' : 0.914398530744, 
     60        'in' : 0.0254, 
     61        'km': 1000.0, 
     62        'link' : 0.201168, 
     63        'link_benoit' : 0.20116782, 
     64        'link_sears' : 0.20116765, 
    4265        'm': 1.0, 
    43         'km': 1000.0, 
    4466        'mi': 1609.344, 
    45         'ft': 0.3048, 
     67        'mm' : 0.001, 
     68        'nm': 1852.0, 
     69        'nm_uk' : 1853.184, 
     70        'rod' : 5.0292, 
     71        'sears_yd' : 0.91439841, 
     72        'survey_ft' : 0.304800609601, 
     73        'um' : 0.000001, 
    4674        'yd': 0.9144, 
    47         'nm': 1852.0, 
    48     } 
     75        } 
     76 
     77    # Unit aliases for `UNIT` terms encountered in Spatial Reference WKT. 
     78    ALIAS = { 
     79        'centimeter' : 'cm', 
     80        'foot' : 'ft', 
     81        'inches' : 'in', 
     82        'kilometer' : 'km', 
     83        'kilometre' : 'km', 
     84        'meter' : 'm', 
     85        'metre' : 'm', 
     86        'micrometer' : 'um', 
     87        'micrometre' : 'um', 
     88        'millimeter' : 'mm', 
     89        'millimetre' : 'mm', 
     90        'mile' : 'mi', 
     91        'yard' : 'yd', 
     92        'British chain (Benoit 1895 B)' : 'british_chain_benoit', 
     93        'British chain (Sears 1922)' : 'british_chain_sears', 
     94        'British chain (Sears 1922 truncated)' : 'british_chain_sears_truncated', 
     95        'British foot (Sears 1922)' : 'british_ft', 
     96        'British yard (Sears 1922)' : 'british_yd', 
     97        "Clarke's Foot" : 'clarke_ft', 
     98        "Clarke's foot" : 'clarke_ft', 
     99        "Clarke's link" : 'clarke_link', 
     100        'Chain (Benoit)' : 'chain_benoit', 
     101        'Chain (Sears)' : 'chain_sears', 
     102        'Decimal Degree' : 'degree', 
     103        'Foot (International)' : 'ft', 
     104        'German legal metre' : 'german_m', 
     105        'Gold Coast foot' : 'gold_coast_ft', 
     106        'Indian yard' : 'indian_yd', 
     107        'Link (Benoit)': 'link_benoit', 
     108        'Link (Sears)': 'link_sears', 
     109        'Nautical Mile' : 'nm', 
     110        'Nautical Mile (UK)' : 'nm_uk', 
     111        'US survey foot' : 'survey_ft', 
     112        'U.S. Foot' : 'survey_ft', 
     113        'Yard (Indian)' : 'indian_yd', 
     114        'Yard (Sears)' : 'sears_yd' 
     115        } 
     116    REV_ALIAS = dict((value, key) for key, value in ALIAS.items()) 
    49117 
    50118    def __init__(self, default_unit=None, **kwargs): 
     119        # The base unit is in meters. 
    51120        self.m = 0.0 
    52121        self._default_unit = 'm' 
     
    56125                self.m += self.UNITS[unit] * value 
    57126                self._default_unit = unit 
     127            elif unit in self.ALIAS: 
     128                u = self.ALIAS[unit] 
     129                self.m += self.UNITS[u] * value 
     130                self._default_unit = u 
    58131            else: 
    59                 raise AttributeError("Unknown unit type: " + unit) 
     132                lower = unit.lower() 
     133                if lower in self.UNITS: 
     134                    self.m += self.UNITS[lower] * value 
     135                    self._default_unit = lower 
     136                elif lower in self.ALIAS: 
     137                    u = self.ALIAS[lower] 
     138                    self.m += self.UNITS[u] * value 
     139                    self._default_unit = u 
     140                else: 
     141                    raise AttributeError('Unknown unit type: %s' % unit) 
    60142 
    61143        if default_unit and isinstance(default_unit, str): 
     
    66148            return self.m / self.UNITS[name] 
    67149        else: 
    68             raise AttributeError("Unknown unit type: " + name) 
     150            raise AttributeError('Unknown unit type: %s' % name) 
    69151     
    70152    def __repr__(self): 
    71         return "Distance(%s=%s)" % (self._default_unit, getattr(self, self._default_unit)) 
     153        return 'Distance(%s=%s)' % (self._default_unit, getattr(self, self._default_unit)) 
    72154 
    73155    def __str__(self): 
    74         return "%s %s" % (getattr(self, self._default_unit), self._default_unit) 
     156        return '%s %s' % (getattr(self, self._default_unit), self._default_unit) 
    75157         
    76158    def __cmp__(self, other): 
     
    84166            return Distance(default_unit=self._default_unit, m=(self.m + other.m)) 
    85167        else: 
    86             raise TypeError("Distance must be added with Distance"
     168            raise TypeError('Distance must be added with Distance'
    87169     
    88170    def __iadd__(self, other): 
     
    91173            return self 
    92174        else: 
    93             raise TypeError("Distance must be added with Distance"
     175            raise TypeError('Distance must be added with Distance'
    94176     
    95177    def __sub__(self, other): 
     
    97179            return Distance(default_unit=self._default_unit, m=(self.m - other.m)) 
    98180        else: 
    99             raise TypeError("Distance must be subtracted from Distance"
     181            raise TypeError('Distance must be subtracted from Distance'
    100182     
    101183    def __isub__(self, other): 
     
    104186            return self 
    105187        else: 
    106             raise TypeError("Distance must be subtracted from Distance"
     188            raise TypeError('Distance must be subtracted from Distance'
    107189     
    108190    def __mul__(self, other): 
     
    112194            return Area(default_unit='sq_' + self._default_unit, sq_m=(self.m * other.m)) 
    113195        else: 
    114             raise TypeError("Distance must be multiplied with number or Distance"
     196            raise TypeError('Distance must be multiplied with number or Distance'
    115197     
    116198    def __imul__(self, other): 
     
    119201            return self 
    120202        else: 
    121             raise TypeError("Distance must be multiplied with number"
     203            raise TypeError('Distance must be multiplied with number'
    122204     
    123205    def __div__(self, other): 
     
    125207            return Distance(default_unit=self._default_unit, m=(self.m / float(other))) 
    126208        else: 
    127             raise TypeError("Distance must be divided with number"
     209            raise TypeError('Distance must be divided with number'
    128210 
    129211    def __idiv__(self, other): 
     
    132214            return self 
    133215        else: 
    134             raise TypeError("Distance must be divided with number"
     216            raise TypeError('Distance must be divided with number'
    135217 
    136218    def __nonzero__(self): 
    137219        return bool(self.m) 
    138220 
     221    @classmethod 
     222    def unit_attname(cls, unit_str): 
     223        """ 
     224        Retrieves the unit attribute name for the given unit string.   
     225        For example, if the given unit string is 'metre', 'm' would be returned.   
     226        An exception is raised if an attribute cannot be found. 
     227        """ 
     228        lower = unit_str.lower() 
     229 
     230        if unit_str in cls.UNITS: 
     231            return unit_str 
     232        elif lower in cls.UNITS: 
     233            return lower 
     234        elif unit_str in cls.ALIAS: 
     235            return cls.ALIAS[unit_str] 
     236        elif lower in cls.ALIAS: 
     237            return cls.ALIAS[lower] 
     238        else: 
     239            raise Exception('Could not find a unit keyword associated with "%s"' % unit_str) 
     240 
    139241class Area(object): 
     242    # TODO: Add units from above. 
    140243    UNITS = { 
    141244        'sq_m': 1.0, 
     
    156259                self._default_unit = unit 
    157260            else: 
    158                 raise AttributeError("Unknown unit type: " + unit) 
     261                raise AttributeError('Unknown unit type: ' + unit) 
    159262 
    160263        if default_unit: 
     
    165268            return self.sq_m / self.UNITS[name] 
    166269        else: 
    167             raise AttributeError("Unknown unit type: " + name) 
     270            raise AttributeError('Unknown unit type: ' + name) 
    168271     
    169272    def __repr__(self): 
    170         return "Area(%s=%s)" % (self._default_unit, getattr(self, self._default_unit)) 
     273        return 'Area(%s=%s)' % (self._default_unit, getattr(self, self._default_unit)) 
    171274 
    172275    def __str__(self): 
    173         return "%s %s" % (getattr(self, self._default_unit), self._default_unit) 
     276        return '%s %s' % (getattr(self, self._default_unit), self._default_unit) 
    174277 
    175278    def __cmp__(self, other): 
     
    183286            return Area(default_unit=self._default_unit, sq_m=(self.sq_m + other.sq_m)) 
    184287        else: 
    185             raise TypeError("Area must be added with Area"
     288            raise TypeError('Area must be added with Area'
    186289     
    187290    def __iadd__(self, other): 
     
    190293            return self 
    191294        else: 
    192             raise TypeError("Area must be added with Area"
     295            raise TypeError('Area must be added with Area'
    193296     
    194297    def __sub__(self, other): 
     
    196299            return Area(default_unit=self._default_unit, sq_m=(self.sq_m - other.sq_m)) 
    197300        else: 
    198             raise TypeError("Area must be subtracted from Area"
     301            raise TypeError('Area must be subtracted from Area'
    199302     
    200303    def __isub__(self, other): 
     
    203306            return self 
    204307        else: 
    205             raise TypeError("Area must be subtracted from Area"
     308            raise TypeError('Area must be subtracted from Area'
    206309     
    207310    def __mul__(self, other): 
     
    209312            return Area(default_unit=self._default_unit, sq_m=(self.sq_m * float(other))) 
    210313        else: 
    211             raise TypeError("Area must be multiplied with number"
     314            raise TypeError('Area must be multiplied with number'
    212315     
    213316    def __imul__(self, other): 
     
    216319            return self 
    217320        else: 
    218             raise TypeError("Area must be multiplied with number"
     321            raise TypeError('Area must be multiplied with number'
    219322     
    220323    def __div__(self, other): 
     
    222325            return Area(default_unit=self._default_unit, sq_m=(self.sq_m / float(other))) 
    223326        else: 
    224             raise TypeError("Area must be divided with number"
     327            raise TypeError('Area must be divided with number'
    225328 
    226329    def __idiv__(self, other): 
     
    229332            return self 
    230333        else: 
    231             raise TypeError("Area must be divided with number"
     334            raise TypeError('Area must be divided with number'
    232335 
    233336    def __nonzero__(self): 
  • django/branches/gis/django/contrib/gis/tests/test_measure.py

    r5635 r6865  
    1515        self.assertEqual(d.m, 100) 
    1616 
    17         d = D(m=100) 
    18         self.assertEqual(d.m, 100) 
    19          
     17        d1, d2, d3 = D(m=100), D(meter=100), D(metre=100) 
     18        for d in (d1, d2, d3): 
     19            self.assertEqual(d.m, 100) 
     20 
    2021        d = D(nm=100) 
    2122        self.assertEqual(d.m, 185200) 
     23 
     24        y1, y2, y3 = D(yd=100), D(yard=100), D(Yard=100) 
     25        for d in (y1, y2, y3): 
     26            self.assertEqual(d.yd, 100) 
     27 
     28        mm1, mm2 = D(millimeter=1000), D(MiLLiMeTeR=1000) 
     29        for d in (mm1, mm2): 
     30            self.assertEqual(d.m, 1.0) 
     31            self.assertEqual(d.mm, 1000.0) 
     32 
    2233     
    2334    def testInitInvalid(self): 
     
    153164        self.assertEqual(repr(d2), 'Distance(km=3.5)') 
    154165 
     166    def testUnitAttName(self): 
     167        "Testing the `unit_attname` class method" 
     168        unit_tuple = [('Yard', 'yd'), ('Nautical Mile', 'nm'), ('German legal metre', 'german_m'), 
     169                      ('Indian yard', 'indian_yd'), ('Chain (Sears)', 'chain_sears'), ('Chain', 'chain')] 
     170        for nm, att in unit_tuple: 
     171            self.assertEqual(att, D.unit_attname(nm)) 
     172 
    155173class AreaTest(unittest.TestCase): 
    156174    "Testing the Area object"