Skip to content

Commit 9516c3a

Browse files
author
wonder
committed
[FEATURE] gradient color ramps now support multiple stops - for adding intermediate colors
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@13333 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 44c916f commit 9516c3a

File tree

7 files changed

+411
-21
lines changed

7 files changed

+411
-21
lines changed

python/core/conversions.sip

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ which are not wrapped by PyQt:
99
- QMap<int, QMap<int, TYPE> >
1010
- QMap<QString, QVariant::Type>
1111
- QMap<TYPE1, TYPE2*>
12+
- QMap<double, TYPE>
1213
- QMultiMap<double, TYPE2>
1314
- QMap<int, QgsOverlayObject*>*
1415
*/
@@ -730,6 +731,107 @@ template<TYPE1, TYPE2>
730731
%End
731732
};
732733

734+
735+
736+
template<double, TYPE>
737+
%MappedType QMap<double, TYPE>
738+
{
739+
%TypeHeaderCode
740+
#include <QMap>
741+
%End
742+
743+
%ConvertFromTypeCode
744+
// Create the dictionary.
745+
PyObject *d = PyDict_New();
746+
747+
if (!d)
748+
return NULL;
749+
750+
// Set the dictionary elements.
751+
QMap<double, TYPE>::iterator i;
752+
753+
for (i = sipCpp->begin(); i != sipCpp->end(); ++i)
754+
{
755+
PyObject *t1obj = PyFloat_FromDouble(i.key());
756+
TYPE* t2 = &i.value();
757+
PyObject *t2obj = sipConvertFromInstance(t2, sipClass_TYPE, sipTransferObj);
758+
759+
if (t1obj == NULL || t2obj == NULL || PyDict_SetItem(d, t1obj, t2obj) < 0)
760+
{
761+
Py_DECREF(d);
762+
763+
if (t1obj)
764+
Py_DECREF(t1obj);
765+
766+
if (t2obj)
767+
Py_DECREF(t2obj);
768+
769+
return NULL;
770+
}
771+
772+
Py_DECREF(t1obj);
773+
Py_DECREF(t2obj);
774+
}
775+
776+
return d;
777+
%End
778+
779+
%ConvertToTypeCode
780+
PyObject *t1obj, *t2obj;
781+
#if PY_VERSION_HEX >= 0x02050000
782+
Py_ssize_t i = 0;
783+
#else
784+
int i = 0;
785+
#endif
786+
787+
// Check the type if that is all that is required.
788+
if (sipIsErr == NULL)
789+
{
790+
if (!PyDict_Check(sipPy))
791+
return 0;
792+
793+
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
794+
{
795+
if (!PyFloat_Check(t1obj))
796+
return 0;
797+
798+
if (!sipCanConvertToInstance(t2obj, sipClass_TYPE, SIP_NOT_NONE))
799+
return 0;
800+
}
801+
802+
return 1;
803+
}
804+
805+
QMap<double, TYPE> *qm = new QMap<double, TYPE>;
806+
807+
while (PyDict_Next(sipPy, &i, &t1obj, &t2obj))
808+
{
809+
int state;
810+
811+
double k = PyFloat_AsDouble(t1obj);
812+
TYPE *t2 = reinterpret_cast<TYPE *>(sipConvertToInstance(t2obj, sipClass_TYPE, sipTransferObj, SIP_NOT_NONE, &state, sipIsErr));
813+
814+
if (*sipIsErr)
815+
{
816+
sipReleaseInstance(t2, sipClass_TYPE, state);
817+
delete qm;
818+
return 0;
819+
}
820+
821+
qm->insert(k, *t2);
822+
823+
sipReleaseInstance(t2, sipClass_TYPE, state);
824+
}
825+
826+
*sipCppPtr = qm;
827+
828+
return sipGetState(sipTransferObj);
829+
%End
830+
};
831+
832+
833+
834+
733835
template<double, TYPE2>
734836
%MappedType QMultiMap<double, TYPE2>
735837
{

python/core/symbology-ng-core.sip

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -762,19 +762,59 @@ class QgsVectorColorRampV2
762762
#include <qgsvectorcolorrampv2.h>
763763
%End
764764

765+
%ConvertToSubClassCode
766+
if (sipCpp->type() == "gradient")
767+
{
768+
sipClass = sipClass_QgsVectorGradientColorRampV2;
769+
}
770+
else
771+
sipClass = 0;
772+
%End
773+
765774
public:
766775
virtual ~QgsVectorColorRampV2();
767776

768777
virtual QColor color(double value) const = 0;
769778

770779
virtual QString type() const = 0;
771780

772-
virtual QgsVectorColorRampV2* clone() const = 0;
781+
virtual QgsVectorColorRampV2* clone() const = 0 /Factory/;
773782

774783
virtual QgsStringMap properties() const = 0;
775784

776785
};
777786

