/[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 171 by bh, Tue May 14 14:16:24 2002 UTC revision 545 by jonathan, Thu Mar 20 09:44:04 2003 UTC
# Line 1  Line 1 
1  # Copyright (c) 2001, 2002 by Intevation GmbH  # Copyright (c) 2001, 2002 by Intevation GmbH
2  # Authors:  # Authors:
3  # Bernhard Herzog <[email protected]>  # Bernhard Herzog <[email protected]>
4    # Jonathan Coles <[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    
9  __version__ = "$Revision$"  __version__ = "$Revision$"
10    
11    import os
12  from math import log, ceil  from math import log, ceil
13    
14    from Thuban import _
15    
16  import shapelib, shptree  import shapelib, shptree
17    
18  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
19       LAYER_VISIBILITY_CHANGED       LAYER_VISIBILITY_CHANGED, LAYER_CHANGED
20    
21  from color import Color  from color import Color
 # Some predefined colors for internal use  
 _black = Color(0, 0, 0)  
22    
23    import classification
24    
25  from table import Table  from table import Table
26    
# Line 83  class BaseLayer(TitledObject, Modifiable Line 86  class BaseLayer(TitledObject, Modifiable
86          """Set the layer's visibility."""          """Set the layer's visibility."""
87          self.visible = visible          self.visible = visible
88          self.issue(LAYER_VISIBILITY_CHANGED, self)          self.issue(LAYER_VISIBILITY_CHANGED, self)
89            
90            
91  class Layer(BaseLayer):  class Layer(BaseLayer):
92    
93      """Represent the information of one geodata file (currently a shapefile)      """Represent the information of one geodata file (currently a shapefile)
# Line 104  class Layer(BaseLayer): Line 107  class Layer(BaseLayer):
107      """      """
108    
109      def __init__(self, title, filename, projection = None,      def __init__(self, title, filename, projection = None,
110                   fill = None, stroke = _black, stroke_width = 1, visible = 1):                   fill = Color.None,
111                     stroke = Color.Black,
112                     lineWidth = 1,
113                     visible = 1):
114          """Initialize the layer.          """Initialize the layer.
115    
116          title -- the title          title -- the title
# Line 112  class Layer(BaseLayer): Line 118  class Layer(BaseLayer):
118          projection -- the projection object. Its Inverse method is          projection -- the projection object. Its Inverse method is
119                 assumed to map the layer's coordinates to lat/long                 assumed to map the layer's coordinates to lat/long
120                 coordinates                 coordinates
121          fill -- the fill color or None if the shapes are not filled          fill -- the fill color or Color.None if the shapes are not filled
122          stroke -- the stroke color or None if the shapes are not stroked          stroke -- the stroke color or Color.None if the shapes are not stroked
123          visible -- boolean. If true the layer is visible.          visible -- boolean. If true the layer is visible.
124    
125          colors are expected to be instances of Color class          colors are expected to be instances of Color class
126          """          """
127          BaseLayer.__init__(self, title, visible = visible)          BaseLayer.__init__(self, title, visible = visible)
128          self.filename = filename  
129            # Make the filename absolute. The filename will be
130            # interpreted relative to that anyway, but when saving a
131            # session we need to compare absolute paths and it's usually
132            # safer to always work with absolute paths.
133            self.filename = os.path.abspath(filename)
134    
135          self.projection = projection          self.projection = projection
         self.fill = fill  
         self.stroke = stroke  
         self.stroke_width = stroke_width  
136          self.shapefile = None          self.shapefile = None
137          self.shapetree = None          self.shapetree = None
138          self.open_shapefile()          self.open_shapefile()
# Line 133  class Layer(BaseLayer): Line 142  class Layer(BaseLayer):
142          self.shapetable = Table(filename)          self.shapetable = Table(filename)
143          self.table = self.shapetable          self.table = self.shapetable
144    
145            #
146            # this is really important so that when the classification class
147            # tries to set its parent layer the variable will exist
148            #
149            self.__classification = None
150            self.__setClassLock = False
151    
152    
153            self.SetClassification(None)
154    
155            self.__classification.SetDefaultLineColor(stroke)
156            self.__classification.SetDefaultLineWidth(lineWidth)
157            self.__classification.SetDefaultFill(fill)
158            self.__classification.SetLayer(self)
159    
160            self.UnsetModified()
161    
162      def open_shapefile(self):      def open_shapefile(self):
163          if self.shapefile is None:          if self.shapefile is None:
164              self.shapefile = shapelib.ShapeFile(self.filename)              self.shapefile = shapelib.ShapeFile(self.filename)
165              numshapes, shapetype, mins, maxs = self.shapefile.info()              numshapes, shapetype, mins, maxs = self.shapefile.info()
166              self.numshapes = numshapes              self.numshapes = numshapes
167              self.shapetype = shapelib_shapetypes[shapetype]              self.shapetype = shapelib_shapetypes[shapetype]
168              self.bbox = mins[:2] + maxs[:2]  
169                # if there are shapes, set the bbox accordinly. Otherwise
170                # set it to None.
171                if self.numshapes:
172                    self.bbox = mins[:2] + maxs[:2]
173                else:
174                    self.bbox = None
175    
176              # estimate a good depth for the quad tree. Each depth              # estimate a good depth for the quad tree. Each depth
177              # multiplies the number of nodes by four, therefore we              # multiplies the number of nodes by four, therefore we
# Line 153  class Layer(BaseLayer): Line 185  class Layer(BaseLayer):
185              self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,              self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,
186                                               maxdepth)                                               maxdepth)
187    
188        def Destroy(self):
189            BaseLayer.Destroy(self)
190            if self.shapefile is not None:
191                self.shapefile.close()
192                self.shapefile = None
193                self.shapetree = None
194            self.SetClassification(None)
195            self.table.Destroy()
196    
197      def BoundingBox(self):      def BoundingBox(self):
198          """Return the bounding box of the layer's shapes in their default          """Return the layer's bounding box in the intrinsic coordinate system.
199          coordinate system"""  
200            If the layer has no shapes, return None.
201            """
202            # The bbox will be set by open_shapefile just as we need it
203            # here.
204          self.open_shapefile()          self.open_shapefile()
205          return self.bbox          return self.bbox
206    
207      def LatLongBoundingBox(self):      def LatLongBoundingBox(self):
208          """Return the layer's bounding box in lat/long coordinates"""          """Return the layer's bounding box in lat/long coordinates.
209          llx, lly, urx, ury = self.BoundingBox()  
210          if self.projection is not None:          Return None, if the layer doesn't contain any shapes.
211              llx, lly = self.projection.Inverse(llx, lly)          """
212              urx, ury = self.projection.Inverse(urx, ury)          bbox = self.BoundingBox()
213          return llx, lly, urx, ury          if bbox is not None:
214                llx, lly, urx, ury = bbox
215                if self.projection is not None:
216                    llx, lly = self.projection.Inverse(llx, lly)
217                    urx, ury = self.projection.Inverse(urx, ury)
218                return llx, lly, urx, ury
219            else:
220                return None
221    
222        def GetFieldType(self, fieldName):
223            self.open_shapefile()
224            info = self.table.field_info_by_name(fieldName)
225            if info is not None:
226                return info[0]
227            else:
228                return None
229    
230      def NumShapes(self):      def NumShapes(self):
231          """Return the number of shapes in the layer"""          """Return the number of shapes in the layer"""
# Line 183  class Layer(BaseLayer): Line 243  class Layer(BaseLayer):
243          """Return the shape with index index"""          """Return the shape with index index"""
244          self.open_shapefile()          self.open_shapefile()
245          shape = self.shapefile.read_object(index)          shape = self.shapefile.read_object(index)
246    
247          if self.shapetype == SHAPETYPE_POINT:          if self.shapetype == SHAPETYPE_POINT:
248              points = shape.vertices()              points = shape.vertices()
249          else:          else:
# Line 191  class Layer(BaseLayer): Line 252  class Layer(BaseLayer):
252              points = []              points = []
253              for x, y in poly:              for x, y in poly:
254                  points.append((x, y))                  points.append((x, y))
255    
256          return Shape(points)          return Shape(points)
257    
258      def ShapesInRegion(self, box):      def ShapesInRegion(self, box):
# Line 207  class Layer(BaseLayer): Line 269  class Layer(BaseLayer):
269          self.projection = projection          self.projection = projection
270          self.changed(LAYER_PROJECTION_CHANGED, self)          self.changed(LAYER_PROJECTION_CHANGED, self)
271    
272      def SetFill(self, fill):      def GetClassification(self):
273          """Set the layer's fill color. None means the shapes are not filled"""          return self.__classification
         self.fill = fill  
         self.changed(LAYER_LEGEND_CHANGED, self)  
