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

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

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

revision 886 by jonathan, Fri May 9 16:36:56 2003 UTC revision 2441 by joey, Thu Dec 9 10:50:34 2004 UTC
# Line 1  Line 1 
1  # Copyright (c) 2003 by Intevation GmbH  # -*- encoding: iso-8859-1 -*-
2    #
3    # Copyright (c) 2003-2004 by Intevation GmbH
4  # Authors:  # Authors:
5  # Jonathan Coles <[email protected]>  # Jan-Oliver Wagner <[email protected]> (2004)
6    # Bernhard Herzog <[email protected]> (2003)
7    # Thomas K�ster <[email protected]> (2003)
8    # Jonathan Coles <[email protected]> (2003)
9  #  #
10  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
11  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
12    
13    """
14    Functions to generate Classifications
15    """
16    
17    __version__ = "$Revision$"
18    # $Source$
19    # $Id$
20    
21  import operator  import operator
22    
23  from color import Color  from color import Color, Transparent
24  from range import Range  from range import Range
25  from classification import Classification, ClassGroupSingleton, \  from classification import Classification, ClassGroupSingleton, \
26      ClassGroupRange, ClassGroupProperties      ClassGroupRange, ClassGroupProperties
27    
28  class ClassGenerator:  def generate_singletons(_list, ramp):
29        """Generate a new classification consisting solely of singletons.
30    
31      def GenSingletonsFromList(self, list, numGroups, ramp):      The resulting classification will consist of one group for each
32          """Generate a new classification consisting solely of singletons.      item in _list whose properties ramp between 'prop1' and 'prop2'.
33    
34          The resulting classification will consist of at most 'numGroups'      _list -- a list of values for each singleton
         groups whose group properties ramp between 'prop1' and 'prop2'. There  
         could be fewer groups if 'list' contains fewer that 'numGroups' items.  
35    
36          list -- any object that implements the iterator interface      ramp -- an object which implements the CustomRamp interface
37        """
38    
39          numGroups -- how many groups to generate. This can not be      clazz = Classification()
                      determined while the classification is being  
                      generated because the stepping values must  
                      be precalculated to ramp between prop1 and prop2.  
40    
41          prop1 -- initial group property values      i = 0
42        maxValue = float(len(_list) - 1)
43        if maxValue < 1: maxValue = 1
44    
45          prop2 -- final group property values      for value in _list:
46          """          prop = ramp.GetProperties(i / maxValue)
47            clazz.AppendGroup(ClassGroupSingleton(value, prop))
48            i += 1
49    
50          clazz = Classification()      return clazz
         if numGroups == 0: return clazz  
51    
52          ramp.SetNumGroups(numGroups)  def generate_uniform_distribution(min, max, numGroups, ramp, intStep = False):
53        """Generate a classification with numGroups range groups
54        each with the same interval.
55    
56          for value, prop in zip(list, ramp):      intStep -- force the calculated stepping to an integer.
57              clazz.AppendGroup(ClassGroupSingleton(value, prop))                 Useful if the values are integers but the
58                   number of groups specified doesn't evenly
59                   divide (max - min).
60        """
61    
62          return clazz      clazz = Classification()
63    
64      def GenSingletons(self, min, max, numGroups, ramp):      cur_min = min
65    
66          clazz = Classification()      end = "["
67        maxValue = float(numGroups - 1)
68        if maxValue < 1: maxValue = 1
69    
70          #step = int((max - min) / float(numGroups))      for i in range(1, numGroups + 1):
71    
72          if numGroups > 0:          prop = ramp.GetProperties(float(i-1) / maxValue)
73    
74              step = int((max - min + 1) / float(numGroups))          if intStep:
75              cur_value = min              cur_max = min + int(round((i * (max - min + 1)) / float(numGroups)))
76            else:
77                cur_max = min + (i * (max - min)) / float(numGroups)
78    
79              ramp.SetNumGroups(numGroups)          if i == numGroups:
80                cur_max = max
81                end = "]"
82    
83              for prop in ramp:          if cur_min == cur_max:
84                  clazz.AppendGroup(ClassGroupSingleton(cur_value), prop)              _range = Range(("[", cur_min, cur_max, "]"))
85                  cur_value += step          else:
86                _range = Range(("[", cur_min, cur_max, end))
87    
88          return clazz          clazz.AppendGroup(ClassGroupRange(_range, prop))
89    
90      def GenUnifromDistribution(self, min, max, numGroups,          cur_min = cur_max
                                ramp, intStep = False):  
         """Generate a classification with numGroups range groups  
         each with the same interval.  
91    
92          intStep -- force the calculated stepping to an integer.      return clazz
                    Useful if the values are integers but the  
                    number of groups specified doesn't evenly  
                    divide (max - min).  
         """  
93    
94          clazz = Classification()  def generate_quantiles(_list, percents, ramp, _range):
95          if numGroups == 0: return clazz      """Generates a Classification which has groups of ranges that
96        represent quantiles of _list at the percentages given in percents.
97        Only the values that fall within _range are considered.
98    
99          ramp.SetNumGroups(numGroups)      Returns a tuple (adjusted, Classification) where adjusted is
100        True if the Classification does not exactly represent the given
101        range, or if the Classification is empty.
102    
103          step = (max - min) / float(numGroups)      _list -- a sort list of values
104    
105          if intStep:      percents -- a sorted list of floats in the range 0.0-1.0 which
106              step = int(step)                  represent the upper bound of each quantile. the
107                    union of all percentiles should be the entire
108                    range from 0.0-1.0
109    
110          cur_min = min      ramp -- an object which implements the CustomRamp interface
         cur_max = cur_min + step  
111    
112          i = 0      _range -- a Range object
         end = "["  
         for prop in ramp:  
113    
114              if i == (numGroups - 1):      Raises a Value Error if 'percents' has fewer than two items, or
115                  cur_max = max      does not cover the entire range.
116                  end = "]"      """
117    
118        clazz = Classification()
119        quantiles = calculate_quantiles(_list, percents, _range)
120        adjusted = True
121    
122              # this check guards against rounding issues      if quantiles is not None:
             if cur_min != cur_max:  
                 range = Range("[" + str(float(cur_min)) + ";" +  
                                     str(float(cur_max)) + end)  
                 clazz.AppendGroup(ClassGroupRange(range, None, prop))  
123    
124              cur_min = cur_max          numGroups = len(quantiles[3])
             cur_max += step  
             i += 1  
125    
126          return clazz          if numGroups != 0:
127    
128                adjusted = quantiles[0]
129    
130      def GenQuantiles(self, list, percents, ramp, _range):              start, min, endMax, right = _range.GetRange()
         clazz = Classification()  
         quantiles = self.CalculateQuantiles(list, percents, _range)  
         numGroups = len(quantiles[1])  
         if numGroups == 0: return clazz  
131    
132          ramp.SetNumGroups(numGroups)              oldp = 0
133                i = 1
134                end = "]"
135    
136          left, min, max, right = _range.GetRange()              maxValue = float(numGroups - 1)
137                if maxValue < 1: maxValue = 1
138                for (q, p) in quantiles[3]:
139    
140          start = "["                  prop = ramp.GetProperties(float(i-1) / maxValue)
         oldp = 0  
         for (q, p), prop in zip(quantiles[1], ramp):  
             max = list[q]  
             group = ClassGroupRange(Range(start + str(min) + ";" +  
                                                   str(max) + "]"),  
                                     None, prop)  
141    
142              group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),                  if i == numGroups:
143                                              round(p*100, 2)))                      max = endMax
144              oldp = p                      end = right
145              start = "]"                  else:
146              min = max                      max = _list[q]
             clazz.AppendGroup(group)  
147    
148          return (quantiles[0], clazz)                  group = ClassGroupRange(Range((start, min, max, end)), prop)
149    
150      def CalculateQuantiles(self, list, percents, _range):                  group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),
151          """Calculate quantiles for the given list of percents from the                                                  round(p*100, 2)))
152          sorted list of values that are in range.                  oldp = p
153                                                                                                    start = "]"
154          percents is a sorted list of floats in the range 0.0-1.0                  min = max
155                    clazz.AppendGroup(group)
156                    i += 1
157    
158          This may not actually generate numGroups quantiles if      return (adjusted, clazz)
         many of the values that fall on quantile borders are the same.  
159    
         Returns a tuple of the form: (adjusted, [quantile_list])  
160    
161          where adjusted is true if the the quantile percentages differ from  def calculate_quantiles(_list, percents, _range):
162          those supplied, and quantile_list is a list of tuples of the form:      """Calculate quantiles for the given _list of percents from the
163              (list_index, quantile_percentage)      sorted list of values that are in range.
         """  
       
         quantiles = []  
                                                                                   
         adjusted = False  
         if len(percents) != 0:  
                                                                                 
             #print "list:", list  
             #print "percents:", percents  
             #print "numGroups:", numGroups  
       
             #  
             # find what part of the list range covers  
             #  
             minIndex = -1  
             maxIndex = -2  
             for i in xrange(0, len(list), 1):  
                 if operator.contains(_range, list[i]):  
                     minIndex = i  
                     break  
   
             for i in xrange(len(list)-1, -1, -1):  
                 if operator.contains(_range, list[i]):  
                     maxIndex = i  
                     break;  
   
             numValues = maxIndex - minIndex + 1  
             #print "minIndex:", minIndex, "maxIndex:", maxIndex  
             if minIndex <= maxIndex:  
   
                 #  
                 # build a list of unique indices into list of where each  
                 # quantile should be  
                 #  
                 quantiles = {}  
                 for p in percents:  
                     index = min(minIndex + int(p*numValues)-1, maxIndex)  
   
                     adjusted = adjusted \  
                         or quantiles.has_key(index) \  
                         or ((index+1) / float(numValues)) != p  
   
                     quantiles[index] = 0  
   
                 quantiles = quantiles.keys()  
                 quantiles.sort()  
   
                 #print "quantiles:", quantiles  
       
                 #  
                 # the current quantile index must be strictly greater than  
                 # the lowerBound  
                 #  
                 lowerBound = minIndex - 1  
       
                 for qindex in range(len(quantiles)):  
                     if lowerBound >= maxIndex:  
                         # discard higher quantiles  
                         quantiles = quantiles[:qindex]  
                         break  
       
                     # lowerBound + 1 is always a valid index  
       
       
                     #  
                     # bump up the current quantile index to be a usable index  
                     # if it currently falls below the lowerBound  
                     #  
                     if quantiles[qindex] <= lowerBound:  
                         quantiles[qindex] = min(lowerBound + 1, maxIndex)  
           
                     listIndex = quantiles[qindex]  
                     value = list[quantiles[qindex]]  
       
                     #print "-----------------------------------"  
                     #print "listIndex:", listIndex  
                     #print "value:", value  
       
                     #  
                     # look for similar values around the quantile index  
                     #  
                   
                     #print "lowerBound:", lowerBound  
                     lindex = listIndex - 1  
                     lcount = 0  
                     while lindex > lowerBound:  
                         if value != list[lindex]: break  
                         lcount += 1  
                         lindex -= 1  
       
                     rindex = listIndex + 1  
                     rcount = 0  
                     while rindex < maxIndex + 1:  
                         if value != list[rindex]: break  
                         rcount += 1  
                         rindex += 1  
       
                     #print lcount, "(lcount)", rcount, "(rcount)"  
                     #print lindex, "(lindex)", rindex, "(rindex)"  
       
                     #  
                     # adjust the current quantile index based on how many  
                     # numbers in the list are the same as the current value  
                     #  
                     newIndex = listIndex  
                     if lcount == rcount:  
                         if lcount != 0:  
                             #  
                             # there are an equal number of numbers to the left  
                             # and right, try going to the left first unless  
                             # doing so creates an empty quantile.  
                             #  
                             if lindex != lowerBound:  
                                 newIndex = lindex  
                                 #quantiles[qindex] = lindex  
                             else:  
                                 newIndex = rindex - 1  
                                 #quantiles[qindex] = rindex - 1  
       
                     elif lcount < rcount:  
                         # there are fewer items to the left, so  
                         # try going to the left first unless  
                         # doing so creates an empty quantile.  
                         if lindex != lowerBound:  
                             newIndex = lindex  
                             #quantiles[qindex] = lindex  
                         else:  
                             newIndex = rindex - 1  
                             #quantiles[qindex] = rindex - 1  
       
                     elif rcount < lcount:  
                         # there are fewer items to the right, so go to the right  
                         #quantiles[qindex] = rindex - 1  
                         newIndex = rindex - 1  
       
                     quantiles[qindex] = newIndex  
                     lowerBound = quantiles[qindex]  
       
                     #print "quantiles:", quantiles  
                     #print "lowerBound:", lowerBound  
           
                 #print "================================="  
                 #print "quantiles:", quantiles  
                 #print "qindex:", qindex  
       
         return (adjusted, [(q, (q+1) / float(numValues)) for q in quantiles])  
164    
165  CLR  = 0      This may not actually generate len(percents) quantiles if
166  STEP = 1      many of the values that fall on quantile borders are the same.
 class CustomRamp:  
167    
168      def __init__(self, prop1, prop2):      Returns a tuple of the form:
169          self.prop1 = prop1          (adjusted, minIndex, maxIndex, [quantile_list])
         self.prop2 = prop2  
170    
171          self.count = 0      where adjusted is True if the the quantile percentages differ from
172        those supplied, minIndex is the index into _list where the
173        minimum value used is located, maxIndex is the index into _list
174        where the maximum value used is located, and quantile_list is a
175        list of tuples of the form: (list_index, quantile_percentage)
176    
177      def __iter__(self):      Returns None, if no quantiles could be generated based on the
178          return self      given range or input list.
179    
180      def GetRamp(self):      _list -- a sort list of values
         return self  
181    
182      def SetNumGroups(self, num):      percents -- a sorted list of floats in the range 0.0-1.0 which
183                    represent the upper bound of each quantile. the
184                    union of all percentiles should be the entire
185                    range from 0.0-1.0
186    
187          if num <= 0:      _range -- a Range object
             return False  
188    
189          self.count = int(num)      Raises a Value Error if 'percents' has fewer than two items, or
190          num = float(num)      does not cover the entire range.
191        """
192    
193          prop1 = self.prop1      quantiles = []
194          prop2 = self.prop2      adjusted = False
195    
196          clr = prop1.GetLineColor()      if len(percents) <= 1:
197          lineColor2 = prop2.GetLineColor()          raise ValueError("percents parameter must have more than one item")
           
         self.noLine = clr is not Color.Transparent \  
                         and lineColor2 is not Color.Transparent  
