Quantum GIS API Documentation  1.8
src/core/renderer/qgscontinuouscolorrenderer.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                          qgscontinuouscolorrenderer.cpp  -  description
00003                              -------------------
00004     begin                : Nov 2003
00005     copyright            : (C) 2003 by Marco Hugentobler
00006     email                : mhugent@geo.unizh.ch
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "qgscontinuouscolorrenderer.h"
00019 #include "qgsmarkercatalogue.h"
00020 #include "qgssymbol.h"
00021 #include "qgssymbologyutils.h"
00022 #include "qgsvectordataprovider.h"
00023 #include "qgsvectorlayer.h"
00024 #include "qgsrendercontext.h"
00025 
00026 #include <cfloat>
00027 #include <QDomElement>
00028 #include <QPainter>
00029 #include <QImage>
00030 
00031 QgsContinuousColorRenderer::QgsContinuousColorRenderer( QGis::GeometryType type ): mMinimumSymbol( 0 ), mMaximumSymbol( 0 )
00032 {
00033   mGeometryType = type;
00034 }
00035 
00036 QgsContinuousColorRenderer::QgsContinuousColorRenderer( const QgsContinuousColorRenderer& other )
00037 {
00038   mGeometryType = other.mGeometryType;
00039   mClassificationField = other.mClassificationField;
00040   mMinimumSymbol = new QgsSymbol( *other.mMinimumSymbol );
00041   mMaximumSymbol = new QgsSymbol( *other.mMaximumSymbol );
00042 }
00043 
00044 QgsContinuousColorRenderer& QgsContinuousColorRenderer::operator=( const QgsContinuousColorRenderer & other )
00045 {
00046   if ( this != &other )
00047   {
00048     mGeometryType = other.mGeometryType;
00049     mClassificationField = other.mClassificationField;
00050     delete mMinimumSymbol;
00051     delete mMaximumSymbol;
00052     mMinimumSymbol = new QgsSymbol( *other.mMinimumSymbol );
00053     mMaximumSymbol = new QgsSymbol( *other.mMaximumSymbol );
00054   }
00055   return *this;
00056 }
00057 
00058 QgsContinuousColorRenderer::~QgsContinuousColorRenderer()
00059 {
00060   delete mMinimumSymbol;
00061   delete mMaximumSymbol;
00062 }
00063 
00064 void QgsContinuousColorRenderer::setMinimumSymbol( QgsSymbol* sy )
00065 {
00066   delete mMinimumSymbol;
00067   mMinimumSymbol = sy;
00068 }
00069 
00070 void QgsContinuousColorRenderer::setMaximumSymbol( QgsSymbol* sy )
00071 {
00072   delete mMaximumSymbol;
00073   mMaximumSymbol = sy;
00074 }
00075 
00076 void QgsContinuousColorRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature & f, QImage* img, bool selected, double opacity )
00077 {
00078   QPainter *p = renderContext.painter();
00079 
00080   if (( mMinimumSymbol && mMaximumSymbol ) )
00081   {
00082     //first find out the value for the classification attribute
00083     const QgsAttributeMap& attrs = f.attributeMap();
00084     if ( attrs[mClassificationField].isNull() )
00085     {
00086       if ( img )
00087         *img = QImage();
00088     }
00089     double fvalue = attrs[mClassificationField].toDouble();
00090 
00091     //double fvalue = vec[mClassificationField].fieldValue().toDouble();
00092     double minvalue = mMinimumSymbol->lowerValue().toDouble();
00093     double maxvalue = mMaximumSymbol->lowerValue().toDouble();
00094 
00095     QColor mincolor, maxcolor;
00096 
00097     if ( mGeometryType == QGis::Line || mGeometryType == QGis::Point )
00098     {
00099       mincolor = mMinimumSymbol->pen().color();
00100       maxcolor = mMaximumSymbol->pen().color();
00101     }
00102     else                    //if polygon
00103     {
00104       p->setPen( mMinimumSymbol->pen() );
00105       mincolor = mMinimumSymbol->fillColor();
00106       maxcolor = mMaximumSymbol->fillColor();
00107     }
00108 
00109     int red, green, blue;
00110 
00111     if (( maxvalue - minvalue ) != 0 )
00112     {
00113       red = int ( maxcolor.red() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.red() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
00114       green = int ( maxcolor.green() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.green() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
00115       blue =  int ( maxcolor.blue() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.blue() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
00116     }
00117     else
00118     {
00119       red = int ( mincolor.red() );
00120       green = int ( mincolor.green() );
00121       blue = int ( mincolor.blue() );
00122     }
00123 
00124     if ( mGeometryType == QGis::Point && img )
00125     {
00126       // TODO we must get always new marker -> slow, but continuous color for points
00127       // probably is not used frequently
00128 
00129 
00130       // Use color for both pen and brush (user can add another layer with outpine)
00131       // later add support for both pen and brush to dialog
00132       QPen pen = mMinimumSymbol->pen();
00133       pen.setColor( QColor( red, green, blue ) );
00134       pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
00135 
00136       QBrush brush = mMinimumSymbol->brush();
00137 
00138       if ( selected )
00139       {
00140         pen.setColor( mSelectionColor );
00141         brush.setColor( mSelectionColor );
00142       }
00143       else
00144       {
00145         brush.setColor( QColor( red, green, blue ) );
00146       }
00147       brush.setStyle( Qt::SolidPattern );
00148 
00149       *img = QgsMarkerCatalogue::instance()->imageMarker( mMinimumSymbol->pointSymbolName(),
00150              mMinimumSymbol->pointSize() * renderContext.scaleFactor() * renderContext.rasterScaleFactor(),
00151              pen, brush, opacity );
00152 
00153     }
00154     else if ( mGeometryType == QGis::Line )
00155     {
00156       QPen linePen;
00157       linePen.setColor( QColor( red, green, blue ) );
00158       linePen.setWidthF( renderContext.scaleFactor()*mMinimumSymbol->pen().widthF() );
00159       p->setPen( linePen );
00160     }
00161     else //polygon
00162     {
00163       p->setBrush( QColor( red, green, blue ) );
00164       if ( mDrawPolygonOutline )
00165       {
00166         QPen pen;
00167         pen.setColor( QColor( 0, 0, 0 ) );
00168         pen.setWidthF( renderContext.scaleFactor()*mMinimumSymbol->pen().widthF() );
00169         p->setPen( pen );
00170       }
00171       else
00172       {
00173         p->setPen( Qt::NoPen );
00174       }
00175     }
00176     if ( selected )
00177     {
00178       //for polygons we don't use selection color for outline
00179       //otherwise adjacent features appear merged when selected
00180       if ( mGeometryType != QGis::Polygon )
00181       {
00182         QPen pen = mMinimumSymbol->pen();
00183         pen.setColor( mSelectionColor );
00184         p->setPen( pen );
00185       }
00186       QBrush brush = mMinimumSymbol->brush();
00187       brush.setColor( mSelectionColor );
00188       p->setBrush( brush );
00189     }
00190   }
00191 }
00192 
00193 int QgsContinuousColorRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl )
00194 {
00195   mGeometryType = vl.geometryType();
00196   QDomNode classnode = rnode.namedItem( "classificationfield" );
00197   QString classificationField = classnode.toElement().text();
00198 
00199   QgsVectorDataProvider* theProvider = vl.dataProvider();
00200   if ( !theProvider )
00201   {
00202     return 1;
00203   }
00204   int classificationId = theProvider->fieldNameIndex( classificationField );
00205   if ( classificationId == -1 )
00206   {
00207     //go on. Because with joins, it might be the joined layer is not loaded yet
00208   }
00209   setClassificationField( classificationId );
00210 
00211   //polygon outline
00212   QDomNode polyoutlinenode = rnode.namedItem( "polygonoutline" );
00213   QString polyoutline = polyoutlinenode.toElement().text();
00214   if ( polyoutline == "0" )
00215   {
00216     mDrawPolygonOutline = false;
00217   }
00218   else if ( polyoutline == "1" )
00219   {
00220     mDrawPolygonOutline = true;
00221   }
00222 
00223   //read the settings for the renderitem of the minimum value
00224   QDomNode lowernode = rnode.namedItem( "lowestsymbol" );
00225   QDomNode lsymbolnode = lowernode.namedItem( "symbol" );
00226   if ( ! lsymbolnode.isNull() )
00227   {
00228     QgsSymbol* lsy = new QgsSymbol( mGeometryType );
00229     lsy->readXML( lsymbolnode, &vl );
00230     setMinimumSymbol( lsy );
00231   }
00232   QDomNode uppernode = rnode.namedItem( "highestsymbol" );
00233   QDomNode usymbolnode = uppernode.namedItem( "symbol" );
00234   if ( ! usymbolnode.isNull() )
00235   {
00236     QgsSymbol* usy = new QgsSymbol( mGeometryType );
00237     usy->readXML( usymbolnode, &vl );
00238     setMaximumSymbol( usy );
00239   }
00240   vl.setRenderer( this );
00241   return 0;
00242 }
00243 
00244 QgsAttributeList QgsContinuousColorRenderer::classificationAttributes() const
00245 {
00246   QgsAttributeList list;
00247   list.append( mClassificationField );
00248   return list;
00249 }
00250 
00251 QString QgsContinuousColorRenderer::name() const
00252 {
00253   return "Continuous Color";
00254 }
00255 
00256 bool QgsContinuousColorRenderer::writeXML( QDomNode & layer_node, QDomDocument & document, const QgsVectorLayer& vl ) const
00257 {
00258   const QgsVectorDataProvider* theProvider = vl.dataProvider();
00259   if ( !theProvider )
00260   {
00261     return false;
00262   }
00263 
00264   QString classificationFieldName;
00265   QgsFieldMap::const_iterator field_it = theProvider->fields().find( mClassificationField );
00266   if ( field_it != theProvider->fields().constEnd() )
00267   {
00268     classificationFieldName = field_it.value().name();
00269   }
00270   bool returnval = true;
00271 
00272   QDomElement continuoussymbol = document.createElement( "continuoussymbol" );
00273   layer_node.appendChild( continuoussymbol );
00274   QDomElement classificationfield = document.createElement( "classificationfield" );
00275   QDomText classificationfieldtxt = document.createTextNode( classificationFieldName );
00276   classificationfield.appendChild( classificationfieldtxt );
00277   continuoussymbol.appendChild( classificationfield );
00278 
00279   //polygon outlines
00280   QDomElement drawPolygonOutlines = document.createElement( "polygonoutline" );
00281   int drawPolyInt = mDrawPolygonOutline ? 1 : 0;
00282   QDomText drawPolygonText = document.createTextNode( QString::number( drawPolyInt ) );
00283   drawPolygonOutlines.appendChild( drawPolygonText );
00284   continuoussymbol.appendChild( drawPolygonOutlines );
00285 
00286   QDomElement lowestsymbol = document.createElement( "lowestsymbol" );
00287   continuoussymbol.appendChild( lowestsymbol );
00288   if ( mMinimumSymbol )
00289   {
00290     mMinimumSymbol->writeXML( lowestsymbol, document, &vl );
00291   }
00292   QDomElement highestsymbol = document.createElement( "highestsymbol" );
00293   continuoussymbol.appendChild( highestsymbol );
00294   if ( mMaximumSymbol )
00295   {
00296     mMaximumSymbol->writeXML( highestsymbol, document, &vl );
00297   }
00298 
00299   return returnval;
00300 }
00301 
00302 const QList<QgsSymbol*> QgsContinuousColorRenderer::symbols() const
00303 {
00304   QList<QgsSymbol*> list;
00305   list.append( mMinimumSymbol );
00306   list.append( mMaximumSymbol );
00307   return list;
00308 }
00309 
00310 QgsRenderer* QgsContinuousColorRenderer::clone() const
00311 {
00312   QgsContinuousColorRenderer* r = new QgsContinuousColorRenderer( *this );
00313   return r;
00314 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines