Quantum GIS API Documentation
1.8
|
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 }