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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
183
191