Quantum GIS API Documentation  1.8
src/gui/qgsrubberband.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002     qgsrubberband.cpp - Rubberband widget for drawing multilines and polygons
00003      --------------------------------------
00004     Date                 : 07-Jan-2006
00005     Copyright            : (C) 2006 by Tom Elwertowski
00006     Email                : telwertowski at users dot sourceforge dot net
00007  ***************************************************************************
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 
00016 #include "qgsrubberband.h"
00017 #include "qgsfeature.h"
00018 #include "qgsgeometry.h"
00019 #include "qgslogger.h"
00020 #include "qgsmapcanvas.h"
00021 #include "qgsmaprenderer.h"
00022 #include "qgsvectorlayer.h"
00023 #include <QPainter>
00024 
00030 QgsRubberBand::QgsRubberBand( QgsMapCanvas* mapCanvas, bool isPolygon )
00031     : QgsMapCanvasItem( mapCanvas )
00032     , mIsPolygon( isPolygon )
00033     , mTranslationOffsetX( 0.0 )
00034     , mTranslationOffsetY( 0.0 )
00035 {
00036   reset( isPolygon );
00037   setColor( QColor( Qt::lightGray ) );
00038 }
00039 
00040 QgsRubberBand::QgsRubberBand(): QgsMapCanvasItem( 0 )
00041 {
00042 }
00043 
00044 QgsRubberBand::~QgsRubberBand()
00045 {
00046 }
00047 
00051 void QgsRubberBand::setColor( const QColor & color )
00052 {
00053   mPen.setColor( color );
00054   QColor fillColor( color.red(), color.green(), color.blue(), 63 );
00055   mBrush.setColor( fillColor );
00056   mBrush.setStyle( Qt::SolidPattern );
00057 }
00058 
00062 void QgsRubberBand::setWidth( int width )
00063 {
00064   mPen.setWidth( width );
00065 }
00066 
00070 void QgsRubberBand::reset( bool isPolygon )
00071 {
00072   mPoints.clear();
00073   mIsPolygon = isPolygon;
00074   updateRect();
00075   update();
00076 }
00077 
00081 void QgsRubberBand::addPoint( const QgsPoint & p, bool do_update /* = true */, int geometryIndex )
00082 {
00083   if ( geometryIndex < 0 )
00084   {
00085     geometryIndex = mPoints.size() - 1;
00086   }
00087 
00088   if ( geometryIndex < 0 || geometryIndex > mPoints.size() )
00089   {
00090     return;
00091   }
00092 
00093   if ( geometryIndex == mPoints.size() )
00094   {
00095     mPoints.push_back( QList<QgsPoint>() << p );
00096   }
00097 
00098   if ( mPoints[geometryIndex].size() == 2 &&
00099        mPoints[geometryIndex][0] == mPoints[geometryIndex][1] )
00100   {
00101     mPoints[geometryIndex].last() = p;
00102   }
00103   else
00104   {
00105     mPoints[geometryIndex] << p;
00106   }
00107 
00108 
00109   if ( do_update )
00110   {
00111     updateRect();
00112     update();
00113   }
00114 }
00115 
00116 void QgsRubberBand::removeLastPoint( int geometryIndex )
00117 {
00118   if ( mPoints.size() < geometryIndex + 1 )
00119   {
00120     return;
00121   }
00122 
00123   if ( mPoints[geometryIndex].size() > 0 )
00124   {
00125     mPoints[geometryIndex].pop_back();
00126   }
00127 
00128   updateRect();
00129   update();
00130 }
00131 
00135 void QgsRubberBand::movePoint( const QgsPoint & p, int geometryIndex )
00136 {
00137   if ( mPoints.size() < geometryIndex + 1 )
00138   {
00139     return;
00140   }
00141 
00142   if ( mPoints.at( geometryIndex ).size() < 1 )
00143   {
00144     return;
00145   }
00146 
00147   mPoints[geometryIndex].last() = p;
00148 
00149   updateRect();
00150   update();
00151 }
00152 
00153 void QgsRubberBand::movePoint( int index, const QgsPoint& p, int geometryIndex )
00154 {
00155   if ( mPoints.size() < geometryIndex + 1 )
00156   {
00157     return;
00158   }
00159 
00160   if ( mPoints.at( geometryIndex ).size() < index )
00161   {
00162     return;
00163   }
00164 
00165   mPoints[geometryIndex][index] = p;
00166 
00167   updateRect();
00168   update();
00169 }
00170 
00171 void QgsRubberBand::setToGeometry( QgsGeometry* geom, QgsVectorLayer* layer )
00172 {
00173   reset( mIsPolygon );
00174   addGeometry( geom, layer );
00175 }
00176 
00177 void QgsRubberBand::addGeometry( QgsGeometry* geom, QgsVectorLayer* layer )
00178 {
00179   if ( !geom )
00180   {
00181     return;
00182   }
00183 
00184   //maprender object of canvas
00185   QgsMapRenderer* mr = mMapCanvas->mapRenderer();
00186   if ( !mr )
00187   {
00188     return;
00189   }
00190 
00191   int idx = mPoints.size();
00192 
00193   switch ( geom->wkbType() )
00194   {
00195 
00196     case QGis::WKBPoint:
00197     case QGis::WKBPoint25D:
00198     {
00199       mIsPolygon = true;
00200       double d = mMapCanvas->extent().width() * 0.005;
00201       QgsPoint pt;
00202       if ( layer )
00203       {
00204         pt = mr->layerToMapCoordinates( layer, geom->asPoint() );
00205       }
00206       else
00207       {
00208         pt = geom->asPoint();
00209       }
00210       addPoint( QgsPoint( pt.x() - d, pt.y() - d ), false, idx );
00211       addPoint( QgsPoint( pt.x() + d, pt.y() - d ), false, idx );
00212       addPoint( QgsPoint( pt.x() + d, pt.y() + d ), false, idx );
00213       addPoint( QgsPoint( pt.x() - d, pt.y() + d ), false, idx );
00214     }
00215     break;
00216 
00217     case QGis::WKBMultiPoint:
00218     case QGis::WKBMultiPoint25D:
00219     {
00220       mIsPolygon = true;
00221       double d = mMapCanvas->extent().width() * 0.005;
00222       QgsMultiPoint mpt = geom->asMultiPoint();
00223       for ( int i = 0; i < mpt.size(); ++i, ++idx )
00224       {
00225         QgsPoint pt = mpt[i];
00226         if ( layer )
00227         {
00228           addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() - d, pt.y() - d ) ), false, idx );
00229           addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() + d, pt.y() - d ) ), false, idx );
00230           addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() + d, pt.y() + d ) ), false, idx );
00231           addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() - d, pt.y() + d ) ), false, idx );
00232         }
00233         else
00234         {
00235           addPoint( QgsPoint( pt.x() - d, pt.y() - d ), false, idx );
00236           addPoint( QgsPoint( pt.x() + d, pt.y() - d ), false, idx );
00237           addPoint( QgsPoint( pt.x() + d, pt.y() + d ), false, idx );
00238           addPoint( QgsPoint( pt.x() - d, pt.y() + d ), false, idx );
00239         }
00240       }
00241     }
00242     break;
00243 
00244     case QGis::WKBLineString:
00245     case QGis::WKBLineString25D:
00246     {
00247       mIsPolygon = false;
00248       QgsPolyline line = geom->asPolyline();
00249       for ( int i = 0; i < line.count(); i++ )
00250       {
00251         if ( layer )
00252         {
00253           addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx );
00254         }
00255         else
00256         {
00257           addPoint( line[i], false, idx );
00258         }
00259       }
00260     }
00261     break;
00262 
00263     case QGis::WKBMultiLineString:
00264     case QGis::WKBMultiLineString25D:
00265     {
00266       mIsPolygon = false;
00267       mPoints.clear();
00268 
00269       QgsMultiPolyline mline = geom->asMultiPolyline();
00270       for ( int i = 0; i < mline.size(); ++i, ++idx )
00271       {
00272         QgsPolyline line = mline[i];
00273         for ( int j = 0; j < line.size(); ++j )
00274         {
00275           if ( layer )
00276           {
00277             addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx );
00278           }
00279           else
00280           {
00281             addPoint( line[j], false, idx );
00282           }
00283         }
00284       }
00285     }
00286     break;
00287 
00288     case QGis::WKBPolygon:
00289     case QGis::WKBPolygon25D:
00290     {
00291       mIsPolygon = true;
00292       QgsPolygon poly = geom->asPolygon();
00293       QgsPolyline line = poly[0];
00294       for ( int i = 0; i < line.count(); i++ )
00295       {
00296         if ( layer )
00297         {
00298           addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx );
00299         }
00300         else
00301         {
00302           addPoint( line[i], false, idx );
00303         }
00304       }
00305     }
00306     break;
00307 
00308     case QGis::WKBMultiPolygon:
00309     case QGis::WKBMultiPolygon25D:
00310     {
00311       mIsPolygon = true;
00312       mPoints.clear();
00313 
00314       QgsMultiPolygon multipoly = geom->asMultiPolygon();
00315       for ( int i = 0; i < multipoly.size(); ++i, ++idx )
00316       {
00317         QgsPolygon poly = multipoly[i];
00318         QgsPolyline line = poly[0];
00319         for ( int j = 0; j < line.count(); ++j )
00320         {
00321           if ( layer )
00322           {
00323             addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx );
00324           }
00325           else
00326           {
00327             addPoint( line[j], false, idx );
00328           }
00329         }
00330       }
00331     }
00332     break;
00333 
00334     case QGis::WKBUnknown:
00335     default:
00336       return;
00337   }
00338 
00339   updateRect();
00340   update();
00341 }
00342 
00343 void QgsRubberBand::setToCanvasRectangle( const QRect& rect )
00344 {
00345   if ( !mMapCanvas )
00346   {
00347     return;
00348   }
00349 
00350   const QgsMapToPixel* transform = mMapCanvas->getCoordinateTransform();
00351   QgsPoint ll = transform->toMapCoordinates( rect.left(), rect.bottom() );
00352   QgsPoint ur = transform->toMapCoordinates( rect.right(), rect.top() );
00353 
00354   reset( true );
00355   addPoint( ll, false );
00356   addPoint( QgsPoint( ur.x(), ll.y() ), false );
00357   addPoint( ur, false );
00358   addPoint( QgsPoint( ll.x(), ur.y() ), true );
00359 }
00360 
00364 void QgsRubberBand::paint( QPainter* p )
00365 {
00366   QList<QgsPoint> currentList;
00367   if ( mPoints.size() > 0 )
00368   {
00369     p->setPen( mPen );
00370     p->setBrush( mBrush );
00371 
00372     for ( int i = 0; i < mPoints.size(); ++i )
00373     {
00374       QPolygonF pts;
00375       QList<QgsPoint>::const_iterator it = mPoints.at( i ).constBegin();
00376       for ( ; it != mPoints.at( i ).constEnd(); ++it )
00377       {
00378         pts.append( toCanvasCoordinates( QgsPoint( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY ) ) - pos() );
00379       }
00380 
00381       if ( mIsPolygon )
00382       {
00383         p->drawPolygon( pts );
00384       }
00385       else
00386       {
00387         p->drawPolyline( pts );
00388       }
00389     }
00390   }
00391 }
00392 
00393 void QgsRubberBand::updateRect()
00394 {
00395   if ( mPoints.size() > 0 )
00396   {
00397     //initial point
00398     QList<QgsPoint>::const_iterator it = mPoints.at( 0 ).constBegin();
00399     if ( it == mPoints.at( 0 ).constEnd() )
00400     {
00401       return;
00402     }
00403     QgsRectangle r( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY,
00404                     it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY );
00405 
00406     for ( int i = 0; i < mPoints.size(); ++i )
00407     {
00408       QList<QgsPoint>::const_iterator it = mPoints.at( i ).constBegin();
00409       for ( ; it != mPoints.at( i ).constEnd(); ++it )
00410       {
00411         r.combineExtentWith( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY );
00412       }
00413     }
00414     setRect( r );
00415   }
00416   else
00417   {
00418     setRect( QgsRectangle() );
00419   }
00420   setVisible( mPoints.size() > 0 );
00421 }
00422 
00423 void QgsRubberBand::setTranslationOffset( double dx, double dy )
00424 {
00425   mTranslationOffsetX = dx;
00426   mTranslationOffsetY = dy;
00427   updateRect();
00428 }
00429 
00430 int QgsRubberBand::size() const
00431 {
00432   return mPoints.size();
00433 }
00434 
00435 int QgsRubberBand::numberOfVertices() const
00436 {
00437   int count = 0;
00438   QList<QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
00439   for ( ; it != mPoints.constEnd(); ++it )
00440   {
00441     QList<QgsPoint>::const_iterator iter = it->constBegin();
00442     for ( ; iter != it->constEnd(); ++iter )
00443     {
00444       ++count;
00445     }
00446   }
00447   return count;
00448 }
00449 
00450 const QgsPoint *QgsRubberBand::getPoint( int i, int j ) const
00451 {
00452   if ( i < mPoints.size() && j < mPoints[i].size() )
00453     return &mPoints[i][j];
00454   else
00455     return 0;
00456 }
00457 
00458 QgsGeometry *QgsRubberBand::asGeometry()
00459 {
00460   QgsGeometry *geom = NULL;
00461   if ( mIsPolygon )
00462   {
00463     QgsPolygon polygon;
00464     QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
00465     for ( ; it != mPoints.constEnd(); ++it )
00466     {
00467       polygon.append( getPolyline( *it ) );
00468     }
00469     geom = QgsGeometry::fromPolygon( polygon );
00470   }
00471   else
00472   {
00473     if ( mPoints.size() > 0 )
00474     {
00475       if ( mPoints.size() > 1 )
00476       {
00477         QgsMultiPolyline multiPolyline;
00478         QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
00479         for ( ; it != mPoints.constEnd(); ++it )
00480         {
00481           multiPolyline.append( getPolyline( *it ) );
00482         }
00483         geom = QgsGeometry::fromMultiPolyline( multiPolyline );
00484       }
00485       else
00486       {
00487         geom = QgsGeometry::fromPolyline( getPolyline( mPoints[0] ) );
00488       }
00489     }
00490   }
00491   return geom;
00492 }
00493 
00494 QgsPolyline QgsRubberBand::getPolyline( const QList<QgsPoint> & points )
00495 {
00496   QgsPolyline polyline;
00497   QList<QgsPoint>::const_iterator iter = points.constBegin();
00498   for ( ; iter != points.constEnd(); ++iter )
00499   {
00500     polyline.append( *iter );
00501   }
00502   return polyline;
00503 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines