Skip to content

Commit 37b6052

Browse files
committed
Add Rectangle from 3 points
1 parent 46e66c3 commit 37b6052

8 files changed

+264
-14
lines changed

src/app/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ SET(QGIS_APP_SRCS
144144
qgsmaptooladdregularpolygon.cpp
145145
qgsmaptoolrectanglecenter.cpp
146146
qgsmaptoolrectangleextent.cpp
147+
qgsmaptoolrectangle3points.cpp
147148
qgsmaptoolsquarecenter.cpp
148149
qgsmaptoolregularpolygon2points.cpp
149150
qgsmaptoolregularpolygoncenterpoint.cpp
@@ -317,6 +318,7 @@ SET (QGIS_APP_MOC_HDRS
317318
qgsmaptooladdregularpolygon.h
318319
qgsmaptoolrectanglecenter.h
319320
qgsmaptoolrectangleextent.h
321+
qgsmaptoolrectangle3points.h
320322
qgsmaptoolsquarecenter.h
321323
qgsmaptoolregularpolygon2points.h
322324
qgsmaptoolregularpolygoncenterpoint.h

src/app/qgisapp.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
342342
#include "qgsmaptoolellipsefoci.h"
343343
#include "qgsmaptoolrectanglecenter.h"
344344
#include "qgsmaptoolrectangleextent.h"
345+
#include "qgsmaptoolrectangle3points.h"
345346
#include "qgsmaptoolsquarecenter.h"
346347
#include "qgsmaptoolregularpolygon2points.h"
347348
#include "qgsmaptoolregularpolygoncenterpoint.h"
@@ -1407,6 +1408,7 @@ QgisApp::~QgisApp()
14071408
delete mMapTools.mEllipseFoci;
14081409
delete mMapTools.mRectangleCenterPoint;
14091410
delete mMapTools.mRectangleExtent;
1411+
delete mMapTools.mRectangle3Points;
14101412
delete mMapTools.mSquareCenter;
14111413
delete mMapTools.mRegularPolygon2Points;
14121414
delete mMapTools.mRegularPolygonCenterPoint;
@@ -1866,6 +1868,7 @@ void QgisApp::createActions()
18661868
connect( mActionEllipseFoci, &QAction::triggered, this, &QgisApp::ellipseFoci );
18671869
connect( mActionRectangleCenterPoint, &QAction::triggered, this, &QgisApp::rectangleCenterPoint );
18681870
connect( mActionRectangleExtent, &QAction::triggered, this, &QgisApp::rectangleExtent );
1871+
connect( mActionRectangle3Points, &QAction::triggered, this, &QgisApp::rectangle3Points );
18691872
connect( mActionSquareCenter, &QAction::triggered, this, &QgisApp::squareCenter );
18701873
connect( mActionRegularPolygon2Points, &QAction::triggered, this, &QgisApp::regularPolygon2Points );
18711874
connect( mActionRegularPolygonCenterPoint, &QAction::triggered, this, &QgisApp::regularPolygonCenterPoint );
@@ -2153,6 +2156,7 @@ void QgisApp::createActionGroups()
21532156
mMapToolGroup->addAction( mActionEllipseFoci );
21542157
mMapToolGroup->addAction( mActionRectangleCenterPoint );
21552158
mMapToolGroup->addAction( mActionRectangleExtent );
2159+
mMapToolGroup->addAction( mActionRectangle3Points );
21562160
mMapToolGroup->addAction( mActionSquareCenter );
21572161
mMapToolGroup->addAction( mActionRegularPolygon2Points );
21582162
mMapToolGroup->addAction( mActionRegularPolygonCenterPoint );
@@ -2693,6 +2697,7 @@ void QgisApp::createToolBars()
26932697
tbAddRectangle->setPopupMode( QToolButton::MenuButtonPopup );
26942698
tbAddRectangle->addAction( mActionRectangleCenterPoint );
26952699
tbAddRectangle->addAction( mActionRectangleExtent );
2700+
tbAddRectangle->addAction( mActionRectangle3Points );
26962701
tbAddRectangle->addAction( mActionSquareCenter );
26972702
tbAddRectangle->setDefaultAction( mActionRectangleCenterPoint );
26982703
connect( tbAddRectangle, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
@@ -3296,6 +3301,8 @@ void QgisApp::createCanvasTools()
32963301
mMapTools.mRectangleCenterPoint->setAction( mActionRectangleCenterPoint );
32973302
mMapTools.mRectangleExtent = new QgsMapToolRectangleExtent( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
32983303
mMapTools.mRectangleExtent->setAction( mActionRectangleExtent );
3304+
mMapTools.mRectangle3Points = new QgsMapToolRectangle3Points( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
3305+
mMapTools.mRectangle3Points->setAction( mActionRectangle3Points );
32993306
mMapTools.mSquareCenter = new QgsMapToolSquareCenter( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
33003307
mMapTools.mSquareCenter->setAction( mActionSquareCenter );
33013308
mMapTools.mRegularPolygon2Points = new QgsMapToolRegularPolygon2Points( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
@@ -7917,6 +7924,11 @@ void QgisApp::rectangleExtent()
79177924
mMapCanvas->setMapTool( mMapTools.mRectangleExtent );
79187925
}
79197926

7927+
void QgisApp::rectangle3Points()
7928+
{
7929+
mMapCanvas->setMapTool( mMapTools.mRectangle3Points );
7930+
}
7931+
79207932
void QgisApp::squareCenter()
79217933
{
79227934
mMapCanvas->setMapTool( mMapTools.mSquareCenter );
@@ -11397,6 +11409,8 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )
1139711409
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
1139811410
mActionRectangleExtent->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
1139911411
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
11412+
mActionRectangle3Points->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
11413+
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
1140011414
mActionSquareCenter->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
1140111415
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
1140211416
mActionRegularPolygon2Points->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )

src/app/qgisapp.h

+4
Original file line numberDiff line numberDiff line change
@@ -1235,6 +1235,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
12351235
void rectangleCenterPoint();
12361236
//! activates the add rectangle from extent tool
12371237
void rectangleExtent();
1238+
//! activates the add rectangle from 3 points tool
1239+
void rectangle3Points();
12381240
//! activates the add square from center tool
12391241
void squareCenter();
12401242
//! activates the add regular polygon from 2 points tool
@@ -1819,6 +1821,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
18191821
, mEllipseFoci( nullptr )
18201822
, mRectangleCenterPoint( nullptr )
18211823
, mRectangleExtent( nullptr )
1824+
, mRectangle3Points( nullptr )
18221825
, mSquareCenter( nullptr )
18231826
, mRegularPolygon2Points( nullptr )
18241827
, mRegularPolygonCenterPoint( nullptr )
@@ -1878,6 +1881,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
18781881
QgsMapTool *mEllipseFoci = nullptr;
18791882
QgsMapTool *mRectangleCenterPoint = nullptr;
18801883
QgsMapTool *mRectangleExtent = nullptr;
1884+
QgsMapTool *mRectangle3Points = nullptr;
18811885
QgsMapTool *mSquareCenter = nullptr;
18821886
QgsMapTool *mRegularPolygon2Points = nullptr;
18831887
QgsMapTool *mRegularPolygonCenterPoint = nullptr;

src/app/qgsmaptooladdrectangle.cpp

+46-10
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,26 @@ QgsMapToolAddRectangle::QgsMapToolAddRectangle( QgsMapCanvas *canvas )
4242
clean();
4343
}
4444

45+
void QgsMapToolAddRectangle::setAzimuth( const double azimuth )
46+
{
47+
mAzimuth = azimuth;
48+
}
49+
50+
void QgsMapToolAddRectangle::setDistance1( const double distance1 )
51+
{
52+
mDistance1 = distance1;
53+
}
54+
55+
void QgsMapToolAddRectangle::setDistance2( const double distance2 )
56+
{
57+
mDistance2 = distance2;
58+
}
59+
60+
void QgsMapToolAddRectangle::setSide( const int side )
61+
{
62+
mSide = side;
63+
}
64+
4565
QgsMapToolAddRectangle::~QgsMapToolAddRectangle()
4666
{
4767
clean();
@@ -70,45 +90,61 @@ void QgsMapToolAddRectangle::keyReleaseEvent( QKeyEvent *e )
7090
}
7191
}
7292

73-
QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( ) const
93+
QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOriented ) const
7494
{
7595
std::unique_ptr<QgsLineString> ext( new QgsLineString() );
7696
if ( mRectangle.isEmpty() )
7797
{
7898
return ext.release();
7999
}
80100

81-
ext->addVertex( QgsPoint( mRectangle.xMinimum(), mRectangle.yMinimum() ) );
82-
ext->addVertex( QgsPoint( mRectangle.xMinimum(), mRectangle.yMaximum() ) );
83-
ext->addVertex( QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() ) );
84-
ext->addVertex( QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() ) );
85-
ext->addVertex( QgsPoint( mRectangle.xMinimum(), mRectangle.yMinimum() ) );
101+
QgsPoint x0( mRectangle.xMinimum(), mRectangle.yMinimum() );
102+
103+
QgsPoint x1, x2, x3;
104+
if ( isOriented )
105+
{
106+
double perpendicular = 90.0 * mSide;
107+
x1 = x0.project( mDistance1, mAzimuth );
108+
x3 = x0.project( mDistance2, mAzimuth + perpendicular );
109+
x2 = x1.project( mDistance2, mAzimuth + perpendicular );
110+
}
111+
else
112+
{
113+
x1 = QgsPoint( mRectangle.xMinimum(), mRectangle.yMaximum() );
114+
x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() );
115+
x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() );
116+
}
117+
ext->addVertex( x0 );
118+
ext->addVertex( x1 );
119+
ext->addVertex( x2 );
120+
ext->addVertex( x3 );
121+
ext->addVertex( x0 );
86122

