/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/classification.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/classification.py

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

revision 410 by jonathan, Wed Feb 19 16:51:12 2003 UTC revision 436 by jonathan, Thu Feb 27 15:53:03 2003 UTC
# Line 16  an input value falls with a range that d Line 16  an input value falls with a range that d
16  If no mapping can be found then default data will  If no mapping can be found then default data will
17  be returned. Input values must be hashable objects  be returned. Input values must be hashable objects
18    
19  See the description of getProperties() for more information  See the description of GetClassData() for more information
20  on the mapping algorithm.  on the mapping algorithm.
21  """  """
22        
23  # fix for people using python2.1  # fix for people using python2.1
24  from __future__ import nested_scopes  from __future__ import nested_scopes
25    
26    from types import *
27    
28  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \  from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
29       LAYER_VISIBILITY_CHANGED       LAYER_VISIBILITY_CHANGED
30    
31  from Thuban import _  from Thuban import _
32  from Thuban.Model.color import Color  from Thuban.Model.color import Color
33    
34    import Thuban.Model.layer
35    
36  from wxPython.wx import *  from wxPython.wx import *
37    
38  # constants  # constants
# Line 47  class Classification: Line 51  class Classification:
51                      is to be used to classify layer properties                      is to be used to classify layer properties
52          """          """
53    
54            self.layer = None # stop message sending
55    
56            self.SetDefaultGroup(ClassGroupDefault())
57            self.SetField(field)
58    
59          self.layer = layer          self.layer = layer
60          self.points = {}          self.points = []
61          self.ranges = []          self.ranges = []
62          self.maps   = []          self.maps   = []
         self.DefaultData = ClassDataDefault()  
         self.field = field  
         #self.SetField(field)  
63    
64      def SendMessage(self, message):      def __iter__(self):
65            return ClassIterator(self.DefaultGroup,
66                                 self.points,
67                                 self.ranges,
68                                 self.maps)
69    
70        def __SendMessage(self, message):
71          if self.layer is not None:          if self.layer is not None:
72              self.layer.changed(message, self.layer)              self.layer.changed(message, self.layer)
73            
# Line 65  class Classification: Line 77  class Classification:
77             field -- if None then all values map to the default data             field -- if None then all values map to the default data
78          """          """
79    
80            if field == "":
81                field = None
82    
83          self.field = field          self.field = field
84          self.SendMessage(LAYER_LEGEND_CHANGED)          self.__SendMessage(LAYER_LEGEND_CHANGED)
85    
86      def GetField(self):      def GetField(self):
87          return self.field          return self.field
88    
89      def SetLayer(self, layer):      def SetLayer(self, layer):
90            assert(isinstance(layer, Thuban.Model.layer.Layer))
91          self.layer = layer          self.layer = layer
92          self.SendMessage(LAYER_LEGEND_CHANGED)          self.__SendMessage(LAYER_LEGEND_CHANGED)
93    
94      def GetLayer(self):      def GetLayer(self):
95          return layer.self          return layer.self
96    
97      def SetDefaultData(self, data):      def SetDefaultGroup(self, group):
98          """Set the data to be used when a value can't be classified.          """Set the group to be used when a value can't be classified.
99    
100             data -- data that the value maps to. See class description.             group -- group that the value maps to. See class description.
101          """          """
102    
103          self.DefaultData = data          assert(isinstance(group, ClassGroupDefault))
104            self.DefaultGroup = group
105    
106        def GetDefaultGroup(self):
107            return self.DefaultGroup
108    
109      def GetDefaultData(self):      #
110          return self.DefaultData      # these SetDefault* methods are really only provided for
111        # some backward compatibility. they should be considered
112        # for removal once all the classification code is finished.
113        #
114    
115      def SetDefaultFill(self, fill):      def SetDefaultFill(self, fill):
116          self.DefaultData.SetFill(fill)          assert(isinstance(fill, Color))
117          self.SendMessage(LAYER_LEGEND_CHANGED)          self.DefaultGroup.GetProperties().SetFill(fill)
118            self.__SendMessage(LAYER_LEGEND_CHANGED)
119                    
120      def GetDefaultFill(self):      def GetDefaultFill(self):
121          return self.DefaultData.GetFill()          return self.DefaultGroup.GetProperties().GetFill()
122                    
123      def SetDefaultStroke(self, stroke):      def SetDefaultStroke(self, stroke):
124          self.DefaultData.SetStroke(stroke)          assert(isinstance(stroke, Color))
125          self.SendMessage(LAYER_LEGEND_CHANGED)          self.DefaultGroup.GetProperties().SetStroke(stroke)
126            self.__SendMessage(LAYER_LEGEND_CHANGED)
127                    
128      def GetDefaultStroke(self):      def GetDefaultStroke(self):
129          return self.DefaultData.GetStroke()          return self.DefaultGroup.GetProperties().GetStroke()
130                    
131      def SetDefaultStrokeWidth(self, strokeWidth):      def SetDefaultStrokeWidth(self, strokeWidth):
132          self.DefaultData.SetStrokeWidth(strokeWidth)          assert(isinstance(strokeWidth, IntType))
133          self.SendMessage(LAYER_LEGEND_CHANGED)          self.DefaultGroup.GetProperties().SetStrokeWidth(strokeWidth)
134            self.__SendMessage(LAYER_LEGEND_CHANGED)
135                    
136      def GetDefaultStrokeWidth(self):      def GetDefaultStrokeWidth(self):
137          return self.DefaultData.GetStrokeWidth()          return self.DefaultGroup.GetProperties().GetStrokeWidth()
138                    
139      def AddClassData(self, item):      def AddGroup(self, item):
140          type = item.GetType()          assert(isinstance(item, ClassGroup))
141    
142          if type == ClassData.POINT:          if isinstance(item, ClassGroupDefault):
143              self.points[item.GetValue()] = item              self.SetDefaultGroup(item)
144          elif type == ClassData.RANGE:          elif isinstance(item, ClassGroupSingleton):
145                self.points.append(item)
146            elif isinstance(item, ClassGroupRange):
147              self.ranges.append(item)              self.ranges.append(item)
148          elif type == ClassData.MAP:          elif isinstance(item, ClassGroupMap):
149              self.maps.append(item)              self.maps.append(item)
         elif type == ClassData.DEFAULT:  
             self.DefaultData = item  
