00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "qgsrubberband.h"
00018 #include "qgsfeature.h"
00019 #include "qgsgeometry.h"
00020 #include "qgslogger.h"
00021 #include "qgsmapcanvas.h"
00022 #include "qgsmaprenderer.h"
00023 #include "qgsvectorlayer.h"
00024 #include <QPainter>
00025
00031 QgsRubberBand::QgsRubberBand( QgsMapCanvas* mapCanvas, bool isPolygon )
00032 : QgsMapCanvasItem( mapCanvas ), mIsPolygon( isPolygon ), mTranslationOffsetX( 0.0 ), mTranslationOffsetY( 0.0 )
00033 {
00034 reset( isPolygon );
00035 setColor( QColor( Qt::lightGray ) );
00036 }
00037
00038 QgsRubberBand::QgsRubberBand(): QgsMapCanvasItem( 0 )
00039 {}
00040
00041 QgsRubberBand::~QgsRubberBand()
00042 {}
00043
00047 void QgsRubberBand::setColor( const QColor & color )
00048 {
00049 mPen.setColor( color );
00050 QColor fillColor( color.red(), color.green(), color.blue(), 63 );
00051 mBrush.setColor( fillColor );
00052 mBrush.setStyle( Qt::SolidPattern );
00053 }
00054
00058 void QgsRubberBand::setWidth( int width )
00059 {
00060 mPen.setWidth( width );
00061 }
00062
00066 void QgsRubberBand::reset( bool isPolygon )
00067 {
00068 mPoints.clear();
00069 mIsPolygon = isPolygon;
00070 updateRect();
00071 update();
00072 }
00073
00077 void QgsRubberBand::addPoint( const QgsPoint & p, bool do_update , int geometryIndex )
00078 {
00079 if ( geometryIndex < 0 )
00080 {
00081 geometryIndex = mPoints.size() - 1;
00082 }
00083
00084 if ( geometryIndex < 0 || geometryIndex > mPoints.size() )
00085 {
00086 return;
00087 }
00088
00089 if ( geometryIndex == mPoints.size() )
00090 {
00091 mPoints.push_back( QList<QgsPoint>() );
00092 }
00093
00094
00095 if ( mPoints[geometryIndex].size() == 0 )
00096 {
00097 mPoints[geometryIndex].push_back( p );
00098 }
00099 mPoints[geometryIndex].push_back( p );
00100
00101 if ( do_update )
00102 {
00103 updateRect();
00104 update();
00105 }
00106 }
00107
00108 void QgsRubberBand::removeLastPoint( int geometryIndex )
00109 {
00110 if ( mPoints.size() < geometryIndex + 1 )
00111 {
00112 return;
00113 }
00114
00115 if ( mPoints[geometryIndex].size() > 0 )
00116 {
00117 mPoints[geometryIndex].pop_back();
00118 }
00119
00120 updateRect();
00121 update();
00122 }
00123
00127 void QgsRubberBand::movePoint( const QgsPoint & p, int geometryIndex )
00128 {
00129 if ( mPoints.size() < geometryIndex + 1 )
00130 {
00131 return;
00132 }
00133
00134 if ( mPoints.at( geometryIndex ).size() < 1 )
00135 {
00136 return;
00137 }
00138
00139 mPoints[geometryIndex][mPoints.at( geometryIndex ).size() - 1] = p;
00140
00141 updateRect();
00142 update();
00143 }
00144
00145 void QgsRubberBand::movePoint( int index, const QgsPoint& p, int geometryIndex )
00146 {
00147 if ( mPoints.size() < geometryIndex + 1 )
00148 {
00149 return;
00150 }
00151
00152 if ( mPoints.at( geometryIndex ).size() < index )
00153 {
00154 return;
00155 }
00156
00157 mPoints[geometryIndex][index] = p;
00158
00159 updateRect();
00160 update();
00161 }
00162
00163 void QgsRubberBand::setToGeometry( QgsGeometry* geom, QgsVectorLayer* layer )
00164 {
00165 reset( mIsPolygon );
00166 addGeometry( geom, layer );
00167 }
00168
00169 void QgsRubberBand::addGeometry( QgsGeometry* geom, QgsVectorLayer* layer )
00170 {
00171 if ( !geom )
00172 {
00173 return;
00174 }
00175
00176
00177 QgsMapRenderer* mr = mMapCanvas->mapRenderer();
00178 if ( !mr )
00179 {
00180 return;
00181 }
00182
00183 int idx = mPoints.size();
00184
00185 switch ( geom->wkbType() )
00186 {
00187
00188 case QGis::WKBPoint:
00189 case QGis::WKBPoint25D:
00190 {
00191 mIsPolygon = true;
00192 double d = mMapCanvas->extent().width() * 0.005;
00193 QgsPoint pt;
00194 if ( layer )
00195 {
00196 pt = mr->layerToMapCoordinates( layer, geom->asPoint() );
00197 }
00198 else
00199 {
00200 pt = geom->asPoint();
00201 }
00202 addPoint( QgsPoint( pt.x() - d, pt.y() - d ), false, idx );
00203 addPoint( QgsPoint( pt.x() + d, pt.y() - d ), false, idx );
00204 addPoint( QgsPoint( pt.x() + d, pt.y() + d ), false, idx );
00205 addPoint( QgsPoint( pt.x() - d, pt.y() + d ), false, idx );
00206 }
00207 break;
00208
00209 case QGis::WKBMultiPoint:
00210 case QGis::WKBMultiPoint25D:
00211 {
00212 mIsPolygon = true;
00213 double d = mMapCanvas->extent().width() * 0.005;
00214 QgsMultiPoint mpt = geom->asMultiPoint();
00215 for ( int i = 0; i < mpt.size(); ++i, ++idx )
00216 {
00217 QgsPoint pt = mpt[i];
00218 if ( layer )
00219 {
00220 addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() - d, pt.y() - d ) ), false, idx );
00221 addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() + d, pt.y() - d ) ), false, idx );
00222 addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() + d, pt.y() + d ) ), false, idx );
00223 addPoint( mr->layerToMapCoordinates( layer, QgsPoint( pt.x() - d, pt.y() + d ) ), false, idx );
00224 }
00225 else
00226 {
00227 addPoint( QgsPoint( pt.x() - d, pt.y() - d ), false, idx );
00228 addPoint( QgsPoint( pt.x() + d, pt.y() - d ), false, idx );
00229 addPoint( QgsPoint( pt.x() + d, pt.y() + d ), false, idx );
00230 addPoint( QgsPoint( pt.x() - d, pt.y() + d ), false, idx );
00231 }
00232 }
00233 }
00234 break;
00235
00236 case QGis::WKBLineString:
00237 case QGis::WKBLineString25D:
00238 {
00239 mIsPolygon = false;
00240 QgsPolyline line = geom->asPolyline();
00241 for ( int i = 0; i < line.count(); i++ )
00242 {
00243 if ( layer )
00244 {
00245 addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx );
00246 }
00247 else
00248 {
00249 addPoint( line[i], false, idx );
00250 }
00251 }
00252 }
00253 break;
00254
00255 case QGis::WKBMultiLineString:
00256 case QGis::WKBMultiLineString25D:
00257 {
00258 mIsPolygon = false;
00259 mPoints.clear();
00260
00261 QgsMultiPolyline mline = geom->asMultiPolyline();
00262 for ( int i = 0; i < mline.size(); ++i, ++idx )
00263 {
00264 QgsPolyline line = mline[i];
00265 for ( int j = 0; j < line.size(); ++j )
00266 {
00267 if ( layer )
00268 {
00269 addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx );
00270 }
00271 else
00272 {
00273 addPoint( line[j], false, idx );
00274 }
00275 }
00276 }
00277 }
00278 break;
00279
00280 case QGis::WKBPolygon:
00281 case QGis::WKBPolygon25D:
00282 {
00283 mIsPolygon = true;
00284 QgsPolygon poly = geom->asPolygon();
00285 QgsPolyline line = poly[0];
00286 for ( int i = 0; i < line.count(); i++ )
00287 {
00288 if ( layer )
00289 {
00290 addPoint( mr->layerToMapCoordinates( layer, line[i] ), false, idx );
00291 }
00292 else
00293 {
00294 addPoint( line[i], false, idx );
00295 }
00296 }
00297 }
00298 break;
00299
00300 case QGis::WKBMultiPolygon:
00301 case QGis::WKBMultiPolygon25D:
00302 {
00303 mIsPolygon = true;
00304 mPoints.clear();
00305
00306 QgsMultiPolygon multipoly = geom->asMultiPolygon();
00307 for ( int i = 0; i < multipoly.size(); ++i, ++idx )
00308 {
00309 QgsPolygon poly = multipoly[i];
00310 QgsPolyline line = poly[0];
00311 for ( int j = 0; j < line.count(); ++j )
00312 {
00313 if ( layer )
00314 {
00315 addPoint( mr->layerToMapCoordinates( layer, line[j] ), false, idx );
00316 }
00317 else
00318 {
00319 addPoint( line[j], false, idx );
00320 }
00321 }
00322 }
00323 }
00324 break;
00325
00326 case QGis::WKBUnknown:
00327 default:
00328 return;
00329 }
00330
00331 updateRect();
00332 update();
00333 }
00334
00338 void QgsRubberBand::paint( QPainter* p )
00339 {
00340 QList<QgsPoint> currentList;
00341 if ( mPoints.size() > 0 )
00342 {
00343 p->setPen( mPen );
00344 p->setBrush( mBrush );
00345
00346 for ( int i = 0; i < mPoints.size(); ++i )
00347 {
00348 QPolygonF pts;
00349 QList<QgsPoint>::const_iterator it = mPoints.at( i ).constBegin();
00350 for ( ; it != mPoints.at( i ).constEnd(); ++it )
00351 {
00352
00353 pts.append( toCanvasCoordinates( QgsPoint( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY ) ) - pos() );
00354 }
00355
00356 if ( mIsPolygon )
00357 {
00358 p->drawPolygon( pts );
00359 }
00360 else
00361 {
00362 p->drawPolyline( pts );
00363 }
00364 }
00365 }
00366 }
00367
00368 void QgsRubberBand::updateRect()
00369 {
00370 if ( mPoints.size() > 0 )
00371 {
00372
00373 QList<QgsPoint>::const_iterator it = mPoints.at( 0 ).constBegin();
00374 if ( it == mPoints.at( 0 ).constEnd() )
00375 {
00376 return;
00377 }
00378 QgsRectangle r( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY,
00379 it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY );
00380
00381 for ( int i = 0; i < mPoints.size(); ++i )
00382 {
00383 QList<QgsPoint>::const_iterator it = mPoints.at( i ).constBegin();
00384 for ( ; it != mPoints.at( i ).constEnd(); ++it )
00385 {
00386 r.combineExtentWith( it->x() + mTranslationOffsetX, it->y() + mTranslationOffsetY );
00387
00388 }
00389
00390 }
00391 setRect( r );
00392 }
00393 else
00394 {
00395 setRect( QgsRectangle() );
00396 }
00397 setVisible( mPoints.size() > 0 );
00398 }
00399
00400 void QgsRubberBand::setTranslationOffset( double dx, double dy )
00401 {
00402 mTranslationOffsetX = dx;
00403 mTranslationOffsetY = dy;
00404 updateRect();
00405 }
00406
00407 int QgsRubberBand::size() const
00408 {
00409 return mPoints.size();
00410 }
00411
00412 int QgsRubberBand::numberOfVertices() const
00413 {
00414 int count = 0;
00415 QList<QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
00416 for ( ; it != mPoints.constEnd(); ++it )
00417 {
00418 QList<QgsPoint>::const_iterator iter = it->constBegin();
00419 for ( ; iter != it->constEnd(); ++iter )
00420 {
00421 ++count;
00422 }
00423 }
00424 return count;
00425 }
00426
00427 const QgsPoint *QgsRubberBand::getPoint( int i, int j ) const
00428 {
00429 if ( i < mPoints.size() && j < mPoints[i].size() )
00430 return &mPoints[i][j];
00431 else
00432 return 0;
00433 }
00434
00435 QgsGeometry *QgsRubberBand::asGeometry()
00436 {
00437 QgsGeometry *geom = NULL;
00438 if ( mIsPolygon )
00439 {
00440 QgsPolygon polygon;
00441 QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
00442 for ( ; it != mPoints.constEnd(); ++it )
00443 {
00444 polygon.append( getPolyline( *it ) );
00445 }
00446 geom = QgsGeometry::fromPolygon( polygon );
00447 }
00448 else
00449 {
00450 if ( mPoints.size() > 0 )
00451 {
00452 if ( mPoints.size() > 1 )
00453 {
00454 QgsMultiPolyline multiPolyline;
00455 QList< QList<QgsPoint> >::const_iterator it = mPoints.constBegin();
00456 for ( ; it != mPoints.constEnd(); ++it )
00457 {
00458 multiPolyline.append( getPolyline( *it ) );
00459 }
00460 geom = QgsGeometry::fromMultiPolyline( multiPolyline );
00461 }
00462 else
00463 {
00464 geom = QgsGeometry::fromPolyline( getPolyline( mPoints[0] ) );
00465 }
00466 }
00467 }
00468 return geom;
00469 }
00470
00471 QgsPolyline QgsRubberBand::getPolyline( const QList<QgsPoint> & points )
00472 {
00473 QgsPolyline polyline;
00474 QList<QgsPoint>::const_iterator iter = points.constBegin();
00475 for ( ; iter != points.constEnd(); ++iter )
00476 {
00477 polyline.append( *iter );
00478 }
00479 return polyline;
00480 }