diff --git a/images/images.qrc b/images/images.qrc
index 6abbaaed3ed6..61c9be0bdece 100644
--- a/images/images.qrc
+++ b/images/images.qrc
@@ -565,6 +565,10 @@
themes/default/mActionCircle2Points.svg
themes/default/mActionCircle3Points.svg
themes/default/mActionCircleCenterPoint.svg
+ themes/default/mActionEllipseFoci.svg
+ themes/default/mActionEllipseCenter2Points.svg
+ themes/default/mActionEllipseCenterPoint.svg
+ themes/default/mActionEllipseExtent.svg
qgis_tips/symbol_levels.png
diff --git a/images/themes/default/mActionEllipseCenter2Points.svg b/images/themes/default/mActionEllipseCenter2Points.svg
new file mode 100644
index 000000000000..3ecb59e29f5a
--- /dev/null
+++ b/images/themes/default/mActionEllipseCenter2Points.svg
@@ -0,0 +1,124 @@
+
+
diff --git a/images/themes/default/mActionEllipseCenterPoint.svg b/images/themes/default/mActionEllipseCenterPoint.svg
new file mode 100644
index 000000000000..63809c80d4ea
--- /dev/null
+++ b/images/themes/default/mActionEllipseCenterPoint.svg
@@ -0,0 +1,120 @@
+
+
diff --git a/images/themes/default/mActionEllipseExtent.svg b/images/themes/default/mActionEllipseExtent.svg
new file mode 100644
index 000000000000..a1844a312747
--- /dev/null
+++ b/images/themes/default/mActionEllipseExtent.svg
@@ -0,0 +1,126 @@
+
+
diff --git a/images/themes/default/mActionEllipseFoci.svg b/images/themes/default/mActionEllipseFoci.svg
new file mode 100644
index 000000000000..47b1f15f45ec
--- /dev/null
+++ b/images/themes/default/mActionEllipseFoci.svg
@@ -0,0 +1,118 @@
+
+
diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt
index f96cfafff3c6..bc8fba21be6c 100755
--- a/src/app/CMakeLists.txt
+++ b/src/app/CMakeLists.txt
@@ -136,6 +136,11 @@ SET(QGIS_APP_SRCS
qgsmaptoolcircle2points.cpp
qgsmaptoolcircle3points.cpp
qgsmaptoolcirclecenterpoint.cpp
+ qgsmaptooladdellipse.cpp
+ qgsmaptoolellipsefoci.cpp
+ qgsmaptoolellipseextent.cpp
+ qgsmaptoolellipsecenterpoint.cpp
+ qgsmaptoolellipsecenter2points.cpp
composer/qgsattributeselectiondialog.cpp
composer/qgscomposer.cpp
@@ -291,6 +296,11 @@ SET (QGIS_APP_MOC_HDRS
qgsmaptoolcircle2points.h
qgsmaptoolcircle3points.h
qgsmaptoolcirclecenterpoint.h
+ qgsmaptooladdellipse.h
+ qgsmaptoolellipsefoci.h
+ qgsmaptoolellipseextent.h
+ qgsmaptoolellipsecenterpoint.h
+ qgsmaptoolellipsecenter2points.h
nodetool/qgsselectedfeature.h
diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp
index dedd4b854177..e39007c0b75d 100644
--- a/src/app/qgisapp.cpp
+++ b/src/app/qgisapp.cpp
@@ -332,6 +332,10 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgsmaptoolcircle2points.h"
#include "qgsmaptoolcircle3points.h"
#include "qgsmaptoolcirclecenterpoint.h"
+#include "qgsmaptoolellipsecenter2points.h"
+#include "qgsmaptoolellipsecenterpoint.h"
+#include "qgsmaptoolellipseextent.h"
+#include "qgsmaptoolellipsefoci.h"
#include "qgsmaptooldeletering.h"
#include "qgsmaptooldeletepart.h"
#include "qgsmaptoolfeatureaction.h"
@@ -1373,6 +1377,10 @@ QgisApp::~QgisApp()
delete mMapTools.mCircle2Points;
delete mMapTools.mCircle3Points;
delete mMapTools.mCircleCenterPoint;
+ delete mMapTools.mEllipseCenter2Points;
+ delete mMapTools.mEllipseCenterPoint;
+ delete mMapTools.mEllipseExtent;
+ delete mMapTools.mEllipseFoci;
delete mpMaptip;
@@ -1796,6 +1804,10 @@ void QgisApp::createActions()
connect( mActionCircle2Points, &QAction::triggered, this, &QgisApp::circle2Points );
connect( mActionCircle3Points, &QAction::triggered, this, &QgisApp::circle3Points );
connect( mActionCircleCenterPoint, &QAction::triggered, this, &QgisApp::circleCenterPoint );
+ connect( mActionEllipseCenter2Points, &QAction::triggered, this, &QgisApp::ellipseCenter2Points );
+ connect( mActionEllipseCenterPoint, &QAction::triggered, this, &QgisApp::ellipseCenterPoint );
+ connect( mActionEllipseExtent, &QAction::triggered, this, &QgisApp::ellipseExtent );
+ connect( mActionEllipseFoci, &QAction::triggered, this, &QgisApp::ellipseFoci );
connect( mActionMoveFeature, &QAction::triggered, this, &QgisApp::moveFeature );
connect( mActionMoveFeature, &QAction::triggered, this, &QgisApp::moveFeature );
connect( mActionMoveFeatureCopy, &QAction::triggered, this, &QgisApp::moveFeatureCopy );
@@ -2073,6 +2085,10 @@ void QgisApp::createActionGroups()
mMapToolGroup->addAction( mActionCircle2Points );
mMapToolGroup->addAction( mActionCircle3Points );
mMapToolGroup->addAction( mActionCircleCenterPoint );
+ mMapToolGroup->addAction( mActionEllipseCenter2Points );
+ mMapToolGroup->addAction( mActionEllipseCenterPoint );
+ mMapToolGroup->addAction( mActionEllipseExtent );
+ mMapToolGroup->addAction( mActionEllipseFoci );
mMapToolGroup->addAction( mActionMoveFeature );
mMapToolGroup->addAction( mActionMoveFeatureCopy );
mMapToolGroup->addAction( mActionRotateFeature );
@@ -2551,6 +2567,17 @@ void QgisApp::createToolBars()
connect( tbAddCircle, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
mRegularShapeDigitizeToolBar->insertWidget( mActionNodeTool, tbAddCircle );
+ //ellipse digitize tool button
+ QToolButton *tbAddEllipse = new QToolButton( mRegularShapeDigitizeToolBar );
+ tbAddEllipse->setPopupMode( QToolButton::MenuButtonPopup );
+ tbAddEllipse->addAction( mActionEllipseCenter2Points );
+ tbAddEllipse->addAction( mActionEllipseCenterPoint );
+ tbAddEllipse->addAction( mActionEllipseExtent );
+ tbAddEllipse->addAction( mActionEllipseFoci );
+ tbAddEllipse->setDefaultAction( mActionEllipseCenter2Points );
+ connect( tbAddEllipse, &QToolButton::triggered, this, &QgisApp::toolButtonActionTriggered );
+ mRegularShapeDigitizeToolBar->insertWidget( mActionNodeTool, tbAddEllipse );
+
// move feature tool button
QToolButton *moveFeatureButton = new QToolButton( mDigitizeToolBar );
moveFeatureButton->setPopupMode( QToolButton::MenuButtonPopup );
@@ -3138,6 +3165,14 @@ void QgisApp::createCanvasTools()
mMapTools.mCircle3Points->setAction( mActionCircle3Points );
mMapTools.mCircleCenterPoint = new QgsMapToolCircleCenterPoint( dynamic_cast( mMapTools.mAddFeature ), mMapCanvas );
mMapTools.mCircleCenterPoint->setAction( mActionCircleCenterPoint );
+ mMapTools.mEllipseCenter2Points = new QgsMapToolEllipseCenter2Points( dynamic_cast( mMapTools.mAddFeature ), mMapCanvas );
+ mMapTools.mEllipseCenter2Points->setAction( mActionEllipseCenter2Points );
+ mMapTools.mEllipseCenterPoint = new QgsMapToolEllipseCenterPoint( dynamic_cast( mMapTools.mAddFeature ), mMapCanvas );
+ mMapTools.mEllipseCenterPoint->setAction( mActionEllipseCenterPoint );
+ mMapTools.mEllipseExtent = new QgsMapToolEllipseExtent( dynamic_cast( mMapTools.mAddFeature ), mMapCanvas );
+ mMapTools.mEllipseExtent->setAction( mActionEllipseExtent );
+ mMapTools.mEllipseFoci = new QgsMapToolEllipseFoci( dynamic_cast( mMapTools.mAddFeature ), mMapCanvas );
+ mMapTools.mEllipseFoci->setAction( mActionEllipseFoci );
mMapTools.mMoveFeature = new QgsMapToolMoveFeature( mMapCanvas, QgsMapToolMoveFeature::Move );
mMapTools.mMoveFeature->setAction( mActionMoveFeature );
mMapTools.mMoveFeatureCopy = new QgsMapToolMoveFeature( mMapCanvas, QgsMapToolMoveFeature::CopyMove );
@@ -7829,6 +7864,26 @@ void QgisApp::circleCenterPoint()
mMapCanvas->setMapTool( mMapTools.mCircleCenterPoint );
}
+void QgisApp::ellipseCenter2Points()
+{
+ mMapCanvas->setMapTool( mMapTools.mEllipseCenter2Points );
+}
+
+void QgisApp::ellipseCenterPoint()
+{
+ mMapCanvas->setMapTool( mMapTools.mEllipseCenterPoint );
+}
+
+void QgisApp::ellipseExtent()
+{
+ mMapCanvas->setMapTool( mMapTools.mEllipseExtent );
+}
+
+void QgisApp::ellipseFoci()
+{
+ mMapCanvas->setMapTool( mMapTools.mEllipseFoci );
+}
+
void QgisApp::selectFeatures()
{
mMapCanvas->setMapTool( mMapTools.mSelectFeatures );
@@ -11116,6 +11171,10 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )
mActionCircle2Points->setEnabled( false );
mActionCircle3Points->setEnabled( false );
mActionCircleCenterPoint->setEnabled( false );
+ mActionEllipseCenter2Points->setEnabled( false );
+ mActionEllipseCenterPoint->setEnabled( false );
+ mActionEllipseExtent->setEnabled( false );
+ mActionEllipseFoci->setEnabled( false );
mActionMoveFeature->setEnabled( false );
mActionMoveFeatureCopy->setEnabled( false );
mActionRotateFeature->setEnabled( false );
@@ -11257,6 +11316,14 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
mActionCircleCenterPoint->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
&& ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
+ mActionEllipseCenter2Points->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
+ && ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
+ mActionEllipseCenterPoint->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
+ && ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
+ mActionEllipseExtent->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
+ && ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
+ mActionEllipseFoci->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry )
+ && ( vlayer->geometryType() == QgsWkbTypes::LineGeometry || vlayer->geometryType() == QgsWkbTypes::PolygonGeometry ) );
//does provider allow deleting of features?
mActionDeleteSelected->setEnabled( isEditable && canDeleteFeatures && layerHasSelection );
mActionCutFeatures->setEnabled( isEditable && canDeleteFeatures && layerHasSelection );
diff --git a/src/app/qgisapp.h b/src/app/qgisapp.h
index 3c1e1f473b32..c74d3a0ec64d 100644
--- a/src/app/qgisapp.h
+++ b/src/app/qgisapp.h
@@ -1203,6 +1203,14 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
void circle3Points();
//! activates the add circle from center and radius tool
void circleCenterPoint();
+ //! activates the add ellipse from center and 2 points tool
+ void ellipseCenter2Points();
+ //! activates the add ellipse from center point tool
+ void ellipseCenterPoint();
+ //! activates the add ellipse from extent tool
+ void ellipseExtent();
+ //! activates the add ellipse from foci tool
+ void ellipseFoci();
//! activates the move feature tool
void moveFeature();
//! activates the copy and move feature tool
@@ -1754,6 +1762,10 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
, mCircle2Points( nullptr )
, mCircle3Points( nullptr )
, mCircleCenterPoint( nullptr )
+ , mEllipseCenter2Points( nullptr )
+ , mEllipseCenterPoint( nullptr )
+ , mEllipseExtent( nullptr )
+ , mEllipseFoci( nullptr )
, mMoveFeature( nullptr )
, mOffsetCurve( nullptr )
, mReshapeFeatures( nullptr )
@@ -1803,6 +1815,10 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsMapTool *mCircle2Points = nullptr;
QgsMapTool *mCircle3Points = nullptr;
QgsMapTool *mCircleCenterPoint = nullptr;
+ QgsMapTool *mEllipseCenter2Points = nullptr;
+ QgsMapTool *mEllipseCenterPoint = nullptr;
+ QgsMapTool *mEllipseExtent = nullptr;
+ QgsMapTool *mEllipseFoci = nullptr;
QgsMapTool *mMoveFeature = nullptr;
QgsMapTool *mMoveFeatureCopy = nullptr;
QgsMapTool *mOffsetCurve = nullptr;
diff --git a/src/app/qgsmaptooladdellipse.cpp b/src/app/qgsmaptooladdellipse.cpp
new file mode 100644
index 000000000000..c725d232fa36
--- /dev/null
+++ b/src/app/qgsmaptooladdellipse.cpp
@@ -0,0 +1,118 @@
+/***************************************************************************
+ qgsmaptooladdellipse.cpp - map tool for adding ellipse
+ ---------------------
+ begin : July 2017
+ copyright : (C) 2017
+ 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgsmaptooladdellipse.h"
+#include "qgscompoundcurve.h"
+#include "qgscurvepolygon.h"
+#include "qgsgeometryrubberband.h"
+#include "qgsgeometryutils.h"
+#include "qgslinestring.h"
+#include "qgsmapcanvas.h"
+#include "qgspoint.h"
+#include "qgisapp.h"
+
+QgsMapToolAddEllipse::QgsMapToolAddEllipse( QgsMapToolCapture *parentTool, QgsMapCanvas *canvas, CaptureMode mode )
+ : QgsMapToolCapture( canvas, QgisApp::instance()->cadDockWidget(), mode )
+ , mParentTool( parentTool )
+ , mTempRubberBand( nullptr )
+ , mEllipse( QgsEllipse() )
+{
+ if ( mCanvas )
+ {
+ connect( mCanvas, &QgsMapCanvas::mapToolSet, this, &QgsMapToolAddEllipse::setParentTool );
+ }
+}
+
+QgsMapToolAddEllipse::QgsMapToolAddEllipse( QgsMapCanvas *canvas )
+ : QgsMapToolCapture( canvas, QgisApp::instance()->cadDockWidget() )
+ , mParentTool( nullptr )
+ , mTempRubberBand( nullptr )
+ , mEllipse( QgsEllipse() )
+{
+ if ( mCanvas )
+ {
+ connect( mCanvas, &QgsMapCanvas::mapToolSet, this, &QgsMapToolAddEllipse::setParentTool );
+ }
+}
+
+QgsMapToolAddEllipse::~QgsMapToolAddEllipse()
+{
+ delete mTempRubberBand;
+ mPoints.clear();
+}
+
+void QgsMapToolAddEllipse::setParentTool( QgsMapTool *newTool, QgsMapTool *oldTool )
+{
+ QgsMapToolCapture *tool = dynamic_cast( oldTool );
+ QgsMapToolAddEllipse *csTool = dynamic_cast( oldTool );
+ if ( csTool && newTool == this )
+ {
+ mParentTool = csTool->mParentTool;
+ }
+ else if ( tool && newTool == this )
+ {
+ mParentTool = tool;
+ }
+}
+
+void QgsMapToolAddEllipse::keyPressEvent( QKeyEvent *e )
+{
+ if ( e && e->isAutoRepeat() )
+ {
+ return;
+ }
+
+ if ( e && e->key() == Qt::Key_Escape )
+ {
+ mPoints.clear();
+ delete mTempRubberBand;
+ mTempRubberBand = nullptr;
+ if ( mParentTool )
+ mParentTool->keyPressEvent( e );
+ }
+}
+
+void QgsMapToolAddEllipse::keyReleaseEvent( QKeyEvent *e )
+{
+ if ( e && e->isAutoRepeat() )
+ {
+ return;
+ }
+}
+
+void QgsMapToolAddEllipse::deactivate()
+{
+ if ( !mParentTool || mEllipse.isEmpty() )
+ {
+ return;
+ }
+
+ mParentTool->addCurve( mEllipse.toLineString() );
+
+ delete mTempRubberBand;
+ mTempRubberBand = nullptr;
+ mPoints.clear();
+ mEllipse = QgsEllipse();
+ QgsMapToolCapture::deactivate();
+}
+
+void QgsMapToolAddEllipse::activate()
+{
+ if ( mParentTool )
+ {
+ mParentTool->deleteTempRubberBand();
+ }
+ QgsMapToolCapture::activate();
+}
diff --git a/src/app/qgsmaptooladdellipse.h b/src/app/qgsmaptooladdellipse.h
new file mode 100644
index 000000000000..9eb7186712f7
--- /dev/null
+++ b/src/app/qgsmaptooladdellipse.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ qgsmaptooladdellipse.h - map tool for adding ellipse
+ ---------------------
+ begin : July 2017
+ copyright : (C) 2017
+ 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef QGSMAPTOOLADDELLIPSE_H
+#define QGSMAPTOOLADDELLIPSE_H
+
+#include "qgsmaptoolcapture.h"
+#include "qgsellipse.h"
+
+class QgsGeometryRubberBand;
+
+class QgsMapToolAddEllipse: public QgsMapToolCapture
+{
+ Q_OBJECT
+ public:
+ QgsMapToolAddEllipse( QgsMapToolCapture *parentTool, QgsMapCanvas *canvas, CaptureMode mode = CaptureLine );
+ ~QgsMapToolAddEllipse();
+
+ void keyPressEvent( QKeyEvent *e ) override;
+ void keyReleaseEvent( QKeyEvent *e ) override;
+
+ void deactivate() override;
+
+ void activate() override;
+
+ private slots:
+ void setParentTool( QgsMapTool *newTool, QgsMapTool *oldTool );
+
+ protected:
+ explicit QgsMapToolAddEllipse( QgsMapCanvas *canvas ); //forbidden
+
+ /** The parent map tool, e.g. the add feature tool.
+ * Completed ellipse will be added to this tool by calling its toLineString() method.
+ * */
+ QgsMapToolCapture *mParentTool = nullptr;
+ //! Ellipse points (in map coordinates)
+ QgsPointSequence mPoints;
+ //! The rubberband to show the ellipse currently working on
+ QgsGeometryRubberBand *mTempRubberBand = nullptr;
+ //! Ellipse
+ QgsEllipse mEllipse;
+
+};
+
+#endif // QGSMAPTOOLADDELLIPSE_H
diff --git a/src/app/qgsmaptoolellipsecenter2points.cpp b/src/app/qgsmaptoolellipsecenter2points.cpp
new file mode 100644
index 000000000000..44b591ea2ba9
--- /dev/null
+++ b/src/app/qgsmaptoolellipsecenter2points.cpp
@@ -0,0 +1,86 @@
+/***************************************************************************
+ qgmaptoolellilpsecenter2points.cpp - map tool for adding ellipse
+ from center and 2 points
+ ---------------------
+ begin : July 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "qgsmaptoolellipsecenter2points.h"
+#include "qgsgeometryrubberband.h"
+#include "qgslinestring.h"
+#include "qgsmapcanvas.h"
+#include "qgspoint.h"
+#include
+
+QgsMapToolEllipseCenter2Points::QgsMapToolEllipseCenter2Points( QgsMapToolCapture *parentTool,
+ QgsMapCanvas *canvas, CaptureMode mode )
+ : QgsMapToolAddEllipse( parentTool, canvas, mode )
+{
+}
+
+QgsMapToolEllipseCenter2Points::~QgsMapToolEllipseCenter2Points()
+{
+}
+
+void QgsMapToolEllipseCenter2Points::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
+{
+ QgsPoint mapPoint( e->mapPoint() );
+
+ if ( e->button() == Qt::LeftButton )
+ {
+ 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();
+ if ( mParentTool )
+ {
+ mParentTool->canvasReleaseEvent( e );
+ }
+ }
+}
+
+void QgsMapToolEllipseCenter2Points::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 );
+ }
+ break;
+ case 2:
+ {
+ mEllipse = QgsEllipse().fromCenter2Points( mPoints.at( 0 ), mPoints.at( 1 ), mapPoint );
+ mTempRubberBand->setGeometry( mEllipse.toPolygon() );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/app/qgsmaptoolellipsecenter2points.h b/src/app/qgsmaptoolellipsecenter2points.h
new file mode 100644
index 000000000000..53e6fc7a3305
--- /dev/null
+++ b/src/app/qgsmaptoolellipsecenter2points.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ qgmaptoolellilpsecenter2points.h - map tool for adding ellipse
+ from center and 2 points
+ ---------------------
+ begin : July 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. *
+ * *
+ ***************************************************************************/
+#ifndef QGSMAPTOOLELLIPSECENTER2POINTS_H
+#define QGSMAPTOOLELLIPSECENTER2POINTS_H
+
+#include "qgsmaptooladdellipse.h"
+
+class QgsMapToolEllipseCenter2Points: public QgsMapToolAddEllipse
+{
+ Q_OBJECT
+
+ public:
+ QgsMapToolEllipseCenter2Points( QgsMapToolCapture *parentTool, QgsMapCanvas *canvas, CaptureMode mode = CaptureLine );
+ ~QgsMapToolEllipseCenter2Points();
+
+ void cadCanvasReleaseEvent( QgsMapMouseEvent *e ) override;
+ void cadCanvasMoveEvent( QgsMapMouseEvent *e ) override;
+};
+
+#endif // QGSMAPTOOLELLIPSECENTER2POINTS_H
diff --git a/src/app/qgsmaptoolellipsecenterpoint.cpp b/src/app/qgsmaptoolellipsecenterpoint.cpp
new file mode 100644
index 000000000000..034b413ebf9c
--- /dev/null
+++ b/src/app/qgsmaptoolellipsecenterpoint.cpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+ qgmaptoolellipsecenterpoint.cpp - map tool for adding ellipse
+ from center and a point
+ ---------------------
+ begin : July 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "qgsmaptoolellipsecenterpoint.h"
+#include "qgsgeometryrubberband.h"
+#include "qgsmapcanvas.h"
+#include "qgspoint.h"
+#include
+
+QgsMapToolEllipseCenterPoint::QgsMapToolEllipseCenterPoint( QgsMapToolCapture *parentTool,
+ QgsMapCanvas *canvas, CaptureMode mode )
+ : QgsMapToolAddEllipse( parentTool, canvas, mode )
+{
+
+}
+
+QgsMapToolEllipseCenterPoint::~QgsMapToolEllipseCenterPoint()
+{
+}
+
+void QgsMapToolEllipseCenterPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
+{
+ QgsPoint mapPoint( e->mapPoint() );
+
+ if ( e->button() == Qt::LeftButton )
+ {
+ 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();
+ if ( mParentTool )
+ {
+ mParentTool->canvasReleaseEvent( e );
+ }
+ }
+}
+
+void QgsMapToolEllipseCenterPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e )
+{
+ QgsPoint mapPoint( e->mapPoint() );
+ if ( mTempRubberBand )
+ {
+ mEllipse = QgsEllipse().fromCenterPoint( mPoints.at( 0 ), mapPoint );
+ mTempRubberBand->setGeometry( mEllipse.toPolygon() );
+ }
+}
diff --git a/src/app/qgsmaptoolellipsecenterpoint.h b/src/app/qgsmaptoolellipsecenterpoint.h
new file mode 100644
index 000000000000..65a865b82ffe
--- /dev/null
+++ b/src/app/qgsmaptoolellipsecenterpoint.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ qgmaptoolellipsecenterpoint.h - map tool for adding ellipse
+ from center and a point
+ ---------------------
+ begin : July 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef QGSMAPTOOLELLIPSECENTERPOINT_H
+#define QGSMAPTOOLELLIPSECENTERPOINT_H
+
+#include "qgsmaptooladdellipse.h"
+
+class QgsMapToolEllipseCenterPoint: public QgsMapToolAddEllipse
+{
+ Q_OBJECT
+
+ public:
+ QgsMapToolEllipseCenterPoint( QgsMapToolCapture *parentTool, QgsMapCanvas *canvas, CaptureMode mode = CaptureLine );
+ ~QgsMapToolEllipseCenterPoint();
+
+ void cadCanvasReleaseEvent( QgsMapMouseEvent *e ) override;
+ void cadCanvasMoveEvent( QgsMapMouseEvent *e ) override;
+};
+
+#endif // QGSMAPTOOLELLIPSECENTERPOINT_H
diff --git a/src/app/qgsmaptoolellipseextent.cpp b/src/app/qgsmaptoolellipseextent.cpp
new file mode 100644
index 000000000000..a8bd186c2c1f
--- /dev/null
+++ b/src/app/qgsmaptoolellipseextent.cpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+ qgmaptoolellipseextent.cpp - map tool for adding ellipse
+ from extent
+ ---------------------
+ begin : July 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "qgsmaptoolellipseextent.h"
+#include "qgsgeometryrubberband.h"
+#include "qgsmapcanvas.h"
+#include "qgspoint.h"
+#include
+
+QgsMapToolEllipseExtent::QgsMapToolEllipseExtent( QgsMapToolCapture *parentTool,
+ QgsMapCanvas *canvas, CaptureMode mode )
+ : QgsMapToolAddEllipse( parentTool, canvas, mode )
+{
+
+}
+
+QgsMapToolEllipseExtent::~QgsMapToolEllipseExtent()
+{
+}
+
+void QgsMapToolEllipseExtent::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
+{
+ QgsPoint mapPoint( e->mapPoint() );
+
+ if ( e->button() == Qt::LeftButton )
+ {
+ 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();
+ if ( mParentTool )
+ {
+ mParentTool->canvasReleaseEvent( e );
+ }
+ }
+}
+
+void QgsMapToolEllipseExtent::cadCanvasMoveEvent( QgsMapMouseEvent *e )
+{
+ QgsPoint mapPoint( e->mapPoint() );
+ if ( mTempRubberBand )
+ {
+ mEllipse = QgsEllipse().fromExtent( mPoints.at( 0 ), mapPoint );
+ mTempRubberBand->setGeometry( mEllipse.toPolygon() );
+ }
+}
diff --git a/src/app/qgsmaptoolellipseextent.h b/src/app/qgsmaptoolellipseextent.h
new file mode 100644
index 000000000000..3c4625bded9d
--- /dev/null
+++ b/src/app/qgsmaptoolellipseextent.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ qgmaptoolellipseextent.h - map tool for adding ellipse
+ from extent
+ ---------------------
+ begin : July 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#ifndef QGSMAPTOOLELLIPSEEXTENT_H
+#define QGSMAPTOOLELLIPSEEXTENT_H
+
+#include "qgsmaptooladdellipse.h"
+
+class QgsMapToolEllipseExtent: public QgsMapToolAddEllipse
+{
+ Q_OBJECT
+
+ public:
+ QgsMapToolEllipseExtent( QgsMapToolCapture *parentTool, QgsMapCanvas *canvas, CaptureMode mode = CaptureLine );
+ ~QgsMapToolEllipseExtent();
+
+ void cadCanvasReleaseEvent( QgsMapMouseEvent *e ) override;
+ void cadCanvasMoveEvent( QgsMapMouseEvent *e ) override;
+};
+
+#endif // QGSMAPTOOLELLIPSEEXTENT_H
diff --git a/src/app/qgsmaptoolellipsefoci.cpp b/src/app/qgsmaptoolellipsefoci.cpp
new file mode 100644
index 000000000000..42f5b29fc7b2
--- /dev/null
+++ b/src/app/qgsmaptoolellipsefoci.cpp
@@ -0,0 +1,86 @@
+/***************************************************************************
+ qgmaptoolellipsefoci.cpp - map tool for adding ellipse
+ from foci and a point
+ ---------------------
+ begin : July 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 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+#include "qgsmaptoolellipsefoci.h"
+#include "qgsgeometryrubberband.h"
+#include "qgslinestring.h"
+#include "qgsmapcanvas.h"
+#include "qgspoint.h"
+#include
+
+QgsMapToolEllipseFoci::QgsMapToolEllipseFoci( QgsMapToolCapture *parentTool,
+ QgsMapCanvas *canvas, CaptureMode mode )
+ : QgsMapToolAddEllipse( parentTool, canvas, mode )
+{
+}
+
+QgsMapToolEllipseFoci::~QgsMapToolEllipseFoci()
+{
+}
+
+void QgsMapToolEllipseFoci::cadCanvasReleaseEvent( QgsMapMouseEvent *e )
+{
+ QgsPoint mapPoint( e->mapPoint() );
+
+ if ( e->button() == Qt::LeftButton )
+ {
+ 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();
+ if ( mParentTool )
+ {
+ mParentTool->canvasReleaseEvent( e );
+ }
+ }
+}
+
+void QgsMapToolEllipseFoci::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 );
+ }
+ break;
+ case 2:
+ {
+ mEllipse = QgsEllipse().fromFoci( mPoints.at( 0 ), mPoints.at( 1 ), mapPoint );
+ mTempRubberBand->setGeometry( mEllipse.toPolygon() );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
diff --git a/src/app/qgsmaptoolellipsefoci.h b/src/app/qgsmaptoolellipsefoci.h
new file mode 100644
index 000000000000..782fae3a77bc
--- /dev/null
+++ b/src/app/qgsmaptoolellipsefoci.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ qgmaptoolellipsefoci.h - map tool for adding ellipse
+ from foci and a point
+ ---------------------
+ begin : July 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. *
+ * *
+ ***************************************************************************/
+#ifndef QGSMAPTOOLELLIPSEFOCI_H
+#define QGSMAPTOOLELLIPSEFOCI_H
+
+#include "qgsmaptooladdellipse.h"
+
+class QgsMapToolEllipseFoci: public QgsMapToolAddEllipse
+{
+ Q_OBJECT
+
+ public:
+ QgsMapToolEllipseFoci( QgsMapToolCapture *parentTool, QgsMapCanvas *canvas, CaptureMode mode = CaptureLine );
+ ~QgsMapToolEllipseFoci();
+
+ void cadCanvasReleaseEvent( QgsMapMouseEvent *e ) override;
+ void cadCanvasMoveEvent( QgsMapMouseEvent *e ) override;
+};
+
+#endif // QGSMAPTOOLELLIPSEFOCI_H
diff --git a/src/core/geometry/qgsellipse.cpp b/src/core/geometry/qgsellipse.cpp
index 5f1fcc30b4cb..39e735e3fcaf 100644
--- a/src/core/geometry/qgsellipse.cpp
+++ b/src/core/geometry/qgsellipse.cpp
@@ -242,6 +242,7 @@ QgsLineString *QgsEllipse::toLineString( unsigned int segments ) const
QgsPointSequence pts;
pts = points( segments );
+ pts.append( pts.at( 0 ) ); // close linestring
ext->setPoints( pts );
diff --git a/src/ui/qgisapp.ui b/src/ui/qgisapp.ui
index 8f89f5ddbc75..ee5f0f18b1d1 100755
--- a/src/ui/qgisapp.ui
+++ b/src/ui/qgisapp.ui
@@ -272,6 +272,23 @@
+
+
@@ -284,9 +301,8 @@
-
-
-
+
+
@@ -2723,12 +2739,72 @@ Acts on currently active editable layer
:/images/themes/default/mActionCircleCenterPoint.svg:/images/themes/default/mActionCircleCenterPoint.svg
- Add Circle by a center point and another point
+ &Add Circle by a center point and another point
Add Circle by a center point and another point
+
+
+ true
+
+
+
+ :/images/themes/default/mActionEllipseCenter2Points.svg:/images/themes/default/mActionEllipseCenter2Points.svg
+
+
+ &Add Ellipse from Center and 2 Points
+
+
+ Add Ellipse from center and 2 points
+
+
+
+
+ true
+
+
+
+ :/images/themes/default/mActionEllipseCenterPoint.svg:/images/themes/default/mActionEllipseCenterPoint.svg
+
+
+ Add Ellipse from &Center and a Point
+
+
+ Add Ellipse from center and a point
+
+
+
+
+ true
+
+
+
+ :/images/themes/default/mActionEllipseExtent.svg:/images/themes/default/mActionEllipseExtent.svg
+
+
+ Add Ellipse from &Extent
+
+
+ Add Ellipse from extent
+
+
+
+
+ true
+
+
+
+ :/images/themes/default/mActionEllipseFoci.svg:/images/themes/default/mActionEllipseFoci.svg
+
+
+ Add Ellipse from &Foci
+
+
+ Add Ellipse from foci
+
+
diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp
index 23f64c382fd5..b3531444b2c9 100644
--- a/tests/src/core/testqgsgeometry.cpp
+++ b/tests/src/core/testqgsgeometry.cpp
@@ -4014,7 +4014,7 @@ void TestQgsGeometry::ellipse()
QgsLineString *l = new QgsLineString();
l = QgsEllipse( QgsPoint( 0, 0 ), 5, 2, 0 ).toLineString( 4 );
- QCOMPARE( l->numPoints(), 4 );
+ QCOMPARE( l->numPoints(), 5 ); // closed linestring
QgsPointSequence pts_l;
l->points( pts_l );
QCOMPARE( pts, pts_l );