Package madrona :: Package unit_converter :: Module models
[hide private]

Source Code for Module madrona.unit_converter.models

  1  from django.db import models, connection 
  2  from django.conf import settings 
  3  from osgeo import osr 
  4  from django.contrib.gis.measure import * 
  5  from django.contrib.gis.geos.polygon import Polygon 
6 7 -def srid_list():
8 """Return a list of numberic srids by looking in the spatial_ref_sys table of the db.""" 9 cursor = connection.cursor() 10 query = "select auth_srid from spatial_ref_sys" 11 cursor.execute(query) 12 results = cursor.fetchall() 13 return [a[0] for a in results]
14
15 -def units_from_srid(srid):
16 """Get the linear units name from the srid definition.""" 17 srs = osr.SpatialReference() 18 srs.ImportFromEPSG(srid) 19 units = srs.GetLinearUnitsName() 20 if units.lower() == 'meter' or units.lower() == 'metre': 21 units = 'meter' 22 return units
23
24 -def area_unit_code_from_srid_unit(srid_unit):
25 """Look at Area.LALIAS (a dictionary of lower case aliases found in srid definitions for units) and return the proper unit 26 abbreviation used in the django.contrib.gis.measure.Area class.""" 27 return Area.LALIAS[srid_unit.lower()]
28
29 -def distance_unit_code_from_srid_unit(srid_unit):
30 """Look at Distance.LALIAS (a dictionary of lower case aliases found in srid definitions for units) and return the proper unit 31 abbreviation used in the django.contrib.gis.measure.Distance class.""" 32 return Distance.LALIAS[srid_unit.lower()]
33
34 -def area_unit_code_from_srid(srid):
35 """Return the unit code used in django.contrib.gis.measure.Area to represent the units of the given srid. For example srid 36 3310 (California Albers) has a linear unit value of 'metre'. django.contrib.gis.measure.Area uses 'sq_m' to represent square 37 meters so that's what this method will return for srid 3310.""" 38 return area_unit_code_from_srid_unit(units_from_srid(srid))
39
40 -def distance_unit_code_from_srid(srid):
41 """Return the unit code used in django.contrib.gis.measure.Distance to represent the units of the given srid. For example srid 42 3310 (California Albers) has a linear unit value of 'metre'. django.contrib.gis.measure.Distance uses 'm' to represent 43 meters so that's what this method will return for srid 3310.""" 44 return distance_unit_code_from_srid_unit(units_from_srid(srid))
45
46 -def units_list():
47 """Return a non repeating list of all the linear units from the spatial_ref_sys table.""" 48 units = [] 49 for srid in srid_list(): 50 unit = units_from_srid(srid) 51 if not unit in units: 52 units.append(unit) 53 return units
54
55 -def units_count_dict():
56 """Return a dictionary with linear units as keys and a count of how many projections in the spatial_ref_sys table use 57 those units as values.""" 58 units = {} 59 for srid in srid_list(): 60 unit = units_from_srid(srid) 61 if not unit in units.keys(): 62 units.update({unit: 1}) 63 else: 64 cnt = units[unit] + 1 65 units.update({unit: cnt}) 66 return units
67
68 @property 69 -def units(self):
70 """Returns the name of the units, derived from the projection, for a given geometry.""" 71 if self.srid: 72 return units_from_srid(self.srid) 73 else: 74 raise Exception("This geometry must have an srid if you want to know the units.")
75
76 @property 77 -def distance_object(self):
78 """Return the django.contrib.gis.measure.Distance object for a given geometry with origin units determined by 79 the geometry's srid. This object can be evaluated by looking at the attribute named after the proper units. 80 For instance if you want to see the distance in miles, call distance_object.mi""" 81 eval_str = "Distance(%s=%f)" % (distance_unit_code_from_srid(self.srid),self.length) 82 return eval(eval_str)
83
84 @property 85 -def area_object(self):
86 """Return the django.contrib.gis.measure.Area object for a given geometry with origin units determined by 87 the geometry's srid. This object can be evaluated by looking at the attribute named after the proper units. 88 For instance if you want to see the area in square miles, call distance_object.sq_mi""" 89 eval_str = "Area(%s=%f)" % (area_unit_code_from_srid(self.srid),self.area) 90 return eval(eval_str)
91
92 -def add_dist_meth(cls,unit):
93 """Add a method to cls called length_UNIT (where UNIT is the value of unit) that will return the length in 94 those units. unit must be one of the values found in django.contrib.gis.measure.Distance.UNITS Most 95 common will be mi, m, km, nm, ft""" 96 @property 97 def new_dist_meth(self): 98 return self.distance_object.__getattr__(unit)
99 name = "length_%s" % unit 100 setattr(cls,name,new_dist_meth) 101
102 -def add_area_meth(cls,unit):
103 """Add a method to cls called area_UNIT (where UNIT is the value of unit) that will return the length in 104 those units. unit must be one of the values found in django.contrib.gis.measure.Area.UNITS Most 105 common will be sq_mi, sq_m, sq_km, sq_nm, sq_ft""" 106 @property 107 def new_area_meth(self): 108 return self.area_object.__getattr__(unit)
109 name = "area_%s" % unit 110 setattr(cls,name,new_area_meth) 111
112 -def add_conversion_methods_to_GEOSGeometry():
113 """Add a bunch of methods to the GEOSGeometry object. After running this method once, all subsequent geos 114 geometries will have methods to report out their length and area in any of the units listed in Area.UNITS or 115 Distance.UNITS. If you have a polygon called poly and want its length in mi, you can just call poly.length_mi. 116 If you want the area in square centimeters, call poly.area_sq_cm. Additionally, you can call poly.area_in_display_units 117 or poly.length_in_display_units and get the measurments in the units specified in settings.""" 118 from django.contrib.gis.geos import GEOSGeometry as GG 119 GG.units = units 120 GG.distance_object = distance_object 121 GG.area_object = area_object 122 for unit in Distance.UNITS.keys(): 123 add_dist_meth(GG,unit) 124 for unit in Area.UNITS.keys(): 125 add_area_meth(GG,unit) 126 if settings.DISPLAY_LENGTH_UNITS: 127 GG.length_units = settings.DISPLAY_LENGTH_UNITS 128 l_meth_name = 'length_' + settings.DISPLAY_LENGTH_UNITS 129 GG.length_in_display_units = getattr(GG,l_meth_name) 130 if settings.DISPLAY_AREA_UNITS: 131 GG.area_units = settings.DISPLAY_AREA_UNITS 132 a_meth_name = 'area_' + settings.DISPLAY_AREA_UNITS 133 GG.area_in_display_units = getattr(GG,a_meth_name)
134
135 136 ################################################## 137 # The following methods do not depend on the ones above. 138 # They're generally much simpler and easier to use but 139 # they're not as cool (and by cool I mean dorky). 140 ################################################## 141 142 -def convert_float_to_length_display_units(float_value):
143 """Given a float value, this method will convert from the units found in settings.GEOMETRY_DB_SRID 144 to the units defined in settings.DISPLAY_LENGTH_UNITS.""" 145 eval_str = "Distance(%s=%f).%s" % (distance_unit_code_from_srid(settings.GEOMETRY_DB_SRID), float_value, settings.DISPLAY_LENGTH_UNITS) 146 return eval(eval_str)
147
148 -def convert_float_to_area_display_units(float_value):
149 """Given a float value, this method will convert from the units found in settings.GEOMETRY_DB_SRID 150 to the units defined in settings.DISPLAY_AREA_UNITS.""" 151 eval_str = "Area(%s=%f).%s" % (area_unit_code_from_srid(settings.GEOMETRY_DB_SRID), float_value, settings.DISPLAY_AREA_UNITS) 152 return eval(eval_str)
153
154 -def geometry_length_in_display_units(geom):
155 """For a given geometry, return the geometry length in the units specified as settings.DISPLAY_LENGTH_UNITS. If the geometry has 156 an srid, assume the origin units are the ones appropriate to that srid. If there is no assigned srid, assume the srid is the one 157 in settings.GEOMETRY_DB_SRID.""" 158 if geom.srid: 159 srid = geom.srid 160 else: 161 srid = settings.GEOMETRY_DB_SRID 162 eval_str = "Distance(%s=%f).%s" % (distance_unit_code_from_srid(srid),geom.length,settings.DISPLAY_LENGTH_UNITS) 163 return eval(eval_str)
164
165 -def geometry_area_in_display_units(geom):
166 """For a given geometry, return the geometry area in the units specified as settings.DISPLAY_AREA_UNITS. If the geometry has 167 an srid, assume the origin units are the ones appropriate to that srid. If there is no assigned srid, assume the srid is the one 168 in settings.GEOMETRY_DB_SRID.""" 169 if geom.srid: 170 srid = geom.srid 171 else: 172 srid = settings.GEOMETRY_DB_SRID 173 eval_str = "Area(%s=%f).%s" % (area_unit_code_from_srid(srid),geom.area,settings.DISPLAY_AREA_UNITS) 174 return eval(eval_str)
175
176 -def length_in_display_units(geom_or_num):
177 """Take either a geometry or a numeric length value and convert to display units.""" 178 from django.contrib.gis.geos import GEOSGeometry as GG 179 if issubclass(geom_or_num.__class__,GG): # This means it is a geometry 180 return geometry_length_in_display_units(geom_or_num) 181 else: 182 return convert_float_to_length_display_units(geom_or_num)
183
184 -def area_in_display_units(geom_or_num):
185 """Take either a geometry or a numeric area value and convert to display units.""" 186 from django.contrib.gis.geos import GEOSGeometry as GG 187 if issubclass(geom_or_num.__class__,GG): # This means it is a geometry 188 return geometry_area_in_display_units(geom_or_num) 189 else: 190 return convert_float_to_area_display_units(geom_or_num)
191