/[thuban]/trunk/thuban/Thuban/Model/layer.py
ViewVC logotype

Diff of /trunk/thuban/Thuban/Model/layer.py

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

revision 492 by jonathan, Mon Mar 10 10:44:57 2003 UTC revision 791 by jan, Wed Apr 30 12:26:33 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002 by Intevation GmbH  # Copyright (c) 2001, 2002, 2003 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4  # Jonathan Coles <[email protected]>  # Jonathan Coles <[email protected]>
# Line 8  Line 8 
8    
9  __version__ = "$Revision$"  __version__ = "$Revision$"
10    
 import os  
11  from math import log, ceil  from math import log, ceil
12    
13  from Thuban import _  from Thuban import _
14    
15  import shapelib, shptree  import shapelib, shptree
16    
17  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  from messages import LAYER_PROJECTION_CHANGED, LAYER_VISIBILITY_CHANGED, \
18       LAYER_VISIBILITY_CHANGED       LAYER_CHANGED
19    
20  from color import Color  from color import Color
21    
22  import classification  import classification
23    
 from table import Table  
   
24  from base import TitledObject, Modifiable  from base import TitledObject, Modifiable
25    
26    
27  class Shape:  class Shape:
28    
29      """Represent one shape"""      """Represent one shape"""
# Line 68  class BaseLayer(TitledObject, Modifiable Line 66  class BaseLayer(TitledObject, Modifiable
66    
67      """Base class for the layers."""      """Base class for the layers."""
68    
69      def __init__(self, title, visible = 1):      def __init__(self, title, visible = True):
70          """Initialize the layer.          """Initialize the layer.
71    
72          title -- the title          title -- the title
# Line 102  class Layer(BaseLayer): Line 100  class Layer(BaseLayer):
100    
101          TITLE_CHANGED -- The title has changed.          TITLE_CHANGED -- The title has changed.
102          LAYER_PROJECTION_CHANGED -- the projection has changed.          LAYER_PROJECTION_CHANGED -- the projection has changed.
         LAYER_LEGEND_CHANGED -- the fill or stroke attributes have changed  
   
103      """      """
104    
105      def __init__(self, title, filename, projection = None,      def __init__(self, title, data, projection = None,
106                   fill = Color.None,                   fill = Color.Transparent,
107                   stroke = Color.Black,                   stroke = Color.Black,
108                   lineWidth = 1,                   lineWidth = 1,
109                   visible = 1):                   visible = True):
110          """Initialize the layer.          """Initialize the layer.
111    
112          title -- the title          title -- the title
113          filename -- the name of the shapefile          data -- datastore object for the shape data shown by the layer
114          projection -- the projection object. Its Inverse method is          projection -- the projection object. Its Inverse method is
115                 assumed to map the layer's coordinates to lat/long                 assumed to map the layer's coordinates to lat/long
116                 coordinates                 coordinates
117          fill -- the fill color or Color.None if the shapes are not filled          fill -- the fill color or Color.Transparent if the shapes are
118          stroke -- the stroke color or Color.None if the shapes are not stroked                  not filled
119            stroke -- the stroke color or Color.Transparent if the shapes
120                    are not stroked
121          visible -- boolean. If true the layer is visible.          visible -- boolean. If true the layer is visible.
122    
123          colors are expected to be instances of Color class          colors are expected to be instances of Color class
124          """          """
125          BaseLayer.__init__(self, title, visible = visible)          BaseLayer.__init__(self, title, visible = visible)
126    
         # Make the filename absolute. The filename will be  
         # interpreted relative to that anyway, but when saving a  
         # session we need to compare absolute paths and it's usually  
         # safer to always work with absolute paths.  
         self.filename = os.path.abspath(filename)  
   
127          self.projection = projection          self.projection = projection
         self.shapefile = None  
         self.shapetree = None  
         self.open_shapefile()  
         # shapetable is the table associated with the shapefile, while  
         # table is the default table used to look up attributes for  
         # display  
         self.shapetable = Table(filename)  
         self.table = self.shapetable  
