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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26