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