/[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 82 by bh, Fri Feb 15 17:11:04 2002 UTC revision 389 by jonathan, Mon Feb 10 15:25:30 2003 UTC
# Line 7  Line 7 
7    
8  __version__ = "$Revision$"  __version__ = "$Revision$"
9    
10  import shapelib  import os
11    from math import log, ceil
12    
13    from Thuban import _
14    
15    import shapelib, shptree
16    
17  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
18       LAYER_VISIBILITY_CHANGED       LAYER_VISIBILITY_CHANGED
# Line 16  from color import Color Line 21  from color import Color
21  # Some predefined colors for internal use  # Some predefined colors for internal use
22  _black = Color(0, 0, 0)  _black = Color(0, 0, 0)
23    
24    from classification import Classification
25    
26  from table import Table  from table import Table
27    
# Line 81  class BaseLayer(TitledObject, Modifiable Line 87  class BaseLayer(TitledObject, Modifiable
87          """Set the layer's visibility."""          """Set the layer's visibility."""
88          self.visible = visible          self.visible = visible
89          self.issue(LAYER_VISIBILITY_CHANGED, self)          self.issue(LAYER_VISIBILITY_CHANGED, self)
90            
91            
92  class Layer(BaseLayer):  class Layer(BaseLayer):
93    
94      """Represent the information of one geodata file (currently a shapefile)      """Represent the information of one geodata file (currently a shapefile)
# Line 117  class Layer(BaseLayer): Line 123  class Layer(BaseLayer):
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          self.filename = filename  
127            # Make the filename absolute. The filename will be
128            # interpreted relative to that anyway, but when saving a
129            # session we need to compare absolute paths and it's usually
130            # safer to always work with absolute paths.
131            self.filename = os.path.abspath(filename)
132    
133          self.projection = projection          self.projection = projection
134          self.fill = fill          self.fill = fill
135          self.stroke = stroke          self.stroke = stroke
136          self.stroke_width = stroke_width          self.stroke_width = stroke_width
137          self.shapefile = None          self.shapefile = None
138            self.shapetree = None
139          self.open_shapefile()          self.open_shapefile()
140          # shapetable is the table associated with the shapefile, while          # shapetable is the table associated with the shapefile, while
141          # table is the default table used to look up attributes for          # table is the default table used to look up attributes for
# Line 130  class Layer(BaseLayer): Line 143  class Layer(BaseLayer):
143          self.shapetable = Table(filename)          self.shapetable = Table(filename)
144          self.table = self.shapetable          self.table = self.shapetable
145    
146            self.classification = Classification(self)
147            self.classification.SetDefaultStroke(stroke)
148            self.classification.SetDefaultStrokeWidth(stroke_width)
149            self.classification.SetDefaultFill(fill)
150    
151            self.UnsetModified()
152    
153      def open_shapefile(self):      def open_shapefile(self):
154          if self.shapefile is None:          if self.shapefile is None:
155              self.shapefile = shapelib.ShapeFile(self.filename)              self.shapefile = shapelib.ShapeFile(self.filename)
156              numshapes, shapetype, mins, maxs = self.shapefile.info()              numshapes, shapetype, mins, maxs = self.shapefile.info()
157              self.numshapes = numshapes              self.numshapes = numshapes
158              self.shapetype = shapelib_shapetypes[shapetype]              self.shapetype = shapelib_shapetypes[shapetype]
159              self.bbox = mins[:2] + maxs[:2]  
160                # if there are shapes, set the bbox accordinly. Otherwise
161                # set it to None.
162                if self.numshapes:
163                    self.bbox = mins[:2] + maxs[:2]
164                else:
165                    self.bbox = None
166    
167                # estimate a good depth for the quad tree. Each depth
168                # multiplies the number of nodes by four, therefore we
169                # basically take the base 4 logarithm of the number of
170                # shapes.
171                if self.numshapes < 4:
172                    maxdepth = 1
173                else:
174                    maxdepth = int(ceil(log(self.numshapes / 4.0) / log(4)))
175    
176                self.shapetree = shptree.SHPTree(self.shapefile.cobject(), 2,
177                                                 maxdepth)
178    
179        def Destroy(self):
180            BaseLayer.Destroy(self)
181            if self.shapefile is not None:
182                self.shapefile.close()
183                self.shapefile = None
184                self.shapetree = None
185            self.table.Destroy()
186    
187      def BoundingBox(self):      def BoundingBox(self):
188          """Return the bounding box of the layer's shapes in their default          """Return the layer's bounding box in the intrinsic coordinate system.
189          coordinate system"""  
190            If the layer has no shapes, return None.
191            """
192            # The bbox will be set by open_shapefile just as we need it
193            # here.
194          self.open_shapefile()          self.open_shapefile()
195          return self.bbox          return self.bbox
196    
197      def LatLongBoundingBox(self):      def LatLongBoundingBox(self):
198          """Return the layer's bounding box in lat/long coordinates"""          """Return the layer's bounding box in lat/long coordinates.
199          llx, lly, urx, ury = self.BoundingBox()  
200          if self.projection is not None:          Return None, if the layer doesn't contain any shapes.
201              llx, lly = self.projection.Inverse(llx, lly)          """
202              urx, ury = self.projection.Inverse(urx, ury)          bbox = self.BoundingBox()
203          return llx, lly, urx, ury          if bbox is not None:
204                llx, lly, urx, ury = bbox
205                if self.projection is not None:
206                    llx, lly = self.projection.Inverse(llx, lly)
207                    urx, ury = self.projection.Inverse(urx, ury)
208                return llx, lly, urx, ury
209            else:
210                return None
211    
212      def NumShapes(self):      def NumShapes(self):
213          """Return the number of shapes in the layer"""          """Return the number of shapes in the layer"""
# Line 168  class Layer(BaseLayer): Line 225  class Layer(BaseLayer):
225          """Return the shape with index index"""          """Return the shape with index index"""
226          self.open_shapefile()          self.open_shapefile()
227          shape = self.shapefile.read_object(index)          shape = self.shapefile.read_object(index)
228    
229          if self.shapetype == SHAPETYPE_POINT:          if self.shapetype == SHAPETYPE_POINT:
230              points = shape.vertices()              points = shape.vertices()
231          else:          else:
# Line 176  class Layer(BaseLayer): Line 234  class Layer(BaseLayer):
234              points = []              points = []
235              for x, y in poly:              for x, y in poly:
236                  points.append((x, y))                  points.append((x, y))
237    
238          return Shape(points)          return Shape(points)
239    
240        def ShapesInRegion(self, box):
241            """Return the ids of the shapes that overlap the box.
242    
243            Box is a tuple (left, bottom, right, top) in the coordinate
244            system used by the layer's shapefile.
245            """
246            left, bottom, right, top = box
247            return self.shapetree.find_shapes((left, bottom), (right, top))
248    
249      def SetProjection(self, projection):      def SetProjection(self, projection):
250          """Set the layer's projection"""          """Set the layer's projection"""
251          self.projection = projection          self.projection = projection
252          self.changed(LAYER_PROJECTION_CHANGED, self)          self.changed(LAYER_PROJECTION_CHANGED, self)
253    
254      def SetFill(self, fill):      def TreeInfo(self):
255          """Set the layer's fill color. None means the shapes are not filled"""          items = []
         self.fill = fill  
         self.changed(LAYER_LEGEND_CHANGED, self)  
256    
257      def SetStroke(self, stroke):          if self.Visible():
258          """Set the layer's stroke color. None means the shapes are not              items.append(_("Shown"))
259          stroked."""          else:
260          self.stroke = stroke              items.append(_("Hidden"))
261          self.changed(LAYER_LEGEND_CHANGED, self)          items.append(_("Shapes: %d") % self.NumShapes())
262    
263            bbox = self.LatLongBoundingBox()
264            if bbox is not None:
265                items.append(_("Extent (lat-lon): (%g, %g, %g, %g)") % bbox)
266            else:
267                items.append(_("Extent (lat-lon):"))
268            items.append(_("Shapetype: %s") % shapetype_names[self.ShapeType()])
269    
270            def color_string(color):
271                if color is None:
272                    return "None"
273                return "(%.3f, %.3f, %.3f)" % (color.red, color.green, color.blue)
274    
275            # layers will always have a classification with at least a NULL data set
276    
277            #items.append((_("Fill: %s") % color_string(self.fill), self.fill))
278            #items.append((_("Outline: %s") % color_string(self.stroke), self.stroke))
279    
280            items.append(self.classification)
281    
282            return (_("Layer '%s'") % self.Title(), items)
283    
     def SetStrokeWidth(self, width):  
         """Set the layer's stroke width."""  
         self.stroke_width = width  
         self.changed(LAYER_LEGEND_CHANGED, self)  

Legend:
Removed from v.82  
changed lines
  Added in v.389

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26