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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 410 - (show annotations)
Wed Feb 19 16:51:12 2003 UTC (22 years ago) by jonathan
Original Path: trunk/thuban/Thuban/Model/classification.py
File MIME type: text/x-python
File size: 8995 byte(s)
(Classification):
        Uses the new ClassData* classes. Modification messages are
        passed up to the parent layer (if it exists).
(ClassData): New class to encapsulate the common data in each
        classification property.
(ClassDataDefault): Represents the Default class. data.
(ClassDataPoint): Represents a single class. data point
(ClassDataRange): Represents a class. range
(ClassDataMap): Represents a class. map (unused).

1 # 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 If no mapping can be found then default data will
17 be returned. Input values must be hashable objects
18
19 See the description of getProperties() for more information
20 on the mapping algorithm.
21 """
22
23 # fix for people using python2.1
24 from __future__ import nested_scopes
25
26 from messages import LAYER_PROJECTION_CHANGED, LAYER_LEGEND_CHANGED, \
27 LAYER_VISIBILITY_CHANGED
28
29 from Thuban import _
30 from Thuban.Model.color import Color
31
32 from wxPython.wx import *
33
34 # constants
35 RANGE_MIN = 0
36 RANGE_MAX = 1
37 RANGE_DATA = 2
38
39 class Classification:
40
41 def __init__(self, layer = None, field = None):
42 """Initialize a classification.
43
44 layer -- the layer object who owns this classification
45
46 field -- the name of the data table field that
47 is to be used to classify layer properties
48 """
49
50 self.layer = layer
51 self.points = {}
52 self.ranges = []
53 self.maps = []
54 self.DefaultData = ClassDataDefault()
55 self.field = field
56 #self.SetField(field)
57
58 def SendMessage(self, message):
59 if self.layer is not None:
60 self.layer.changed(message, self.layer)
61
62 def SetField(self, field):
63 """Set the name of the data table field to use.
64
65 field -- if None then all values map to the default data
66 """
67
68 self.field = field
69 self.SendMessage(LAYER_LEGEND_CHANGED)
70
71 def GetField(self):
72 return self.field
73
74 def SetLayer(self, layer):
75 self.layer = layer
76 self.SendMessage(LAYER_LEGEND_CHANGED)
77
78 def GetLayer(self):
79 return layer.self
80
81 def SetDefaultData(self, data):
82 """Set the data to be used when a value can't be classified.
83
84 data -- data that the value maps to. See class description.
85 """
86
87 self.DefaultData = data
88
89 def GetDefaultData(self):
90 return self.DefaultData
91
92 def SetDefaultFill(self, fill):
93 self.DefaultData.SetFill(fill)
94 self.SendMessage(LAYER_LEGEND_CHANGED)
95
96 def GetDefaultFill(self):
97 return self.DefaultData.GetFill()
98
99 def SetDefaultStroke(self, stroke):
100 self.DefaultData.SetStroke(stroke)
101 self.SendMessage(LAYER_LEGEND_CHANGED)
102
103 def GetDefaultStroke(self):
104 return self.DefaultData.GetStroke()
105
106 def SetDefaultStrokeWidth(self, strokeWidth):
107 self.DefaultData.SetStrokeWidth(strokeWidth)
108 self.SendMessage(LAYER_LEGEND_CHANGED)
109
110 def GetDefaultStrokeWidth(self):
111 return self.DefaultData.GetStrokeWidth()
112
113 def AddClassData(self, item):
114 type = item.GetType()
115
116 if type == ClassData.POINT:
117 self.points[item.GetValue()] = item
118 elif type == ClassData.RANGE:
119 self.ranges.append(item)
120 elif type == ClassData.MAP:
121 self.maps.append(item)
122 elif type == ClassData.DEFAULT:
123 self.DefaultData = item
124 else:
125 raise ValueError(_("Unrecognized ClassData type %s") % type)
126
127 self.SendMessage(LAYER_LEGEND_CHANGED)
128
129 def GetProperties(self, value):
130 """Return the associated data, or the default data.
131
132 The following search technique is used:
133 (1) if the field is None, return the default data
134 (2) check if the value exists as a single value
135 (3) check if the value falls within a range. Ranges
136 are checked in the order they were added to
137 the classification.
138
139 value -- the value to classify. If there is no mapping,
140 or value is None, return the default data
141 (which may be None)
142 """
143
144 if self.field is not None and value is not None:
145 #
146 # check the discrete values
147 #
148 if self.points.has_key(value):
149 return self.points[value]
150
151 #
152 # check the ranges
153 #
154 for p in self.ranges:
155 if p.InRange(value):
156 return p
157
158 #
159 # check the maps
160 #
161 for p in self.maps:
162 try:
163 return p.Map(value)
164 except: pass
165
166 return self.DefaultData
167
168 def TreeInfo(self):
169 items = []
170
171 def build_color_item(text, color):
172 if color is Color.None:
173 return ("%s: %s" % (text, _("None")), None)
174
175 return ("%s: (%.3f, %.3f, %.3f)" %
176 (text, color.red, color.green, color.blue),
177 color)
178
179 def build_item(data, string):
180 label = data.GetLabel()
181 if label == "":
182 label = string
183 else:
184 label += " (%s)" % string
185
186 i = []
187 v = data.GetStroke()
188 i.append(build_color_item(_("Stroke"), v))
189 v = data.GetStrokeWidth()
190 i.append(_("Stroke Width: %s") % v)
191 v = data.GetFill()
192 i.append(build_color_item(_("Fill"), v))
193 return (label, i)
194
195 items.append(build_item(self.DefaultData, _("'DEFAULT'")))
196
197 for p in self.points.values():
198 items.append(build_item(p, str(p.GetValue())))
199
200 for p in self.ranges:
201 items.append(build_item(p, "%s - %s" % (p.GetMin(), p.GetMax())))
202
203 return (_("Classifications"), items)
204
205
206 class ClassData:
207
208 INVALID = -1
209 DEFAULT = 0
210 POINT = 1
211 RANGE = 2
212 MAP = 3
213
214 def __init__(self, type = INVALID, classData = None):
215
216 if classData is not None:
217 self.SetStroke(classData.GetStroke())
218 self.SetStrokeWidth(classData.GetStrokeWidth())
219 self.SetFill(classData.GetFill())
220 else:
221 self.SetStroke(Color.None)
222 self.SetStrokeWidth(1)
223 self.SetFill(Color.None)
224
225 self.type = type
226 self.label = ""
227
228 def GetType(self):
229 return self.type
230
231 def GetStroke(self):
232 return self.stroke
233
234 def SetStroke(self, stroke):
235 assert(isinstance(stroke, Color))
236 self.stroke = stroke
237
238 def GetStrokeWidth(self):
239 return self.stroke_width
240
241 def SetStrokeWidth(self, stroke_width):
242 if (stroke_width < 1):
243 raise ValueError(_("stroke_width < 1"))
244
245 self.stroke_width = stroke_width
246
247 def GetFill(self):
248 return self.fill
249
250 def SetFill(self, fill):
251 assert(isinstance(fill, Color))
252 self.fill = fill
253
254 def GetLabel(self):
255 return self.label
256
257 def SetLabel(self, label):
258 self.label = label
259
260 class ClassDataDefault(ClassData):
261 def __init__(self, classData = None):
262 ClassData.__init__(self, ClassData.DEFAULT, classData)
263
264 class ClassDataPoint(ClassData):
265
266 def __init__(self, value = 0, classData = None):
267 ClassData.__init__(self, ClassData.POINT, classData)
268
269 self.value = value
270
271 def GetValue(self):
272 return self.value
273
274 def SetValue(self, value):
275 self.value = value
276
277 class ClassDataRange(ClassData):
278
279 def __init__(self, min = 0, max = 1, classData = None):
280 ClassData.__init__(self, ClassData.RANGE, classData)
281
282 if min >= max:
283 raise ValueError(_("ClassDataRange: %i(min) >= %i(max)!") %
284 (min, max))
285
286 self.SetRange(min, max)
287
288 def GetMin(self):
289 return self.min
290
291 def SetMin(self, min):
292 self.SetRange(min, self.max)
293
294 def GetMax(self):
295 return self.max
296
297 def SetMax(self, max):
298 self.SetRange(self.min, max)
299
300 def SetRange(self, min, max):
301 self.min = min
302 self.max = max
303 if min >= max:
304 raise ValueError(_("ClassDataRange: %i(min) >= %i(max)!") %
305 (min, max))
306
307 def GetRange(self):
308 return (self.min, self.max)
309
310 def InRange(self, value):
311 return self.min <= value < self.max
312
313 class ClassDataMap(ClassData):
314
315 FUNC_ID = "id"
316
317 def __init__(self, map_type = FUNC_ID, func = None, classData = None):
318 ClassData.__init__(self, ClassData.MAP, classData)
319
320 self.map_type = map_type
321 self.func = func
322
323 if self.func is None:
324 self.func = func_id
325
326 def Map(self, value):
327 return self.func(value)
328
329 #
330 # built-in mappings
331 #
332 def func_id(value):
333 return value
334

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26