gradsymbol_ramps_20071027.diff

Proof-of-concept patch for graduated symbol color ramps using .cpt files - perrygeo -, 2007-10-27 03:29 PM

Download (12 KB)

View differences:

src/app/qgsgraduatedsymboldialog.h (working copy)
22 22
#include "ui_qgsgraduatedsymboldialogbase.h"
23 23
#include "qgssinglesymboldialog.h"
24 24
#include <map>
25
#include <string>
26
#include <vector>
27
#include <QString>
25 28

  
26 29
class QgsVectorLayer;
27 30

  
31
    struct SColor 
32
    {
33
    int Red;
34
    int Green;
35
    int Blue;
36
    };
28 37

  
38
    struct SRampSegment 
39
    {
40
    float BeginVal;
41
    float EndVal;
42
    SColor BeginColor;
43
    SColor EndColor;
44
    };
45

  
46

  
29 47
class QgsGraduatedSymbolDialog: public QDialog, private Ui::QgsGraduatedSymbolDialogBase
30 48
{
31 49
    Q_OBJECT
......
39 57
 protected slots:
40 58
     /**Changes only the number of classes*/
41 59
     void adjustNumberOfClasses();
60
     /** Get a color ramp from cpt file **/
61
     std::vector<SRampSegment*> readColorRamp(QString rampFile);
62
     /**Gets the color value along a specified ramp **/
63
     QColor getColorFromRamp( std::vector<SRampSegment*> ramp, float value);
42 64
     /**Sets a new classification field and a new classification mode*/
43 65
     void adjustClassification();
44 66
     /**Changes the display of the single symbol dialog*/
src/app/qgsgraduatedsymboldialog.cpp (working copy)
25 25
#include "qgsvectorlayer.h"
26 26
#include <algorithm>
27 27
#include <cmath>
28
/* added by mp for the color ramp business */
29
#include <iostream>
30
#include <stdlib.h>
31
#include <fstream>
32
#include <list>
33
#include <string> 
34
#include <vector>
35
#include "qgsapplication.h"
28 36

  
29

  
30 37
QgsGraduatedSymbolDialog::QgsGraduatedSymbolDialog(QgsVectorLayer * layer): QDialog(), mVectorLayer(layer), sydialog(layer)
31 38
{
32 39
    setupUi(this);
......
224 231
	mVectorLayer->setRenderer(renderer);
225 232
}
226 233

  
234
std::vector<SRampSegment*> QgsGraduatedSymbolDialog::readColorRamp(QString RampName)
235
{
236
  std::ifstream ScaleFile;
237
  std::string Buffer;
238
  std::vector<SRampSegment*> colorRamp;
239
  SRampSegment* TempColorPoint;
240
  char * pch;
241
  char * temp;
242
  int i;
243
  QString RampDirectory;
244
  QString filename;
245

  
246
  // Read the named color ramp from the system color ramp directory
247
  // todo: get this from QgsApplication
248
  RampDirectory = QgsApplication::pkgDataPath() + "/ramps/";
249
  filename = RampDirectory + RampName + ".cpt";
250
  ScaleFile.open(filename.toAscii(), std::ios::in);
251

  
252
  if (!ScaleFile.is_open())
253
  {
254
      // todo: give a proper error message to the user - this color ramp not found at ...
255
      return colorRamp;
256
  }
257

  
258
  while (!ScaleFile.eof())
259
  {
260
      getline(ScaleFile, Buffer);
261

  
262
      // If not a blank line or a commented line or a non-value line
263
      if ((Buffer != "") && (Buffer[0] != '#') && 
264
	  (Buffer[0] != 'B') && (Buffer[0] != 'F') && (Buffer[0] != 'N') )
265
      {
266
	  TempColorPoint = new SRampSegment;
267
 
268
          /* 
269
             Parse the line into the eight 
270
             components of a .cpt color ramp segment: 
271
             begining value, r, g, b, ending value, r, g, b 
272
	  */
273
	  temp = (char *)Buffer.c_str();
274
	  pch = strtok(temp," \t");
275
	  i = 0;
276
	  while (pch != NULL)
277
	  {
278
	      switch (i) 
279
              {
280
		case 0:
281
		  TempColorPoint->BeginVal = atof(pch);
282
		case 1:
283
		  TempColorPoint->BeginColor.Red = atoi(pch);
284
		case 2:
285
		  TempColorPoint->BeginColor.Green = atoi(pch);
286
		case 3:
287
		  TempColorPoint->BeginColor.Blue = atoi(pch);
288
		case 4:
289
		  TempColorPoint->EndVal = atof(pch);
290
		case 5:
291
		  TempColorPoint->EndColor.Red = atoi(pch);
292
		case 6:
293
		  TempColorPoint->EndColor.Green = atoi(pch);
294
		case 7:
295
		  TempColorPoint->EndColor.Blue = atoi(pch);
296
              }
297
	      pch = strtok (NULL, " \t");
298
	      i++;
299
	  }
300

  
301
	  colorRamp.push_back(TempColorPoint);
302
	}
303
    }
304

  
305
  ScaleFile.close();
306
  return colorRamp;
307
}
308

  
309

  
310
QColor QgsGraduatedSymbolDialog::getColorFromRamp(std::vector<SRampSegment*> colorRamp, float value)
311
{
312
  QColor color = QColor(0,0,0);
313
  SRampSegment* seg;
314
  float diffFactor;
315

  
316
  if ((value<0)||(value>1)) 
317
  {
318
    // this shouldn't happen but, if so, return default color (black)
319
    return color;
320
  }
321

  
322
  // Find min and max of this color ramp and
323
  // scale the given value from 0->1 to min->max of color ramp
324
  seg = colorRamp[0];
325
  float minv = seg->BeginVal;
326
  float maxv = seg->EndVal; 
327
  for (unsigned int i = 1; i < colorRamp.size(); i++)
328
  {
329
      seg = colorRamp[i];
330

  
331
      if (seg->BeginVal < minv)
332
	minv = seg->BeginVal;
333
    
334
      if (seg->EndVal > maxv)
335
	maxv = seg->EndVal;    
336
  }
337
  value = ((maxv-minv)*value)+minv;
338

  
339
  // Loop through color ramp segments and determine the color via linear interp. in RGB space
340
  for (unsigned int i = 0; i < colorRamp.size(); i++)
341
  {
342
      seg = colorRamp[i];
343

  
344
      // find the matching ramp segment
345
      if ((value <= seg->EndVal) && (value >= seg->BeginVal))
346
      {     
347
	diffFactor = (value - seg->BeginVal) / (seg->EndVal - seg->BeginVal);
348

  
349
        // interpolate a color along the ramp segment
350
	color = QColor( (int)((seg->EndColor.Red - seg->BeginColor.Red) * diffFactor) + seg->BeginColor.Red, 
351
	                (int)((seg->EndColor.Green - seg->BeginColor.Green) * diffFactor) + seg->BeginColor.Green,
352
			(int)((seg->EndColor.Blue - seg->BeginColor.Blue) * diffFactor) + seg->BeginColor.Blue );
353
      }
354
  }
355

  
356
  return color;
357
}
358

  
227 359
void QgsGraduatedSymbolDialog::adjustClassification()
228 360
{
229 361
    mClassListWidget->clear();
......
231 363
    QgsVectorDataProvider *provider = dynamic_cast<QgsVectorDataProvider *>(mVectorLayer->getDataProvider());
232 364
    double minimum = 0;
233 365
    double maximum = 0;
366
    float scaledval;
234 367
    
235 368
    //delete all previous entries
236 369
    for(std::map<QString, QgsSymbol*>::iterator it=mEntries.begin();it!=mEntries.end();++it)
......
266 399
	}
267 400
    }
268 401

  
269
    //todo: setup a data structure which holds the symbols
402
    // Obtain the color ramp
403
    QString rampName = rampLine->text(); 
404
    std::vector<SRampSegment*> ramp;
405
    ramp = readColorRamp(rampName);
406

  
407

  
270 408
    std::list<QgsSymbol*> symbolList;
271 409
    for(int i = 0; i < numberofclassesspinbox->value(); ++i)
272 410
      {
......
274 412
	symbol->setLabel("");
275 413
	QPen pen;
276 414
	QBrush brush;
415
        
416
        // Calculate the step along the classification ramp; scaled from 0 to 1 
417
        scaledval = ( (float)i + 0.5) / (float) numberofclassesspinbox->value();
277 418

  
278
	// todo: These color ramps should come from a dropdown list  
279
        QString ramp; 
280
        ramp = "red_to_green"; 
281
        if (m_type == QGis::Line) 
282
        { 
283
          pen.setColor(getColorFromRamp(ramp,i, numberofclassesspinbox->value())); 
284
        }  
285
        else //point or polygon 
286
        { 
287
          brush.setColor(getColorFromRamp(ramp,i, numberofclassesspinbox->value())); 
288
          pen.setColor(Qt::black); 
289
        } 
290

  
419
        if (m_type == QGis::Line)
420
	{
421
	  pen.setColor(getColorFromRamp(ramp,scaledval));
422
	} 
423
	else //point or polygon
424
	{
425
	  brush.setColor(getColorFromRamp(ramp,scaledval));
426
	  pen.setColor(Qt::black);
427
	}
428
	
291 429
	pen.setWidth(1);
292 430
	brush.setStyle(Qt::SolidPattern);
293 431
	symbol->setPen(pen);
......
507 645
}
508 646

  
509 647

  
510
QColor QgsGraduatedSymbolDialog::getColorFromRamp(QString ramp, int step, int totalSteps) 
511
{ 
512
  QColor color; 
513
  /* To do: 
514
     Grab the ramp by name from a file or ramp registry 
515
       and apply determine the color for the given step. 
516
     Ideally there would be two types of ramps: 
517
       - discrete colors: the number of steps would have to match totalSteps 
518
       - continuous colors: (eg grass or gmt ramps) would need to code a method 
519
          for determining an RGB color for any point along the continuum 
520
     Color ramps should be plugin-able; should be defined in a simple text file format 
521
       and read from a directory where users can add their own ramps.  
522
  */ 
523
  if (step == 0) 
524
  { 
525
    color = QColor(0,255,0); 
526
  }  
527
  else 
528
  { 
529
    color = QColor(0,255-((255/totalSteps)*step+1),((255/totalSteps)*step+1));     
530
  }  
531
  return color; 
532
} 
648

  
src/ui/qgsgraduatedsymboldialogbase.ui (working copy)
25 25
   <string>graduated Symbol</string>