274    
275      def SetStroke(self, stroke):      def SetClassification(self, clazz):
276          """Set the layer's stroke color. None means the shapes are not          """Set the classification to 'clazz'
277          stroked."""  
278          self.stroke = stroke          If 'clazz' is None a default classification is created
279          self.changed(LAYER_LEGEND_CHANGED, self)          """
280    
281            # prevent infinite recursion when calling SetLayer()
282            if self.__setClassLock: return
283    
284            self.__setClassLock = True
285    
286            if clazz is None:
287                if self.__classification is not None:
288                    self.__classification.SetLayer(None)
289                self.__classification = classification.Classification()
290            else:
291                self.__classification = clazz
292                try:
293                    self.__classification.SetLayer(self)
294                except ValueError:
295                    self.__setClassLock = False
296                    raise ValueError
297    
298      def SetStrokeWidth(self, width):          self.changed(LAYER_CHANGED, self)
299          """Set the layer's stroke width."""  
300          self.stroke_width = width          self.__setClassLock = False
301    
302        def ClassChanged(self):
303            """Called from the classification object when it has changed."""
304          self.changed(LAYER_LEGEND_CHANGED, self)          self.changed(LAYER_LEGEND_CHANGED, self)
305    
306        def TreeInfo(self):
307            items = []
308    
309            if self.Visible():
310                items.append(_("Shown"))
311            else:
312                items.append(_("Hidden"))
313            items.append(_("Shapes: %d") % self.NumShapes())
314    
315            bbox = self.LatLongBoundingBox()
316            if bbox is not None:
317                items.append(_("Extent (lat-lon): (%g, %g, %g, %g)") % bbox)
318            else:
319                items.append(_("Extent (lat-lon):"))
320            items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])
321    
322            items.append(self.__classification)
323    
324            return (_("Layer '%s'") % self.Title(), items)
325    

Legend:
Removed from v.171  
changed lines
  Added in v.545

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26