Skip to content

Commit

Permalink
make QgsCptCityColorRampV2 subclass of QgsVectorGradientColorRampV2 a…
Browse files Browse the repository at this point in the history
…nd adjust both accordingly (changed stops map to list)
  • Loading branch information
etiennesky committed Nov 17, 2012
1 parent 724f190 commit 31c11ed
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 158 deletions.
20 changes: 16 additions & 4 deletions python/core/symbology-ng/qgsvectorcolorrampv2.sip
Expand Up @@ -26,14 +26,25 @@ class QgsVectorColorRampV2

};

struct QgsGradientStop
{
double offset;
QColor color;
QgsGradientStop( double o, const QColor& c );
};

typedef QList<QgsGradientStop> QgsGradientStopsList;

class QgsVectorGradientColorRampV2 : QgsVectorColorRampV2
{
%TypeHeaderCode
#include <qgsvectorcolorrampv2.h>
%End
public:
QgsVectorGradientColorRampV2( QColor color1 = DEFAULT_GRADIENT_COLOR1,
QColor color2 = DEFAULT_GRADIENT_COLOR2 );
QColor color2 = QColor(0,255,0),
bool discrete = false,
QgsGradientStopsList stops = QgsGradientStopsList() );

static QgsVectorColorRampV2* create( const QgsStringMap& properties = QgsStringMap() ) /Factory/;

Expand All @@ -51,10 +62,11 @@ class QgsVectorGradientColorRampV2 : QgsVectorColorRampV2
void setColor1( QColor color );
void setColor2( QColor color );

typedef QMap<double, QColor> StopsMap;
bool isDiscrete() const;
void setDiscrete( bool discrete );

void setStops( const StopsMap& stops );
const StopsMap& stops() const;
void setStops( const QgsGradientStopsList& stops );
const QgsGradientStopsList& stops() const;
};

class QgsVectorRandomColorRampV2 : QgsVectorColorRampV2
Expand Down
16 changes: 9 additions & 7 deletions src/core/symbology-ng/qgscptcityarchive.cpp
Expand Up @@ -730,16 +730,18 @@ void QgsCptCityColorRampItem::init( )
if ( variantList.isEmpty() )
{
int count = mRamp.count();
QgsCptCityColorRampV2::GradientType type = mRamp.gradientType();
if ( type == QgsCptCityColorRampV2::Discrete )
if ( mRamp.isDiscrete() )
count--;
mInfo = QString::number( count ) + " " + tr( "colors" ) + " - ";
if ( type == QgsCptCityColorRampV2::Continuous )
mInfo += tr( "continuous" );
else if ( type == QgsCptCityColorRampV2::ContinuousMulti )
mInfo += tr( "continuous (multi)" );
else if ( type == QgsCptCityColorRampV2::Discrete )
if ( mRamp.isDiscrete() )
mInfo += tr( "discrete" );
else
{
if ( !mRamp.hasMultiStops() )
mInfo += tr( "continuous" );
else
mInfo += tr( "continuous (multi)" );
}
mShortInfo = QFileInfo( mName ).fileName();
}
else
Expand Down
172 changes: 69 additions & 103 deletions src/core/symbology-ng/qgsvectorcolorrampv2.cpp
Expand Up @@ -24,8 +24,23 @@
#include <stdlib.h> // for random()
#include <QTime>

QgsVectorGradientColorRampV2::QgsVectorGradientColorRampV2( QColor color1, QColor color2 )
: mColor1( color1 ), mColor2( color2 )
//////////////

static QColor _interpolate( QColor c1, QColor c2, double value )
{
int r = ( int )( c1.red() + value * ( c2.red() - c1.red() ) );
int g = ( int )( c1.green() + value * ( c2.green() - c1.green() ) );
int b = ( int )( c1.blue() + value * ( c2.blue() - c1.blue() ) );
int a = ( int )( c1.alpha() + value * ( c2.alpha() - c1.alpha() ) );

return QColor::fromRgb( r, g, b, a );
}

//////////////

QgsVectorGradientColorRampV2::QgsVectorGradientColorRampV2( QColor color1, QColor color2,
bool discrete, QgsGradientStopsList stops )
: mColor1( color1 ), mColor2( color2 ), mDiscrete( discrete ), mStops( stops )
{
}