150          else:          else:
151              raise ValueError(_("Unrecognized ClassData type %s") % type)              raise ValueError(_("Unrecognized ClassGroup"))
152    
153          self.SendMessage(LAYER_LEGEND_CHANGED)          self.__SendMessage(LAYER_LEGEND_CHANGED)
154    
155      def GetProperties(self, value):      def GetGroup(self, value):
156          """Return the associated data, or the default data.          """Return the associated data, or the default data.
157    
158             The following search technique is used:             The following search technique is used:
# Line 137  class Classification: Line 163  class Classification:
163                     the classification.                     the classification.
164    
165             value -- the value to classify. If there is no mapping,             value -- the value to classify. If there is no mapping,
166                      or value is None, return the default data                      or value is None, return the default properties
                     (which may be None)  
167          """          """
168    
169          if self.field is not None and value is not None:          if self.field is not None and value is not None:
170              #  
171              # check the discrete values              for p in self:
172              #                  if p.Matches(value):
             if self.points.has_key(value):  
                 return self.points[value]  
   
             #  
             # check the ranges  
             #  
             for p in self.ranges:  
                 if p.InRange(value):  
173                      return p                      return p
174    #           #
175    #           # check the discrete values
176    #           #
177    #           if self.points.has_key(value):
178    #               return self.points[value]
179    #           #for p in self.points:
180    #               #if p.Value
181    
182    #           #
183    #           # check the ranges
184    #           #
185    #           for p in self.ranges:
186    #               if p.InRange(value):
187    #                   return p
188    
189    #           #
190    #           # check the maps
191    #           #
192    #           for p in self.maps:
193    #               try:
194    #                   return p.Map(value)
195    #               except: pass
196    
197              #          return self.DefaultGroup
             # check the maps  
             #  
             for p in self.maps:  
                 try:  
                     return p.Map(value)  
                 except: pass  
