/[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 986 by tkoester, Thu May 22 16:41:10 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  ClassGenerator  Functions to generate Classifications
13  """  """
14    
15  __version__ = "$Revision$"  __version__ = "$Revision$"
# Line 15  __version__ = "$Revision$" Line 18  __version__ = "$Revision$"
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          ramp -- an object which implements the CustomRamp interface      i = 0
40          """      maxValue = float(len(_list) - 1)
41        if maxValue < 1: maxValue = 1
42    
43          clazz = Classification()      for value in _list:
44          if numGroups == 0: return clazz          prop = ramp.GetProperties(i / maxValue)
45            clazz.AppendGroup(ClassGroupSingleton(value, prop))
46            i += 1
47    
48          ramp.SetNumGroups(numGroups)      return clazz
49    
50          for value, prop in zip(_list, ramp):  def generate_uniform_distribution(min, max, numGroups, ramp, intStep = False):
51              clazz.AppendGroup(ClassGroupSingleton(value, prop))      """Generate a classification with numGroups range groups
52        each with the same interval.
53    
54          return clazz      intStep -- force the calculated stepping to an integer.
55                   Useful if the values are integers but the
56                   number of groups specified doesn't evenly
57                   divide (max - min).
58        """
59    
60      def GenSingletons(self, min, max, numGroups, ramp):      clazz = Classification()
61    
62          clazz = Classification()      cur_min = min
63    
64          #step = int((max - min) / float(numGroups))      end = "["
65        maxValue = float(numGroups - 1)
66        if maxValue < 1: maxValue = 1
67    
68          if numGroups > 0:      for i in range(1, numGroups + 1):
69    
70              step = int((max - min + 1) / float(numGroups))          prop = ramp.GetProperties(float(i-1) / maxValue)
             cur_value = min  
71    
72              ramp.SetNumGroups(numGroups)          if intStep:
73                cur_max = min + int(round((i * (max - min + 1)) / float(numGroups)))
74            else:
75                cur_max = min + (i * (max - min)) / float(numGroups)
76    
77              for prop in ramp:          if i == numGroups:
78                  clazz.AppendGroup(ClassGroupSingleton(cur_value), prop)              cur_max = max
79                  cur_value += step              end = "]"
80    
81          return clazz          if cur_min == cur_max:
82                _range = Range(("[", cur_min, cur_max, "]"))
83            else:
84                _range = Range(("[", cur_min, cur_max, end))
85    
86      def GenUniformDistribution(self, min, max, numGroups,          clazz.AppendGroup(ClassGroupRange(_range, prop))
                                ramp, intStep = False):  
         """Generate a classification with numGroups range groups  
         each with the same interval.  
87    
88          intStep -- force the calculated stepping to an integer.          cur_min = cur_max
                    Useful if the values are integers but the  
                    number of groups specified doesn't evenly  
                    divide (max - min).  
         """  
89    
90          clazz = Classification()      return clazz
         if numGroups == 0: return clazz  
91    
92          ramp.SetNumGroups(numGroups)  def generate_quantiles(_list, percents, ramp, _range):
93        """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          step = (max - min) / float(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          if intStep:      _list -- a sort list of values
             step = int(step)  
102    
103          cur_min = min      percents -- a sorted list of floats in the range 0.0-1.0 which
104          cur_max = cur_min + 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          i = 0      ramp -- an object which implements the CustomRamp interface
         end = "["  
         for prop in ramp:  
109    
110              if i == (numGroups - 1):      _range -- a Range object
                 cur_max = max  
                 end = "]"  
111    
112        Raises a Value Error if 'percents' has fewer than two items, or
113        does not cover the entire range.
114        """
115    
116              # this check guards against rounding issues      clazz = Classification()
117              if cur_min != cur_max:      quantiles = calculate_quantiles(_list, percents, _range)
118                  range = Range(("[", cur_min, cur_max, end))      adjusted = True
                 clazz.AppendGroup(ClassGroupRange(range, None, prop))  
119    
120              cur_min = cur_max      if quantiles is not None:
             cur_max += step  
             i += 1  
121    
122          return clazz          numGroups = len(quantiles[3])
123    
124            if numGroups != 0:
125    
126      def GenQuantiles(self, _list, percents, ramp, _range):              adjusted = quantiles[0]
         """Generates a Classification which has groups of ranges that  
         represent quantiles of _list at the percentages given in percents.  
         Only the values that fall within _range are considered.  
127    
128          Returns a tuple (adjusted, Classification) where adjusted is              start, min, endMax, right = _range.GetRange()
         True if the Classification does not exactly represent the given  
         range, or if the Classification is empty.  
129    
130          _list -- a sort list of values              oldp = 0
131                i = 1
132                end = "]"
133    
134          percents -- a sorted list of floats in the range 0.0-1.0 which              maxValue = float(numGroups - 1)
135                      represent the upper bound of each quantile              if maxValue < 1: maxValue = 1
136                for (q, p) in quantiles[3]:
137    
138          ramp -- an object which implements the CustomRamp interface                  prop = ramp.GetProperties(float(i-1) / maxValue)
139    
140          _range -- a Range object                  if i == numGroups:
141          """                      max = endMax
142                        end = right
143                    else:
144                        max = _list[q]
145    
146          clazz = Classification()                  group = ClassGroupRange(Range((start, min, max, end)), prop)
         quantiles = self.CalculateQuantiles(_list, percents, _range)  
         adjusted = True  
147    
148          if quantiles is not None:                  group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),
149                                                    round(p*100, 2)))
150                    oldp = p
151                    start = "]"
152                    min = max
153                    clazz.AppendGroup(group)
154                    i += 1
155    
156              numGroups = len(quantiles[3])      return (adjusted, clazz)
157    
             if numGroups != 0:  
158    
159                  adjusted = quantiles[0]  def calculate_quantiles(_list, percents, _range):
160        """Calculate quantiles for the given _list of percents from the
161        sorted list of values that are in range.
162    
163                  ramp.SetNumGroups(numGroups)      This may not actually generate len(percents) quantiles if
164        many of the values that fall on quantile borders are the same.
165    
166                  start, min, endMax, right = _range.GetRange()      Returns a tuple of the form:
167            (adjusted, minIndex, maxIndex, [quantile_list])
168    
169                  oldp = 0      where adjusted is True if the the quantile percentages differ from
170                  i = 1      those supplied, minIndex is the index into _list where the
171                  end = "]"      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                  for (q, p), prop in zip(quantiles[3], ramp):      Returns None, if no quantiles could be generated based on the
176                      if i == numGroups:      given range or input list.
                         max = endMax  
                         end = right  
                     else:  
                         max = _list[q]  
177    
178                      group = ClassGroupRange(Range((start, min, max, end)),      _list -- a sort list of values
                                             None, prop)  
           
                     group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),  
                                                     round(p*100, 2)))  
                     oldp = p  
                     start = "]"  
                     min = max  
                     clazz.AppendGroup(group)  
                     i += 1  
   
         return (adjusted, clazz)  
   
     def CalculateQuantiles(self, _list, percents, _range):  
         """Calculate quantiles for the given _list of percents from the  
         sorted list of values that are in range.  
                                                                                   
         This may not actually generate len(percents) quantiles if  
         many of the values that fall on quantile borders are the same.  
   
         Returns a tuple of the form:  
             (adjusted, minIndex, maxIndex, [quantile_list])  
   
         where adjusted is True if the the quantile percentages differ from  
         those supplied, minIndex is the index into _list where the  
         minimum value used is located, maxIndex is the index into _list  
         where the maximum value used is located, and quantile_list is a  
         list of tuples of the form: (list_index, quantile_percentage)  
   
         Returns None, if no quantiles could be generated based on the  
         given range or input list.  
179    
180          _list -- a sort list of values      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          percents -- a sorted list of floats in the range 0.0-1.0 which      _range -- a Range object
                     represent the upper bound of each quantile  
186    
187          _range -- a Range object      Raises a Value Error if 'percents' has fewer than two items, or
188          """      does not cover the entire range.
189            """
         quantiles = []  
         adjusted = False  
190    
191          if len(percents) != 0:      quantiles = []
192                                                                                      adjusted = False
             #  
             # 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  
   
             if numValues > 0:  
   
                 #  
                 # build a list of unique indices into list of where each  
                 # quantile *should* be. set adjusted if the resulting  
                 # indices are different  
                 #  
                 quantiles = {}  
                 for p in percents:  
                     index = min(minIndex + int(p*numValues)-1, maxIndex)  
   
                     adjusted = adjusted \  
                         or quantiles.has_key(index) \  
                         or ((index - minIndex + 1) / float(numValues)) != p  
   
                     quantiles[index] = 0  
   
                 quantiles = quantiles.keys()  
                 quantiles.sort()  
   
                 #  
                 # the current quantile index must be strictly greater than  
                 # the lowerBound  
                 #  
                 lowerBound = minIndex - 1  
       
                 for qindex in xrange(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] = lowerBound + 1  
           
                     listIndex = quantiles[qindex]  
                     value = _list[listIndex]  
       
                     #  
                     # look for similar values around the quantile index  
                     #  
                     lindex = listIndex - 1  
                     while lindex > lowerBound and value == _list[lindex]:  
                         lindex -= 1  
                     lcount = (listIndex - 1) - lindex  
       
                     rindex = listIndex + 1  
                     while rindex < maxIndex + 1 and value == _list[rindex]:  
                         rindex += 1  
                     rcount = (listIndex + 1) - 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  
                             else:  
                                 newIndex = 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  
                         else:  
                             newIndex = rindex - 1  
       
                     elif rcount < lcount:  
                         # there are fewer items to the right, so go to the right  
                         newIndex = rindex - 1  
       
                     adjusted = adjusted or newIndex != listIndex  
193    
194                      quantiles[qindex] = newIndex      if len(percents) <= 1:
195                      lowerBound = quantiles[qindex]          raise ValueError("percents parameter must have more than one item")
       
         #  
         # since quantiles is only set if the code is at least a little  
         # successful, an empty list will be generated in the case that  
         # we fail to get to the real body of the algorithm  
         #  
         if len(quantiles) == 0:  
             return None  
         else:  
             return (adjusted, minIndex, maxIndex,  
                     [(q, (q - minIndex+1) / float(numValues)) \  
                      for q in quantiles])  
196    
197  CLR  = 0      if percents[-1] != 1.0:
198  STEP = 1          raise ValueError("percents does not cover the entire range")
 class CustomRamp:  
199    
200      def __init__(self, prop1, prop2):      #
201          self.prop1 = prop1      # find what part of the _list range covers
202          self.prop2 = prop2      #
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.count = 0      for i in xrange(len(_list)-1, -1, -1):
211            if operator.contains(_range, _list[i]):
212                maxIndex = i
213                break
214    
215      def __iter__(self):      numValues = maxIndex - minIndex + 1
         return self  
216    
217      def GetRamp(self):      if numValues > 0:
         return self  
218    
219      def SetNumGroups(self, num):          #
220            # build a list of unique indices into list of where each
221            # 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                adjusted = adjusted \
229                    or quantiles.has_key(index) \
230                    or ((index - minIndex + 1) / float(numValues)) != p
231    
232          if num <= 0:              quantiles[index] = 0
             return False  
233    
234          self.count = int(num)          quantiles = quantiles.keys()
235          num = float(num)          quantiles.sort()
236    
237          prop1 = self.prop1          #
238          prop2 = self.prop2          # the current quantile index must be strictly greater than
239            # the lowerBound
240            #
241            lowerBound = minIndex - 1
242    
243          clr = prop1.GetLineColor()          for qindex in xrange(len(quantiles)):
244          lineColor2 = prop2.GetLineColor()              if lowerBound >= maxIndex:
245                            # discard higher quantiles
246          self.noLine = clr is not Color.Transparent \                  quantiles = quantiles[:qindex]
247                          and lineColor2 is not Color.Transparent                  break
248    
249                # lowerBound + 1 is always a valid index
250    
251          self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),              #
252                                              prop2.GetLineColor(),              # bump up the current quantile index to be a usable index
253                                              num)              # if it currently falls below the lowerBound
254                #
255                if quantiles[qindex] <= lowerBound:
256                    quantiles[qindex] = lowerBound + 1
257    
258          self.fillInfo = self.__GetColorInfo(prop1.GetFill(),              listIndex = quantiles[qindex]
259                                              prop2.GetFill(),              value = _list[listIndex]
                                             num)  
260    
261          self.lineWidth = prop1.GetLineWidth()              #
262          self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num              # 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    
274          return True              #
275                # adjust the current quantile index based on how many
276                # numbers in the _list are the same as the current value
277                #
278                newIndex = listIndex
279                if lcount == rcount:
280                    if lcount != 0:
281                        #
282                        # there are an equal number of numbers to the left
283                        # and right, try going to the left first unless
284                        # doing so creates an empty quantile.
285                        #
286                        if lindex != lowerBound:
287                            newIndex = lindex
288                        else:
289                            newIndex = rindex - 1
290    
291      def next(self):              elif lcount < rcount:
292          if self.count == 0:                  # there are fewer items to the left, so
293              raise StopIteration                  # 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          prop = ClassGroupProperties()  class CustomRamp:
   
         if self.lineInfo is None:  
             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]  
317    
318          if self.fillInfo is None:      def __init__(self, prop1, prop2):
319              prop.SetFill(Color.Transparent)          """Create a ramp between prop1 and prop2."""
320          else:          self.prop1 = prop1
321              prop.SetFill(Color(self.fillInfo[CLR][0] / 255,          self.prop2 = prop2
                             self.fillInfo[CLR][1] / 255,  
                             self.fillInfo[CLR][2] / 255))  
322    
323              self.fillInfo[CLR][0] += self.fillInfo[STEP][0]      def GetRamp(self):
324              self.fillInfo[CLR][1] += self.fillInfo[STEP][1]          """Return this ramp."""
325              self.fillInfo[CLR][2] += self.fillInfo[STEP][2]          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          prop.SetLineWidth(int(self.lineWidth))          index -- a value such that 0 <= index <= 1
333          self.lineWidth        += self.lineWidthStep          """
334    
335          self.count -= 1          if not (0 <= index <= 1):
336                raise ValueError(_("invalid index"))
337    
338          return prop          newProps = ClassGroupProperties()
339    
340      def __GetColorInfo(self, color1, color2, numGroups):          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 Color.Transparent and color2 is Color.Transparent:          if color1 is Transparent and color2 is Transparent:
365              #              setf(Transparent)
366              # returning early          elif color1 is Transparent:
367              #              setf(Color(
368              return None                   color2.red   * index,
369          elif color1 is not Color.Transparent and color2 is Color.Transparent:                   color2.green * index,
370              color = [color1.red   * 255,                   color2.blue  * index))
371                       color1.green * 255,          elif color2 is Transparent:
372                       color1.blue  * 255]              setf(Color(
373              step = (0, 0, 0)                   color1.red   * index,
374          elif color1 is Color.Transparent and color2 is not Color.Transparent:                   color1.green * index,
375              color = [color2.red   * 255,                   color1.blue  * index))
                      color2.green * 255,  
                      color2.blue  * 255]  
             step = (0, 0, 0)  
376          else:          else:
377              color = [color1.red   * 255,              setf(Color(
378                       color1.green * 255,                  (color2.red   - color1.red)   * index + color1.red,
379                       color1.blue  * 255]                  (color2.green - color1.green) * index + color1.green,
380              step = ((color2.red   * 255 - color1.red   * 255)   / numGroups,                  (color2.blue  - color1.blue)  * index + color1.blue))
                     (color2.green * 255 - color1.green * 255) / numGroups,  
                     (color2.blue  * 255 - color1.blue  * 255)  / numGroups)  
   
   
         return (color, step)  
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 448  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.986  
changed lines
  Added in v.2385

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26