198    
199        if percents[-1] != 1.0:
200            raise ValueError("percents does not cover the entire range")
201    
202          self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),      #
203                                              prop2.GetLineColor(),      # find what part of the _list range covers
204                                              num)      #
205        minIndex = -1
206        maxIndex = -2
207        for i in xrange(0, len(_list), 1):
208            if operator.contains(_range, _list[i]):
209                minIndex = i
210                break
211    
212          self.fillInfo = self.__GetColorInfo(prop1.GetFill(),      for i in xrange(len(_list)-1, -1, -1):
213                                              prop2.GetFill(),          if operator.contains(_range, _list[i]):
214                                              num)              maxIndex = i
215                break
216    
217          self.lineWidth = prop1.GetLineWidth()      numValues = maxIndex - minIndex + 1
         self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num  
218    
219          return True      if numValues > 0:
220    
221      def next(self):          #
222          if self.count == 0:          # build a list of unique indices into list of where each
223              raise StopIteration          # quantile *should* be. set adjusted if the resulting
224            # indices are different
225            #
226            quantiles = {}
227            for p in percents:
228                index = min(minIndex + int(p*numValues)-1, maxIndex)
229    
230          prop = ClassGroupProperties()              adjusted = adjusted \
231                    or quantiles.has_key(index) \
232                    or ((index - minIndex + 1) / float(numValues)) != p
233    
234          if self.lineInfo is None:              quantiles[index] = 0
             prop.SetLineColor(Color.Transparent)  
         else:  
             prop.SetLineColor(Color(self.lineInfo[CLR][0] / 255,  
                                     self.lineInfo[CLR][1] / 255,  
                                     self.lineInfo[CLR][2] / 255))  
   
             self.lineInfo[CLR][0] += self.lineInfo[STEP][0]  
             self.lineInfo[CLR][1] += self.lineInfo[STEP][1]  
             self.lineInfo[CLR][2] += self.lineInfo[STEP][2]  
