Quantum GIS API Documentation
1.8
|
00001 /*************************************************************************** 00002 qgscontinuouscolorrenderer.cpp - description 00003 ------------------- 00004 begin : Nov 2003 00005 copyright : (C) 2003 by Marco Hugentobler 00006 email : [email protected] 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 }