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

Legend:
Removed from v.900  
changed lines
  Added in v.1759

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26