/[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 143 by bh, Tue May 7 14:17:20 2002 UTC revision 437 by jonathan, Thu Feb 27 15:53:21 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                     stroke_width = 1,
113                     visible = 1):
114          """Initialize the layer.          """Initialize the layer.
115    
116          title -- the title          title -- the title
# Line 117  class Layer(BaseLayer): Line 125  class Layer(BaseLayer):
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            self.__classification = classification.Classification(self)
146            self.__classification.SetDefaultStroke(stroke)
147            self.__classification.SetDefaultStrokeWidth(stroke_width)
148            self.__classification.SetDefaultFill(fill)
149    
150            self.UnsetModified()
151    
152      def open_shapefile(self):      def open_shapefile(self):
153          if self.shapefile is None:          if self.shapefile is None:
154              self.shapefile = shapelib.ShapeFile(self.filename)              self.shapefile = shapelib.ShapeFile(self.filename)
155              numshapes, shapetype, mins, maxs = self.shapefile.info()              numshapes, shapetype, mins, maxs = self.shapefile.info()
156              self.numshapes = numshapes              self.numshapes = numshapes
157              self.shapetype = shapelib_shapetypes[shapetype]              self.shapetype = shapelib_shapetypes[shapetype]
158              self.bbox = mins[:2] + maxs[:2]  
159              #print "building tree for", self.filename, "..."              # if there are shapes, set the bbox accordinly. Otherwise
160              self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2, 0)              # set it to None.
161              #print "done"              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    
178        def Destroy(self):
179            BaseLayer.Destroy(self)
180            if self.shapefile is not None:
181                self.shapefile.close()
182                self.shapefile = None
183                self.shapetree = None
184            self.table.Destroy()
185    
186      def BoundingBox(self):      def BoundingBox(self):
187          """Return the bounding box of the layer's shapes in their default          """Return the layer's bounding box in the intrinsic coordinate system.
188          coordinate system"""  
189            If the layer has no shapes, return None.
190            """
191            # The bbox will be set by open_shapefile just as we need it
192            # here.
193          self.open_shapefile()          self.open_shapefile()
194          return self.bbox          return self.bbox
195    
196      def LatLongBoundingBox(self):      def LatLongBoundingBox(self):
197          """Return the layer's bounding box in lat/long coordinates"""          """Return the layer's bounding box in lat/long coordinates.
198          llx, lly, urx, ury = self.BoundingBox()  
199          if self.projection is not None:          Return None, if the layer doesn't contain any shapes.
200              llx, lly = self.projection.Inverse(llx, lly)          """
201              urx, ury = self.projection.Inverse(urx, ury)          bbox = self.BoundingBox()
202          return llx, lly, urx, ury          if bbox is not None:
203                llx, lly, urx, ury = bbox
204                if self.projection is not None:
205                    llx, lly = self.projection.Inverse(llx, lly)
206                    urx, ury = self.projection.Inverse(urx, ury)
207                return llx, lly, urx, ury
208            else:
209                return None
210    
211      def NumShapes(self):      def NumShapes(self):
212          """Return the number of shapes in the layer"""          """Return the number of shapes in the layer"""
# Line 172  class Layer(BaseLayer): Line 224  class Layer(BaseLayer):
224          """Return the shape with index index"""          """Return the shape with index index"""
225          self.open_shapefile()          self.open_shapefile()
226          shape = self.shapefile.read_object(index)          shape = self.shapefile.read_object(index)
227    
228          if self.shapetype == SHAPETYPE_POINT:          if self.shapetype == SHAPETYPE_POINT:
229              points = shape.vertices()              points = shape.vertices()
230          else:          else:
# Line 180  class Layer(BaseLayer): Line 233  class Layer(BaseLayer):
233              points = []              points = []
234              for x, y in poly:              for x, y in poly:
235                  points.append((x, y))                  points.append((x, y))
236    
237          return Shape(points)          return Shape(points)
238    
239      def ShapesInRegion(self, box):      def ShapesInRegion(self, box):
# Line 189  class Layer(BaseLayer): Line 243  class Layer(BaseLayer):
243          system used by the layer's shapefile.          system used by the layer's shapefile.
244          """          """
245          left, bottom, right, top = box          left, bottom, right, top = box
246          import time          return self.shapetree.find_shapes((left, bottom), (right, top))
         start = time.time()  
         ids = self.shapetree.find_shapes((left, bottom), (right, top))  
         print "ShapesInRegion", time.time() - start  
         return ids  
247    
248      def SetProjection(self, projection):      def SetProjection(self, projection):
249          """Set the layer's projection"""          """Set the layer's projection"""
250          self.projection = projection          self.projection = projection
251          self.changed(LAYER_PROJECTION_CHANGED, self)          self.changed(LAYER_PROJECTION_CHANGED, self)
252    
253      def SetFill(self, fill):      def GetClassification(self):
254          """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)  
255    
256      def SetStroke(self, stroke):      def SetClassification(self, clazz):
257          """Set the layer's stroke color. None means the shapes are not          self.__classification = clazz
         stroked."""  
         self.stroke = stroke  
258          self.changed(LAYER_LEGEND_CHANGED, self)          self.changed(LAYER_LEGEND_CHANGED, self)
259    
260      def SetStrokeWidth(self, width):      def TreeInfo(self):
261          """Set the layer's stroke width."""          items = []
262          self.stroke_width = width  
263          self.changed(LAYER_LEGEND_CHANGED, self)          if self.Visible():
264                items.append(_("Shown"))
265            else:
266                items.append(_("Hidden"))
267            items.append(_("Shapes: %d") % self.NumShapes())
268    
269            bbox = self.LatLongBoundingBox()
270            if bbox is not None:
271                items.append(_("Extent (lat-lon): (%g, %g, %g, %g)") % bbox)
272            else:
273                items.append(_("Extent (lat-lon):"))
274            items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])
275    
276            items.append(self.__classification)
277    
278            return (_("Layer '%s'") % self.Title(), items)
279    

Legend:
Removed from v.143  
changed lines
  Added in v.437

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26