235    
236          if self.fillInfo is None:          quantiles = quantiles.keys()
237              prop.SetFill(Color.Transparent)          quantiles.sort()
         else:  
             prop.SetFill(Color(self.fillInfo[CLR][0] / 255,  
                             self.fillInfo[CLR][1] / 255,  
                             self.fillInfo[CLR][2] / 255))  
238    
239              self.fillInfo[CLR][0] += self.fillInfo[STEP][0]          #
240              self.fillInfo[CLR][1] += self.fillInfo[STEP][1]          # the current quantile index must be strictly greater than
241              self.fillInfo[CLR][2] += self.fillInfo[STEP][2]          # the lowerBound
242            #
243            lowerBound = minIndex - 1
244    
245            for qindex in xrange(len(quantiles)):
246                if lowerBound >= maxIndex:
247                    # discard higher quantiles
248                    quantiles = quantiles[:qindex]
249                    break
250    
251          prop.SetLineWidth(int(self.lineWidth))              # lowerBound + 1 is always a valid index
         self.lineWidth        += self.lineWidthStep  
252    
253          self.count -= 1              #
254                # bump up the current quantile index to be a usable index
255                # if it currently falls below the lowerBound
256                #
257                if quantiles[qindex] <= lowerBound:
258                    quantiles[qindex] = lowerBound + 1
259    
260          return prop              listIndex = quantiles[qindex]
261                value = _list[listIndex]
262    
263      def __GetColorInfo(self, color1, color2, numGroups):              #
264                # look for similar values around the quantile index
265                #
266                lindex = listIndex - 1
267                while lindex > lowerBound and value == _list[lindex]:
268                    lindex -= 1
269                lcount = (listIndex - 1) - lindex
270    
271                rindex = listIndex + 1
272                while rindex < maxIndex + 1 and value == _list[rindex]:
273                    rindex += 1
274                rcount = (listIndex + 1) - rindex
275    
         if color1 is Color.Transparent and color2 is Color.Transparent:  
