QISG学习之-在图层上画图

来源:互联网 发布:淘宝买家查号131458 编辑:程序博客网 时间:2024/06/05 10:16

研究过源码的人都知道 QGIS对于在地图上的功能操作都是通过QgsMapTool来管理的,有一篇博客有详细讲解:http://blog.csdn.net/deirjie/article/details/50878670


所以要实现画图也很简单了。


首先继承QgsMapTool,这里提供了各种坐标转换,我们当然非常需要。


#ifndef MEASURETOOL_H

#define MEASURETOOL_H
#include <qgsmaptool.h>
#include <QList>
class QgsDistanceArea;
class QgsMapCanvas;
class QgsRubberBand;
class  MeasureTool : public QgsMapTool
{
    Q_OBJECT
  public:
    MeasureTool( QgsMapCanvas* canvas, bool measureArea );
    ~MeasureTool();
    //virtual Flags flags() const override { return QgsMapTool::AllowZoomRect; }
    //! returns whether measuring distance or area
    bool measureArea() { return mMeasureArea; }
    //! When we have added our last point, and not following
    bool done() { return mDone; }
    //! Reset and start new
    void restart();
    //! Add new point
    void addPoint( const QgsPoint &point );
    //! Returns reference to array of the points
    const QList<QgsPoint>& points();
    // Inherited from QgsMapTool
    //! Mouse move event for overriding
    virtual void canvasMoveEvent( QgsMapMouseEvent* e ) override;
    //! Mouse press event for overriding
    virtual void canvasPressEvent( QgsMapMouseEvent* e ) override;
    //! Mouse release event for overriding
    virtual void canvasReleaseEvent( QgsMapMouseEvent* e ) override;
    //! called when set as currently active map tool
    virtual void activate() override;
    //! called when map tool is being deactivated
    virtual void deactivate() override;
    virtual void keyPressEvent( QKeyEvent* e ) override;
  public slots:
    //! updates the projections we're using
    void updateSettings();
  protected:
    QList<QgsPoint> mPoints;
    //! Rubberband widget tracking the lines being drawn
    QgsRubberBand *mRubberBand;
    //! Rubberband widget tracking the added nodes to line
    QgsRubberBand *mRubberBandPoints;
    //! indicates whether we're measuring distances or areas
    bool mMeasureArea;
    //! indicates whether we've just done a right mouse click
    bool mDone;
    //! indicates whether we've recently warned the user about having the wrong
    // project projection
    bool mWrongProjectProjection;
    //! Destination CoordinateReferenceSystem used by the MapCanvas
    QgsCoordinateReferenceSystem mDestinationCrs;
    //! Returns the snapped (map) coordinate
    //@param p (pixel) coordinate
    QgsPoint snapPoint( const QPoint& p );
    /** Removes the last vertex from mRubberBand*/
    void undo();
};
#endif // MEASURETOOL_H


源文件:

#include "qgsdistancearea.h"

