gradsymbol_ramps_20071028.diff
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" |
|
36 |
#include <QDir> |
|
28 | 37 | |
29 | ||
30 | 38 |
QgsGraduatedSymbolDialog::QgsGraduatedSymbolDialog(QgsVectorLayer * layer): QDialog(), mVectorLayer(layer), sydialog(layer) |
31 | 39 |
{ |
32 | 40 |
setupUi(this); |
... | ... | |
102 | 110 |
} |
103 | 111 |
|
104 | 112 |
} |
113 | ||
114 |
// add the color ramps |
|
115 |
QDir rampList(QgsApplication::pkgDataPath() + "/ramps/", "*.cpt", QDir::Name | QDir::IgnoreCase); |
|
116 |
for (uint i = 0; i < rampList.count(); i++) |
|
117 |
{ |
|
118 |
QString packageName = rampList[i]; |
|
119 |
rampComboBox->insertItem(packageName); |
|
120 |
} |
|
105 | 121 |
|
106 | 122 |
//do the necessary signal/slot connections |
107 | 123 |
QObject::connect(mClassifyButton, SIGNAL(clicked()), this, SLOT(adjustClassification())); |
... | ... | |
224 | 240 |
mVectorLayer->setRenderer(renderer); |
225 | 241 |
} |
226 | 242 | |
243 |
std::vector<SRampSegment*> QgsGraduatedSymbolDialog::readColorRamp(QString RampName) |
|
244 |
{ |
|
245 |
std::ifstream ScaleFile; |
|
246 |
std::string Buffer; |
|
247 |
std::vector<SRampSegment*> colorRamp; |
|
248 |
SRampSegment* TempColorPoint; |
|
249 |
char * pch; |
|
250 |
char * temp; |
|
251 |
int i; |
|
252 |
QString RampDirectory; |
|
253 |
QString filename; |
|
254 | ||
255 |
// Read the named color ramp from the system color ramp directory |
|
256 |
// todo: get this from QgsApplication |
|
257 |
RampDirectory = QgsApplication::pkgDataPath() + "/ramps/"; |
|
258 |
filename = RampDirectory + RampName; |
|
259 |
ScaleFile.open(filename.toAscii(), std::ios::in); |
|
260 | ||
261 |
if (!ScaleFile.is_open()) |
|
262 |
{ |
|
263 |
// todo: give a proper error message to the user - this color ramp not found at ... |
|
264 |
return colorRamp; |
|
265 |
} |
|
266 | ||
267 |
while (!ScaleFile.eof()) |
|
268 |
{ |
|
269 |
getline(ScaleFile, Buffer); |
|
270 | ||
271 |
// If not a blank line or a commented line or a non-value line |
|
272 |
if ((Buffer != "") && (Buffer[0] != '#') && |
|
273 |
(Buffer[0] != 'B') && (Buffer[0] != 'F') && (Buffer[0] != 'N') ) |
|
274 |
{ |
|
275 |
TempColorPoint = new SRampSegment; |
|
276 |
|
|
277 |
/* |
|
278 |
Parse the line into the eight |
|
279 |
components of a .cpt color ramp segment: |
|
280 |
begining value, r, g, b, ending value, r, g, b |
|
281 |
*/ |
|
282 |
temp = (char *)Buffer.c_str(); |
|
283 |
pch = strtok(temp," \t"); |
|
284 |
i = 0; |
|
285 |
while (pch != NULL) |
|
286 |
{ |
|
287 |
switch (i) |
|
288 |
{ |
|
289 |
case 0: |
|
290 |
TempColorPoint->BeginVal = atof(pch); |
|
291 |
case 1: |
|
292 |
TempColorPoint->BeginColor.Red = atoi(pch); |
|
293 |
case 2: |
|
294 |
TempColorPoint->BeginColor.Green = atoi(pch); |
|
295 |
case 3: |
|
296 |
TempColorPoint->BeginColor.Blue = atoi(pch); |
|
297 |
case 4: |
|
298 |
TempColorPoint->EndVal = atof(pch); |
|
299 |
case 5: |
|
300 |
TempColorPoint->EndColor.Red = atoi(pch); |
|
301 |
case 6: |
|
302 |
TempColorPoint->EndColor.Green = atoi(pch); |
|
303 |
case 7: |
|
304 |
TempColorPoint->EndColor.Blue = atoi(pch); |
|
305 |
} |
|
306 |
pch = strtok (NULL, " \t"); |
|
307 |
i++; |
|
308 |
} |
|
309 | ||
310 |
colorRamp.push_back(TempColorPoint); |
|
311 |
} |
|
312 |
} |
|
313 | ||
314 |
ScaleFile.close(); |
|
315 |
return colorRamp; |
|
316 |
} |
|
317 | ||
318 | ||
319 |
QColor QgsGraduatedSymbolDialog::getColorFromRamp(std::vector<SRampSegment*> colorRamp, float value) |
|
320 |
{ |
|
321 |
QColor color = QColor(0,0,0); |
|
322 |
SRampSegment* seg; |
|
323 |
float diffFactor; |
|
324 | ||
325 |
if ((value<0)||(value>1)) |
|
326 |
{ |
|
327 |
// this shouldn't happen but, if so, return default color (black) |
|
328 |
return color; |
|
329 |
} |
|
330 | ||
331 |
// Find min and max of this color ramp and |
|
332 |
// scale the given value from 0->1 to min->max of color ramp |
|
333 |
seg = colorRamp[0]; |
|
334 |
float minv = seg->BeginVal; |
|
335 |
float maxv = seg->EndVal; |
|
336 |
for (unsigned int i = 1; i < colorRamp.size(); i++) |
|
337 |
{ |
|
338 |
seg = colorRamp[i]; |
|
339 | ||
340 |
if (seg->BeginVal < minv) |
|
341 |
minv = seg->BeginVal; |
|
342 |
|
|
343 |
if (seg->EndVal > maxv) |
|
344 |
maxv = seg->EndVal; |
|
345 |
} |
|
346 |
value = ((maxv-minv)*value)+minv; |
|
347 | ||
348 |
// Loop through color ramp segments and determine the color via linear interp. in RGB space |
|
349 |
for (unsigned int i = 0; i < colorRamp.size(); i++) |
|
350 |
{ |
|
351 |
seg = colorRamp[i]; |
|
352 | ||
353 |
// find the matching ramp segment |
|
354 |
if ((value <= seg->EndVal) && (value >= seg->BeginVal)) |
|
355 |
{ |
|
356 |
diffFactor = (value - seg->BeginVal) / (seg->EndVal - seg->BeginVal); |
|
357 | ||
358 |
// interpolate a color along the ramp segment |
|
359 |
color = QColor( (int)((seg->EndColor.Red - seg->BeginColor.Red) * diffFactor) + seg->BeginColor.Red, |
|
360 |
(int)((seg->EndColor.Green - seg->BeginColor.Green) * diffFactor) + seg->BeginColor.Green, |
|
361 |
(int)((seg->EndColor.Blue - seg->BeginColor.Blue) * diffFactor) + seg->BeginColor.Blue ); |
|
362 |
} |
|
363 |
} |
|
364 | ||
365 |
return color; |
|
366 |
} |
|
367 | ||
227 | 368 |
void QgsGraduatedSymbolDialog::adjustClassification() |
228 | 369 |
{ |
229 | 370 |
mClassListWidget->clear(); |
... | ... | |
231 | 372 |
QgsVectorDataProvider *provider = dynamic_cast<QgsVectorDataProvider *>(mVectorLayer->getDataProvider()); |
232 | 373 |
double minimum = 0; |
233 | 374 |
double maximum = 0; |
375 |
float scaledval; |
|
234 | 376 |
|
235 | 377 |
//delete all previous entries |
236 | 378 |
for(std::map<QString, QgsSymbol*>::iterator it=mEntries.begin();it!=mEntries.end();++it) |
... | ... | |
266 | 408 |
} |
267 | 409 |
} |
268 | 410 | |
269 |
//todo: setup a data structure which holds the symbols |
|
411 |
// Obtain the color ramp |
|
412 |
QString rampName = rampComboBox->currentText(); |
|
413 |
std::vector<SRampSegment*> ramp; |
|
414 |
ramp = readColorRamp(rampName); |
|
415 | ||
416 | ||
270 | 417 |
std::list<QgsSymbol*> symbolList; |
271 | 418 |
for(int i = 0; i < numberofclassesspinbox->value(); ++i) |
272 | 419 |
{ |
... | ... | |
274 | 421 |
symbol->setLabel(""); |
275 | 422 |
QPen pen; |
276 | 423 |
QBrush brush; |
424 |
|
|
425 |
// Calculate the step along the classification ramp; scaled from 0 to 1 |
|
426 |
scaledval = ( (float)i + 0.5) / (float) numberofclassesspinbox->value(); |
|
277 | 427 | |
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 | ||
428 |
if (m_type == QGis::Line) |
|
429 |
{ |
|
430 |
pen.setColor(getColorFromRamp(ramp,scaledval)); |
|
431 |
} |
|
432 |
else //point or polygon |
|
433 |
{ |
|
434 |
brush.setColor(getColorFromRamp(ramp,scaledval)); |
|
435 |
pen.setColor(Qt::black); |
|
436 |
} |
|
437 |
|
|
291 | 438 |
pen.setWidth(1); |
292 | 439 |
brush.setStyle(Qt::SolidPattern); |
293 | 440 |
symbol->setPen(pen); |
... | ... | |
507 | 654 |
} |
508 | 655 | |
509 | 656 | |
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 |
} |
|
657 |
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="QComboBox" name="rampComboBox" /> |
|
201 |
</item> |
|
152 | 202 |
</layout> |
153 | 203 |
</item> |
154 | 204 |
</layout> |