198    
199          return self.DefaultData      def GetProperties(self, value):
200            return self.GetGroup(value).GetProperties()
201    
202      def TreeInfo(self):      def TreeInfo(self):
203          items = []          items = []
# Line 176  class Classification: Line 210  class Classification:
210                      (text, color.red, color.green, color.blue),                      (text, color.red, color.green, color.blue),
211                      color)                      color)
212    
213          def build_item(data, string):          def build_item(group, string):
214              label = data.GetLabel()              label = group.GetLabel()
215              if label == "":              if label == "":
216                  label = string                  label = string
217              else:              else:
218                  label += " (%s)" % string                  label += " (%s)" % string
219    
220                props = group.GetProperties()
221              i = []              i = []
222              v = data.GetStroke()              v = props.GetStroke()
223              i.append(build_color_item(_("Stroke"), v))              i.append(build_color_item(_("Stroke"), v))
224              v = data.GetStrokeWidth()              v = props.GetStrokeWidth()
225              i.append(_("Stroke Width: %s") % v)              i.append(_("Stroke Width: %s") % v)
226              v = data.GetFill()              v = props.GetFill()
227              i.append(build_color_item(_("Fill"), v))              i.append(build_color_item(_("Fill"), v))
228              return (label, i)              return (label, i)
229    
230          items.append(build_item(self.DefaultData, _("'DEFAULT'")))          for p in self:
231                if isinstance(p, ClassGroupDefault):
232                    items.append(build_item(self.DefaultGroup, _("'DEFAULT'")))
233                elif isinstance(p, ClassGroupSingleton):
234                    items.append(build_item(p, str(p.GetValue())))
235                elif isinstance(p, ClassGroupRange):
236                    items.append(build_item(p, "%s - %s" %
237                                               (p.GetMin(), p.GetMax())))
238    
239          for p in self.points.values():  #       for p in self.points.values():
240              items.append(build_item(p, str(p.GetValue())))  #           items.append(build_item(p, str(p.GetValue())))
241    
242          for p in self.ranges:  #       for p in self.ranges:
243              items.append(build_item(p, "%s - %s" % (p.GetMin(), p.GetMax())))  #           items.append(build_item(p, "%s - %s" % (p.GetMin(), p.GetMax())))
244    
245          return (_("Classifications"), items)          return (_("Classification"), items)
246    
247    class ClassIterator:
248    
249  class ClassData:      def __init__(self, default, points, ranges, maps):
250            self.data = [default, points, ranges, maps]
251      INVALID = -1          self.data_iter = iter(self.data)
252      DEFAULT = 0          self.iter = None
253      POINT = 1  
254      RANGE = 2      def __iter__(self):
255      MAP   = 3          return self
256    
257      def __init__(self, type = INVALID, classData = None):      def next(self):
258            if self.iter is None:
259          if classData is not None:              try:
260              self.SetStroke(classData.GetStroke())                  self.data_item = self.data_iter.next()
261              self.SetStrokeWidth(classData.GetStrokeWidth())                  self.iter = iter(self.data_item)
262              self.SetFill(classData.GetFill())              except TypeError:
263                    return self.data_item
264    
265            try:
266                return self.iter.next()
267            except StopIteration:
268                self.iter = None
269                return self.next()
270          
271    class ClassGroupProperties:
272    
273        def __init__(self, prop = None):
274    
275            if prop is not None:
276                self.SetStroke(prop.GetStroke())
277                self.SetStrokeWidth(prop.GetStrokeWidth())
278                self.SetFill(prop.GetFill())
279          else:          else:
280              self.SetStroke(Color.None)              self.SetStroke(Color.None)
281              self.SetStrokeWidth(1)              self.SetStrokeWidth(1)
282              self.SetFill(Color.None)              self.SetFill(Color.None)
283    
         self.type = type  
         self.label = ""  
       
     def GetType(self):  
         return self.type  
   
284      def GetStroke(self):      def GetStroke(self):
285          return self.stroke          return self.stroke
286    
# Line 239  class ClassData: Line 292  class ClassData:
292          return self.stroke_width          return self.stroke_width
293    
294      def SetStrokeWidth(self, stroke_width):      def SetStrokeWidth(self, stroke_width):
295            assert(isinstance(stroke_width, IntType))
296          if (stroke_width < 1):          if (stroke_width < 1):
297              raise ValueError(_("stroke_width < 1"))              raise ValueError(_("stroke_width < 1"))
298    
# Line 251  class ClassData: Line 305  class ClassData:
305          assert(isinstance(fill, Color))          assert(isinstance(fill, Color))
306          self.fill = fill          self.fill = fill
307    
308    
309    class ClassGroup:
310    
311        def __init__(self, label = ""):
312            self.label = label
313    
314      def GetLabel(self):      def GetLabel(self):
315          return self.label          return self.label
316    
317      def SetLabel(self, label):      def SetLabel(self, label):
318          self.label = label          self.label = label
319    
320  class ClassDataDefault(ClassData):      def Matches(self, value):
321      def __init__(self, classData = None):          """This needs to be implemented by all subclasses."""
322          ClassData.__init__(self, ClassData.DEFAULT, classData)          pass
323    
324        def GetProperties(self, value):
325            """This needs to be implemented by all subclasses."""
326            pass
327    
328            
329  class ClassDataPoint(ClassData):  class ClassGroupSingleton(ClassGroup):
330    
331      def __init__(self, value = 0, classData = None):      def __init__(self, value = 0, prop = None, label = ""):
332          ClassData.__init__(self, ClassData.POINT, classData)          ClassGroup.__init__(self, label)
333    
334          self.value = value          self.SetValue(value)
335            self.SetProperties(prop)
336    
337        def __copy__(self):
338            return ClassGroupSingleton(self.value, self.prop, self.label)
339    
340      def GetValue(self):      def GetValue(self):
341          return self.value          return self.value
# Line 274  class ClassDataPoint(ClassData): Line 343  class ClassDataPoint(ClassData):
343      def SetValue(self, value):      def SetValue(self, value):
344          self.value = value          self.value = value
345    
346  class ClassDataRange(ClassData):      def Matches(self, value):
347            return self.value == value
348    
349      def __init__(self, min = 0, max = 1, classData = None):      def GetProperties(self, value = None):
350          ClassData.__init__(self, ClassData.RANGE, classData)          if value is None: return self.prop
351    
352          if min >= max:          if self.Matches(value):
353              raise ValueError(_("ClassDataRange: %i(min) >= %i(max)!") %              return self.prop
354                               (min, max))          else:
355                return None
356    
357        def SetProperties(self, prop):
358            if prop is None: prop = ClassGroupProperties()
359            assert(isinstance(prop, ClassGroupProperties))
360            self.prop = prop
361    
362    
363    class ClassGroupDefault(ClassGroupSingleton):
364        def __init__(self, prop = None, label = ""):
365            ClassGroupSingleton.__init__(self, 0, prop, label)
366    
367        def __copy__(self):
368            return ClassGroupDefault(self.prop, self.label)
369    
370        def GetProperties(self, value = None):
371            return self.prop
372    
373    class ClassGroupRange(ClassGroup):
374    
375        def __init__(self, min = 0, max = 1, prop = None, label = ""):
376            ClassGroup.__init__(self, label)
377    
378          self.SetRange(min, max)          self.SetRange(min, max)
379            self.SetProperties(prop)
380    
381        def __copy__(self):
382            return ClassGroupRange(self.min, self.max, self.prop, self.label)
383    
384      def GetMin(self):      def GetMin(self):
385          return self.min          return self.min
# Line 298  class ClassDataRange(ClassData): Line 394  class ClassDataRange(ClassData):
394          self.SetRange(self.min, max)          self.SetRange(self.min, max)
395    
396      def SetRange(self, min, max):      def SetRange(self, min, max):
         self.min = min  
         self.max = max  
397          if min >= max:          if min >= max:
398              raise ValueError(_("ClassDataRange: %i(min) >= %i(max)!") %              raise ValueError(_("ClassGroupRange: %i(min) >= %i(max)!") %
399                               (min, max))                               (min, max))
400            self.min = min
401            self.max = max
402    
403      def GetRange(self):      def GetRange(self):
404          return (self.min, self.max)          return (self.min, self.max)
405    
406      def InRange(self, value):      def Matches(self, value):
407          return self.min <= value < self.max          return self.min <= value < self.max
408    
409  class ClassDataMap(ClassData):      def GetProperties(self, value):
410            if value is None: return self.prop
411    
412            if self.Matches(value):
413                return self.prop
414            else:
415                return None
416    
417        def SetProperties(self, prop):
418            if prop is None: prop = ClassGroupProperties()
419            assert(isinstance(prop, ClassGroupProperties))
420            self.prop = prop
421    
422    class ClassGroupMap(ClassGroup):
423    
424      FUNC_ID = "id"      FUNC_ID = "id"
425    
426      def __init__(self, map_type = FUNC_ID, func = None, classData = None):      def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):
427          ClassData.__init__(self, ClassData.MAP, classData)          ClassGroup.__init__(self, prop)
428    
429          self.map_type = map_type          self.map_type = map_type
430          self.func = func          self.func = func

Legend:
Removed from v.410  
changed lines
  Added in v.436

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26