Expand All @@ -38,7 +53,7 @@ QgsVectorColorRampV2* QgsVectorGradientColorRampV2::create( const QgsStringMap&
if ( props.contains( "color2" ) )
color2 = QgsSymbolLayerV2Utils::decodeColor( props["color2"] );

StopsMap stops;
QgsGradientStopsList stops;
if ( props.contains( "stops" ) )
{
foreach ( QString stop, props["stops"].split( ':' ) )
Expand All @@ -48,48 +63,51 @@ QgsVectorColorRampV2* QgsVectorGradientColorRampV2::create( const QgsStringMap&
continue;

QColor c = QgsSymbolLayerV2Utils::decodeColor( stop.mid( i + 1 ) );
stops.insert( stop.left( i ).toDouble(), c );
stops.append( QgsGradientStop( stop.left( i ).toDouble(), c ) );
}
}
bool discrete = false;
if ( props.contains( "discrete" ) )
{
if ( props["discrete"] == "1" )
discrete = true;
}

QgsVectorGradientColorRampV2* r = new QgsVectorGradientColorRampV2( color1, color2 );
r->setStops( stops );
QgsVectorGradientColorRampV2* r = new QgsVectorGradientColorRampV2( color1, color2, discrete, stops );
return r;
}

static QColor _interpolate( QColor c1, QColor c2, double value )
{
int r = ( int )( c1.red() + value * ( c2.red() - c1.red() ) );
int g = ( int )( c1.green() + value * ( c2.green() - c1.green() ) );
int b = ( int )( c1.blue() + value * ( c2.blue() - c1.blue() ) );
int a = ( int )( c1.alpha() + value * ( c2.alpha() - c1.alpha() ) );

return QColor::fromRgb( r, g, b, a );
}

QColor QgsVectorGradientColorRampV2::color( double value ) const
{
if ( mStops.isEmpty() )
{
if ( mDiscrete )
return mColor1;
return _interpolate( mColor1, mColor2, value );
}
else
{
double lower = 0, upper;
double lower = 0, upper = 0;
QColor c1 = mColor1, c2;
for ( StopsMap::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
for ( QgsGradientStopsList::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
{
if ( it.key() >= value )
if ( it->offset > value )
{
upper = it.key();
c2 = it.value();
if ( mDiscrete )
return c1;

upper = it->offset;
c2 = it->color;

return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
}
lower = it.key();
c1 = it.value();
lower = it->offset;
c1 = it->color;
}

if ( mDiscrete )
return c1;

upper = 1;
c2 = mColor2;
return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
Expand All @@ -98,8 +116,8 @@ QColor QgsVectorGradientColorRampV2::color( double value ) const

QgsVectorColorRampV2* QgsVectorGradientColorRampV2::clone() const
{
QgsVectorGradientColorRampV2* r = new QgsVectorGradientColorRampV2( mColor1, mColor2 );
r->setStops( mStops );
QgsVectorGradientColorRampV2* r = new QgsVectorGradientColorRampV2( mColor1, mColor2,
mDiscrete, mStops );
return r;
}

Expand All @@ -111,15 +129,17 @@ QgsStringMap QgsVectorGradientColorRampV2::properties() const
if ( !mStops.isEmpty() )
{
QStringList lst;
for ( StopsMap::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
for ( QgsGradientStopsList::const_iterator it = mStops.begin(); it != mStops.end(); ++it )
{
lst.append( QString( "%1;%2" ).arg( it.key() ).arg( QgsSymbolLayerV2Utils::encodeColor( it.value() ) ) );
lst.append( QString( "%1;%2" ).arg( it->offset ).arg( QgsSymbolLayerV2Utils::encodeColor( it->color ) ) );
}
map["stops"] = lst.join( ":" );
}
map["discrete"] = mDiscrete ? "1" : "0";
return map;
}


//////////////


Expand Down Expand Up @@ -256,33 +276,12 @@ QgsStringMap QgsVectorColorBrewerColorRampV2::properties() const

////////////

/*
TODO
- return a suitable name (scheme_variant) ??
- re-organize and rename colorramp classes and widgets
*/

/*
TODO load schemes
- don't show empty dirs? (e.g. jjg/hatch)
- better grouping:
- cl/fs2????
- cw
- dca
- dirs with one scheme ( cl/ es/ ma/ occ/ wkp/
jjg/neo10/env/green-crystal jjg/neo10/face/eyes/blue )
- fix rendering:
- ibcao
*/

QgsCptCityColorRampV2::QgsCptCityColorRampV2( QString schemeName, QString variantName,
bool doLoadFile )
: mSchemeName( schemeName ), mVariantName( variantName ),
mVariantList( QStringList() ), mFileLoaded( false ),
mGradientType( Continuous )
: QgsVectorGradientColorRampV2(),
mSchemeName( schemeName ), mVariantName( variantName ),
mVariantList( QStringList() ), mFileLoaded( false ), mMultiStops( false )
{
// TODO replace this with hard-coded data in the default case
// don't load file if variant is missing
Expand All @@ -292,9 +291,9 @@ QgsCptCityColorRampV2::QgsCptCityColorRampV2( QString schemeName, QString varian

QgsCptCityColorRampV2::QgsCptCityColorRampV2( QString schemeName, QStringList variantList,
QString variantName, bool doLoadFile )
: mSchemeName( schemeName ), mVariantName( variantName ),
mVariantList( variantList ), mFileLoaded( false ),
mGradientType( Continuous )
: QgsVectorGradientColorRampV2(),
mSchemeName( schemeName ), mVariantName( variantName ),
mVariantList( variantList ), mFileLoaded( false ), mMultiStops( false )
{
mVariantList = variantList;

Expand All @@ -317,41 +316,6 @@ QgsVectorColorRampV2* QgsCptCityColorRampV2::create( const QgsStringMap& props )
return new QgsCptCityColorRampV2( schemeName, variantName );
}

QColor QgsCptCityColorRampV2::color( double value ) const
{
int numStops = mPalette.count();
if ( mPalette.isEmpty() || value < 0 || value > 1 || numStops < 2 )
return QColor( 255, 0, 0 ); // red color as a warning :)

double lower = 0, upper = 0;
QColor c1, c2;
c1 = mPalette[0].second;
for ( int i = 0; i < numStops; i++ )
{
if ( mPalette[i].first > value )
{
if ( mGradientType == Discrete )
return c1;

upper = mPalette[i].first;
c2 = mPalette[i].second;

return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
}

lower = mPalette[i].first;
c1 = mPalette[i].second;
}

if ( mGradientType == Discrete )
return c1;

upper = 1;
c2 = mPalette[ numStops - 1 ].second;

return upper == lower ? c1 : _interpolate( c1, c2, ( value - lower ) / ( upper - lower ) );
}

QgsVectorColorRampV2* QgsCptCityColorRampV2::clone() const
{
QgsCptCityColorRampV2* ramp = new QgsCptCityColorRampV2( "", "", false );
Expand All @@ -363,15 +327,14 @@ void QgsCptCityColorRampV2::copy( const QgsCptCityColorRampV2* other )
{
if ( ! other )
return;
mColor1 = other->color1();
mColor2 = other->color2();
mDiscrete = other->isDiscrete();
mStops = other->stops();
mSchemeName = other->mSchemeName;
mVariantName = other->mVariantName;
mVariantList = other->mVariantList;
mFileLoaded = other->mFileLoaded;
if ( other->mFileLoaded )
{
mGradientType = other->mGradientType;
mPalette = other->mPalette;
}
}

QgsStringMap QgsCptCityColorRampV2::properties() const
Expand Down Expand Up @@ -434,12 +397,13 @@ bool QgsCptCityColorRampV2::loadFile()

// add colors to palette
mFileLoaded = false;
mPalette.clear();
mStops.clear();
QMap<double, QPair<QColor, QColor> >::const_iterator it, prev;
// first detect if file is gradient is continuous or dicrete
// discrete: stop contains 2 colors and first color is identical to previous second
// multi: stop contains 2 colors and no relation with previous stop
mGradientType = Continuous;
mDiscrete = false;
mMultiStops = false;
it = prev = colorMap.constBegin();
while ( it != colorMap.constEnd() )
{
Expand All @@ -448,12 +412,12 @@ bool QgsCptCityColorRampV2::loadFile()
{
if ( it.value().first == prev.value().second )
{
mGradientType = Discrete;
mDiscrete = true;
break;
}
else
{
mGradientType = ContinuousMulti;
mMultiStops = true;
break;
}
}
Expand All @@ -464,17 +428,19 @@ bool QgsCptCityColorRampV2::loadFile()
it = prev = colorMap.constBegin();
while ( it != colorMap.constEnd() )
{
if ( mGradientType == Discrete )
if ( mDiscrete )
{
mPalette << qMakePair( it.key(), it.value().second );
// mPalette << qMakePair( it.key(), it.value().second );
mStops.append( QgsGradientStop( it.key(), it.value().second ) );
}
else
{
mPalette << qMakePair( it.key(), it.value().first );
if (( mGradientType == ContinuousMulti ) &&
// mPalette << qMakePair( it.key(), it.value().first );
mStops.append( QgsGradientStop( it.key(), it.value().first ) );
if (( mMultiStops ) &&
( it.key() != 0.0 && it.key() != 1.0 ) )
{
mPalette << qMakePair( it.key(), it.value().second );
mStops.append( QgsGradientStop( it.key(), it.value().second ) );
}
}
prev = it;
Expand Down

0 comments on commit 31c11ed

Please sign in to comment.