128    
129          #          #
130          # this is really important so that when the classification class          # this is really important so that when the classification class
131          # tries to set its parent layer the variable will exist          # tries to set its parent layer the variable will exist
132          #          #
133          self.__classification = None          self.__classification = None
134            self.__setClassLock = False
135    
136            self.SetShapeStore(data)
137    
138          self.SetClassification(None)          self.SetClassification(None)
139    
# Line 158  class Layer(BaseLayer): Line 144  class Layer(BaseLayer):
144    
145          self.UnsetModified()          self.UnsetModified()
146    
     def open_shapefile(self):  
         if self.shapefile is None:  
             self.shapefile = shapelib.ShapeFile(self.filename)  
             numshapes, shapetype, mins, maxs = self.shapefile.info()  
             self.numshapes = numshapes  
             self.shapetype = shapelib_shapetypes[shapetype]  
   
             # if there are shapes, set the bbox accordinly. Otherwise  
             # set it to None.  
             if self.numshapes:  
                 self.bbox = mins[:2] + maxs[:2]  
             else:  
                 self.bbox = None  
   
             # estimate a good depth for the quad tree. Each depth  
             # multiplies the number of nodes by four, therefore we  
             # basically take the base 4 logarithm of the number of  
             # shapes.  
             if self.numshapes < 4:  
                 maxdepth = 1  
             else:  
                 maxdepth = int(ceil(log(self.numshapes / 4.0) / log(4)))  
147    
148              self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,      def SetShapeStore(self, store):
149                                               maxdepth)          self.store = store
150            self.shapefile = self.store.Shapefile()
151            self.shapetable = self.store.Table()
152            self.filename = self.store.filename
153            self.table = self.shapetable
154    
155            numshapes, shapetype, mins, maxs = self.shapefile.info()
156            self.numshapes = numshapes
157            self.shapetype = shapelib_shapetypes[shapetype]
158    
159            # if there are shapes, set the bbox accordingly. Otherwise
160            # set it to None.
161            if self.numshapes:
162                self.bbox = mins[:2] + maxs[:2]
163            else:
164                self.bbox = None
165    
166            # estimate a good depth for the quad tree. Each depth
167            # multiplies the number of nodes by four, therefore we
168            # basically take the base 4 logarithm of the number of
169            # shapes.
170            if self.numshapes < 4:
171                maxdepth = 1
172            else:
173                maxdepth = int(ceil(log(self.numshapes / 4.0) / log(4)))
174    
175            self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,
176                                             maxdepth)
177            if self.__classification is not None:
178                fieldname = self.__classification.GetField()
179                if fieldname is not None and \
180                   not self.store.Table().field_info_by_name(fieldname):
181                    self.SetClassification(None)
182            self.changed(LAYER_CHANGED, self)
183    
184        def ShapeStore(self):
185            return self.store
186    
187      def Destroy(self):      def Destroy(self):
188          BaseLayer.Destroy(self)          BaseLayer.Destroy(self)
189          if self.shapefile is not None:          self.SetClassification(None)
             self.shapefile.close()  
             self.shapefile = None  
             self.shapetree = None  
         self.table.Destroy()  
190    
191      def BoundingBox(self):      def BoundingBox(self):
192          """Return the layer's bounding box in the intrinsic coordinate system.          """Return the layer's bounding box in the intrinsic coordinate system.
193    
194          If the layer has no shapes, return None.          If the layer has no shapes, return None.
195          """          """
         # The bbox will be set by open_shapefile just as we need it  
         # here.  
         self.open_shapefile()  
196          return self.bbox          return self.bbox
197    
198      def LatLongBoundingBox(self):      def LatLongBoundingBox(self):
# Line 218  class Layer(BaseLayer): Line 211  class Layer(BaseLayer):
211              return None              return None
212    
213      def GetFieldType(self, fieldName):      def GetFieldType(self, fieldName):
         self.open_shapefile()  
