|
Quantum GIS API Documentation
master-2bfffaa
|
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 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 QString name = f.attribute( mSymbol0->symbolField() ).toString(); 00121 QgsDebugMsgLevel( QString( "Feature has name %1" ).arg( name ), 3 ); 00122 00123 if ( !mSymbols.contains( name ) ) 00124 { 00125 sy = new QgsSymbol( mGeometryType ); 00126 sy->setNamedPointSymbol( name ); 00127 mSymbols[ name ] = sy; 00128 } 00129 else 00130 { 00131 sy = mSymbols[ name ]; 00132 } 00133 00134 sy->setPointSize( mSymbol0->pointSize() ); 00135 sy->setPointSizeUnits( mSymbol0->pointSizeUnits() ); 00136 } 00137 00138 if ( mSymbol0->scaleClassificationField() >= 0 ) 00139 { 00140 //first find out the value for the scale classification attribute 00141 fieldScale = sqrt( qAbs( f.attribute( mSymbol0->scaleClassificationField() ).toDouble() ) ); 00142 QgsDebugMsgLevel( QString( "Feature has field scale factor %1" ).arg( fieldScale ), 3 ); 00143 } 00144 if ( mSymbol0->rotationClassificationField() >= 0 ) 00145 { 00146 rotation = f.attribute( mSymbol0->rotationClassificationField() ).toDouble(); 00147 QgsDebugMsgLevel( QString( "Feature has rotation factor %1" ).arg( rotation ), 3 ); 00148 } 00149 00150 double scale = renderContext.scaleFactor(); 00151 00152 if ( sy->pointSizeUnits() ) 00153 { 00154 scale = 1.0 / renderContext.mapToPixel().mapUnitsPerPixel(); 00155 } 00156 00157 *img = sy->getPointSymbolAsImage( scale, selected, mSelectionColor, fieldScale, rotation, renderContext.rasterScaleFactor(), opacity ); 00158 } 00159 00160 // Line, polygon 00161 if ( mGeometryType != QGis::Point ) 00162 { 00163 if ( !selected ) 00164 { 00165 QPen pen = mSymbol0->pen(); 00166 pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); 00167 p->setPen( pen ); 00168 00169 if ( mGeometryType == QGis::Polygon ) 00170 { 00171 QBrush brush = mSymbol0->brush(); 00172 scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout 00173 p->setBrush( brush ); 00174 } 00175 } 00176 else 00177 { 00178 QPen pen = mSymbol0->pen(); 00179 pen.setWidthF( renderContext.scaleFactor() * pen.widthF() ); 00180 if ( mGeometryType == QGis::Polygon ) 00181 { 00182 QBrush brush = mSymbol0->brush(); 00183 scaleBrush( brush, renderContext.rasterScaleFactor() ); //scale brush content for printout 00184 brush.setColor( mSelectionColor ); 00185 p->setBrush( brush ); 00186 } 00187 else //for lines we draw in selection color 00188 { 00189 // We set pen color in case it is an area with no brush (transparent). 00190 // Previously, this was only done for lines. Why? 00191 pen.setColor( mSelectionColor ); 00192 } 00193 p->setPen( pen ); 00194 } 00195 } 00196 } 00197 00198 int QgsSingleSymbolRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl ) 00199 { 00200 mGeometryType = vl.geometryType(); 00201 QgsSymbol* sy = new QgsSymbol( mGeometryType ); 00202 00203 QDomNode synode = rnode.namedItem( "symbol" ); 00204 00205 if ( synode.isNull() ) 00206 { 00207 QgsDebugMsg( "No symbol node in project file's renderitem Dom" ); 00208 // XXX abort? 00209 } 00210 else 00211 { 00212 sy->readXML( synode, &vl ); 00213 } 00214 updateSymbolAttributes(); 00215 00216 //create a renderer and add it to the vector layer 00217 addSymbol( sy ); 00218 vl.setRenderer( this ); 00219 return 0; 00220 } 00221 00222 bool QgsSingleSymbolRenderer::writeXML( QDomNode & layer_node, QDomDocument & document, const QgsVectorLayer& vl ) const 00223 { 00224 bool returnval = false; 00225 QDomElement singlesymbol = document.createElement( "singlesymbol" ); 00226 layer_node.appendChild( singlesymbol ); 00227 00228 if ( mSymbol0 ) 00229 { 00230 returnval = mSymbol0->writeXML( singlesymbol, document, &vl ); 00231 } 00232 return returnval; 00233 } 00234 00235 00236 QgsAttributeList QgsSingleSymbolRenderer::classificationAttributes() const 00237 { 00238 return mSymbolAttributes; 00239 } 00240 00241 void QgsSingleSymbolRenderer::updateSymbolAttributes() 00242 { 00243 // This function is only called after changing field specifier in the GUI. 00244 // Timing is not so important. 00245 00246 mSymbolAttributes.clear(); 00247 int rotationField = mSymbol0->rotationClassificationField(); 00248 if ( rotationField >= 0 && !( mSymbolAttributes.contains( rotationField ) ) ) 00249 { 00250 mSymbolAttributes.append( rotationField ); 00251 } 00252 int scaleField = mSymbol0->scaleClassificationField(); 00253 if ( scaleField >= 0 && !( mSymbolAttributes.contains( scaleField ) ) ) 00254 { 00255 mSymbolAttributes.append( scaleField ); 00256 } 00257 int symbolField = mSymbol0->symbolField(); 00258 if ( symbolField >= 0 && !( mSymbolAttributes.contains( symbolField ) ) ) 00259 { 00260 mSymbolAttributes.append( symbolField ); 00261 } 00262 } 00263 00264 QString QgsSingleSymbolRenderer::name() const 00265 { 00266 return "Single Symbol"; 00267 } 00268 00269 const QList<QgsSymbol*> QgsSingleSymbolRenderer::symbols() const 00270 { 00271 return mSymbols.values(); 00272 } 00273 00274 QgsRenderer* QgsSingleSymbolRenderer::clone() const 00275 { 00276 QgsSingleSymbolRenderer* r = new QgsSingleSymbolRenderer( *this ); 00277 return r; 00278 }