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

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26