1 /***************************************************************************
2     qgsmapmouseevent.cpp  -  mouse event in map coordinates and ability to snap
3     ----------------------
4     begin                : October 2014
5     copyright            : (C) Denis Rouzaud
6     email                : denis.rouzaud@gmail.com
7  ***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 
16 
17 #include "qgsmapmouseevent.h"
18 #include "qgsmapcanvas.h"
19 
20 #include "qgssnappingutils.h"
21 #include "qgssnappingconfig.h"
22 
QgsMapMouseEvent(QgsMapCanvas * mapCanvas,QMouseEvent * event)23 QgsMapMouseEvent::QgsMapMouseEvent( QgsMapCanvas *mapCanvas, QMouseEvent *event )
24   : QMouseEvent( event->type(), event->pos(), event->button(), event->buttons(), event->modifiers() )
25   , mHasCachedSnapResult( false )
26   , mOriginalMapPoint( mapCanvas ? mapCanvas->mapSettings().mapToPixel().toMapCoordinates( event->pos() ) : QgsPointXY() )
27   , mMapPoint( mOriginalMapPoint )
28   , mPixelPoint( event->pos() )
29   , mMapCanvas( mapCanvas )
30 {
31 }
32 
QgsMapMouseEvent(QgsMapCanvas * mapCanvas,QEvent::Type type,QPoint pos,Qt::MouseButton button,Qt::MouseButtons buttons,Qt::KeyboardModifiers modifiers)33 QgsMapMouseEvent::QgsMapMouseEvent( QgsMapCanvas *mapCanvas, QEvent::Type type, QPoint pos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers )
34   : QMouseEvent( type, pos, button, buttons, modifiers )
35   , mHasCachedSnapResult( false )
36   , mOriginalMapPoint( mapCanvas ? mapCanvas->mapSettings().mapToPixel().toMapCoordinates( pos ) : QgsPointXY() )
37   , mMapPoint( mOriginalMapPoint )
38   , mPixelPoint( pos )
39   , mMapCanvas( mapCanvas )
40 {
41 }
42 
snapPoint()43 QgsPointXY QgsMapMouseEvent::snapPoint()
44 {
45   // Use cached result
46   if ( mHasCachedSnapResult )
47     return mMapPoint;
48 
49   mHasCachedSnapResult = true;
50 
51   QgsSnappingUtils *snappingUtils = mMapCanvas->snappingUtils();
52   mSnapMatch = snappingUtils->snapToMap( mMapPoint, nullptr, true );
53 
54   if ( mSnapMatch.isValid() )
55   {
56     mMapPoint = mSnapMatch.point();
57     mPixelPoint = mapToPixelCoordinates( mMapPoint );
58   }
59   else
60   {
61     mMapPoint = mOriginalMapPoint;
62     mPixelPoint = pos();
63   }
64 
65   return mMapPoint;
66 }
67 
setMapPoint(const QgsPointXY & point)68 void QgsMapMouseEvent::setMapPoint( const QgsPointXY &point )
69 {
70   mMapPoint = point;
71   mPixelPoint = mapToPixelCoordinates( point );
72 }
73 
snapToGrid(double precision,const QgsCoordinateReferenceSystem & crs)74 void QgsMapMouseEvent::snapToGrid( double precision, const QgsCoordinateReferenceSystem &crs )
75 {
76   if ( precision <= 0 )
77     return;
78 
79   try
80   {
81     QgsCoordinateTransform ct( mMapCanvas->mapSettings().destinationCrs(), crs, mMapCanvas->mapSettings().transformContext() );
82 
83     QgsPointXY pt = ct.transform( mMapPoint );
84 
85     pt.setX( std::round( pt.x() / precision ) * precision );
86     pt.setY( std::round( pt.y() / precision ) * precision );
87 
88     pt = ct.transform( pt, QgsCoordinateTransform::ReverseTransform );
89 
90     setMapPoint( pt );
91   }
92   catch ( QgsCsException &e )
93   {
94     Q_UNUSED( e )
95   }
96 }
97 
mapToPixelCoordinates(const QgsPointXY & point)98 QPoint QgsMapMouseEvent::mapToPixelCoordinates( const QgsPointXY &point )
99 {
100   double x = point.x(), y = point.y();
101 
102   mMapCanvas->mapSettings().mapToPixel().transformInPlace( x, y );
103 
104   return QPoint( std::round( x ), std::round( y ) );
105 }
106