87123
return ext.release();
88124
}
89125

90-
QgsPolygonV2 *QgsMapToolAddRectangle::rectangleToPolygon() const
126+
QgsPolygonV2 *QgsMapToolAddRectangle::rectangleToPolygon( const bool isOriented ) const
91127
{
92128
std::unique_ptr<QgsPolygonV2> polygon( new QgsPolygonV2() );
93129
if ( mRectangle.isEmpty() )
94130
{
95131
return polygon.release();
96132
}
97133

98-
polygon->setExteriorRing( rectangleToLinestring( ) );
134+
polygon->setExteriorRing( rectangleToLinestring( isOriented ) );
99135

100136
return polygon.release();
101137
}
102138

103-
void QgsMapToolAddRectangle::deactivate()
139+
void QgsMapToolAddRectangle::deactivate( const bool isOriented )
104140
{
105141
if ( !mParentTool || mRectangle.isEmpty() )
106142
{
107143
return;
108144
}
109145

110146
mParentTool->clearCurve( );
111-
mParentTool->addCurve( rectangleToLinestring() );
147+
mParentTool->addCurve( rectangleToLinestring( isOriented ) );
112148
clean();
113149

114150
QgsMapToolCapture::deactivate();

src/app/qgsmaptooladdrectangle.h

+34-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class QgsPolygonV2;
2424
class QgsMapToolAddRectangle: public QgsMapToolCapture
2525
{
2626
Q_OBJECT
27+
2728
//! convenient method to clean members
2829
void clean();
2930
public:
@@ -33,7 +34,7 @@ class QgsMapToolAddRectangle: public QgsMapToolCapture
3334
void keyPressEvent( QKeyEvent *e ) override;
3435
void keyReleaseEvent( QKeyEvent *e ) override;
3536

36-
void deactivate() override;
37+
void deactivate( const bool isOriented = false );
3738

3839
void activate() override;
3940

@@ -51,8 +52,38 @@ class QgsMapToolAddRectangle: public QgsMapToolCapture
5152
//! Rectangle
5253
QgsRectangle mRectangle;
5354

54-
QgsLineString *rectangleToLinestring() const;
55-
QgsPolygonV2 *rectangleToPolygon() const;
55+
//! Convenient method to export a QgsRectangle to a LineString
56+
QgsLineString *rectangleToLinestring( const bool isOriented = false ) const;
57+
//! Convenient method to export a QgsRectangle to a Polygon
58+
QgsPolygonV2 *rectangleToPolygon( const bool isOriented = false ) const;
59+
60+
//! Sets the azimuth. \see mAzimuth
61+
void setAzimuth( const double azimuth );
62+
//! Sets the first distance. \see mDistance1
63+
void setDistance1( const double distance1 );
64+
//! Sets the second distance. \see mDistance2
65+
void setDistance2( const double distance2 );
66+
//! Sets the side. \see mSide
67+
void setSide( const int side );
68+
69+
//! Returns the azimuth. \see mAzimuth
70+
double azimuth( ) const { return mAzimuth; }
71+
//! Returns the first distance. \see mDistance1
72+
double distance1( ) const { return mDistance1; }
73+
//! Returns the second distance. \see mDistance2
74+
double distance2( ) const { return mDistance2; }
75+
//! Returns the side. \see mSide
76+
int side( ) const { return mSide; }
77+
78+
private:
79+
//! Convenient member for the azimuth of the rotated rectangle. \see QgsMapToolRectangle3Points
80+
double mAzimuth = 0.0;
81+
//! Convenient member for the first distance of the rotated rectangle. \see QgsMapToolRectangle3Points
82+
double mDistance1 = 0.0;
83+
//! Convenient member for the second distance of the rotated rectangle. \see QgsMapToolRectangle3Points
84+
double mDistance2 = 0.0;
85+
//! Convenient member for the side where the second distance is drawn. \see QgsMapToolRectangle3Points
86+
int mSide = 1;
5687
};
5788

5889

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
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+
#include "qgsmaptoolrectangle3points.h"
17+
#include "qgsgeometryrubberband.h"
18+
#include "qgsgeometryutils.h"
19+
#include "qgslinestring.h"
20+
#include "qgsmapcanvas.h"
21+
#include "qgspoint.h"
22+
#include <QMouseEvent>
23+
#include <memory>
24+
25+
QgsMapToolRectangle3Points::QgsMapToolRectangle3Points( QgsMapToolCapture *parentTool,
26+
QgsMapCanvas *canvas, CaptureMode mode )
27+
: QgsMapToolAddRectangle( parentTool, canvas, mode )
28+
{
29+
}
30+
31+
QgsMapToolRectangle3Points::~QgsMapToolRectangle3Points()
32+
{
33+
}
34+
35+
void QgsMapToolRectangle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
36+
{
37+
QgsPoint mapPoint( e->mapPoint() );
38+
39+
if ( e->button() == Qt::LeftButton )
40+
{
41+
if ( mPoints.size() < 2 )
42+
mPoints.append( mapPoint );
43+
44+
if ( !mPoints.isEmpty() )
45+
{
46+
if ( !mTempRubberBand )
47+
{
48+
mTempRubberBand = createGeometryRubberBand( ( mode() == CapturePolygon ) ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry, true );
49+
mTempRubberBand->show();
50+
}
51+
}
52+
}
53+
else if ( e->button() == Qt::RightButton )
54+
{
55+
deactivate( true );
56+
if ( mParentTool )
57+
{
58+
mParentTool->canvasReleaseEvent( e );
59+
}
60+
}
61+
}
62+
63+
void QgsMapToolRectangle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e )
64+
{
65+
QgsPoint mapPoint( e->mapPoint() );
66+
67+
if ( mTempRubberBand )
68+
{
69+
switch ( mPoints.size() )
70+
{
71+
case 1:
72+
{
73+
QgsLineString *line = new QgsLineString();
74+
line->addVertex( mPoints.at( 0 ) );
75+
line->addVertex( mapPoint );
76+
mTempRubberBand->setGeometry( line );
77+
setAzimuth( mPoints.at( 0 ).azimuth( mapPoint ) );
78+
setDistance1( mPoints.at( 0 ).distance( mapPoint ) );
79+
}
80+
break;
81+
case 2:
82+
{
83+
84+
setDistance2( mPoints.at( 1 ).distance( mapPoint ) );
85+
double side = QgsGeometryUtils::leftOfLine( mapPoint.x(), mapPoint.y(),
86+
mPoints.at( 0 ).x(), mPoints.at( 0 ).y(),
87+
mPoints.at( 1 ).x(), mPoints.at( 1 ).y() );
88+
89+
setSide( side < 0 ? -1 : 1 );
90+
91+
double xMin = mPoints.at( 0 ).x();
92+
double xMax = mPoints.at( 0 ).x() + distance2( );
93+
94+
double yMin = mPoints.at( 0 ).y();
95+
double yMax = mPoints.at( 0 ).y() + distance1();
96+
97+
mRectangle = QgsRectangle( xMin, yMin,
98+
xMax, yMax );
99+
100+
101+
mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon( true ) );
102+
}
103+
break;
104+
default:
105+
break;
106+
}
107+
}
108+
109+
}

0 commit comments

Comments
 (0)