26 26
  </property>
27 27
  <layout class="QGridLayout" >
28
   <property name="margin" >
28
   <property name="leftMargin" >
29 29
    <number>9</number>
30 30
   </property>
31
   <property name="spacing" >
31
   <property name="topMargin" >
32
    <number>9</number>
33
   </property>
34
   <property name="rightMargin" >
35
    <number>9</number>
36
   </property>
37
   <property name="bottomMargin" >
38
    <number>9</number>
39
   </property>
40
   <property name="horizontalSpacing" >
32 41
    <number>6</number>
33 42
   </property>
43
   <property name="verticalSpacing" >
44
    <number>6</number>
45
   </property>
34 46
   <item rowspan="2" row="1" column="0" >
35 47
    <widget class="QStackedWidget" name="mSymbolWidgetStack" >
36 48
     <widget class="QWidget" name="page" />
......
39 51
   </item>
40 52
   <item row="0" column="0" colspan="3" >
41 53
    <layout class="QHBoxLayout" >
42
     <property name="margin" >
43
      <number>0</number>
44
     </property>
45 54
     <property name="spacing" >
46 55
      <number>6</number>
47 56
     </property>
57
     <property name="leftMargin" >
58
      <number>0</number>
59
     </property>
60
     <property name="topMargin" >
61
      <number>0</number>
62
     </property>
63
     <property name="rightMargin" >
64
      <number>0</number>
65
     </property>
66
     <property name="bottomMargin" >
67
      <number>0</number>
68
     </property>
48 69
     <item>
49 70
      <layout class="QVBoxLayout" >
50
       <property name="margin" >
51
        <number>0</number>
52
       </property>
53 71
       <property name="spacing" >
54 72
        <number>6</number>
55 73
       </property>
74
       <property name="leftMargin" >
75
        <number>0</number>
76
       </property>
77
       <property name="topMargin" >
78
        <number>0</number>
79
       </property>
80
       <property name="rightMargin" >
81
        <number>0</number>
82
       </property>
83
       <property name="bottomMargin" >
84
        <number>0</number>
85
       </property>
56 86
       <item>
57 87
        <widget class="QLabel" name="classvarlabel" >
58 88
         <property name="sizePolicy" >
59
          <sizepolicy>
60
           <hsizetype>5</hsizetype>
61
           <vsizetype>5</vsizetype>
89
          <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
62 90
           <horstretch>0</horstretch>
63 91
           <verstretch>0</verstretch>
64 92
          </sizepolicy>
......
109 137
         </property>
110 138
        </widget>
111 139
       </item>
140
       <item>
141
        <widget class="QLabel" name="colorramplabel" >
142
         <property name="text" >
143
          <string>Color Ramp:</string>
144
         </property>
145
         <property name="alignment" >
146
          <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
147
         </property>
148
        </widget>
149
       </item>
112 150
      </layout>
113 151
     </item>
114 152
     <item>
115 153
      <layout class="QVBoxLayout" >
116
       <property name="margin" >
154
       <property name="spacing" >
155
        <number>5</number>
156
       </property>
157
       <property name="leftMargin" >
117 158
        <number>0</number>
118 159
       </property>
119
       <property name="spacing" >
120
        <number>6</number>
160
       <property name="topMargin" >
161
        <number>0</number>
121 162
       </property>
163
       <property name="rightMargin" >
164
        <number>0</number>
165
       </property>
166
       <property name="bottomMargin" >
167
        <number>0</number>
168
       </property>
122 169
       <item>
123 170
        <widget class="QComboBox" name="classificationComboBox" >
124 171
         <property name="minimumSize" >
......
149 196
         </property>
150 197
        </widget>
151 198
       </item>
199
       <item>
200
        <widget class="QLineEdit" name="rampLine" >
201
         <property name="text" >
202
          <string>red_white_blue</string>
203
         </property>
204
        </widget>
205
       </item>
152 206
      </layout>
153 207
     </item>
154 208
    </layout>