Skip to content
Permalink
Browse files

Add Rectangle from 3 points

  • Loading branch information
lbartoletti committed Sep 6, 2017
1 parent 46e66c3 commit 37b60527f2ff505ffa8725226ab3370a3b8e31a8
@@ -144,6 +144,7 @@ SET(QGIS_APP_SRCS
qgsmaptooladdregularpolygon.cpp
qgsmaptoolrectanglecenter.cpp
qgsmaptoolrectangleextent.cpp
qgsmaptoolrectangle3points.cpp
qgsmaptoolsquarecenter.cpp
qgsmaptoolregularpolygon2points.cpp
qgsmaptoolregularpolygoncenterpoint.cpp
@@ -317,6 +318,7 @@ SET (QGIS_APP_MOC_HDRS
qgsmaptooladdregularpolygon.h
qgsmaptoolrectanglecenter.h
qgsmaptoolrectangleextent.h
qgsmaptoolrectangle3points.h
qgsmaptoolsquarecenter.h
qgsmaptoolregularpolygon2points.h
qgsmaptoolregularpolygoncenterpoint.h
@@ -342,6 +342,7 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsmaptoolellipsefoci.h"
#include "qgsmaptoolrectanglecenter.h"
#include "qgsmaptoolrectangleextent.h"
#include "qgsmaptoolrectangle3points.h"
#include "qgsmaptoolsquarecenter.h"
#include "qgsmaptoolregularpolygon2points.h"
#include "qgsmaptoolregularpolygoncenterpoint.h"
@@ -1407,6 +1408,7 @@ QgisApp::~QgisApp()
delete mMapTools.mEllipseFoci;
delete mMapTools.mRectangleCenterPoint;
delete mMapTools.mRectangleExtent;
delete mMapTools.mRectangle3Points;
delete mMapTools.mSquareCenter;
delete mMapTools.mRegularPolygon2Points;
delete mMapTools.mRegularPolygonCenterPoint;
@@ -1866,6 +1868,7 @@ void QgisApp::createActions()
connect( mActionEllipseFoci, &QAction::triggered, this, &QgisApp::ellipseFoci );
connect( mActionRectangleCenterPoint, &QAction::triggered, this, &QgisApp::rectangleCenterPoint );
connect( mActionRectangleExtent, &QAction::triggered, this, &QgisApp::rectangleExtent );
connect( mActionRectangle3Points, &QAction::triggered, this, &QgisApp::rectangle3Points );
connect( mActionSquareCenter, &QAction::triggered, this, &QgisApp::squareCenter );
connect( mActionRegularPolygon2Points, &QAction::triggered, this, &QgisApp::regularPolygon2Points );
connect( mActionRegularPolygonCenterPoint, &QAction::triggered, this, &QgisApp::regularPolygonCenterPoint );
@@ -2153,6 +2156,7 @@ void QgisApp::createActionGroups()
mMapToolGroup->addAction( mActionEllipseFoci );
mMapToolGroup->addAction( mActionRectangleCenterPoint );
mMapToolGroup->addAction( mActionRectangleExtent );
mMapToolGroup->addAction( mActionRectangle3Points );
mMapToolGroup->addAction( mActionSquareCenter );
mMapToolGroup->addAction( mActionRegularPolygon2Points );
mMapToolGroup->addAction( mActionRegularPolygonCenterPoint );
@@ -2693,6 +2697,7 @@ void QgisApp::createToolBars()
tbAddRectangle->setPopupMode( QToolButton::MenuButtonPopup );
tbAddRectangle->addAction( mActionRectangleCenterPoint );
tbAddRectangle->addAction( mActionRectangleExtent );
tbAddRectangle->addAction( mActionRectangle3Points );
tbAddRectangle->addAction( mActionSquareCenter );
tbAddRectangle->setDefaultAction( mActionRectangleCenterPoint );
connect( tbAddRectangle, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
@@ -3296,6 +3301,8 @@ void QgisApp::createCanvasTools()
mMapTools.mRectangleCenterPoint->setAction( mActionRectangleCenterPoint );
mMapTools.mRectangleExtent = new QgsMapToolRectangleExtent( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
mMapTools.mRectangleExtent->setAction( mActionRectangleExtent );
mMapTools.mRectangle3Points = new QgsMapToolRectangle3Points( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
mMapTools.mRectangle3Points->setAction( mActionRectangle3Points );
mMapTools.mSquareCenter = new QgsMapToolSquareCenter( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
mMapTools.mSquareCenter->setAction( mActionSquareCenter );
mMapTools.mRegularPolygon2Points = new QgsMapToolRegularPolygon2Points( dynamic_cast<QgsMapToolAddFeature *>( mMapTools.mAddFeature ), mMapCanvas );
@@ -7917,6 +7924,11 @@ void QgisApp::rectangleExtent()
mMapCanvas->setMapTool( mMapTools.mRectangleExtent );
}

void QgisApp::rectangle3Points()
{
mMapCanvas->setMapTool( mMapTools.mRectangle3Points );
}

void QgisApp::squareCenter()
{
mMapCanvas->setMapTool( mMapTools.mSquareCenter );
@@ -11397,6 +11409,8 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
mActionRectangleExtent->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
mActionRectangle3Points->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
mActionSquareCenter->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
mActionRegularPolygon2Points->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
@@ -1235,6 +1235,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void rectangleCenterPoint();
//! activates the add rectangle from extent tool
void rectangleExtent();
//! activates the add rectangle from 3 points tool
void rectangle3Points();
//! activates the add square from center tool
void squareCenter();
//! activates the add regular polygon from 2 points tool
@@ -1819,6 +1821,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
, mEllipseFoci( nullptr )
, mRectangleCenterPoint( nullptr )
, mRectangleExtent( nullptr )
, mRectangle3Points( nullptr )
, mSquareCenter( nullptr )
, mRegularPolygon2Points( nullptr )
, mRegularPolygonCenterPoint( nullptr )
@@ -1878,6 +1881,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsMapTool *mEllipseFoci = nullptr;
QgsMapTool *mRectangleCenterPoint = nullptr;
QgsMapTool *mRectangleExtent = nullptr;
QgsMapTool *mRectangle3Points = nullptr;
QgsMapTool *mSquareCenter = nullptr;
QgsMapTool *mRegularPolygon2Points = nullptr;
QgsMapTool *mRegularPolygonCenterPoint = nullptr;
@@ -42,6 +42,26 @@ QgsMapToolAddRectangle::QgsMapToolAddRectangle( QgsMapCanvas *canvas )
clean();
}

void QgsMapToolAddRectangle::setAzimuth( const double azimuth )
{
mAzimuth = azimuth;
}

void QgsMapToolAddRectangle::setDistance1( const double distance1 )
{
mDistance1 = distance1;
}

void QgsMapToolAddRectangle::setDistance2( const double distance2 )
{
mDistance2 = distance2;
}

void QgsMapToolAddRectangle::setSide( const int side )
{
mSide = side;
}

QgsMapToolAddRectangle::~QgsMapToolAddRectangle()
{
clean();
@@ -70,45 +90,61 @@ void QgsMapToolAddRectangle::keyReleaseEvent( QKeyEvent *e )
}
}

QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( ) const
QgsLineString *QgsMapToolAddRectangle::rectangleToLinestring( const bool isOriented ) const
{
std::unique_ptr<QgsLineString> ext( new QgsLineString() );
if ( mRectangle.isEmpty() )
{
return ext.release();
}

ext->addVertex( QgsPoint( mRectangle.xMinimum(), mRectangle.yMinimum() ) );
ext->addVertex( QgsPoint( mRectangle.xMinimum(), mRectangle.yMaximum() ) );
ext->addVertex( QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() ) );
ext->addVertex( QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() ) );
ext->addVertex( QgsPoint( mRectangle.xMinimum(), mRectangle.yMinimum() ) );
QgsPoint x0( mRectangle.xMinimum(), mRectangle.yMinimum() );

QgsPoint x1, x2, x3;
if ( isOriented )
{
double perpendicular = 90.0 * mSide;
x1 = x0.project( mDistance1, mAzimuth );
x3 = x0.project( mDistance2, mAzimuth + perpendicular );
x2 = x1.project( mDistance2, mAzimuth + perpendicular );
}
else
{
x1 = QgsPoint( mRectangle.xMinimum(), mRectangle.yMaximum() );
x2 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMaximum() );
x3 = QgsPoint( mRectangle.xMaximum(), mRectangle.yMinimum() );
}
ext->addVertex( x0 );
ext->addVertex( x1 );
ext->addVertex( x2 );
ext->addVertex( x3 );
ext->addVertex( x0 );

return ext.release();
}

QgsPolygonV2 *QgsMapToolAddRectangle::rectangleToPolygon() const
QgsPolygonV2 *QgsMapToolAddRectangle::rectangleToPolygon( const bool isOriented ) const
{
std::unique_ptr<QgsPolygonV2> polygon( new QgsPolygonV2() );
if ( mRectangle.isEmpty() )
{
return polygon.release();
}

polygon->setExteriorRing( rectangleToLinestring( ) );
polygon->setExteriorRing( rectangleToLinestring( isOriented ) );

return polygon.release();
}

void QgsMapToolAddRectangle::deactivate()
void QgsMapToolAddRectangle::deactivate( const bool isOriented )
{
if ( !mParentTool || mRectangle.isEmpty() )
{
return;
}

mParentTool->clearCurve( );
mParentTool->addCurve( rectangleToLinestring() );
mParentTool->addCurve( rectangleToLinestring( isOriented ) );
clean();

QgsMapToolCapture::deactivate();
@@ -24,6 +24,7 @@ class QgsPolygonV2;
class QgsMapToolAddRectangle: public QgsMapToolCapture
{
Q_OBJECT

//! convenient method to clean members
void clean();
public:
@@ -33,7 +34,7 @@ class QgsMapToolAddRectangle: public QgsMapToolCapture
void keyPressEvent( QKeyEvent *e ) override;
void keyReleaseEvent( QKeyEvent *e ) override;

void deactivate() override;
void deactivate( const bool isOriented = false );

void activate() override;

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

QgsLineString *rectangleToLinestring() const;
QgsPolygonV2 *rectangleToPolygon() const;
//! Convenient method to export a QgsRectangle to a LineString
QgsLineString *rectangleToLinestring( const bool isOriented = false ) const;
//! Convenient method to export a QgsRectangle to a Polygon
QgsPolygonV2 *rectangleToPolygon( const bool isOriented = false ) const;

//! Sets the azimuth. \see mAzimuth
void setAzimuth( const double azimuth );
//! Sets the first distance. \see mDistance1
void setDistance1( const double distance1 );
//! Sets the second distance. \see mDistance2
void setDistance2( const double distance2 );
//! Sets the side. \see mSide
void setSide( const int side );

//! Returns the azimuth. \see mAzimuth
double azimuth( ) const { return mAzimuth; }
//! Returns the first distance. \see mDistance1
double distance1( ) const { return mDistance1; }
//! Returns the second distance. \see mDistance2
double distance2( ) const { return mDistance2; }
//! Returns the side. \see mSide
int side( ) const { return mSide; }

private:
//! Convenient member for the azimuth of the rotated rectangle. \see QgsMapToolRectangle3Points
double mAzimuth = 0.0;
//! Convenient member for the first distance of the rotated rectangle. \see QgsMapToolRectangle3Points
double mDistance1 = 0.0;
//! Convenient member for the second distance of the rotated rectangle. \see QgsMapToolRectangle3Points
double mDistance2 = 0.0;
//! Convenient member for the side where the second distance is drawn. \see QgsMapToolRectangle3Points
int mSide = 1;
};


@@ -0,0 +1,109 @@
/***************************************************************************
qgsmaptoolrectangle3points.cpp - map tool for adding rectangle
from 3 points
---------------------
begin : September 2017
copyright : (C) 2017 by Loïc Bartoletti
email : lbartoletti at tuxfamily dot org
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsmaptoolrectangle3points.h"
#include "qgsgeometryrubberband.h"
#include "qgsgeometryutils.h"
#include "qgslinestring.h"
#include "qgsmapcanvas.h"
#include "qgspoint.h"
#include <QMouseEvent>
#include <memory>

QgsMapToolRectangle3Points::QgsMapToolRectangle3Points( QgsMapToolCapture *parentTool,
QgsMapCanvas *canvas, CaptureMode mode )
: QgsMapToolAddRectangle( parentTool, canvas, mode )
{
}

QgsMapToolRectangle3Points::~QgsMapToolRectangle3Points()
{
}

void QgsMapToolRectangle3Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
{
QgsPoint mapPoint( e->mapPoint() );

if ( e->button() == Qt::LeftButton )
{
if ( mPoints.size() < 2 )
mPoints.append( mapPoint );

if ( !mPoints.isEmpty() )
{
if ( !mTempRubberBand )
{
mTempRubberBand = createGeometryRubberBand( ( mode() == CapturePolygon ) ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry, true );
mTempRubberBand->show();
}
}
}
else if ( e->button() == Qt::RightButton )
{
deactivate( true );
if ( mParentTool )
{
mParentTool->canvasReleaseEvent( e );
}
}
}

void QgsMapToolRectangle3Points::cadCanvasMoveEvent( QgsMapMouseEvent *e )
{
QgsPoint mapPoint( e->mapPoint() );

if ( mTempRubberBand )
{
switch ( mPoints.size() )
{
case 1:
{
QgsLineString *line = new QgsLineString();
line->addVertex( mPoints.at( 0 ) );
line->addVertex( mapPoint );
mTempRubberBand->setGeometry( line );
setAzimuth( mPoints.at( 0 ).azimuth( mapPoint ) );
setDistance1( mPoints.at( 0 ).distance( mapPoint ) );
}
break;
case 2:
{

setDistance2( mPoints.at( 1 ).distance( mapPoint ) );
double side = QgsGeometryUtils::leftOfLine( mapPoint.x(), mapPoint.y(),
mPoints.at( 0 ).x(), mPoints.at( 0 ).y(),
mPoints.at( 1 ).x(), mPoints.at( 1 ).y() );

setSide( side < 0 ? -1 : 1 );

double xMin = mPoints.at( 0 ).x();
double xMax = mPoints.at( 0 ).x() + distance2( );

double yMin = mPoints.at( 0 ).y();
double yMax = mPoints.at( 0 ).y() + distance1();

mRectangle = QgsRectangle( xMin, yMin,
xMax, yMax );


mTempRubberBand->setGeometry( QgsMapToolAddRectangle::rectangleToPolygon( true ) );
}
break;
default:
break;
}
}

}

0 comments on commit 37b6052

Please sign in to comment.
You can’t perform that action at this time.