/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/proj.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/proj.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 708 by jonathan, Wed Apr 23 08:44:52 2003 UTC revision 2699 by bernhard, Mon Sep 18 13:59:40 2006 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001 by Intevation GmbH  # Copyright (c) 2001, 2003, 2006 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4    # Bernhard Reiter <[email protected]>
5  #  #
6  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
7  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
   
8  __version__ = "$Revision$"  __version__ = "$Revision$"
9    
10    from types import StringTypes
11    import locale
12    
13    from Thuban import _
14    from Thuban.Lib.connector import Publisher
15    
16  import Projection  import Projection
17  BaseProjection = Projection.Projection  BaseProjection = Projection.Projection
18  del Projection  del Projection
19    
20    from messages import PROJECTION_ADDED, PROJECTION_REPLACED, PROJECTION_REMOVED
21    
22    PROJ_UNITS_METERS  = 1
23    PROJ_UNITS_DEGREES = 2
24    
25    def _do_we_have_to_work_around_broken_proj():
26        """ If we have a problematic locale, check if proj results are good. """
27        if locale.localeconv()['decimal_point'] != '.':
28            params = ["proj=latlong", "to_meter=0.01745", "ellps=clrk66"]
29            proj = BaseProjection(params)
30            result1 = proj.Forward(1,1)
31    
32            savedlocale = locale.getlocale(locale.LC_NUMERIC)
33            locale.setlocale(locale.LC_NUMERIC, "C")
34    
35            proj = BaseProjection(params)
36            result2 = proj.Forward(1,1)
37    
38            locale.setlocale(locale.LC_NUMERIC, savedlocale)
39            if result1 != result2:
40                return True
41        return False
42    
43  class Projection(BaseProjection):  class Projection(BaseProjection):
44        """A proj4 projection object that remembers the parameters.
45    
46        The proj library is not robust against decimal_point != '.' locales.
47        Since python 2.4 calls C extensions with the set locale, it can create
48        a problem.  It seems that calling
49            self.assuregoodlocale()
50            self.assureinitlocale()
51        before BaseProjection.__init__() is enough to work around this.
52    
53        We assuming that the locale stays the same after a projection
54        has been initialised
55        and thus we can return to it in self.assureinitlocale().
56        """
57    
58        def __init__(self, params, name = None, epsg = None):
59            """Initialize the Projection
60    
61            Parameters:
62    
63            params -- a list of 'parameter=value' strings
64    
65            name -- (optional) The name of the projection. If None or omitted
66                    it defaults to 'Unknown' in the local language.
67    
68      """A proj4 projection object that remembers the parameters"""          epsg -- (optional) The EPSG code as a string.
69            """
70            self.initlocale = locale.getlocale(locale.LC_NUMERIC)
71            self.work_around_broken_proj = _do_we_have_to_work_around_broken_proj()
72    
73      def __init__(self, params, name = "Unknown"):          self.assuregoodlocale()
74          BaseProjection.__init__(self, params)          BaseProjection.__init__(self, params)
75            self.assureinitlocale()
76    
77            if name is None:
78                self.name = _("Unknown")
79            elif isinstance(name, StringTypes):
80                self.name = name
81    
82            self.epsg = epsg
83          self.params = params          self.params = params
         self.name = name  
84    
85      def ForwardBBox(self, bbox):      def assuregoodlocale(self):
86          """Return the bounding box of the corners of the bounding box bbox          if self.work_around_broken_proj:
87          """              locale.setlocale(locale.LC_NUMERIC, "C")
88    
89        def assureinitlocale(self):
90            if self.work_around_broken_proj:
91                locale.setlocale(locale.LC_NUMERIC, self.initlocale)
92    
93        def _transform_bbox(self, trafo, bbox):
94          # This is not really the correct way to determine the bbox of a          # This is not really the correct way to determine the bbox of a
95          # projected shape, but for now it works well enough          # projected bbox, but for now it works well enough
96          llx, lly, urx, ury = bbox          llx, lly, urx, ury = bbox
97          xs = []; ys = []          xs = []; ys = []
98          x, y = self.Forward(llx, lly)          for x, y in ((llx, lly), (llx, ury), (urx, lly), (urx, ury)):
99          xs.append(x); ys.append(y)              x, y = trafo(x, y)
100          x, y = self.Forward(llx, ury)              xs.append(x); ys.append(y)
         xs.append(x); ys.append(y)  
         x, y = self.Forward(urx, ury)  
         xs.append(x); ys.append(y)  
         x, y = self.Forward(urx, lly)  
         xs.append(x); ys.append(y)  
