1 /***************************************************************************
2 qgsmaptoolrectangle3points.cpp - map tool for adding rectangle
3 from 3 points
4 ---------------------
5 begin : September 2017
6 copyright : (C) 2017 by Loïc Bartoletti
7 email : lbartoletti at tuxfamily dot org
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 3 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include "qgsmaptoolrectangle3points.h"
18 #include "qgsgeometryrubberband.h"
19 #include "qgsgeometryutils.h"
20 #include "qgslinestring.h"
21 #include "qgsmapcanvas.h"
22 #include "qgspoint.h"
23 #include "qgsmapmouseevent.h"
24 #include <memory>
25 #include "qgssnapindicator.h"
26
QgsMapToolRectangle3Points(QgsMapToolCapture * parentTool,QgsMapCanvas * canvas,CreateMode createMode,CaptureMode mode)27 QgsMapToolRectangle3Points::QgsMapToolRectangle3Points( QgsMapToolCapture *parentTool,
28 QgsMapCanvas *canvas, CreateMode createMode, CaptureMode mode )
29 : QgsMapToolAddRectangle( parentTool, canvas, mode ),
30 mCreateMode( createMode )
31 {
32 mToolName = tr( "Add rectangle from 3 points" );
33 }
34
cadCanvasReleaseEvent(QgsMapMouseEvent * e)35 void QgsMapToolRectangle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
36 {
37 QgsPoint point = mapPoint( *e );
38
39 if ( !currentVectorLayer() )
40 {
41 notifyNotVectorLayer();
42 clean();
43 stopCapturing();
44 e->ignore();
45 return;
46 }
47
48 if ( e->button() == Qt::LeftButton )
49 {
50 bool is3D = false;
51 QgsVectorLayer *currentLayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
52 if ( currentLayer )
53 is3D = QgsWkbTypes::hasZ( currentLayer->wkbType() );
54
55 if ( is3D && !point.is3D() )
56 point.addZValue( defaultZValue() );
57
58 if ( mPoints.size() < 2 )
59 {
60 mPoints.append( point );
61 }
62
63 if ( !mPoints.isEmpty() && !mTempRubberBand )
64 {
65 mTempRubberBand = createGeometryRubberBand( mLayerType, true );
66 mTempRubberBand->show();
67 }
68 if ( mPoints.size() == 3 )
69 {
70 delete mTempRubberBand;
71 mTempRubberBand = createGeometryRubberBand( mLayerType, true ); // recreate rubberband for polygon
72 }
73 }
74 else if ( e->button() == Qt::RightButton )
75 {
76 release( e );
77 }
78 }
79
cadCanvasMoveEvent(QgsMapMouseEvent * e)80 void QgsMapToolRectangle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e )
81 {
82 QgsPoint point = mapPoint( *e );
83
84 mSnapIndicator->setMatch( e->mapPointMatch() );
85
86 if ( mTempRubberBand )
87 {
88 switch ( mPoints.size() )
89 {
90 case 1:
91 {
92 std::unique_ptr<QgsLineString> line( new QgsLineString() );
93 line->addVertex( mPoints.at( 0 ) );
94 line->addVertex( point );
95 mTempRubberBand->setGeometry( line.release() );
96 }
97 break;
98 case 2:
99 {
100 bool is3D = false;
101 QgsVectorLayer *currentLayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
102 if ( currentLayer )
103 is3D = QgsWkbTypes::hasZ( currentLayer->wkbType() );
104
105 if ( is3D && !point.is3D() )
106 point.addZValue( defaultZValue() );
107
108 switch ( mCreateMode )
109 {
110 case DistanceMode:
111 mRectangle = QgsQuadrilateral::rectangleFrom3Points( mPoints.at( 0 ), mPoints.at( 1 ), point, QgsQuadrilateral::Distance );
112 break;
113 case ProjectedMode:
114 mRectangle = QgsQuadrilateral::rectangleFrom3Points( mPoints.at( 0 ), mPoints.at( 1 ), point, QgsQuadrilateral::Projected );
115 break;
116 }
117 mTempRubberBand->setGeometry( mRectangle.toPolygon( ) );
118 }
119 break;
120 default:
121 break;
122 }
123 }
124 }
125