276              #              #
277              # returning early              # adjust the current quantile index based on how many
278                # numbers in the _list are the same as the current value
279              #              #
280              return None              newIndex = listIndex
281          elif color1 is not Color.Transparent and color2 is Color.Transparent:              if lcount == rcount:
282              color = [color1.red   * 255,                  if lcount != 0:
283                       color1.green * 255,                      #
284                       color1.blue  * 255]                      # there are an equal number of numbers to the left
285              step = (0, 0, 0)                      # and right, try going to the left first unless
286          elif color1 is Color.Transparent and color2 is not Color.Transparent:                      # doing so creates an empty quantile.
287              color = [color2.red   * 255,                      #
288                       color2.green * 255,                      if lindex != lowerBound:
289                       color2.blue  * 255]                          newIndex = lindex
290              step = (0, 0, 0)                      else:
291          else:                          newIndex = rindex - 1
292              color = [color1.red   * 255,  
293                       color1.green * 255,              elif lcount < rcount:
294                       color1.blue  * 255]                  # there are fewer items to the left, so
295              step = ((color2.red   * 255 - color1.red   * 255)   / numGroups,                  # try going to the left first unless
296                      (color2.green * 255 - color1.green * 255) / numGroups,                  # doing so creates an empty quantile.
297                      (color2.blue  * 255 - color1.blue  * 255)  / numGroups)                  if lindex != lowerBound:
298                        newIndex = lindex
299                    else:
300                        newIndex = rindex - 1
301    
302                elif rcount < lcount:
303                    # there are fewer items to the right, so go to the right
304                    newIndex = rindex - 1
305    
306                adjusted = adjusted or newIndex != listIndex
307    
308                quantiles[qindex] = newIndex
309                lowerBound = quantiles[qindex]
310    
311        if len(quantiles) == 0:
312            return None
313        else:
314            return (adjusted, minIndex, maxIndex,
315                    [(q, (q - minIndex+1) / float(numValues)) \
316                     for q in quantiles])
317    
318    class CustomRamp:
319    
320        def __init__(self, prop1, prop2):
321            """Create a ramp between prop1 and prop2."""
322            self.prop1 = prop1
323            self.prop2 = prop2
324    
325        def GetRamp(self):
326            """Return this ramp."""
327            return self
328    
329        def GetProperties(self, index):
330            """Return a ClassGroupProperties object whose properties
331            represent a point at 'index' between prop1 and prop2 in
332            the constructor.
333    
334            index -- a value such that 0 <= index <= 1
335            """
336    
337            if not (0 <= index <= 1):
338                raise ValueError(_("invalid index"))
339    
340          return (color, step)          newProps = ClassGroupProperties()
341    
342            self.__SetProperty(self.prop1.GetLineColor(),
343                               self.prop2.GetLineColor(),
344                               index, newProps.SetLineColor)
345            self.__SetProperty(self.prop1.GetFill(), self.prop2.GetFill(),
346                               index, newProps.SetFill)
347    
348            w = (self.prop2.GetLineWidth() - self.prop1.GetLineWidth()) \
349                * index \
350                + self.prop1.GetLineWidth()
351            newProps.SetLineWidth(int(round(w)))
352    
353            s = (self.prop2.GetSize() - self.prop1.GetSize()) \
354                * index \
355                + self.prop1.GetSize()
356            newProps.SetSize(int(round(s)))
357    
358            return newProps
359    
360        def __SetProperty(self, color1, color2, index, setf):
361            """Use setf to set the appropriate property for the point
362            index percent between color1 and color2. setf is a function
363            to call that accepts a Color object or Transparent.
364            """
365    
366            if color1 is Transparent and color2 is Transparent:
367                setf(Transparent)
368            elif color1 is Transparent:
369                setf(Color(
370                     color2.red   * index,
371                     color2.green * index,
372                     color2.blue  * index))
373            elif color2 is Transparent:
374                setf(Color(
375                     color1.red   * index,
376                     color1.green * index,
377                     color1.blue  * index))
378            else:
379                setf(Color(
380                    (color2.red   - color1.red)   * index + color1.red,
381                    (color2.green - color1.green) * index + color1.green,
382                    (color2.blue  - color1.blue)  * index + color1.blue))
383    
384  class MonochromaticRamp(CustomRamp):  class MonochromaticRamp(CustomRamp):
385        """Helper class to make ramps between two colors."""
386    
387      def __init__(self, start, end):      def __init__(self, start, end):
388            """Create a Monochromatic Ramp.
389    
390            start -- starting Color
391    
392            end -- ending Color
393            """
394          sp = ClassGroupProperties()          sp = ClassGroupProperties()
395          sp.SetLineColor(start)          sp.SetLineColor(start)
396          sp.SetFill(start)          sp.SetFill(start)
# Line 419  class MonochromaticRamp(CustomRamp): Line 401  class MonochromaticRamp(CustomRamp):
401    
402          CustomRamp.__init__(self, sp, ep)          CustomRamp.__init__(self, sp, ep)
403    
404  class GreyRamp(MonochromaticRamp):  grey_ramp         = MonochromaticRamp(Color(1, 1, 1),  Color(0, 0, 0))
405      def __init__(self):  red_ramp          = MonochromaticRamp(Color(1, 1, 1),  Color(.8, 0, 0))
406          MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))  green_ramp        = MonochromaticRamp(Color(1, 1, 1),  Color(0, .8, 0))
407    blue_ramp         = MonochromaticRamp(Color(1, 1, 1),  Color(0, 0, .8))
408  class RedRamp(MonochromaticRamp):  green_to_red_ramp = MonochromaticRamp(Color(0, .8, 0), Color(1, 0, 0))
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))  
   
 class GreenRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))  
   
 class BlueRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))  
   
 class GreenToRedRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(0, .8, 0), Color(1, 0, 0))  