101          return min(xs), min(ys), max(xs), max(ys)          return min(xs), min(ys), max(xs), max(ys)
102    
103        def ForwardBBox(self, bbox):
104            """Return the bounding box of the corners of the bounding box bbox
105            """
106            return self._transform_bbox(self.Forward, bbox)
107    
108        def InverseBBox(self, bbox):
109            return self._transform_bbox(self.Inverse, bbox)
110    
111      def GetName(self):      def GetName(self):
112            """Return the name of the projection."""
113          return self.name          return self.name
114    
115        def Label(self):
116            if self.epsg:
117                return "EPSG % 5s %s" % (self.epsg, self.name)
118            return self.name
119    
120        def EPSGCode(self):
121            """Return the EPSG code as a string or None if there is none"""
122            return self.epsg
123    
124      def GetParameter(self, param):      def GetParameter(self, param):
125            """Return the projection value for the given parameter.
126    
127            If 'param' exists as a valid parameter return the associated
128            value as a string. If the parameter does not have a value (like
129            e.g. the 'south' parameter for utm) then the value is the
130            parameter name itself.
131    
132            If the parameter doesn't exist return an empty string.
133            """
134    
135          for pair in self.params:          for pair in self.params:
136              p, v = pair.split("=")              if "=" in pair:
137                    p, v = pair.split("=")
138                else:
139                    p = v = pair
140              if p == param:              if p == param:
141                  return v                  return v
142    
143          return ""          return ""
144    
145      def GetAllParameters(self):      def GetAllParameters(self):
146            """Return list of 'parameter=value' strings"""
147          return self.params          return self.params
148    
149        def GetProjectedUnits(self):
150            if self.GetParameter("proj") in [ 'latlong', 'longlat' ]:
151                return PROJ_UNITS_DEGREES
152            else:
153                return PROJ_UNITS_METERS
154    
155      def __repr__(self):      def __repr__(self):
156          return repr(self.params)          return self.name + ": " + repr(self.params)
157    
158    
159  class ProjFile:  class ProjFile(Publisher):
160    
161      def __init__(self, filename):      def __init__(self, filename):
162          self.projs = []          """Intialize the ProjFile.
163    
164            filename -- name of the file that this ProjFile represents.
165            """
166    
167            self.__projs = []
168    
169            self.SetFilename(filename)
170    
         self.SetFileName(filename)  
       
171      def Add(self, proj):      def Add(self, proj):
172          self.projs.append(proj)          """Add the projection to the end of the file."""
173            self.__projs.append(proj)
174            self.issue(PROJECTION_ADDED, proj)
175    
176      def GetFileName(self):      def Remove(self, proj):
177          return self.filename          """Remove the object proj from the projection file.
178    
179      def SetFileName(self, filename):          Raises a ValueError is proj is not found.
180          self.filename = filename          """
181            self.__projs.remove(proj)
182            self.issue(PROJECTION_REMOVED, proj)
183    
184        def Replace(self, oldproj, newproj):
185            """Replace the object 'oldproj' with 'newproj'.
186    
187            Raises ValueError if oldproj is not in the file.
188            """
189            self.__projs[self.__projs.index(oldproj)] = newproj
190            self.issue(PROJECTION_REPLACED, oldproj, newproj)
191    
192        def GetFilename(self):
193            """Return the filename where the ProjFile was read or will be
194            written to.
195            """
196    
197            return self.__filename
198    
199        def SetFilename(self, filename):
200            """Set the filename where the ProjFile will be written to."""
201            self.__filename = filename
202    
203      def GetProjections(self):      def GetProjections(self):
204          return self.projs          """Return a list of the projections in the order they were read
205            from the file or will be written.
206    
207            This is not a deep copy list, so any modifications made to the
208            Projection objects will be written to the file.
209            """
210    
211            return self.__projs
212    

Legend:
Removed from v.708  
changed lines
  Added in v.2699

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26