Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgsrubberband.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsrubberband.cpp - Rubberband widget for drawing multilines and polygons
3  --------------------------------------
4  Date : 07-Jan-2006
5  Copyright : (C) 2006 by Tom Elwertowski
6  Email : telwertowski at users dot sourceforge dot net
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 /* $Id$ */
16 
17 #include "qgsrubberband.h"
18 #include "qgsfeature.h"
19 #include "qgsgeometry.h"
20 #include "qgslogger.h"
21 #include "qgsmapcanvas.h"
22 #include "qgsmaprenderer.h"
23 #include "qgsvectorlayer.h"
24 #include <QPainter>
25 
31 QgsRubberBand::QgsRubberBand( QgsMapCanvas* mapCanvas, bool isPolygon )
32  : QgsMapCanvasItem( mapCanvas )
33  , mIsPolygon( isPolygon )
34  , mTranslationOffsetX( 0.0 )
35  , mTranslationOffsetY( 0.0 )
36 {
37  reset( isPolygon );
38  setColor( QColor( Qt::lightGray ) );
39 }
40 
42 {
43 }
44 
46 {
47 }
48 
52 void QgsRubberBand::setColor( const QColor & color )
53 {
54  mPen.setColor( color );
55  QColor fillColor( color.red(), color.green(), color.blue(), 63 );
56  mBrush.setColor( fillColor );
57  mBrush.setStyle( Qt::SolidPattern );
58 }
59 
63 void QgsRubberBand::setWidth( int width )
64 {
65  mPen.setWidth( width );
66 }
67 
71 void QgsRubberBand::reset( bool isPolygon )
72 {
73  mPoints.clear();
74  mIsPolygon = isPolygon;
75  updateRect();
76  update();
77 }
78 
82 void QgsRubberBand::addPoint( const QgsPoint & p, bool do_update /* = true */, int geometryIndex )
83 {
84  if ( geometryIndex < 0 )
85  {
86  geometryIndex = mPoints.size() - 1;
87  }
88 
89  if ( geometryIndex < 0 || geometryIndex > mPoints.size() )
90  {
91  return;
92  }
93 
94  if ( geometryIndex == mPoints.size() )
95  {
96  mPoints.push_back( QList<QgsPoint>() << p );
97  }
98 
99  if ( mPoints[geometryIndex].size() == 2 &&
100  mPoints[geometryIndex][0] == mPoints[geometryIndex][1] )
101  {
102  mPoints[geometryIndex].last() = p;
103  }
104  else
105  {
106  mPoints[geometryIndex] << p;
107  }
108 
109 
110  if ( do_update )
111  {
112  updateRect();
113  update();
114  }
115 }
116 
117 void QgsRubberBand::removeLastPoint( int geometryIndex )
118 {
119  if ( mPoints.size() < geometryIndex + 1 )
120  {
121  return;
122  }
123 
124  if ( mPoints[geometryIndex].size() > 0 )
125  {
126  mPoints[geometryIndex].pop_back();
127  }
128 
129  updateRect();
130  update();
131 }
132 
136 void QgsRubberBand::movePoint( const QgsPoint & p, int geometryIndex )
137 {
138  if ( mPoints.size() < geometryIndex + 1 )
139  {
140  return;
141  }
142 
143  if ( mPoints.at( geometryIndex ).size() < 1 )
144  {
145  return;
146  }
147 
148  mPoints[geometryIndex].last() = p;
149 
150  updateRect();
151  update();
152 }
153 
154 void QgsRubberBand::movePoint( int index, const QgsPoint& p, int geometryIndex )
155 {
156  if ( mPoints.size() < geometryIndex + 1 )
157  {
158  return;
159  }
160 
161  if ( mPoints.at( geometryIndex ).size() < index )
162  {
163  return;
164  }
165 
166  mPoints[geometryIndex][index] = p;
167 
168  updateRect();
169  update();
170 }
171 
173 {
174  reset( mIsPolygon );
175  addGeometry( geom, layer );
176 }
177 
179 {
180  if ( !geom )
181  {
182  return;
183  }
184 
185  //maprender object of canvas
187  if ( !mr )
188  {
189  return;
190  }
191 
192  int idx = mPoints.size();
193 
194  switch ( geom->wkbType() )
195  {
196 
197  case QGis::WKBPoint:
198  case QGis::WKBPoint25D:
199  {
200  mIsPolygon = true;
201  double d = mMapCanvas->extent().width() * 0.005;
202  QgsPoint pt;
203  if ( layer )
204  {
205  pt = mr->layerToMapCoordinates( layer, geom->asPoint() );
206  }
207  else
208  {
209  pt = geom->asPoint();
210  }
211  addPoint( QgsPoint( pt.x() - d, pt.y() - d ), false, idx );
212  addPoint( QgsPoint( pt.x() + d, pt.y() - d ), false, idx );
213  addPoint( QgsPoint( pt.x() + d, pt.y() + d ), false, idx );
214  addPoint( QgsPoint( pt.x() - d, pt.y() + d ), false, idx );
215  }
216  break;
217 
218  case QGis::WKBMultiPoint:
220  {
221  mIsPolygon = true;
222  double d = mMapCanvas->extent().width() * 0.005;
223  QgsMultiPoint mpt = geom->asMultiPoint();
224  for ( int i = 0; i < mpt.size(); ++i, ++idx )
225  {
226  QgsPoint pt = mpt[i];
227  if ( layer )
228  {
229  addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() - d, pt.y() - d ) ), false, idx );
230  addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() + d, pt.y() - d ) ), false, idx );
231  addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() + d, pt.y() + d ) ), false, idx );
232  addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() - d, pt.y() + d ) ), false, idx );
233  }
234  else
235  {
236  addPoint( QgsPoint( pt.x() - d, pt.y() - d ), false, idx );
237  addPoint( QgsPoint( pt.x() + d, pt.y() - d ), false, idx );
238  addPoint( QgsPoint( pt.x() + d, pt.y() + d ), false, idx );
239  addPoint( QgsPoint( pt.x() - d, pt.y() + d ), false, idx );
240  }
241  }
242  }
243  break;
244 
245  case QGis::WKBLineString:
247  {
248  mIsPolygon = false;
249  QgsPolyline line = geom->asPolyline();
250  for ( int i = 0; i < line.count(); i++ )
251  {
252  if ( layer )
253  {
254  addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx );
255  }
256  else
257  {
258  addPoint( line[i], false, idx );
259  }
260  }
261  }
262  break;
263 
266  {
267  mIsPolygon = false;
268  mPoints.clear();
269 
270  QgsMultiPolyline mline = geom->asMultiPolyline();
271  for ( int i = 0; i < mline.size(); ++i, ++idx )
272  {
273  QgsPolyline line = mline[i];
274  for ( int j = 0; j < line.size(); ++j )
275  {
276  if ( layer )
277  {
278  addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx );
279  }
280  else
281  {
282  addPoint( line[j], false, idx );
283  }
284  }
285  }
286  }
287  break;
288 
289  case QGis::WKBPolygon:
290  case QGis::WKBPolygon25D:
291  {
292  mIsPolygon = true;
293  QgsPolygon poly = geom->asPolygon();
294  QgsPolyline line = poly[0];
295  for ( int i = 0; i < line.count(); i++ )
296  {
297  if ( layer )
298  {
299  addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx );
300  }
301  else
302  {
303  addPoint( line[i], false, idx );
304  }
305  }
306  }
307  break;
308 
311  {
312  mIsPolygon = true;
313  mPoints.clear();
314 
315  QgsMultiPolygon multipoly = geom->asMultiPolygon();
316  for ( int i = 0; i < multipoly.size(); ++i, ++idx )
317  {
318  QgsPolygon poly = multipoly[i];
319  QgsPolyline line = poly[0];
320  for ( int j = 0; j < line.count(); ++j )
321  {
322  if ( layer )
323  {
324  addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx );
325  }
326  else
327  {
328  addPoint( line[j], false, idx );
329  }
330  }
331  }
332  }
333  break;
334 
335  case QGis::WKBUnknown:
336  default:
337  return;
338  }
339 
340  updateRect();
341  update();
342 }
343 
344 void QgsRubberBand::setToCanvasRectangle( const QRect& rect )
345 {
346  if ( !mMapCanvas )
347  {
348  return;
349  }
350 
351  const QgsMapToPixel* transform = mMapCanvas->getCoordinateTransform();
352  QgsPoint ll = transform->toMapCoordinates( rect.left(), rect.bottom() );
353  QgsPoint ur = transform->toMapCoordinates( rect.right(), rect.top() );
354 
355  reset( true );
356  addPoint( ll, false );
357  addPoint( QgsPoint( ur.x(), ll.y() ), false );
358  addPoint( ur, false );
359  addPoint( QgsPoint( ll.x(), ur.y() ), true );
360 }
361 
365 void QgsRubberBand::paint( QPainter* p )
366 {
367  QList<QgsPoint> currentList;
368  if ( mPoints.size() > 0 )
369  {
370  p->setPen( mPen );
371  p->setBrush( mBrush );
372 
373  for ( int i = 0; i < mPoints.size(); ++i )
374  {
375  QPolygonF pts;
376  QList<QgsPoint>::const_iterator it = mPoints.at( i ).constBegin();
377  for ( ; it != mPoints.at( i ).constEnd(); ++it )
378  {
379  pts.append( toCanvasCoordinates( QgsPoint( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY ) ) - pos() );
380  }
381 
382  if ( mIsPolygon )
383  {
384  p->drawPolygon( pts );
385  }
386  else
387  {
388  p->drawPolyline( pts );
389  }
390  }
391  }
392 }
393 
395 {
396  if ( mPoints.size() > 0 )
397  {
398  //initial point
399  QList<QgsPoint>::const_iterator it = mPoints.at( 0 ).constBegin();
400  if ( it == mPoints.at( 0 ).constEnd() )
401  {
402  return;
403  }
404  QgsRectangle r( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY,
405  it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY );
406 
407  for ( int i = 0; i < mPoints.size(); ++i )
408  {
409  QList<QgsPoint>::const_iterator it = mPoints.at( i ).constBegin();
410  for ( ; it != mPoints.at( i ).constEnd(); ++it )
411  {
412  r.combineExtentWith( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY );
413  }
414  }
415  setRect( r );
416  }
417  else
418  {
419  setRect( QgsRectangle() );
420  }
421  setVisible( mPoints.size() > 0 );
422 }
423 
424 void QgsRubberBand::setTranslationOffset( double dx, double dy )
425 {
426  mTranslationOffsetX = dx;
427  mTranslationOffsetY = dy;
428  updateRect();
429 }
430 
432 {
433  return mPoints.size();
434 }
435 
437 {
438  int count = 0;
439  QList<QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
440  for ( ; it != mPoints.constEnd(); ++it )
441  {
442  QList<QgsPoint>::const_iterator iter = it->constBegin();
443  for ( ; iter != it->constEnd(); ++iter )
444  {
445  ++count;
446  }
447  }
448  return count;
449 }
450 
451 const QgsPoint *QgsRubberBand::getPoint( int i, int j ) const
452 {
453  if ( i < mPoints.size() && j < mPoints[i].size() )
454  return &mPoints[i][j];
455  else
456  return 0;
457 }
458 
460 {
461  QgsGeometry *geom = NULL;
462  if ( mIsPolygon )
463  {
464  QgsPolygon polygon;
465  QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
466  for ( ; it != mPoints.constEnd(); ++it )
467  {
468  polygon.append( getPolyline( *it ) );
469  }
470  geom = QgsGeometry::fromPolygon( polygon );
471  }
472  else
473  {
474  if ( mPoints.size() > 0 )
475  {
476  if ( mPoints.size() > 1 )
477  {
478  QgsMultiPolyline multiPolyline;
479  QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
480  for ( ; it != mPoints.constEnd(); ++it )
481  {
482  multiPolyline.append( getPolyline( *it ) );
483  }
484  geom = QgsGeometry::fromMultiPolyline( multiPolyline );
485  }
486  else
487  {
489  }
490  }
491  }
492  return geom;
493 }
494 
495 QgsPolyline QgsRubberBand::getPolyline( const QList<QgsPoint> & points )
496 {
497  QgsPolyline polyline;
498  QList<QgsPoint>::const_iterator iter = points.constBegin();
499  for ( ; iter != points.constEnd(); ++iter )
500  {
501  polyline.append( *iter );
502  }
503  return polyline;
504 }