214          info = self.table.field_info_by_name(fieldName)          info = self.table.field_info_by_name(fieldName)
215          if info is not None:          if info is not None:
216              return info[0]              return info[0]
# Line 227  class Layer(BaseLayer): Line 219  class Layer(BaseLayer):
219    
220      def NumShapes(self):      def NumShapes(self):
221          """Return the number of shapes in the layer"""          """Return the number of shapes in the layer"""
         self.open_shapefile()  
222          return self.numshapes          return self.numshapes
223    
224      def ShapeType(self):      def ShapeType(self):
225          """Return the type of the shapes in the layer.          """Return the type of the shapes in the layer.
226          This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.          This is either SHAPETYPE_POINT, SHAPETYPE_ARC or SHAPETYPE_POLYGON.
227          """          """
         self.open_shapefile()  
228          return self.shapetype          return self.shapetype
229    
230      def Shape(self, index):      def Shape(self, index):
231          """Return the shape with index index"""          """Return the shape with index index"""
         self.open_shapefile()  
232          shape = self.shapefile.read_object(index)          shape = self.shapefile.read_object(index)
233    
234          if self.shapetype == SHAPETYPE_POINT:          if self.shapetype == SHAPETYPE_POINT:
# Line 262  class Layer(BaseLayer): Line 251  class Layer(BaseLayer):
251          left, bottom, right, top = box          left, bottom, right, top = box
252          return self.shapetree.find_shapes((left, bottom), (right, top))          return self.shapetree.find_shapes((left, bottom), (right, top))
253    
254        def GetProjection(self):
255            return self.projection
256    
257      def SetProjection(self, projection):      def SetProjection(self, projection):
258          """Set the layer's projection"""          """Set the layer's projection"""
259          self.projection = projection          self.projection = projection
# Line 276  class Layer(BaseLayer): Line 268  class Layer(BaseLayer):
268          If 'clazz' is None a default classification is created          If 'clazz' is None a default classification is created
269          """          """
270    
271            # prevent infinite recursion when calling SetLayer()
272            if self.__setClassLock: return
273    
274            self.__setClassLock = True
275    
276          if clazz is None:          if clazz is None:
277                if self.__classification is not None:
278                    self.__classification.SetLayer(None)
279              self.__classification = classification.Classification()              self.__classification = classification.Classification()
280          else:          else:
   
             # prevent infinite recursion when calling SetLayer()  
             if clazz == self.__classification:  
                 return  
   
281              self.__classification = clazz              self.__classification = clazz
282              self.__classification.SetLayer(self)              try:
283                    self.__classification.SetLayer(self)
284                except ValueError:
285                    self.__setClassLock = False
286                    raise ValueError
287    
288            self.changed(LAYER_CHANGED, self)
289    
290          self.changed(LAYER_LEGEND_CHANGED, self)          self.__setClassLock = False
291    
292      def ClassChanged(self):      def ClassChanged(self):
293          """Called from the classification object when it has changed."""          """Called from the classification object when it has changed."""
294          self.changed(LAYER_LEGEND_CHANGED, self)          self.changed(LAYER_CHANGED, self)
295    
296      def TreeInfo(self):      def TreeInfo(self):
297          items = []          items = []
# Line 309  class Layer(BaseLayer): Line 309  class Layer(BaseLayer):
309              items.append(_("Extent (lat-lon):"))              items.append(_("Extent (lat-lon):"))
310          items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])          items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])
311    
312            if self.projection and len(self.projection.params) > 0:
313                items.append((_("Projection"),
314                            [str(param) for param in self.projection.params]))
315    
316          items.append(self.__classification)          items.append(self.__classification)
317    
318          return (_("Layer '%s'") % self.Title(), items)          return (_("Layer '%s'") % self.Title(), items)
319    
320    

Legend:
Removed from v.492  
changed lines
  Added in v.791

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26