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