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