Index: src/app/qgsgraduatedsymboldialog.h =================================================================== --- src/app/qgsgraduatedsymboldialog.h (revision 7301) +++ src/app/qgsgraduatedsymboldialog.h (working copy) @@ -22,10 +22,28 @@ #include "ui_qgsgraduatedsymboldialogbase.h" #include "qgssinglesymboldialog.h" #include +#include +#include +#include class QgsVectorLayer; + struct SColor + { + int Red; + int Green; + int Blue; + }; + struct SRampSegment + { + float BeginVal; + float EndVal; + SColor BeginColor; + SColor EndColor; + }; + + class QgsGraduatedSymbolDialog: public QDialog, private Ui::QgsGraduatedSymbolDialogBase { Q_OBJECT @@ -39,6 +57,10 @@ protected slots: /**Changes only the number of classes*/ void adjustNumberOfClasses(); + /** Get a color ramp from cpt file **/ + std::vector readColorRamp(QString rampFile); + /**Gets the color value along a specified ramp **/ + QColor getColorFromRamp( std::vector ramp, float value); /**Sets a new classification field and a new classification mode*/ void adjustClassification(); /**Changes the display of the single symbol dialog*/ Index: src/app/qgsgraduatedsymboldialog.cpp =================================================================== --- src/app/qgsgraduatedsymboldialog.cpp (revision 7301) +++ src/app/qgsgraduatedsymboldialog.cpp (working copy) @@ -25,8 +25,16 @@ #include "qgsvectorlayer.h" #include #include +/* added by mp for the color ramp business */ +#include +#include +#include +#include +#include +#include +#include "qgsapplication.h" +#include - QgsGraduatedSymbolDialog::QgsGraduatedSymbolDialog(QgsVectorLayer * layer): QDialog(), mVectorLayer(layer), sydialog(layer) { setupUi(this); @@ -102,6 +110,14 @@ } } + + // add the color ramps + QDir rampList(QgsApplication::pkgDataPath() + "/ramps/", "*.cpt", QDir::Name | QDir::IgnoreCase); + for (uint i = 0; i < rampList.count(); i++) + { + QString packageName = rampList[i]; + rampComboBox->insertItem(packageName); + } //do the necessary signal/slot connections QObject::connect(mClassifyButton, SIGNAL(clicked()), this, SLOT(adjustClassification())); @@ -224,6 +240,131 @@ mVectorLayer->setRenderer(renderer); } +std::vector QgsGraduatedSymbolDialog::readColorRamp(QString RampName) +{ + std::ifstream ScaleFile; + std::string Buffer; + std::vector colorRamp; + SRampSegment* TempColorPoint; + char * pch; + char * temp; + int i; + QString RampDirectory; + QString filename; + + // Read the named color ramp from the system color ramp directory + // todo: get this from QgsApplication + RampDirectory = QgsApplication::pkgDataPath() + "/ramps/"; + filename = RampDirectory + RampName; + ScaleFile.open(filename.toAscii(), std::ios::in); + + if (!ScaleFile.is_open()) + { + // todo: give a proper error message to the user - this color ramp not found at ... + return colorRamp; + } + + while (!ScaleFile.eof()) + { + getline(ScaleFile, Buffer); + + // If not a blank line or a commented line or a non-value line + if ((Buffer != "") && (Buffer[0] != '#') && + (Buffer[0] != 'B') && (Buffer[0] != 'F') && (Buffer[0] != 'N') ) + { + TempColorPoint = new SRampSegment; + + /* + Parse the line into the eight + components of a .cpt color ramp segment: + begining value, r, g, b, ending value, r, g, b + */ + temp = (char *)Buffer.c_str(); + pch = strtok(temp," \t"); + i = 0; + while (pch != NULL) + { + switch (i) + { + case 0: + TempColorPoint->BeginVal = atof(pch); + case 1: + TempColorPoint->BeginColor.Red = atoi(pch); + case 2: + TempColorPoint->BeginColor.Green = atoi(pch); + case 3: + TempColorPoint->BeginColor.Blue = atoi(pch); + case 4: + TempColorPoint->EndVal = atof(pch); + case 5: + TempColorPoint->EndColor.Red = atoi(pch); + case 6: + TempColorPoint->EndColor.Green = atoi(pch); + case 7: + TempColorPoint->EndColor.Blue = atoi(pch); + } + pch = strtok (NULL, " \t"); + i++; + } + + colorRamp.push_back(TempColorPoint); + } + } + + ScaleFile.close(); + return colorRamp; +} + + +QColor QgsGraduatedSymbolDialog::getColorFromRamp(std::vector colorRamp, float value) +{ + QColor color = QColor(0,0,0); + SRampSegment* seg; + float diffFactor; + + if ((value<0)||(value>1)) + { + // this shouldn't happen but, if so, return default color (black) + return color; + } + + // Find min and max of this color ramp and + // scale the given value from 0->1 to min->max of color ramp + seg = colorRamp[0]; + float minv = seg->BeginVal; + float maxv = seg->EndVal; + for (unsigned int i = 1; i < colorRamp.size(); i++) + { + seg = colorRamp[i]; + + if (seg->BeginVal < minv) + minv = seg->BeginVal; + + if (seg->EndVal > maxv) + maxv = seg->EndVal; + } + value = ((maxv-minv)*value)+minv; + + // Loop through color ramp segments and determine the color via linear interp. in RGB space + for (unsigned int i = 0; i < colorRamp.size(); i++) + { + seg = colorRamp[i]; + + // find the matching ramp segment + if ((value <= seg->EndVal) && (value >= seg->BeginVal)) + { + diffFactor = (value - seg->BeginVal) / (seg->EndVal - seg->BeginVal); + + // interpolate a color along the ramp segment + color = QColor( (int)((seg->EndColor.Red - seg->BeginColor.Red) * diffFactor) + seg->BeginColor.Red, + (int)((seg->EndColor.Green - seg->BeginColor.Green) * diffFactor) + seg->BeginColor.Green, + (int)((seg->EndColor.Blue - seg->BeginColor.Blue) * diffFactor) + seg->BeginColor.Blue ); + } + } + + return color; +} + void QgsGraduatedSymbolDialog::adjustClassification() { mClassListWidget->clear(); @@ -231,6 +372,7 @@ QgsVectorDataProvider *provider = dynamic_cast(mVectorLayer->getDataProvider()); double minimum = 0; double maximum = 0; + float scaledval; //delete all previous entries for(std::map::iterator it=mEntries.begin();it!=mEntries.end();++it) @@ -266,7 +408,12 @@ } } - //todo: setup a data structure which holds the symbols + // Obtain the color ramp + QString rampName = rampComboBox->currentText(); + std::vector ramp; + ramp = readColorRamp(rampName); + + std::list symbolList; for(int i = 0; i < numberofclassesspinbox->value(); ++i) { @@ -274,20 +421,20 @@ symbol->setLabel(""); QPen pen; QBrush brush; + + // Calculate the step along the classification ramp; scaled from 0 to 1 + scaledval = ( (float)i + 0.5) / (float) numberofclassesspinbox->value(); - // todo: These color ramps should come from a dropdown list - QString ramp; - ramp = "red_to_green"; - if (m_type == QGis::Line) - { - pen.setColor(getColorFromRamp(ramp,i, numberofclassesspinbox->value())); - } - else //point or polygon - { - brush.setColor(getColorFromRamp(ramp,i, numberofclassesspinbox->value())); - pen.setColor(Qt::black); - } - + if (m_type == QGis::Line) + { + pen.setColor(getColorFromRamp(ramp,scaledval)); + } + else //point or polygon + { + brush.setColor(getColorFromRamp(ramp,scaledval)); + pen.setColor(Qt::black); + } + pen.setWidth(1); brush.setStyle(Qt::SolidPattern); symbol->setPen(pen); @@ -507,26 +654,4 @@ } -QColor QgsGraduatedSymbolDialog::getColorFromRamp(QString ramp, int step, int totalSteps) -{ - QColor color; - /* To do: - Grab the ramp by name from a file or ramp registry - and apply determine the color for the given step. - Ideally there would be two types of ramps: - - discrete colors: the number of steps would have to match totalSteps - - continuous colors: (eg grass or gmt ramps) would need to code a method - for determining an RGB color for any point along the continuum - Color ramps should be plugin-able; should be defined in a simple text file format - and read from a directory where users can add their own ramps. - */ - if (step == 0) - { - color = QColor(0,255,0); - } - else - { - color = QColor(0,255-((255/totalSteps)*step+1),((255/totalSteps)*step+1)); - } - return color; -} + Index: src/ui/qgsgraduatedsymboldialogbase.ui =================================================================== --- src/ui/qgsgraduatedsymboldialogbase.ui (revision 7301) +++ src/ui/qgsgraduatedsymboldialogbase.ui (working copy) @@ -25,12 +25,24 @@ graduated Symbol - + 9 - + + 9 + + + 9 + + + 9 + + 6 + + 6 + @@ -39,26 +51,42 @@ - - 0 - 6 + + 0 + + + 0 + + + 0 + + + 0 + - - 0 - 6 + + 0 + + + 0 + + + 0 + + + 0 + - - 5 - 5 + 0 0 @@ -109,16 +137,35 @@ + + + + Color Ramp: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + - + + 5 + + 0 - - 6 + + 0 + + 0 + + + 0 + @@ -149,6 +196,9 @@ + + +