Quantum GIS API Documentation
1.7.4
|
00001 /*************************************************************************** 00002 qgssinglesymbolrenderer.cpp - description 00003 ------------------- 00004 begin : Oct 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: qgssinglesymbolrenderer.cpp 5371 2006-04-25 01:52:13Z wonder $ */ 00018 00019 #include "qgis.h" 00020 #include "qgssinglesymbolrenderer.h" 00021 00022 #include "qgsfeature.h" 00023 #include "qgslogger.h" 00024 #include "qgssymbol.h" 00025 #include "qgssymbologyutils.h" 00026 #include "qgsvectorlayer.h" 00027 #include "qgsrendercontext.h" 00028 00029 #include <QDomNode> 00030 #include <QImage> 00031 #include <QPainter> 00032 #include <QString> 00033 #include <cmath> 00034 00035 QgsSingleSymbolRenderer::QgsSingleSymbolRenderer( QGis::GeometryType type ) 00036 { 00037 mGeometryType = type; 00038 00039 //initial setting based on random color 00040 QgsSymbol* sy = new QgsSymbol( mGeometryType ); 00041 00042 //random fill colors for points and polygons and pen colors for lines 00043 int red = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); 00044 int green = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); 00045 int blue = 1 + ( int )( 255.0 * rand() / ( RAND_MAX + 1.0 ) ); 00046 00047 if ( type == QGis::Line ) 00048 { 00049 sy->setColor( QColor( red, green, blue ) ); 00050 } 00051 else 00052 { 00053 sy->setFillColor( QColor( red, green, blue ) ); 00054 sy->setFillStyle( Qt::SolidPattern ); 00055 sy->setColor( QColor( 0, 0, 0 ) ); 00056 } 00057 mSymbol0 = sy; 00058 mSymbols[ QString()] = sy; 00059 updateSymbolAttributes(); 00060 } 00061 00062 QgsSingleSymbolRenderer::QgsSingleSymbolRenderer( const QgsSingleSymbolRenderer& other ) 00063 { 00064 *this = other; 00065 } 00066 00067 QgsSingleSymbolRenderer& QgsSingleSymbolRenderer::operator=( const QgsSingleSymbolRenderer & other ) 00068 { 00069 if ( this != &other ) 00070 { 00071 mGeometryType = other.mGeometryType; 00072 00073 for ( QMap<QString, QgsSymbol *>::const_iterator it = other.mSymbols.begin(); it != other.mSymbols.end(); it++ ) 00074 mSymbols[ it.key()] = new QgsSymbol( *it.value() ); 00075 00076 if ( mSymbols.size() > 0 ) 00077 { 00078 mSymbol0 = mSymbols[0]; 00079 } 00080 else 00081 { 00082 mSymbol0 = 0; 00083 } 00084 } 00085 updateSymbolAttributes(); 00086 return *this; 00087 } 00088 00089 QgsSingleSymbolRenderer::~QgsSingleSymbolRenderer() 00090 { 00091 for ( QMap<QString, QgsSymbol *>::iterator it = mSymbols.begin(); it != mSymbols.end(); it++ ) 00092 delete it.value(); 00093 } 00094 00095 void QgsSingleSymbolRenderer::addSymbol( QgsSymbol *sy ) 00096 { 00097 for ( QMap<QString, QgsSymbol *>::iterator it = mSymbols.begin(); it != mSymbols.end(); it++ ) 00098 delete it.value(); 00099 00100 mSymbol0 = sy; 00101 mSymbols[ QString()] = sy; 00102 00103 updateSymbolAttributes(); 00104 } 00105 00106 void QgsSingleSymbolRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature & f, QImage* img, bool selected, double opacity ) 00107 { 00108 QPainter *p = renderContext.painter(); 00109 00110 // Point 00111 if ( img && mGeometryType == QGis::Point ) 00112 { 00113 00114 // If scale field is non-negative, use it to scale. 00115 double fieldScale = 1.0; 00116 double rotation = 0.0; 00117 QgsSymbol *sy = mSymbol0; 00118 00119 if ( mSymbol0->symbolField() >= 0 ) 00120 { 00121 const QgsAttributeMap& attrs = f.attributeMap(); 00122 QString name = attrs[ mSymbol0->symbolField()].toString(); 00123 QgsDebugMsgLevel( QString( "Feature has name %1" ).arg( name ), 3 ); 00124 00125 if ( !mSymbols.contains( name ) ) 00126 { 00127 sy = new QgsSymbol( mGeometryType ); 00128 sy->setNamedPointSymbol( name ); 00129 mSymbols[ name ] = sy; 00130 } 00131 else 00132 { 00133 sy = mSymbols[ name ]; 00134 } 00135 00136 sy->setPointSize( mSymbol0->pointSize() ); 00137 sy->setPointSizeUnits( mSymbol0->pointSizeUnits() ); 00138 } 00139 00140 if ( mSymbol0->scaleClassificationField() >= 0 ) 00141 { 00142 //first find out the value for the scale classification attribute 00143 const QgsAttributeMap& attrs = f.attributeMap(); 00144 fieldScale = sqrt( qAbs( attrs[ mSymbol0->scaleClassificationField()].toDouble() ) ); 00145 QgsDebugMsgLevel( QString( "Feature has field scale factor %1" ).arg( fieldScale ), 3 ); 00146 } 00147 if ( mSymbol0->rotationClassificationField() >= 0 ) 00148 { 00149 const QgsAttributeMap& attrs = f.attributeMap(); 00150 rotation = attrs[ mSymbol0->rotationClassificationField()].toDouble(); 00151 QgsDebugMsgLevel( QString( "Feature has rotation factor %1" ).arg( rotation ), 3 ); 00152 } 00153 00154 double scale = renderContext.scaleFactor(); 00155 00156 if ( sy->pointSizeUnits() ) 00157 { 00158 scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel(); 00159 } 00160 00161 *img = sy->getPointSymbolAsImage( scale, selected, mSelectionColor, fieldScale, rotation, renderContext.rasterScaleFactor(), opacity ); 00162 } 00163 00164 // Line, polygon 00165 if ( mGeometryType != QGis::Point ) 00166 { 00167 if ( !selected ) 00168 { 00169 QPen pen = mSymbol0->pen(); 00170 pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); 00171 p->setPen( pen ); 00172 00173 if ( mGeometryType == QGis::Polygon ) 00174 { 00175 QBrush brush = mSymbol0->brush(); 00176 scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout 00177 p->setBrush( brush ); 00178 } 00179 } 00180 else 00181 { 00182 QPen pen = mSymbol0->pen(); 00183 pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); 00184 if ( mGeometryType == QGis::Polygon ) 00185 { 00186 QBrush brush = mSymbol0->brush(); 00187 scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout 00188 brush.setColor( mSelectionColor ); 00189 p->setBrush( brush ); 00190 } 00191 else //for lines we draw in selection color 00192 { 00193 // We set pen color in case it is an area with no brush (transparent). 00194 // Previously, this was only done for lines. Why? 00195 pen.setColor( mSelectionColor ); 00196 } 00197 p->setPen( pen ); 00198 } 00199 } 00200 } 00201 00202 int QgsSingleSymbolRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl ) 00203 { 00204 mGeometryType = vl.geometryType(); 00205 QgsSymbol* sy = new QgsSymbol( mGeometryType ); 00206 00207 QDomNode synode = rnode.namedItem( "symbol" ); 00208 00209 if ( synode.isNull() ) 00210 { 00211 QgsDebugMsg( "No symbol node in project file's renderitem Dom" ); 00212 // XXX abort? 00213 } 00214 else 00215 { 00216 sy->readXML( synode, &vl ); 00217 } 00218 updateSymbolAttributes(); 00219 00220 //create a renderer and add it to the vector layer 00221 addSymbol( sy ); 00222 vl.setRenderer( this ); 00223 return 0; 00224 } 00225 00226 bool QgsSingleSymbolRenderer::writeXML( QDomNode & layer_node, QDomDocument & document, const QgsVectorLayer& vl ) const 00227 { 00228 bool returnval = false; 00229 QDomElement singlesymbol = document.createElement( "singlesymbol" ); 00230 layer_node.appendChild( singlesymbol ); 00231 00232 if ( mSymbol0 ) 00233 { 00234 returnval = mSymbol0->writeXML( singlesymbol, document, &vl ); 00235 } 00236 return returnval; 00237 } 00238 00239 00240 QgsAttributeList QgsSingleSymbolRenderer::classificationAttributes() const 00241 { 00242 return mSymbolAttributes; 00243 } 00244 00245 void QgsSingleSymbolRenderer::updateSymbolAttributes() 00246 { 00247 // This function is only called after changing field specifier in the GUI. 00248 // Timing is not so important. 00249 00250 mSymbolAttributes.clear(); 00251 int rotationField = mSymbol0->rotationClassificationField(); 00252 if ( rotationField >= 0 && !( mSymbolAttributes.contains( rotationField ) ) ) 00253 { 00254 mSymbolAttributes.append( rotationField ); 00255 } 00256 int scaleField = mSymbol0->scaleClassificationField(); 00257 if ( scaleField >= 0 && !( mSymbolAttributes.contains( scaleField ) ) ) 00258 { 00259 mSymbolAttributes.append( scaleField ); 00260 } 00261 int symbolField = mSymbol0->symbolField(); 00262 if ( symbolField >= 0 && !( mSymbolAttributes.contains( symbolField ) ) ) 00263 { 00264 mSymbolAttributes.append( symbolField ); 00265 } 00266 } 00267 00268 QString QgsSingleSymbolRenderer::name() const 00269 { 00270 return "Single Symbol"; 00271 } 00272 00273 const QList<QgsSymbol*> QgsSingleSymbolRenderer::symbols() const 00274 { 00275 return mSymbols.values(); 00276 } 00277 00278 QgsRenderer* QgsSingleSymbolRenderer::clone() const 00279 { 00280 QgsSingleSymbolRenderer* r = new QgsSingleSymbolRenderer( *this ); 00281 return r; 00282 }