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

Legend:
Removed from v.959  
changed lines
  Added in v.1525

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26