787+
class QgsVectorGradientColorRampV2 : QgsVectorColorRampV2
788+
{
789+
public:
790+
QgsVectorGradientColorRampV2( QColor color1 = QColor(0,0,255),
791+
QColor color2 = QColor(0,255,0) );
792+
793+
static QgsVectorColorRampV2* create( const QgsStringMap& properties = QgsStringMap() ) /Factory/;
794+
795+
virtual QColor color( double value ) const;
796+
797+
virtual QString type() const;
798+
799+
virtual QgsVectorColorRampV2* clone() const /Factory/;
800+
801+
virtual QgsStringMap properties() const;
802+
803+
QColor color1() const;
804+
QColor color2() const;
805+
806+
void setColor1( QColor color );
807+
void setColor2( QColor color );
808+
809+
typedef QMultiMap<double, QColor> StopsMap;
810+
811+
void setStops(const StopsMap& stops);
812+
const StopsMap& stops() const;
813+
814+
};
815+
816+
817+
778818
//////////
779819

780820
class QgsSymbologyV2Conversion
@@ -858,3 +898,5 @@ class QgsRendererV2Registry
858898
QgsRendererV2Registry();
859899
~QgsRendererV2Registry();
860900
};
901+
902+
///////////////

src/core/symbology-ng/qgsvectorcolorrampv2.cpp

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,84 @@ QgsVectorColorRampV2* QgsVectorGradientColorRampV2::create( const QgsStringMap&
1818
color1 = QgsSymbolLayerV2Utils::decodeColor( props["color1"] );
1919
if ( props.contains( "color2" ) )
2020
color2 = QgsSymbolLayerV2Utils::decodeColor( props["color2"] );
21-
return new QgsVectorGradientColorRampV2( color1, color2 );
21+
22+
StopsMap stops;
23+
if ( props.contains( "stops" ) )
24+
{
25+
foreach( QString stop, props["stops"].split( ':' ) )
26+
{
27+
int i = stop.indexOf( ';' );
28+
if ( i == -1 ) continue;
29+
30+
QColor c = QgsSymbolLayerV2Utils::decodeColor( stop.mid( i + 1 ) );
31+
stops.insert( stop.left( i ).toDouble(), c );
32+
}
33+
}
34+
35+
QgsVectorGradientColorRampV2* r = new QgsVectorGradientColorRampV2( color1, color2 );
36+
r->setStops( stops );
37+
return r;
2238
}
2339

24-
QColor QgsVectorGradientColorRampV2::color( double value ) const
40+
static QColor _interpolate( QColor c1, QColor c2, double value )
2541
{
26-
int r = ( int )( mColor1.red() + value * ( mColor2.red() - mColor1.red() ) );
27-
int g = ( int )( mColor1.green() + value * ( mColor2.green() - mColor1.green() ) );
28-
int b = ( int )( mColor1.blue() + value * ( mColor2.blue() - mColor1.blue() ) );
42+
int r = ( int )( c1.red() + value * ( c2.red() - c1.red() ) );
43+
int g = ( int )( c1.green() + value * ( c2.green() - c1.green() ) );
44+
int b = ( int )( c1.blue() + value * ( c2.blue() - c1.blue() ) );
2945

3046
return QColor::fromRgb( r, g, b );
3147
}
3248

49+
QColor QgsVectorGradientColorRampV2::color( double value ) const
50+
{
51+
if ( mStops.isEmpty() )
52+
{
53+
return _interpolate( mColor1, mColor2, value );
54+
}
55+
else
56+
{
57+
double lower = 0, upper;
58+
QColor c1 = mColor1, c2;
59+
for ( StopsMap::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
60+
{
61+
if ( it.key() >= value )
62+
{
63+
upper = it.key();
64+
c2 = it.value();
65+
66+
return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
67+
}
68+
lower = it.key();
69+
c1 = it.value();
70+
}
71+
72+
upper = 1;
73+
c2 = mColor2;
74+
return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
75+
}
76+
}
77+
3378
QgsVectorColorRampV2* QgsVectorGradientColorRampV2::clone() const
3479
{
35-
return new QgsVectorGradientColorRampV2( mColor1, mColor2 );
80+
QgsVectorGradientColorRampV2* r = new QgsVectorGradientColorRampV2( mColor1, mColor2 );
81+
r->setStops( mStops );
82+
return r;
3683
}
3784

3885
QgsStringMap QgsVectorGradientColorRampV2::properties() const
3986
{
4087
QgsStringMap map;
4188
map["color1"] = QgsSymbolLayerV2Utils::encodeColor( mColor1 );
4289
map["color2"] = QgsSymbolLayerV2Utils::encodeColor( mColor2 );
90+
if ( !mStops.isEmpty() )
91+
{
92+
QStringList lst;
93+
for ( StopsMap::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
94+
{
95+
lst.append( QString( "%1;%2" ).arg( it.key() ).arg( QgsSymbolLayerV2Utils::encodeColor( it.value() ) ) );
96+
}
97+
map["stops"] = lst.join( ":" );
98+
}
4399
return map;
44100
}
45101

src/core/symbology-ng/qgsvectorcolorrampv2.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,14 @@ class CORE_EXPORT QgsVectorGradientColorRampV2 : public QgsVectorColorRampV2
4646
void setColor1( QColor color ) { mColor1 = color; }
4747
void setColor2( QColor color ) { mColor2 = color; }
4848

49+
typedef QMap<double, QColor> StopsMap;
50+
51+
void setStops( const StopsMap& stops ) { mStops = stops; }
52+
const StopsMap& stops() const { return mStops; }
53+
4954
protected:
5055
QColor mColor1, mColor2;
56+
StopsMap mStops;
5157
};
5258

5359
#define DEFAULT_RANDOM_COUNT 10

0 commit comments

Comments
 (0)