Quantum GIS API Documentation
1.7.4
|
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 }