/[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 147 by bh, Tue May 7 16:39:52 2002 UTC revision 481 by jonathan, Thu Mar 6 16:46:36 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
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
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 81  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 102  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 110  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 131  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    
151            self.SetClassification(classification.Classification(self))
152            self.__classification.SetDefaultLineColor(stroke)
153            self.__classification.SetDefaultLineWidth(lineWidth)
154            self.__classification.SetDefaultFill(fill)
155    
156            self.UnsetModified()
157    
158      def open_shapefile(self):      def open_shapefile(self):
159          if self.shapefile is None:          if self.shapefile is None:
160              self.shapefile = shapelib.ShapeFile(self.filename)              self.shapefile = shapelib.ShapeFile(self.filename)
161              numshapes, shapetype, mins, maxs = self.shapefile.info()              numshapes, shapetype, mins, maxs = self.shapefile.info()
162              self.numshapes = numshapes              self.numshapes = numshapes
163              self.shapetype = shapelib_shapetypes[shapetype]              self.shapetype = shapelib_shapetypes[shapetype]
164              self.bbox = mins[:2] + maxs[:2]  
165              #print "building tree for", self.filename, "..."              # if there are shapes, set the bbox accordinly. Otherwise
166              self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2, 0)              # set it to None.
167              #print "done"              if self.numshapes:
168                    self.bbox = mins[:2] + maxs[:2]
169                else:
170                    self.bbox = None
171    
172                # estimate a good depth for the quad tree. Each depth
173                # multiplies the number of nodes by four, therefore we
174                # basically take the base 4 logarithm of the number of
175                # shapes.
176                if self.numshapes < 4:
177                    maxdepth = 1
178                else:
179                    maxdepth = int(ceil(log(self.numshapes / 4.0) / log(4)))
180    
181                self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,
182                                                 maxdepth)
183    
184        def Destroy(self):
185            BaseLayer.Destroy(self)
186            if self.shapefile is not None:
187                self.shapefile.close()
188                self.shapefile = None
189                self.shapetree = None
190            self.table.Destroy()
191    
192      def BoundingBox(self):      def BoundingBox(self):
193          """Return the bounding box of the layer's shapes in their default          """Return the layer's bounding box in the intrinsic coordinate system.
194          coordinate system"""  
195            If the layer has no shapes, return None.
196            """
197            # The bbox will be set by open_shapefile just as we need it
198            # here.
199          self.open_shapefile()          self.open_shapefile()
200          return self.bbox          return self.bbox
201    
202      def LatLongBoundingBox(self):      def LatLongBoundingBox(self):
203          """Return the layer's bounding box in lat/long coordinates"""          """Return the layer's bounding box in lat/long coordinates.
204          llx, lly, urx, ury = self.BoundingBox()  
205          if self.projection is not None:          Return None, if the layer doesn't contain any shapes.
206              llx, lly = self.projection.Inverse(llx, lly)          """
207              urx, ury = self.projection.Inverse(urx, ury)          bbox = self.BoundingBox()
208          return llx, lly, urx, ury          if bbox is not None:
209                llx, lly, urx, ury = bbox
210                if self.projection is not None:
211                    llx, lly = self.projection.Inverse(llx, lly)
212                    urx, ury = self.projection.Inverse(urx, ury)
213                return llx, lly, urx, ury
214            else:
215                return None
216    
217        def GetFieldType(self, fieldName):
218            self.open_shapefile()
219            info = self.table.field_info_by_name(fieldName)
220            if info is not None:
221                return info[0]
222            else:
223                return None
224    
225      def NumShapes(self):      def NumShapes(self):
226          """Return the number of shapes in the layer"""          """Return the number of shapes in the layer"""
# Line 172  class Layer(BaseLayer): Line 238  class Layer(BaseLayer):
238          """Return the shape with index index"""          """Return the shape with index index"""
239          self.open_shapefile()          self.open_shapefile()
240          shape = self.shapefile.read_object(index)          shape = self.shapefile.read_object(index)
241    
242          if self.shapetype == SHAPETYPE_POINT:          if self.shapetype == SHAPETYPE_POINT:
243              points = shape.vertices()              points = shape.vertices()
244          else:          else:
# Line 180  class Layer(BaseLayer): Line 247  class Layer(BaseLayer):
247              points = []              points = []
248              for x, y in poly:              for x, y in poly:
249                  points.append((x, y))                  points.append((x, y))
250    
251          return Shape(points)          return Shape(points)
252    
253      def ShapesInRegion(self, box):      def ShapesInRegion(self, box):
# Line 196  class Layer(BaseLayer): Line 264  class Layer(BaseLayer):
264          self.projection = projection          self.projection = projection
265          self.changed(LAYER_PROJECTION_CHANGED, self)          self.changed(LAYER_PROJECTION_CHANGED, self)
266    
267      def SetFill(self, fill):      def GetClassification(self):
268          """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)  
269    
270      def SetStroke(self, stroke):      def SetClassification(self, clazz):
         """Set the layer's stroke color. None means the shapes are not  
         stroked."""  
         self.stroke = stroke  
         self.changed(LAYER_LEGEND_CHANGED, self)  
271    
272      def SetStrokeWidth(self, width):          # prevent infinite recursion when calling SetLayer()
273          """Set the layer's stroke width."""          if clazz == self.__classification:
274          self.stroke_width = width              return
275    
276            self.__classification = clazz
277            self.__classification.SetLayer(self)
278          self.changed(LAYER_LEGEND_CHANGED, self)          self.changed(LAYER_LEGEND_CHANGED, self)
279    
280        def TreeInfo(self):
281            items = []
282    
283            if self.Visible():
284                items.append(_("Shown"))
285            else:
286                items.append(_("Hidden"))
287            items.append(_("Shapes: %d") % self.NumShapes())
288    
289            bbox = self.LatLongBoundingBox()
290            if bbox is not None:
291                items.append(_("Extent (lat-lon): (%g, %g, %g, %g)") % bbox)
292            else:
293                items.append(_("Extent (lat-lon):"))
294            items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])
295    
296            items.append(self.__classification)
297    
298            return (_("Layer '%s'") % self.Title(), items)
299    

Legend:
Removed from v.147  
changed lines
  Added in v.481

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26