#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsmaprenderer.h"
#include "qgsmaptopixel.h"
#include "qgsrubberband.h"
#include "qgsvectorlayer.h"
#include "qgssnappingutils.h"
#include "qgstolerance.h"
#include "qgscursors.h"
#include "qgsmessagelog.h"
#include "MeasureTool.h"
#include <QMessageBox>
#include <QMouseEvent>
#include <QSettings>
MeasureTool::MeasureTool( QgsMapCanvas* canvas, bool measureArea )
    : QgsMapTool( canvas )
    , mWrongProjectProjection( false )
{
  mMeasureArea = measureArea;
  mRubberBand = new QgsRubberBand( canvas, mMeasureArea ? QGis::Polygon : QGis::Line );
  mRubberBand->setIcon(QgsRubberBand::ICON_FULL_BOX);
  mRubberBandPoints = new QgsRubberBand( canvas, QGis::Point );
  QPixmap myCrossHairQPixmap = QPixmap(( const char ** ) cross_hair_cursor );
  mCursor = QCursor( myCrossHairQPixmap, 8, 8 );
  mDone = true;
  // Append point we will move
  mPoints.append( QgsPoint( 0, 0 ) );
  mDestinationCrs = canvas->mapSettings().destinationCrs();
//  mDialog = new QgsMeasureDialog( this );
//  mDialog->setWindowFlags( mDialog->windowFlags() | Qt::Tool );
//  mDialog->restorePosition();
  connect( canvas, SIGNAL( destinationCrsChanged() ),
           this, SLOT( updateSettings() ) );
}
MeasureTool::~MeasureTool()
{
 // delete mDialog;
  delete mRubberBand;
  delete mRubberBandPoints;
}
const QList<QgsPoint>& MeasureTool::points()
{
  return mPoints;
}
void MeasureTool::activate()
{
 // mDialog->show();
  QgsMapTool::activate();
  // ensure that we have correct settings
  updateSettings();
  // If we suspect that they have data that is projected, yet the
  // map CRS is set to a geographic one, warn them.
  if ( mCanvas->mapSettings().destinationCrs().geographicFlag() &&
       ( mCanvas->extent().height() > 360 ||
         mCanvas->extent().width() > 720 ) )
  {
    QMessageBox::warning( nullptr, tr( "Incorrect measure results" ),
                          tr( "<p>This map is defined with a geographic coordinate system "
                              "(latitude/longitude) "
                              "but the map extents suggests that it is actually a projected "
                              "coordinate system (e.g., Mercator). "
                              "If so, the results from line or area measurements will be "
                              "incorrect.</p>"
                              "<p>To fix this, explicitly set an appropriate map coordinate "
                              "system using the <tt>Settings:Project Properties</tt> menu." ) );
    mWrongProjectProjection = true;
  }
}
void MeasureTool::deactivate()
{
 // mDialog->hide();
  QgsMapTool::deactivate();
}
void MeasureTool::restart()
{
  mPoints.clear();
  mRubberBand->reset( mMeasureArea ? QGis::Polygon : QGis::Line );
  mRubberBandPoints->reset( QGis::Point );
  mDone = true;
  mWrongProjectProjection = false;
}
void MeasureTool::updateSettings()
{
  QSettings settings;
  int myRed = settings.value( "/qgis/default_measure_color_red", 222 ).toInt();
  int myGreen = settings.value( "/qgis/default_measure_color_green", 155 ).toInt();
  int myBlue = settings.value( "/qgis/default_measure_color_blue", 67 ).toInt();
  mRubberBand->setColor( QColor( myRed, myGreen, myBlue, 100 ) );
  mRubberBand->setWidth( 3 );
  mRubberBandPoints->setIcon( QgsRubberBand::ICON_CIRCLE );
  mRubberBandPoints->setIconSize( 10 );
  mRubberBandPoints->setColor( QColor( myRed, myGreen, myBlue, 150 ) );
  // Reproject the points to the new destination CoordinateReferenceSystem
  if ( mRubberBand->size() > 0 && mDestinationCrs != mCanvas->mapSettings().destinationCrs() )
  {
    QList<QgsPoint> points = mPoints;
    bool lastDone = mDone;
   // mDialog->restart();
    mDone = lastDone;
    QgsCoordinateTransform ct( mDestinationCrs, mCanvas->mapSettings().destinationCrs() );
    Q_FOREACH ( const QgsPoint& previousPoint, points )
    {
      try
      {
        QgsPoint point = ct.transform( previousPoint );
        mPoints.append( point );
        mRubberBand->addPoint( point, false );
        mRubberBandPoints->addPoint( point, false );
      }
      catch ( QgsCsException &cse )
      {
        QgsMessageLog::logMessage( QString( "Transform error caught at the MeasureTool: %1" ).arg( cse.what() ) );
      }
    }
    mRubberBand->updatePosition();
    mRubberBand->update();
    mRubberBandPoints->updatePosition();
    mRubberBandPoints->update();
  }
  mDestinationCrs = mCanvas->mapSettings().destinationCrs();
  //mDialog->updateSettings();
  if ( !mDone && mRubberBand->size() > 0 )
  {
    mRubberBand->addPoint( mPoints.last() );
   // mDialog->addPoint( mPoints.last() );
  }
  if ( mRubberBand->size() > 0 )
  {
    mRubberBand->setVisible( true );
    mRubberBandPoints->setVisible( true );
  }
}
//////////////////////////
void MeasureTool::canvasPressEvent( QgsMapMouseEvent* e )
{
  Q_UNUSED( e );
}
void MeasureTool::canvasMoveEvent( QgsMapMouseEvent* e )
{
  if ( ! mDone )
  {
    QgsPoint point = snapPoint( e->pos() );
    mRubberBand->movePoint( point );
   // mDialog->mouseMove( point );
  }
}
void MeasureTool::canvasReleaseEvent( QgsMapMouseEvent* e )
{
  QgsPoint point = snapPoint( e->pos() );
  if ( mDone ) // if we have stopped measuring any mouse click restart measuring
  {
    //mDialog->restart();
  }
  if ( e->button() == Qt::RightButton ) // if we clicked the right button we stop measuring
  {
    mDone = true;
  }
  else if ( e->button() == Qt::LeftButton )
  {
    mDone = false;
  }
  // we always add the clicked point to the measuring feature
  addPoint( point );
 // mDialog->show();
}
void MeasureTool::undo()
{
  if ( mRubberBand )
  {
    if ( mPoints.size() < 1 )
    {
      return;
    }
    if ( mPoints.size() == 1 )
    {
      //removing first point, so restart everything
      restart();
     // mDialog->restart();
    }
    else
    {
      //remove second last point from line band, and last point from points band
      mRubberBand->removePoint( -2, true );
      mRubberBandPoints->removePoint( -1, true );
      mPoints.removeLast();
     // mDialog->removeLastPoint();
    }
  }
}
void MeasureTool::keyPressEvent( QKeyEvent* e )
{
  if (( e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete ) )
  {
    if ( !mDone )
    {
      undo();
    }
    // Override default shortcut management in MapCanvas
    e->ignore();
  }
}
void MeasureTool::addPoint( const QgsPoint &point )
{
  QgsDebugMsg( "point=" + point.toString() );
  // don't add points with the same coordinates
  if ( !mPoints.isEmpty() && mPoints.last() == point )
  {
    return;
  }
  QgsPoint pnt( point );
  // Append point that we will be moving.
  mPoints.append( pnt );
  mRubberBand->addPoint( point );
  mRubberBandPoints->addPoint( point );
  if ( ! mDone )    // Prevent the insertion of a new item in segments measure table
  {
    //mDialog->addPoint( point );
  }
}
QgsPoint MeasureTool::snapPoint( const QPoint& p )
{
  QgsPointLocator::Match m = mCanvas->snappingUtils()->snapToMap( p );
  return m.isValid() ? m.point() : mCanvas->getCoordinateTransform()->toMapCoordinates( p );
}


使用

 线段:

MeasureTool*addFeatureTool =new MeasureTool( mapCanvas, false);

mapCanvas->setMapTool( addFeatureTool );
面积:

MeasureTool*addFeatureTool =new MeasureTool( mapCanvas, true);

mapCanvas->setMapTool( addFeatureTool );