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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 449 - (hide annotations)
Tue Mar 4 10:33:08 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/classification.py
File MIME type: text/x-python
File size: 12359 byte(s)
(ClassGroupRange.GetProperties): Parameter 'value' should default to None.

1 jonathan 371 # Copyright (c) 2001 by Intevation GmbH
2     # Authors:
3     # Jonathan Coles <[email protected]>
4     #
5     # This program is free software under the GPL (>=v2)
6     # Read the file COPYING coming with Thuban for details.
7    
8     __version__ = "$Revision$"
9    
10     """
11     A Classification provides a mapping from an input value
12     to data. This mapping can be specified in two ways.
13     First, specific values can be associated with data.
14     Second, ranges can be associated with data such that if
15     an input value falls with a range that data is returned.
16 jonathan 388 If no mapping can be found then default data will
17 jonathan 371 be returned. Input values must be hashable objects
18    
19 jonathan 449 See the description of GetGroup() for more information
20 jonathan 371 on the mapping algorithm.
21     """
22    
23 jonathan 397 # fix for people using python2.1
24     from __future__ import nested_scopes
25    
26 jonathan 436 from types import *
27    
28 jonathan 388 from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
29     LAYER_VISIBILITY_CHANGED
30    
31 jan 374 from Thuban import _
32 jonathan 381 from Thuban.Model.color import Color
33 jan 374
34 jonathan 436 import Thuban.Model.layer
35    
36 jonathan 381 from wxPython.wx import *
37    
38 jonathan 371 # constants
39     RANGE_MIN = 0
40     RANGE_MAX = 1
41     RANGE_DATA = 2
42    
43     class Classification:
44    
45 jonathan 410 def __init__(self, layer = None, field = None):
46 jonathan 371 """Initialize a classification.
47    
48 jonathan 388 layer -- the layer object who owns this classification
49    
50 jonathan 371 field -- the name of the data table field that
51     is to be used to classify layer properties
52     """
53    
54 jonathan 436 self.layer = None # stop message sending
55    
56     self.SetDefaultGroup(ClassGroupDefault())
57     self.SetField(field)
58    
59 jonathan 388 self.layer = layer
60 jonathan 436 self.points = []
61 jonathan 378 self.ranges = []
62 jonathan 410 self.maps = []
63 jonathan 388
64 jonathan 428 def __iter__(self):
65 jonathan 436 return ClassIterator(self.DefaultGroup,
66     self.points,
67 jonathan 428 self.ranges,
68     self.maps)
69    
70     def __SendMessage(self, message):
71 jonathan 410 if self.layer is not None:
72     self.layer.changed(message, self.layer)
73    
74 jonathan 388 def SetField(self, field):
75 jonathan 371 """Set the name of the data table field to use.
76    
77 jonathan 388 field -- if None then all values map to the default data
78 jonathan 371 """
79    
80 jonathan 436 if field == "":
81     field = None
82    
83 jonathan 371 self.field = field
84 jonathan 428 self.__SendMessage(LAYER_LEGEND_CHANGED)
85 jonathan 371
86 jonathan 388 def GetField(self):
87     return self.field
88    
89 jonathan 410 def SetLayer(self, layer):
90 jonathan 436 assert(isinstance(layer, Thuban.Model.layer.Layer))
91 jonathan 410 self.layer = layer
92 jonathan 428 self.__SendMessage(LAYER_LEGEND_CHANGED)
93 jonathan 410
94     def GetLayer(self):
95     return layer.self
96    
97 jonathan 436 def SetDefaultGroup(self, group):
98     """Set the group to be used when a value can't be classified.
99 jonathan 371
100 jonathan 436 group -- group that the value maps to. See class description.
101 jonathan 371 """
102    
103 jonathan 436 assert(isinstance(group, ClassGroupDefault))
104     self.DefaultGroup = group
105 jonathan 371
106 jonathan 436 def GetDefaultGroup(self):
107     return self.DefaultGroup
108 jonathan 385
109 jonathan 428 #
110     # 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 jonathan 388 def SetDefaultFill(self, fill):
116 jonathan 436 assert(isinstance(fill, Color))
117     self.DefaultGroup.GetProperties().SetFill(fill)
118 jonathan 428 self.__SendMessage(LAYER_LEGEND_CHANGED)
119 jonathan 388
120     def GetDefaultFill(self):
121 jonathan 436 return self.DefaultGroup.GetProperties().GetFill()
122 jonathan 388
123     def SetDefaultStroke(self, stroke):
124 jonathan 436 assert(isinstance(stroke, Color))
125     self.DefaultGroup.GetProperties().SetStroke(stroke)
126 jonathan 428 self.__SendMessage(LAYER_LEGEND_CHANGED)
127 jonathan 388
128     def GetDefaultStroke(self):
129 jonathan 436 return self.DefaultGroup.GetProperties().GetStroke()
130 jonathan 388
131     def SetDefaultStrokeWidth(self, strokeWidth):
132 jonathan 436 assert(isinstance(strokeWidth, IntType))
133     self.DefaultGroup.GetProperties().SetStrokeWidth(strokeWidth)
134 jonathan 428 self.__SendMessage(LAYER_LEGEND_CHANGED)
135 jonathan 388
136     def GetDefaultStrokeWidth(self):
137 jonathan 436 return self.DefaultGroup.GetProperties().GetStrokeWidth()
138 jonathan 388
139 jonathan 436 def AddGroup(self, item):
140     assert(isinstance(item, ClassGroup))
141 jonathan 371
142 jonathan 436 if isinstance(item, ClassGroupDefault):
143     self.SetDefaultGroup(item)
144     elif isinstance(item, ClassGroupSingleton):
145     self.points.append(item)
146     elif isinstance(item, ClassGroupRange):
147 jonathan 410 self.ranges.append(item)
148 jonathan 436 elif isinstance(item, ClassGroupMap):
149 jonathan 410 self.maps.append(item)
150     else:
151 jonathan 436 raise ValueError(_("Unrecognized ClassGroup"))
152 jonathan 371
153 jonathan 428 self.__SendMessage(LAYER_LEGEND_CHANGED)
154 jonathan 371
155 jonathan 436 def GetGroup(self, value):
156 jonathan 388 """Return the associated data, or the default data.
157 jonathan 371
158     The following search technique is used:
159 jonathan 388 (1) if the field is None, return the default data
160 jonathan 371 (2) check if the value exists as a single value
161     (3) check if the value falls within a range. Ranges
162     are checked in the order they were added to
163     the classification.
164    
165 jonathan 388 value -- the value to classify. If there is no mapping,
166 jonathan 428 or value is None, return the default properties
167 jonathan 371 """
168    
169 jonathan 388 if self.field is not None and value is not None:
170 jonathan 371
171 jonathan 436 for p in self:
172     if p.Matches(value):
173 jonathan 410 return p
174 jonathan 436 # #
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 jonathan 371
182 jonathan 436 # #
183     # # check the ranges
184     # #
185     # for p in self.ranges:
186     # if p.InRange(value):
187     # return p
188 jonathan 371
189 jonathan 436 # #
190     # # check the maps
191     # #
192     # for p in self.maps:
193     # try:
194     # return p.Map(value)
195     # except: pass
196 jonathan 371
197 jonathan 436 return self.DefaultGroup
198    
199     def GetProperties(self, value):
200     return self.GetGroup(value).GetProperties()
201    
202 jonathan 381 def TreeInfo(self):
203     items = []
204 jonathan 378
205 jonathan 410 def build_color_item(text, color):
206     if color is Color.None:
207     return ("%s: %s" % (text, _("None")), None)
208 jonathan 381
209 jonathan 410 return ("%s: (%.3f, %.3f, %.3f)" %
210     (text, color.red, color.green, color.blue),
211     color)
212 jonathan 381
213 jonathan 436 def build_item(group, string):
214     label = group.GetLabel()
215 jonathan 410 if label == "":
216     label = string
217     else:
218     label += " (%s)" % string
219    
220 jonathan 436 props = group.GetProperties()
221 jonathan 381 i = []
222 jonathan 436 v = props.GetStroke()
223 jonathan 410 i.append(build_color_item(_("Stroke"), v))
224 jonathan 436 v = props.GetStrokeWidth()
225 jonathan 410 i.append(_("Stroke Width: %s") % v)
226 jonathan 436 v = props.GetFill()
227 jonathan 410 i.append(build_color_item(_("Fill"), v))
228     return (label, i)
229 jonathan 388
230 jonathan 428 for p in self:
231 jonathan 436 if isinstance(p, ClassGroupDefault):
232     items.append(build_item(self.DefaultGroup, _("'DEFAULT'")))
233     elif isinstance(p, ClassGroupSingleton):
234 jonathan 428 items.append(build_item(p, str(p.GetValue())))
235 jonathan 436 elif isinstance(p, ClassGroupRange):
236 jonathan 428 items.append(build_item(p, "%s - %s" %
237     (p.GetMin(), p.GetMax())))
238 jonathan 388
239 jonathan 428 # for p in self.points.values():
240     # items.append(build_item(p, str(p.GetValue())))
241 jonathan 381
242 jonathan 428 # for p in self.ranges:
243     # items.append(build_item(p, "%s - %s" % (p.GetMin(), p.GetMax())))
244 jonathan 388
245 jonathan 436 return (_("Classification"), items)
246 jonathan 381
247 jonathan 428 class ClassIterator:
248 jonathan 388
249 jonathan 428 def __init__(self, default, points, ranges, maps):
250     self.data = [default, points, ranges, maps]
251     self.data_iter = iter(self.data)
252     self.iter = None
253    
254     def __iter__(self):
255     return self
256    
257     def next(self):
258     if self.iter is None:
259     try:
260     self.data_item = self.data_iter.next()
261     self.iter = iter(self.data_item)
262     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 jonathan 436 class ClassGroupProperties:
272 jonathan 388
273 jonathan 436 def __init__(self, prop = None):
274 jonathan 410
275 jonathan 436 if prop is not None:
276     self.SetStroke(prop.GetStroke())
277     self.SetStrokeWidth(prop.GetStrokeWidth())
278     self.SetFill(prop.GetFill())
279 jonathan 410 else:
280     self.SetStroke(Color.None)
281     self.SetStrokeWidth(1)
282     self.SetFill(Color.None)
283    
284 jonathan 388 def GetStroke(self):
285     return self.stroke
286    
287     def SetStroke(self, stroke):
288 jonathan 410 assert(isinstance(stroke, Color))
289 jonathan 388 self.stroke = stroke
290    
291     def GetStrokeWidth(self):
292     return self.stroke_width
293    
294     def SetStrokeWidth(self, stroke_width):
295 jonathan 436 assert(isinstance(stroke_width, IntType))
296 jonathan 410 if (stroke_width < 1):
297     raise ValueError(_("stroke_width < 1"))
298    
299 jonathan 388 self.stroke_width = stroke_width
300    
301     def GetFill(self):
302     return self.fill
303    
304     def SetFill(self, fill):
305 jonathan 410 assert(isinstance(fill, Color))
306 jonathan 388 self.fill = fill
307    
308 jonathan 436
309     class ClassGroup:
310    
311     def __init__(self, label = ""):
312     self.label = label
313    
314 jonathan 388 def GetLabel(self):
315     return self.label
316    
317     def SetLabel(self, label):
318     self.label = label
319    
320 jonathan 436 def Matches(self, value):
321     """This needs to be implemented by all subclasses."""
322     pass
323    
324     def GetProperties(self, value):
325     """This needs to be implemented by all subclasses."""
326     pass
327    
328 jonathan 410
329 jonathan 436 class ClassGroupSingleton(ClassGroup):
330 jonathan 410
331 jonathan 436 def __init__(self, value = 0, prop = None, label = ""):
332     ClassGroup.__init__(self, label)
333 jonathan 410
334 jonathan 436 self.SetValue(value)
335     self.SetProperties(prop)
336 jonathan 410
337 jonathan 436 def __copy__(self):
338     return ClassGroupSingleton(self.value, self.prop, self.label)
339    
340 jonathan 410 def GetValue(self):
341     return self.value
342    
343     def SetValue(self, value):
344     self.value = value
345    
346 jonathan 436 def Matches(self, value):
347     return self.value == value
348 jonathan 410
349 jonathan 436 def GetProperties(self, value = None):
350     if value is None: return self.prop
351 jonathan 410
352 jonathan 436 if self.Matches(value):
353     return self.prop
354     else:
355     return None
356 jonathan 410
357 jonathan 436 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 jonathan 410 self.SetRange(min, max)
379 jonathan 436 self.SetProperties(prop)
380 jonathan 410
381 jonathan 436 def __copy__(self):
382     return ClassGroupRange(self.min, self.max, self.prop, self.label)
383    
384 jonathan 410 def GetMin(self):
385     return self.min
386    
387     def SetMin(self, min):
388     self.SetRange(min, self.max)
389    
390     def GetMax(self):
391     return self.max
392    
393     def SetMax(self, max):
394     self.SetRange(self.min, max)
395    
396     def SetRange(self, min, max):
397 jonathan 436 if min >= max:
398     raise ValueError(_("ClassGroupRange: %i(min) >= %i(max)!") %
399     (min, max))
400 jonathan 410 self.min = min
401     self.max = max
402    
403     def GetRange(self):
404     return (self.min, self.max)
405    
406 jonathan 436 def Matches(self, value):
407 jonathan 410 return self.min <= value < self.max
408    
409 jonathan 449 def GetProperties(self, value = None):
410 jonathan 436 if value is None: return self.prop
411 jonathan 410
412 jonathan 436 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 jonathan 410 FUNC_ID = "id"
425    
426 jonathan 436 def __init__(self, map_type = FUNC_ID, func = None, prop = None, label=""):
427     ClassGroup.__init__(self, prop)
428 jonathan 410
429     self.map_type = map_type
430     self.func = func
431    
432     if self.func is None:
433     self.func = func_id
434    
435     def Map(self, value):
436     return self.func(value)
437    
438     #
439     # built-in mappings
440     #
441     def func_id(value):
442     return value
443    

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26