409    
410  class HotToColdRamp:  class HotToColdRamp:
411        """A ramp that generates properties with colors ranging from
412        'hot' colors (e.g. red, orange) to 'cold' colors (e.g. green, blue)
413        """
414    
     def __iter__(self):  
         return self  
           
415      def GetRamp(self):      def GetRamp(self):
416            """Return this ramp."""
417          return self          return self
418    
419      def SetNumGroups(self, num):      def GetProperties(self, index):
420          if num < 0:          """Return a ClassGroupProperties object whose properties
421              return False          represent a point at 'index' between "hot" and "cold".
422    
423          self.num = float(num)          index -- a value such that 0 <= index <= 1
424          self.index = 0          """
   
         return True  
   
     def next(self):  
         if self.index == self.num:  
             raise StopIteration  
425    
426          clr = [1.0, 1.0, 1.0]          clr = [1.0, 1.0, 1.0]
427    
428          if self.index < (.25 * self.num):          if index < .25:
429              clr[0] = 0              clr[0] = 0
430              clr[1] = 4 * self.index / self.num              clr[1] = 4 * index
431          elif self.index < (.5 * self.num):          elif index < .5:
432              clr[0] = 0              clr[0] = 0
433              clr[2] = 1 + 4 * (.25 * self.num - self.index) / self.num              clr[2] = 1 + 4 * (.25 - index)
434          elif self.index < (.75 * self.num):          elif index < .75:
435              clr[0] = 4 * (self.index - .5 * self.num) / self.num              clr[0] = 4 * (index - .5)
436              clr[2] = 0              clr[2] = 0
437          else:          else:
438              clr[1] = 1 + 4 * (.75 * self.num - self.index) / self.num              clr[1] = 1 + 4 * (.75 - index)
439              clr[2] = 0              clr[2] = 0
440    
         self.index += 1  
   
441          prop = ClassGroupProperties()          prop = ClassGroupProperties()
442          prop.SetLineColor(Color(clr[0], clr[1], clr[2]))          prop.SetLineColor(Color(clr[0], clr[1], clr[2]))
443          prop.SetFill(Color(clr[0], clr[1], clr[2]))          prop.SetFill(Color(clr[0], clr[1], clr[2]))
444    
445          return prop          return prop
446    
447  #class Colors16Ramp:  class FixedRamp:
448  #      """FixedRamp allows particular properties of a ramp to be
449      #def __iter__(self):      held constant over the ramp.
450          #return self      """
451  #  
452      #def GetRamp(self):      def __init__(self, ramp, fixes):
453          #return self          """
454  #          ramp -- a source ramp to get the default properties
455      #def SetNumGroups(self, num):  
456          #if num < 0:          fixes -- a tuple (lineColor, lineWidth, fillColor) such that
457              #return False               if any item is not None, the appropriate property will
458  #               be fixed to that item value.
459          #self.index = 0          """
460  #  
461          #return True          self.fixes = fixes
462            self.ramp = ramp
463    
464        def GetRamp(self):
465            """Return this ramp."""
466            return self
467    
468        def GetProperties(self, index):
469            """Return a ClassGroupProperties object whose properties
470            represent a point at 'index' between the properties in
471            the ramp that initialized this FixedRamp.
472    
473            index -- a value such that 0 <= index <= 1
474            """
475    
476            props = self.ramp.GetProperties(index)
477            if self.fixes[0] is not None: props.SetLineColor(self.fixes[0])
478            if self.fixes[1] is not None: props.SetLineWidth(self.fixes[1])
479            if self.fixes[2] is not None: props.SetFill(self.fixes[2])
480    
481            return props

Legend:
Removed from v.886  
changed lines
  Added in v.2441

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26