Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgscontinuouscolorrenderer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgscontinuouscolorrenderer.cpp - description
3  -------------------
4  begin : Nov 2003
5  copyright : (C) 2003 by Marco Hugentobler
6  email : mhugent@geo.unizh.ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 /* $Id: qgscontinuouscolorrenderer.cpp 5371 2006-04-25 01:52:13Z wonder $ */
18 
20 #include "qgsmarkercatalogue.h"
21 #include "qgssymbol.h"
22 #include "qgssymbologyutils.h"
23 #include "qgsvectordataprovider.h"
24 #include "qgsvectorlayer.h"
25 #include "qgsrendercontext.h"
26 
27 #include <cfloat>
28 #include <QDomElement>
29 #include <QPainter>
30 #include <QImage>
31 
32 QgsContinuousColorRenderer::QgsContinuousColorRenderer( QGis::GeometryType type ): mMinimumSymbol( 0 ), mMaximumSymbol( 0 )
33 {
34  mGeometryType = type;
35 }
36 
38 {
41  mMinimumSymbol = new QgsSymbol( *other.mMinimumSymbol );
42  mMaximumSymbol = new QgsSymbol( *other.mMaximumSymbol );
43 }
44 
46 {
47  if ( this != &other )
48  {
51  delete mMinimumSymbol;
52  delete mMaximumSymbol;
53  mMinimumSymbol = new QgsSymbol( *other.mMinimumSymbol );
54  mMaximumSymbol = new QgsSymbol( *other.mMaximumSymbol );
55  }
56  return *this;
57 }
58 
60 {
61  delete mMinimumSymbol;
62  delete mMaximumSymbol;
63 }
64 
66 {
67  delete mMinimumSymbol;
68  mMinimumSymbol = sy;
69 }
70 
72 {
73  delete mMaximumSymbol;
74  mMaximumSymbol = sy;
75 }
76 
77 void QgsContinuousColorRenderer::renderFeature( QgsRenderContext &renderContext, QgsFeature & f, QImage* img, bool selected, double opacity )
78 {
79  QPainter *p = renderContext.painter();
80 
81  if (( mMinimumSymbol && mMaximumSymbol ) )
82  {
83  //first find out the value for the classification attribute
84  const QgsAttributeMap& attrs = f.attributeMap();
85  if ( attrs[mClassificationField].isNull() )
86  {
87  if ( img )
88  *img = QImage();
89  }
90  double fvalue = attrs[mClassificationField].toDouble();
91 
92  //double fvalue = vec[mClassificationField].fieldValue().toDouble();
93  double minvalue = mMinimumSymbol->lowerValue().toDouble();
94  double maxvalue = mMaximumSymbol->lowerValue().toDouble();
95 
96  QColor mincolor, maxcolor;
97 
99  {
100  mincolor = mMinimumSymbol->pen().color();
101  maxcolor = mMaximumSymbol->pen().color();
102  }
103  else //if polygon
104  {
105  p->setPen( mMinimumSymbol->pen() );
106  mincolor = mMinimumSymbol->fillColor();
107  maxcolor = mMaximumSymbol->fillColor();
108  }
109 
110  int red, green, blue;
111 
112  if (( maxvalue - minvalue ) != 0 )
113  {
114  red = int ( maxcolor.red() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.red() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
115  green = int ( maxcolor.green() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.green() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
116  blue = int ( maxcolor.blue() * ( fvalue - minvalue ) / ( maxvalue - minvalue ) + mincolor.blue() * ( maxvalue - fvalue ) / ( maxvalue - minvalue ) );
117  }
118  else
119  {
120  red = int ( mincolor.red() );
121  green = int ( mincolor.green() );
122  blue = int ( mincolor.blue() );
123  }
124 
125  if ( mGeometryType == QGis::Point && img )
126  {
127  // TODO we must get always new marker -> slow, but continuous color for points
128  // probably is not used frequently
129 
130 
131  // Use color for both pen and brush (user can add another layer with outpine)
132  // later add support for both pen and brush to dialog
133  QPen pen = mMinimumSymbol->pen();
134  pen.setColor( QColor( red, green, blue ) );
135  pen.setWidthF( renderContext.scaleFactor() * pen.widthF() );
136 
137  QBrush brush = mMinimumSymbol->brush();
138 
139  if ( selected )
140  {
141  pen.setColor( mSelectionColor );
142  brush.setColor( mSelectionColor );
143  }
144  else
145  {
146  brush.setColor( QColor( red, green, blue ) );
147  }
148  brush.setStyle( Qt::SolidPattern );
149 
151  mMinimumSymbol->pointSize() * renderContext.scaleFactor() * renderContext.rasterScaleFactor(),
152  pen, brush, opacity );
153 
154  }
155  else if ( mGeometryType == QGis::Line )
156  {
157  QPen linePen;
158  linePen.setColor( QColor( red, green, blue ) );
159  linePen.setWidthF( renderContext.scaleFactor()*mMinimumSymbol->pen().widthF() );
160  p->setPen( linePen );
161  }
162  else //polygon
163  {
164  p->setBrush( QColor( red, green, blue ) );
165  if ( mDrawPolygonOutline )
166  {
167  QPen pen;
168  pen.setColor( QColor( 0, 0, 0 ) );
169  pen.setWidthF( renderContext.scaleFactor()*mMinimumSymbol->pen().widthF() );
170  p->setPen( pen );
171  }
172  else
173  {
174  p->setPen( Qt::NoPen );
175  }
176  }
177  if ( selected )
178  {
179  //for polygons we don't use selection color for outline
180  //otherwise adjacent features appear merged when selected
181  if ( mGeometryType != QGis::Polygon )
182  {
183  QPen pen = mMinimumSymbol->pen();
184  pen.setColor( mSelectionColor );
185  p->setPen( pen );
186  }
187  QBrush brush = mMinimumSymbol->brush();
188  brush.setColor( mSelectionColor );
189  p->setBrush( brush );
190  }
191  }
192 }
193 
194 int QgsContinuousColorRenderer::readXML( const QDomNode& rnode, QgsVectorLayer& vl )
195 {
197  QDomNode classnode = rnode.namedItem( "classificationfield" );
198  QString classificationField = classnode.toElement().text();
199 
200  QgsVectorDataProvider* theProvider = vl.dataProvider();
201  if ( !theProvider )
202  {
203  return 1;
204  }
205  int classificationId = theProvider->fieldNameIndex( classificationField );
206  if ( classificationId == -1 )
207  {
208  //go on. Because with joins, it might be the joined layer is not loaded yet
209  }
210  setClassificationField( classificationId );
211 
212  //polygon outline
213  QDomNode polyoutlinenode = rnode.namedItem( "polygonoutline" );
214  QString polyoutline = polyoutlinenode.toElement().text();
215  if ( polyoutline == "0" )
216  {
217  mDrawPolygonOutline = false;
218  }
219  else if ( polyoutline == "1" )
220  {
221  mDrawPolygonOutline = true;
222  }
223 
224  //read the settings for the renderitem of the minimum value
225  QDomNode lowernode = rnode.namedItem( "lowestsymbol" );
226  QDomNode lsymbolnode = lowernode.namedItem( "symbol" );
227  if ( ! lsymbolnode.isNull() )
228  {
229  QgsSymbol* lsy = new QgsSymbol( mGeometryType );
230  lsy->readXML( lsymbolnode, &vl );
231  setMinimumSymbol( lsy );
232  }
233  QDomNode uppernode = rnode.namedItem( "highestsymbol" );
234  QDomNode usymbolnode = uppernode.namedItem( "symbol" );
235  if ( ! usymbolnode.isNull() )
236  {
237  QgsSymbol* usy = new QgsSymbol( mGeometryType );
238  usy->readXML( usymbolnode, &vl );
239  setMaximumSymbol( usy );
240  }
241  vl.setRenderer( this );
242  return 0;
243 }
244 
246 {
247  QgsAttributeList list;
248  list.append( mClassificationField );
249  return list;
250 }
251 
253 {
254  return "Continuous Color";
255 }
256 
257 bool QgsContinuousColorRenderer::writeXML( QDomNode & layer_node, QDomDocument & document, const QgsVectorLayer& vl ) const
258 {
259  const QgsVectorDataProvider* theProvider = vl.dataProvider();
260  if ( !theProvider )
261  {
262  return false;
263  }
264 
265  QString classificationFieldName;
266  QgsFieldMap::const_iterator field_it = theProvider->fields().find( mClassificationField );
267  if ( field_it != theProvider->fields().constEnd() )
268  {
269  classificationFieldName = field_it.value().name();
270  }
271  bool returnval = true;
272 
273  QDomElement continuoussymbol = document.createElement( "continuoussymbol" );
274  layer_node.appendChild( continuoussymbol );
275  QDomElement classificationfield = document.createElement( "classificationfield" );
276  QDomText classificationfieldtxt = document.createTextNode( classificationFieldName );
277  classificationfield.appendChild( classificationfieldtxt );
278  continuoussymbol.appendChild( classificationfield );
279 
280  //polygon outlines
281  QDomElement drawPolygonOutlines = document.createElement( "polygonoutline" );
282  int drawPolyInt = mDrawPolygonOutline ? 1 : 0;
283  QDomText drawPolygonText = document.createTextNode( QString::number( drawPolyInt ) );
284  drawPolygonOutlines.appendChild( drawPolygonText );
285  continuoussymbol.appendChild( drawPolygonOutlines );
286 
287  QDomElement lowestsymbol = document.createElement( "lowestsymbol" );
288  continuoussymbol.appendChild( lowestsymbol );
289  if ( mMinimumSymbol )
290  {
291  mMinimumSymbol->writeXML( lowestsymbol, document, &vl );
292  }
293  QDomElement highestsymbol = document.createElement( "highestsymbol" );
294  continuoussymbol.appendChild( highestsymbol );
295  if ( mMaximumSymbol )
296  {
297  mMaximumSymbol->writeXML( highestsymbol, document, &vl );
298  }
299 
300  return returnval;
301 }
302 
303 const QList<QgsSymbol*> QgsContinuousColorRenderer::symbols() const
304 {
305  QList<QgsSymbol*> list;
306  list.append( mMinimumSymbol );
307  list.append( mMaximumSymbol );
308  return list;
309 }
310 
312 {
314  return r;
315 }