mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
Merge pull request #2268 from mhugent/curve_capture_tool
Curve capture tool
This commit is contained in:
commit
5807875797
@ -508,6 +508,8 @@
|
||||
<file>themes/default/mIconClear.png</file>
|
||||
<file>flags/zh.png</file>
|
||||
<file>themes/default/mIconPaintEffects.svg</file>
|
||||
<file>themes/default/mActionCircularStringCurvePoint.png</file>
|
||||
<file>themes/default/mActionCircularStringRadius.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/images/tips">
|
||||
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
|
||||
|
BIN
images/themes/default/mActionCircularStringCurvePoint.png
Normal file
BIN
images/themes/default/mActionCircularStringCurvePoint.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 979 B |
BIN
images/themes/default/mActionCircularStringRadius.png
Normal file
BIN
images/themes/default/mActionCircularStringRadius.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
@ -90,7 +90,7 @@ class QgsAbstractGeometryV2
|
||||
virtual QgsRectangle calculateBoundingBox() const;
|
||||
|
||||
//render pipeline
|
||||
virtual void transform( const QgsCoordinateTransform& ct ) = 0;
|
||||
virtual void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) = 0;
|
||||
virtual void transform( const QTransform& t ) = 0;
|
||||
//virtual void clip( const QgsRectangle& rect );
|
||||
virtual void draw( QPainter& p ) const = 0;
|
||||
|
@ -38,7 +38,7 @@ class QgsCircularStringV2: public QgsCurveV2
|
||||
virtual QgsLineStringV2* curveToLine() const;
|
||||
|
||||
void draw( QPainter& p ) const;
|
||||
void transform( const QgsCoordinateTransform& ct );
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform );
|
||||
void transform( const QTransform& t );
|
||||
//void clip( const QgsRectangle& rect );
|
||||
void addToPainterPath( QPainterPath& path ) const;
|
||||
|
@ -45,7 +45,7 @@ class QgsCompoundCurveV2: public QgsCurveV2
|
||||
void close();
|
||||
|
||||
void draw( QPainter& p ) const;
|
||||
void transform( const QgsCoordinateTransform& ct );
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform );
|
||||
void transform( const QTransform& t );
|
||||
void addToPainterPath( QPainterPath& path ) const;
|
||||
void drawAsPolygon( QPainter& p ) const;
|
||||
|
@ -49,7 +49,7 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
|
||||
bool removeInteriorRing( int nr );
|
||||
|
||||
virtual void draw( QPainter& p ) const;
|
||||
void transform( const QgsCoordinateTransform& ct );
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform );
|
||||
void transform( const QTransform& t );
|
||||
|
||||
virtual bool insertVertex( const QgsVertexId& position, const QgsPointV2& vertex );
|
||||
|
@ -23,7 +23,7 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2
|
||||
virtual bool addGeometry( QgsAbstractGeometryV2* g /Transfer/ );
|
||||
virtual bool removeGeometry( int nr );
|
||||
|
||||
virtual void transform( const QgsCoordinateTransform& ct );
|
||||
virtual void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform );
|
||||
void transform( const QTransform& t );
|
||||
//virtual void clip( const QgsRectangle& rect );
|
||||
virtual void draw( QPainter& p ) const;
|
||||
|
@ -38,7 +38,7 @@ class QgsLineStringV2: public QgsCurveV2
|
||||
void append( const QgsLineStringV2* line );
|
||||
|
||||
void draw( QPainter& p ) const;
|
||||
void transform( const QgsCoordinateTransform& ct );
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform );
|
||||
void transform( const QTransform& t );
|
||||
|
||||
void addToPainterPath( QPainterPath& path ) const;
|
||||
|
@ -119,6 +119,9 @@ SET(QGIS_APP_SRCS
|
||||
qgsvectorlayerproperties.cpp
|
||||
qgsvisibilitypresets.cpp
|
||||
qgshandlebadlayers.cpp
|
||||
qgsmaptooladdcircularstring.cpp
|
||||
qgsmaptoolcircularstringcurvepoint.cpp
|
||||
qgsmaptoolcircularstringradius.cpp
|
||||
|
||||
composer/qgsattributeselectiondialog.cpp
|
||||
composer/qgscomposer.cpp
|
||||
@ -217,6 +220,7 @@ SET (QGIS_APP_MOC_HDRS
|
||||
|
||||
qgsmaptooladdfeature.h
|
||||
qgsmaptoolcapture.h
|
||||
qgsmaptoolcircularstringradius.h
|
||||
qgsmaptooladdpart.h
|
||||
qgsmaptooladdring.h
|
||||
qgsmaptooledit.h
|
||||
@ -245,6 +249,7 @@ SET (QGIS_APP_MOC_HDRS
|
||||
qgsmaptoolsimplify.h
|
||||
qgsmaptoolsplitfeatures.h
|
||||
qgsmaptoolsplitparts.h
|
||||
qgsmaptooladdcircularstring.h
|
||||
|
||||
nodetool/qgsmaptoolnodetool.h
|
||||
nodetool/qgsselectedfeature.h
|
||||
|
@ -253,6 +253,8 @@
|
||||
#include "qgsmaptooladdring.h"
|
||||
#include "qgsmaptoolfillring.h"
|
||||
#include "qgsmaptoolannotation.h"
|
||||
#include "qgsmaptoolcircularstringcurvepoint.h"
|
||||
#include "qgsmaptoolcircularstringradius.h"
|
||||
#include "qgsmaptooldeletering.h"
|
||||
#include "qgsmaptooldeletepart.h"
|
||||
#include "qgsmaptoolfeatureaction.h"
|
||||
@ -288,7 +290,6 @@
|
||||
|
||||
// Editor widgets
|
||||
#include "qgseditorwidgetregistry.h"
|
||||
|
||||
//
|
||||
// Conditional Includes
|
||||
//
|
||||
@ -1206,6 +1207,8 @@ void QgisApp::createActions()
|
||||
connect( mActionCopyStyle, SIGNAL( triggered() ), this, SLOT( copyStyle() ) );
|
||||
connect( mActionPasteStyle, SIGNAL( triggered() ), this, SLOT( pasteStyle() ) );
|
||||
connect( mActionAddFeature, SIGNAL( triggered() ), this, SLOT( addFeature() ) );
|
||||
connect( mActionCircularStringCurvePoint, SIGNAL( triggered() ), this, SLOT( circularStringCurvePoint() ) );
|
||||
connect( mActionCircularStringRadius, SIGNAL( triggered() ), this, SLOT( circularStringRadius() ) );
|
||||
connect( mActionMoveFeature, SIGNAL( triggered() ), this, SLOT( moveFeature() ) );
|
||||
connect( mActionRotateFeature, SIGNAL( triggered() ), this, SLOT( rotateFeature() ) );
|
||||
|
||||
@ -1480,6 +1483,8 @@ void QgisApp::createActionGroups()
|
||||
mMapToolGroup->addAction( mActionMeasureArea );
|
||||
mMapToolGroup->addAction( mActionMeasureAngle );
|
||||
mMapToolGroup->addAction( mActionAddFeature );
|
||||
mMapToolGroup->addAction( mActionCircularStringCurvePoint );
|
||||
mMapToolGroup->addAction( mActionCircularStringRadius );
|
||||
mMapToolGroup->addAction( mActionMoveFeature );
|
||||
mMapToolGroup->addAction( mActionRotateFeature );
|
||||
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
|
||||
@ -2329,6 +2334,10 @@ void QgisApp::createCanvasTools()
|
||||
mMapTools.mAnnotation->setAction( mActionAnnotation );
|
||||
mMapTools.mAddFeature = new QgsMapToolAddFeature( mMapCanvas );
|
||||
mMapTools.mAddFeature->setAction( mActionAddFeature );
|
||||
mMapTools.mCircularStringCurvePoint = new QgsMapToolCircularStringCurvePoint( dynamic_cast<QgsMapToolAddFeature*>( mMapTools.mAddFeature ), mMapCanvas );
|
||||
mMapTools.mCircularStringCurvePoint->setAction( mActionCircularStringCurvePoint );
|
||||
mMapTools.mCircularStringRadius = new QgsMapToolCircularStringRadius( dynamic_cast<QgsMapToolAddFeature*>( mMapTools.mAddFeature ), mMapCanvas );
|
||||
mMapTools.mCircularStringRadius->setAction( mActionCircularStringRadius );
|
||||
mMapTools.mMoveFeature = new QgsMapToolMoveFeature( mMapCanvas );
|
||||
mMapTools.mMoveFeature->setAction( mActionMoveFeature );
|
||||
mMapTools.mRotateFeature = new QgsMapToolRotateFeature( mMapCanvas );
|
||||
@ -6233,6 +6242,16 @@ void QgisApp::addFeature()
|
||||
mMapCanvas->setMapTool( mMapTools.mAddFeature );
|
||||
}
|
||||
|
||||
void QgisApp::circularStringCurvePoint()
|
||||
{
|
||||
mMapCanvas->setMapTool( mMapTools.mCircularStringCurvePoint );
|
||||
}
|
||||
|
||||
void QgisApp::circularStringRadius()
|
||||
{
|
||||
mMapCanvas->setMapTool( mMapTools.mCircularStringRadius );
|
||||
}
|
||||
|
||||
void QgisApp::selectFeatures()
|
||||
{
|
||||
mMapCanvas->setMapTool( mMapTools.mSelectFeatures );
|
||||
|
@ -971,6 +971,10 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
void newBookmark();
|
||||
//! activates the add feature tool
|
||||
void addFeature();
|
||||
//! activates the add circular string tool
|
||||
void circularStringCurvePoint();
|
||||
//! activates the circular string radius tool
|
||||
void circularStringRadius();
|
||||
//! activates the move feature tool
|
||||
void moveFeature();
|
||||
//! activates the offset curve tool
|
||||
@ -1481,6 +1485,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
QgsMapTool *mMeasureArea;
|
||||
QgsMapTool *mMeasureAngle;
|
||||
QgsMapTool *mAddFeature;
|
||||
QgsMapTool *mCircularStringCurvePoint;
|
||||
QgsMapTool *mCircularStringRadius;
|
||||
QgsMapTool *mMoveFeature;
|
||||
QgsMapTool *mOffsetCurve;
|
||||
QgsMapTool *mReshapeFeatures;
|
||||
|
182
src/app/qgsmaptooladdcircularstring.cpp
Normal file
182
src/app/qgsmaptooladdcircularstring.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
/***************************************************************************
|
||||
qgsmaptooladdcircularstring.h - map tool for adding circular strings
|
||||
---------------------
|
||||
begin : December 2014
|
||||
copyright : (C) 2014 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgsmaptooladdcircularstring.h"
|
||||
#include "qgscircularstringv2.h"
|
||||
#include "qgscompoundcurvev2.h"
|
||||
#include "qgscurvepolygonv2.h"
|
||||
#include "qgsgeometryrubberband.h"
|
||||
#include "qgsgeometryutils.h"
|
||||
#include "qgslinestringv2.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgspointv2.h"
|
||||
#include <QMouseEvent>
|
||||
|
||||
QgsMapToolAddCircularString::QgsMapToolAddCircularString( QgsMapToolCapture* parentTool, QgsMapCanvas* canvas, CaptureMode mode ): QgsMapToolCapture( canvas, mode ),
|
||||
mParentTool( parentTool ), mRubberBand( 0 ), mShowCenterPointRubberBand( false ), mCenterPointRubberBand( 0 )
|
||||
{
|
||||
if ( mCanvas )
|
||||
{
|
||||
connect( mCanvas, SIGNAL( mapToolSet( QgsMapTool*, QgsMapTool* ) ), this, SLOT( setParentTool( QgsMapTool*, QgsMapTool* ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsMapToolAddCircularString::QgsMapToolAddCircularString( QgsMapCanvas* canvas ): QgsMapToolCapture( canvas ), mParentTool( 0 ),
|
||||
mRubberBand( 0 ), mShowCenterPointRubberBand( false ), mCenterPointRubberBand( 0 )
|
||||
{
|
||||
if ( mCanvas )
|
||||
{
|
||||
connect( mCanvas, SIGNAL( mapToolSet( QgsMapTool*, QgsMapTool* ) ), this, SLOT( setParentTool( QgsMapTool*, QgsMapTool* ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
QgsMapToolAddCircularString::~QgsMapToolAddCircularString()
|
||||
{
|
||||
delete mRubberBand;
|
||||
removeCenterPointRubberBand();
|
||||
}
|
||||
|
||||
void QgsMapToolAddCircularString::setParentTool( QgsMapTool* newTool, QgsMapTool* oldTool )
|
||||
{
|
||||
QgsMapToolCapture* tool = dynamic_cast<QgsMapToolCapture*>( oldTool );
|
||||
QgsMapToolAddCircularString* csTool = dynamic_cast<QgsMapToolAddCircularString*>( oldTool );
|
||||
if ( csTool && newTool == this )
|
||||
{
|
||||
mParentTool = csTool->mParentTool;
|
||||
}
|
||||
else if ( tool && newTool == this )
|
||||
{
|
||||
mParentTool = tool;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolAddCircularString::keyPressEvent( QKeyEvent* e )
|
||||
{
|
||||
if ( e->isAutoRepeat() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( e && e->key() == Qt::Key_R )
|
||||
{
|
||||
mShowCenterPointRubberBand = true;
|
||||
|
||||
createCenterPointRubberBand();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolAddCircularString::keyReleaseEvent( QKeyEvent* e )
|
||||
{
|
||||
if ( e->isAutoRepeat() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( e && e->key() == Qt::Key_R )
|
||||
{
|
||||
removeCenterPointRubberBand();
|
||||
mShowCenterPointRubberBand = false;
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolAddCircularString::deactivate()
|
||||
{
|
||||
if ( !mParentTool || mPoints.size() < 3 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mPoints.size() % 2 == 0 ) //a valid circularstring needs to have an odd number of vertices
|
||||
{
|
||||
mPoints.removeLast();
|
||||
}
|
||||
|
||||
QgsCircularStringV2* c = new QgsCircularStringV2();
|
||||
c->setPoints( mPoints );
|
||||
mParentTool->addCurve( c );
|
||||
mPoints.clear();
|
||||
delete mRubberBand; mRubberBand = 0;
|
||||
removeCenterPointRubberBand();
|
||||
}
|
||||
|
||||
void QgsMapToolAddCircularString::createCenterPointRubberBand()
|
||||
{
|
||||
if ( !mShowCenterPointRubberBand || mPoints.size() < 2 || mPoints.size() % 2 != 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mCenterPointRubberBand = createGeometryRubberBand( QGis::Polygon );
|
||||
mCenterPointRubberBand->show();
|
||||
|
||||
if ( mRubberBand )
|
||||
{
|
||||
const QgsAbstractGeometryV2* rubberBandGeom = mRubberBand->geometry();
|
||||
if ( rubberBandGeom )
|
||||
{
|
||||
QgsVertexId idx; idx.part = 0; idx.ring = 0; idx.vertex = mPoints.size();
|
||||
QgsPointV2 pt = rubberBandGeom->vertexAt( idx );
|
||||
updateCenterPointRubberBand( pt );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolAddCircularString::updateCenterPointRubberBand( const QgsPointV2& pt )
|
||||
{
|
||||
if ( !mShowCenterPointRubberBand || !mCenterPointRubberBand || mPoints.size() < 2 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (( mPoints.size() ) % 2 != 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//create circular string
|
||||
QgsCircularStringV2* cs = new QgsCircularStringV2();
|
||||
QList< QgsPointV2 > csPoints;
|
||||
csPoints.append( mPoints.at( mPoints.size() - 2 ) );
|
||||
csPoints.append( mPoints.at( mPoints.size() - 1 ) );
|
||||
csPoints.append( pt );
|
||||
cs->setPoints( csPoints );
|
||||
|
||||
double centerX, centerY;
|
||||
double radius;
|
||||
QgsGeometryUtils::circleCenterRadius( csPoints.at( 0 ), csPoints.at( 1 ), csPoints.at( 2 ), radius, centerX, centerY );
|
||||
|
||||
QgsLineStringV2* segment1 = new QgsLineStringV2();
|
||||
segment1->addVertex( QgsPointV2( centerX, centerY ) );
|
||||
segment1->addVertex( csPoints.at( 0 ) );
|
||||
|
||||
QgsLineStringV2* segment2 = new QgsLineStringV2();
|
||||
segment2->addVertex( csPoints.at( 2 ) );
|
||||
segment2->addVertex( QgsPointV2( centerX, centerY ) );
|
||||
|
||||
QgsCompoundCurveV2* cc = new QgsCompoundCurveV2();
|
||||
cc->addCurve( segment1 );
|
||||
cc->addCurve( cs );
|
||||
cc->addCurve( segment2 );
|
||||
|
||||
QgsCurvePolygonV2* cp = new QgsCurvePolygonV2();
|
||||
cp->setExteriorRing( cc );
|
||||
mCenterPointRubberBand->setGeometry( cp );
|
||||
mCenterPointRubberBand->show();
|
||||
}
|
||||
|
||||
void QgsMapToolAddCircularString::removeCenterPointRubberBand()
|
||||
{
|
||||
delete mCenterPointRubberBand; mCenterPointRubberBand = 0;
|
||||
}
|
55
src/app/qgsmaptooladdcircularstring.h
Normal file
55
src/app/qgsmaptooladdcircularstring.h
Normal file
@ -0,0 +1,55 @@
|
||||
/***************************************************************************
|
||||
qgsmaptooladdcircularstring.h - map tool for adding circular strings
|
||||
---------------------
|
||||
begin : December 2014
|
||||
copyright : (C) 2014 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSMAPTOOLADDCIRCULARSTRING_H
|
||||
#define QGSMAPTOOLADDCIRCULARSTRING_H
|
||||
|
||||
#include "qgsmaptoolcapture.h"
|
||||
|
||||
class QgsGeometryRubberBand;
|
||||
|
||||
class QgsMapToolAddCircularString: public QgsMapToolCapture
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QgsMapToolAddCircularString( QgsMapToolCapture* parentTool, QgsMapCanvas* canvas, CaptureMode mode = CaptureLine );
|
||||
~QgsMapToolAddCircularString();
|
||||
|
||||
void keyPressEvent( QKeyEvent* e );
|
||||
void keyReleaseEvent( QKeyEvent* e );
|
||||
|
||||
void deactivate();
|
||||
|
||||
private slots:
|
||||
void setParentTool( QgsMapTool* newTool, QgsMapTool* oldTool );
|
||||
|
||||
protected:
|
||||
QgsMapToolAddCircularString( QgsMapCanvas* canvas = 0 ); //forbidden
|
||||
|
||||
QgsMapToolCapture* mParentTool;
|
||||
/** Circular string points (in map coordinates)*/
|
||||
QList< QgsPointV2 > mPoints;
|
||||
QgsGeometryRubberBand* mRubberBand;
|
||||
|
||||
//center point rubber band
|
||||
bool mShowCenterPointRubberBand;
|
||||
QgsGeometryRubberBand* mCenterPointRubberBand;
|
||||
|
||||
void createCenterPointRubberBand();
|
||||
void updateCenterPointRubberBand( const QgsPointV2& pt );
|
||||
void removeCenterPointRubberBand();
|
||||
};
|
||||
|
||||
#endif // QGSMAPTOOLADDCIRCULARSTRING_H
|
@ -17,11 +17,14 @@
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsattributedialog.h"
|
||||
#include "qgscsexception.h"
|
||||
#include "qgscurvepolygonv2.h"
|
||||
#include "qgsfield.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgslinestringv2.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgsmapmouseevent.h"
|
||||
#include "qgspolygonv2.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
@ -199,56 +202,46 @@ void QgsMapToolAddFeature::canvasMapReleaseEvent( QgsMapMouseEvent* e )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( mode() == CapturePolygon )
|
||||
{
|
||||
closePolygon();
|
||||
}
|
||||
|
||||
//create QgsFeature with wkb representation
|
||||
QgsFeature* f = new QgsFeature( vlayer->fields(), 0 );
|
||||
|
||||
QgsGeometry *g;
|
||||
//does compoundcurve contain circular strings?
|
||||
//does provider support circular strings?
|
||||
bool hasCurvedSegments = captureCurve()->hasCurvedSegments();
|
||||
bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries;
|
||||
|
||||
QgsCurveV2* curveToAdd = 0;
|
||||
if ( hasCurvedSegments && providerSupportsCurvedSegments )
|
||||
{
|
||||
curveToAdd = dynamic_cast<QgsCurveV2*>( captureCurve()->clone() );
|
||||
}
|
||||
else
|
||||
{
|
||||
curveToAdd = captureCurve()->curveToLine();
|
||||
}
|
||||
|
||||
if ( mode() == CaptureLine )
|
||||
{
|
||||
if ( layerWKBType == QGis::WKBLineString || layerWKBType == QGis::WKBLineString25D )
|
||||
{
|
||||
g = QgsGeometry::fromPolyline( points().toVector() );
|
||||
}
|
||||
else if ( layerWKBType == QGis::WKBMultiLineString || layerWKBType == QGis::WKBMultiLineString25D )
|
||||
{
|
||||
g = QgsGeometry::fromMultiPolyline( QgsMultiPolyline() << points().toVector() );
|
||||
}
|
||||
else
|
||||
{
|
||||
emit messageEmitted( tr( "Cannot add feature. Unknown WKB type" ), QgsMessageBar::CRITICAL );
|
||||
stopCapturing();
|
||||
delete f;
|
||||
return; //unknown wkbtype
|
||||
}
|
||||
|
||||
f->setGeometry( g );
|
||||
f->setGeometry( new QgsGeometry( curveToAdd ) );
|
||||
}
|
||||
else // polygon
|
||||
else
|
||||
{
|
||||
if ( layerWKBType == QGis::WKBPolygon || layerWKBType == QGis::WKBPolygon25D )
|
||||
QgsCurvePolygonV2* poly = 0;
|
||||
if ( hasCurvedSegments && providerSupportsCurvedSegments )
|
||||
{
|
||||
g = QgsGeometry::fromPolygon( QgsPolygon() << points().toVector() );
|
||||
}
|
||||
else if ( layerWKBType == QGis::WKBMultiPolygon || layerWKBType == QGis::WKBMultiPolygon25D )
|
||||
{
|
||||
g = QgsGeometry::fromMultiPolygon( QgsMultiPolygon() << ( QgsPolygon() << points().toVector() ) );
|
||||
poly = new QgsCurvePolygonV2();
|
||||
}
|
||||
else
|
||||
{
|
||||
emit messageEmitted( tr( "Cannot add feature. Unknown WKB type" ), QgsMessageBar::CRITICAL );
|
||||
stopCapturing();
|
||||
delete f;
|
||||
return; //unknown wkbtype
|
||||
poly = new QgsPolygonV2();
|
||||
}
|
||||
|
||||
if ( !g )
|
||||
{
|
||||
stopCapturing();
|
||||
delete f;
|
||||
return; // invalid geometry; one possibility is from duplicate points
|
||||
}
|
||||
f->setGeometry( g );
|
||||
poly->setExteriorRing( curveToAdd );
|
||||
f->setGeometry( poly );
|
||||
|
||||
int avoidIntersectionsReturn = f->geometry()->avoidIntersections();
|
||||
if ( avoidIntersectionsReturn == 1 )
|
||||
|
@ -14,9 +14,12 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsmaptooladdpart.h"
|
||||
#include "qgscurvepolygonv2.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgslinestringv2.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgslogger.h"
|
||||
|
||||
@ -67,7 +70,7 @@ void QgsMapToolAddPart::canvasMapReleaseEvent( QgsMapMouseEvent * e )
|
||||
return;
|
||||
}
|
||||
|
||||
int errorCode;
|
||||
int errorCode = 0;
|
||||
switch ( mode() )
|
||||
{
|
||||
case CapturePoint:
|
||||
@ -118,33 +121,51 @@ void QgsMapToolAddPart::canvasMapReleaseEvent( QgsMapMouseEvent * e )
|
||||
if ( !isCapturing() )
|
||||
return;
|
||||
|
||||
// we are now going to finish the capturing
|
||||
|
||||
if ( mode() == CapturePolygon )
|
||||
{
|
||||
//close polygon
|
||||
closePolygon();
|
||||
//avoid intersections
|
||||
QgsGeometry* geom = QgsGeometry::fromPolygon( QgsPolygon() << points().toVector() );
|
||||
if ( geom )
|
||||
{
|
||||
geom->avoidIntersections();
|
||||
QgsPolygon poly = geom->asPolygon();
|
||||
if ( poly.size() < 1 )
|
||||
{
|
||||
stopCapturing();
|
||||
delete geom;
|
||||
vlayer->destroyEditCommand();
|
||||
return;
|
||||
}
|
||||
setPoints( geom->asPolygon()[0].toList() );
|
||||
delete geom;
|
||||
}
|
||||
}
|
||||
|
||||
//does compoundcurve contain circular strings?
|
||||
//does provider support circular strings?
|
||||
bool hasCurvedSegments = captureCurve()->hasCurvedSegments();
|
||||
bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries;
|
||||
|
||||
QgsCurveV2* curveToAdd = 0;
|
||||
if ( hasCurvedSegments && providerSupportsCurvedSegments )
|
||||
{
|
||||
curveToAdd = dynamic_cast<QgsCurveV2*>( captureCurve()->clone() );
|
||||
}
|
||||
else
|
||||
{
|
||||
curveToAdd = captureCurve()->curveToLine();
|
||||
}
|
||||
|
||||
vlayer->beginEditCommand( tr( "Part added" ) );
|
||||
errorCode = vlayer->addPart( points() );
|
||||
if ( mode() == CapturePolygon )
|
||||
{
|
||||
//avoid intersections
|
||||
QgsCurvePolygonV2* cp = new QgsCurvePolygonV2();
|
||||
cp->setExteriorRing( curveToAdd );
|
||||
QgsGeometry* geom = new QgsGeometry( cp );
|
||||
geom->avoidIntersections();
|
||||
|
||||
const QgsCurvePolygonV2* cpGeom = dynamic_cast<const QgsCurvePolygonV2*>( geom->geometry() );
|
||||
if ( !cpGeom )
|
||||
{
|
||||
stopCapturing();
|
||||
delete geom;
|
||||
vlayer->destroyEditCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
errorCode = vlayer->addPart( dynamic_cast<QgsCurveV2*>( cpGeom->exteriorRing()->clone() ) );
|
||||
delete geom;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorCode = vlayer->addPart( curveToAdd );
|
||||
}
|
||||
stopCapturing();
|
||||
}
|
||||
break;
|
||||
|
@ -17,8 +17,10 @@
|
||||
|
||||
#include "qgsmaptooladdring.h"
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgslinestringv2.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
|
||||
@ -80,7 +82,23 @@ void QgsMapToolAddRing::canvasMapReleaseEvent( QgsMapMouseEvent * e )
|
||||
closePolygon();
|
||||
|
||||
vlayer->beginEditCommand( tr( "Ring added" ) );
|
||||
int addRingReturnCode = vlayer->addRing( points() );
|
||||
|
||||
//does compoundcurve contain circular strings?
|
||||
//does provider support circular strings?
|
||||
bool hasCurvedSegments = captureCurve()->hasCurvedSegments();
|
||||
bool providerSupportsCurvedSegments = vlayer->dataProvider()->capabilities() & QgsVectorDataProvider::CircularGeometries;
|
||||
|
||||
QgsCurveV2* curveToAdd = 0;
|
||||
if ( hasCurvedSegments && providerSupportsCurvedSegments )
|
||||
{
|
||||
curveToAdd = dynamic_cast<QgsCurveV2*>( captureCurve()->clone() );
|
||||
}
|
||||
else
|
||||
{
|
||||
curveToAdd = captureCurve()->curveToLine();
|
||||
}
|
||||
|
||||
int addRingReturnCode = vlayer->addRing( curveToAdd );
|
||||
if ( addRingReturnCode != 0 )
|
||||
{
|
||||
QString errorMessage;
|
||||
|
@ -19,10 +19,12 @@
|
||||
#include "qgscursors.h"
|
||||
#include "qgsgeometryvalidator.h"
|
||||
#include "qgslayertreeview.h"
|
||||
#include "qgslinestringv2.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsmapmouseevent.h"
|
||||
#include "qgsmaprenderer.h"
|
||||
#include "qgspolygonv2.h"
|
||||
#include "qgsrubberband.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsvertexmarker.h"
|
||||
@ -167,6 +169,13 @@ int QgsMapToolCapture::nextPoint( const QgsPoint& mapPoint, QgsPoint& layerPoint
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QgsMapToolCapture::nextPoint( const QPoint &p, QgsPoint &layerPoint, QgsPoint &mapPoint )
|
||||
{
|
||||
|
||||
mapPoint = toMapCoordinates( p );
|
||||
return nextPoint( mapPoint, layerPoint );
|
||||
}
|
||||
|
||||
int QgsMapToolCapture::addVertex( const QgsPoint& point )
|
||||
{
|
||||
if ( mode() == CaptureNone )
|
||||
@ -188,7 +197,7 @@ int QgsMapToolCapture::addVertex( const QgsPoint& point )
|
||||
mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );
|
||||
}
|
||||
mRubberBand->addPoint( point );
|
||||
mCaptureList.append( layerPoint );
|
||||
mCaptureCurve.addVertex( QgsPointV2( layerPoint.x(), layerPoint.y() ) );
|
||||
|
||||
if ( !mTempRubberBand )
|
||||
{
|
||||
@ -215,6 +224,51 @@ int QgsMapToolCapture::addVertex( const QgsPoint& point )
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QgsMapToolCapture::addCurve( QgsCurveV2* c )
|
||||
{
|
||||
if ( !c )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( !mRubberBand )
|
||||
{
|
||||
mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );
|
||||
}
|
||||
|
||||
QgsLineStringV2* lineString = c->curveToLine();
|
||||
QList<QgsPointV2> linePoints;
|
||||
lineString->points( linePoints );
|
||||
delete lineString;
|
||||
QList<QgsPointV2>::const_iterator ptIt = linePoints.constBegin();
|
||||
for ( ; ptIt != linePoints.constEnd(); ++ptIt )
|
||||
{
|
||||
mRubberBand->addPoint( QgsPoint( ptIt->x(), ptIt->y() ) );
|
||||
}
|
||||
|
||||
if ( !mTempRubberBand )
|
||||
{
|
||||
mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
mTempRubberBand->reset();
|
||||
}
|
||||
QgsPointV2 endPt = c->endPoint();
|
||||
mTempRubberBand->addPoint( QgsPoint( endPt.x(), endPt.y() ) ); //add last point of c
|
||||
|
||||
//transform back to layer CRS in case map CRS and layer CRS are different
|
||||
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
|
||||
const QgsCoordinateTransform* ct = mCanvas->mapSettings().layerTransform( vlayer );
|
||||
if ( ct )
|
||||
{
|
||||
c->transform( *ct, QgsCoordinateTransform::ReverseTransform );
|
||||
}
|
||||
mCaptureCurve.addCurve( c );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void QgsMapToolCapture::undo()
|
||||
{
|
||||
@ -222,7 +276,7 @@ void QgsMapToolCapture::undo()
|
||||
{
|
||||
int rubberBandSize = mRubberBand->numberOfVertices();
|
||||
int tempRubberBandSize = mTempRubberBand->numberOfVertices();
|
||||
int captureListSize = mCaptureList.size();
|
||||
int captureListSize = size();
|
||||
|
||||
if ( rubberBandSize < 1 || captureListSize < 1 )
|
||||
{
|
||||
@ -244,7 +298,9 @@ void QgsMapToolCapture::undo()
|
||||
mTempRubberBand->reset( mCaptureMode == CapturePolygon ? true : false );
|
||||
}
|
||||
|
||||
mCaptureList.removeLast();
|
||||
QgsVertexId vertexToRemove;
|
||||
vertexToRemove.part = 0; vertexToRemove.ring = 0; vertexToRemove.vertex = size() - 1;
|
||||
mCaptureCurve.deleteVertex( vertexToRemove );
|
||||
|
||||
validateGeometry();
|
||||
}
|
||||
@ -298,7 +354,7 @@ void QgsMapToolCapture::stopCapturing()
|
||||
#endif
|
||||
|
||||
mCapturing = false;
|
||||
mCaptureList.clear();
|
||||
mCaptureCurve.clear();
|
||||
mCanvas->refresh();
|
||||
}
|
||||
|
||||
@ -313,7 +369,7 @@ void QgsMapToolCapture::deleteTempRubberBand()
|
||||
|
||||
void QgsMapToolCapture::closePolygon()
|
||||
{
|
||||
mCaptureList.append( mCaptureList[0] );
|
||||
mCaptureCurve.close();
|
||||
}
|
||||
|
||||
void QgsMapToolCapture::validateGeometry()
|
||||
@ -343,14 +399,18 @@ void QgsMapToolCapture::validateGeometry()
|
||||
case CapturePoint:
|
||||
return;
|
||||
case CaptureLine:
|
||||
if ( mCaptureList.size() < 2 )
|
||||
if ( size() < 2 )
|
||||
return;
|
||||
g = QgsGeometry::fromPolyline( mCaptureList.toVector() );
|
||||
g = new QgsGeometry( mCaptureCurve.curveToLine() );
|
||||
break;
|
||||
case CapturePolygon:
|
||||
if ( mCaptureList.size() < 3 )
|
||||
if ( size() < 3 )
|
||||
return;
|
||||
g = QgsGeometry::fromPolygon( QgsPolygon() << ( QgsPolyline() << mCaptureList.toVector() << mCaptureList[0] ) );
|
||||
QgsLineStringV2* exteriorRing = mCaptureCurve.curveToLine();
|
||||
exteriorRing->close();
|
||||
QgsPolygonV2* polygon = new QgsPolygonV2();
|
||||
polygon->setExteriorRing( exteriorRing );
|
||||
g = new QgsGeometry( polygon );
|
||||
break;
|
||||
}
|
||||
|
||||
@ -402,3 +462,29 @@ void QgsMapToolCapture::validationFinished()
|
||||
QStatusBar *sb = QgisApp::instance()->statusBar();
|
||||
sb->showMessage( tr( "Validation finished." ) );
|
||||
}
|
||||
|
||||
int QgsMapToolCapture::size()
|
||||
{
|
||||
return mCaptureCurve.numPoints();
|
||||
}
|
||||
|
||||
QList<QgsPoint> QgsMapToolCapture::points()
|
||||
{
|
||||
QList<QgsPointV2> pts;
|
||||
QList<QgsPoint> points;
|
||||
mCaptureCurve.points( pts );
|
||||
QgsGeometry::convertPointList( pts, points );
|
||||
return points;
|
||||
}
|
||||
|
||||
void QgsMapToolCapture::setPoints( const QList<QgsPoint>& pointList )
|
||||
{
|
||||
QList<QgsPointV2> pts;
|
||||
QgsGeometry::convertPointList( pointList, pts );
|
||||
|
||||
QgsLineStringV2* line = new QgsLineStringV2();
|
||||
line->setPoints( pts );
|
||||
|
||||
mCaptureCurve.clear();
|
||||
mCaptureCurve.addCurve( line );
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
|
||||
#include "qgsmaptooledit.h"
|
||||
#include "qgscompoundcurvev2.h"
|
||||
#include "qgspoint.h"
|
||||
#include "qgsgeometry.h"
|
||||
|
||||
@ -52,6 +53,11 @@ class APP_EXPORT QgsMapToolCapture : public QgsMapToolEdit
|
||||
//! deactive the tool
|
||||
virtual void deactivate() override;
|
||||
|
||||
/** Adds a whole curve (e.g. circularstring) to the captured geometry. Curve must be in map CRS*/
|
||||
int addCurve( QgsCurveV2* c );
|
||||
|
||||
const QgsCompoundCurveV2* captureCurve() const { return &mCaptureCurve; }
|
||||
|
||||
public slots:
|
||||
void currentLayerChanged( QgsMapLayer *layer );
|
||||
void addError( QgsGeometry::Error );
|
||||
@ -59,6 +65,7 @@ class APP_EXPORT QgsMapToolCapture : public QgsMapToolEdit
|
||||
|
||||
protected:
|
||||
int nextPoint( const QgsPoint& mapPoint, QgsPoint& layerPoint );
|
||||
int nextPoint( const QPoint &p, QgsPoint &layerPoint, QgsPoint &mapPoint );
|
||||
|
||||
/** Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates)
|
||||
@return 0 in case of success, 1 if current layer is not a vector layer, 2 if coordinate transformation failed*/
|
||||
@ -72,11 +79,9 @@ class APP_EXPORT QgsMapToolCapture : public QgsMapToolEdit
|
||||
void stopCapturing();
|
||||
void deleteTempRubberBand();
|
||||
|
||||
int size() { return mCaptureList.size(); }
|
||||
QList<QgsPoint>::iterator begin() { return mCaptureList.begin(); }
|
||||
QList<QgsPoint>::iterator end() { return mCaptureList.end(); }
|
||||
const QList<QgsPoint> &points() { return mCaptureList; }
|
||||
void setPoints( const QList<QgsPoint>& pointList ) { mCaptureList = pointList; }
|
||||
int size();
|
||||
QList<QgsPoint> points();
|
||||
void setPoints( const QList<QgsPoint>& pointList );
|
||||
void closePolygon();
|
||||
|
||||
private:
|
||||
@ -90,7 +95,7 @@ class APP_EXPORT QgsMapToolCapture : public QgsMapToolEdit
|
||||
QgsRubberBand* mTempRubberBand;
|
||||
|
||||
/** List to store the points of digitised lines and polygons (in layer coordinates)*/
|
||||
QList<QgsPoint> mCaptureList;
|
||||
QgsCompoundCurveV2 mCaptureCurve;
|
||||
|
||||
void validateGeometry();
|
||||
QString mTip;
|
||||
|
87
src/app/qgsmaptoolcircularstringcurvepoint.cpp
Normal file
87
src/app/qgsmaptoolcircularstringcurvepoint.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include "qgsmaptoolcircularstringcurvepoint.h"
|
||||
#include "qgscircularstringv2.h"
|
||||
#include "qgscompoundcurvev2.h"
|
||||
#include "qgsgeometryrubberband.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgspointv2.h"
|
||||
#include <QMouseEvent>
|
||||
|
||||
QgsMapToolCircularStringCurvePoint::QgsMapToolCircularStringCurvePoint( QgsMapToolCapture* parentTool,
|
||||
QgsMapCanvas* canvas, CaptureMode mode ): QgsMapToolAddCircularString( parentTool, canvas, mode )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QgsMapToolCircularStringCurvePoint::~QgsMapToolCircularStringCurvePoint()
|
||||
{
|
||||
}
|
||||
|
||||
void QgsMapToolCircularStringCurvePoint::canvasMapReleaseEvent( QgsMapMouseEvent* e )
|
||||
{
|
||||
QgsPointV2 mapPoint( e->mapPoint().x(), e->mapPoint().y() );
|
||||
|
||||
if ( e->button() == Qt::LeftButton )
|
||||
{
|
||||
if ( mPoints.size() < 1 ) //connection to vertex of previous line segment needed?
|
||||
{
|
||||
const QgsCompoundCurveV2* compoundCurve = mParentTool->captureCurve();
|
||||
if ( compoundCurve )
|
||||
{
|
||||
if ( compoundCurve->nCurves() > 0 )
|
||||
{
|
||||
const QgsCurveV2* curve = compoundCurve->curveAt( compoundCurve->nCurves() - 1 );
|
||||
if ( curve )
|
||||
{
|
||||
//mParentTool->captureCurve() is in layer coordinates, but we need map coordinates
|
||||
QgsPointV2 endPointLayerCoord = curve->endPoint();
|
||||
QgsPoint mapPoint = toMapCoordinates( mCanvas->currentLayer(), QgsPoint( endPointLayerCoord.x(), endPointLayerCoord.y() ) );
|
||||
mPoints.append( QgsPointV2( mapPoint.x(), mapPoint.y() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mPoints.append( mapPoint );
|
||||
if ( !mCenterPointRubberBand && mShowCenterPointRubberBand )
|
||||
{
|
||||
createCenterPointRubberBand();
|
||||
}
|
||||
|
||||
if ( mPoints.size() > 1 )
|
||||
{
|
||||
if ( !mRubberBand )
|
||||
{
|
||||
mRubberBand = createGeometryRubberBand(( mCaptureMode == CapturePolygon ) ? QGis::Polygon : QGis::Line );
|
||||
mRubberBand->show();
|
||||
}
|
||||
|
||||
QgsCircularStringV2* c = new QgsCircularStringV2();
|
||||
QList< QgsPointV2 > rubberBandPoints = mPoints;
|
||||
rubberBandPoints.append( mapPoint );
|
||||
c->setPoints( rubberBandPoints );
|
||||
mRubberBand->setGeometry( c );
|
||||
}
|
||||
if (( mPoints.size() ) % 2 == 1 )
|
||||
{
|
||||
removeCenterPointRubberBand();
|
||||
}
|
||||
}
|
||||
else if ( e->button() == Qt::RightButton )
|
||||
{
|
||||
deactivate();
|
||||
if ( mParentTool )
|
||||
{
|
||||
mParentTool->canvasReleaseEvent( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolCircularStringCurvePoint::canvasMapMoveEvent( QgsMapMouseEvent* e )
|
||||
{
|
||||
QgsPointV2 mapPoint( e->mapPoint().x(), e->mapPoint().y() );
|
||||
QgsVertexId idx; idx.part = 0; idx.ring = 0; idx.vertex = mPoints.size();
|
||||
if ( mRubberBand )
|
||||
{
|
||||
mRubberBand->moveVertex( idx, mapPoint );
|
||||
updateCenterPointRubberBand( mapPoint );
|
||||
}
|
||||
}
|
32
src/app/qgsmaptoolcircularstringcurvepoint.h
Normal file
32
src/app/qgsmaptoolcircularstringcurvepoint.h
Normal file
@ -0,0 +1,32 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolcircularstringcurvepoint.h - map tool for adding circular
|
||||
strings by start / curve / endpoint
|
||||
---------------------
|
||||
begin : Feb 2015
|
||||
copyright : (C) 2015 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSMAPTOOLCIRCULARSTRINGCURVEPOINT_H
|
||||
#define QGSMAPTOOLCIRCULARSTRINGCURVEPOINT_H
|
||||
|
||||
#include "qgsmaptooladdcircularstring.h"
|
||||
|
||||
class QgsMapToolCircularStringCurvePoint: public QgsMapToolAddCircularString
|
||||
{
|
||||
public:
|
||||
QgsMapToolCircularStringCurvePoint( QgsMapToolCapture* parentTool, QgsMapCanvas* canvas, CaptureMode mode = CaptureLine );
|
||||
~QgsMapToolCircularStringCurvePoint();
|
||||
|
||||
void canvasMapReleaseEvent( QgsMapMouseEvent* e ) override;
|
||||
void canvasMapMoveEvent( QgsMapMouseEvent* e ) override;
|
||||
};
|
||||
|
||||
#endif // QGSMAPTOOLCIRCULARSTRINGCURVEPOINT_H
|
170
src/app/qgsmaptoolcircularstringradius.cpp
Normal file
170
src/app/qgsmaptoolcircularstringradius.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolcircularstringradius.h - map tool for adding circular strings
|
||||
---------------------
|
||||
begin : Feb 2015
|
||||
copyright : (C) 2015 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgsmaptoolcircularstringradius.h"
|
||||
#include "qgisapp.h"
|
||||
#include "qgscircularstringv2.h"
|
||||
#include "qgscompoundcurvev2.h"
|
||||
#include "qgsgeometryutils.h"
|
||||
#include "qgsgeometryrubberband.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgspointv2.h"
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QMouseEvent>
|
||||
#include <cmath>
|
||||
|
||||
QgsMapToolCircularStringRadius::QgsMapToolCircularStringRadius( QgsMapToolCapture* parentTool, QgsMapCanvas* canvas, CaptureMode mode ) :
|
||||
QgsMapToolAddCircularString( parentTool, canvas, mode ), mTemporaryEndPointX( 0.0 ), mTemporaryEndPointY( 0.0 ), mRadiusMode( false ), mRadius( 0.0 ),
|
||||
mRadiusSpinBox( 0 )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QgsMapToolCircularStringRadius::~QgsMapToolCircularStringRadius()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QgsMapToolCircularStringRadius::canvasMapReleaseEvent( QgsMapMouseEvent* e )
|
||||
{
|
||||
QgsPointV2 mapPoint( e->mapPoint().x(), e->mapPoint().y() );
|
||||
|
||||
if ( e->button() == Qt::LeftButton )
|
||||
{
|
||||
if ( mPoints.size() == 0 )
|
||||
{
|
||||
//get first point from parent tool if there. Todo: move to upper class
|
||||
const QgsCompoundCurveV2* compoundCurve = mParentTool->captureCurve();
|
||||
if ( compoundCurve && compoundCurve->nCurves() > 0 )
|
||||
{
|
||||
const QgsCurveV2* curve = compoundCurve->curveAt( compoundCurve->nCurves() - 1 );
|
||||
if ( curve )
|
||||
{
|
||||
//mParentTool->captureCurve() is in layer coordinates, but we need map coordinates
|
||||
QgsPointV2 endPointLayerCoord = curve->endPoint();
|
||||
QgsPoint mapPoint = toMapCoordinates( mCanvas->currentLayer(), QgsPoint( endPointLayerCoord.x(), endPointLayerCoord.y() ) );
|
||||
mPoints.append( QgsPointV2( mapPoint.x(), mapPoint.y() ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mPoints.append( mapPoint );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( mPoints.size() % 2 == 1 )
|
||||
{
|
||||
if ( !mRadiusMode )
|
||||
{
|
||||
delete mRubberBand; mRubberBand = 0;
|
||||
mTemporaryEndPointX = mapPoint.x();
|
||||
mTemporaryEndPointY = mapPoint.y();
|
||||
mRadiusMode = true;
|
||||
|
||||
//initial radius is distance( tempPoint - mPoints.last ) / 2.0
|
||||
double minRadius = sqrt( QgsGeometryUtils::sqrDistance2D( mPoints.last(), QgsPointV2( mTemporaryEndPointX, mTemporaryEndPointY ) ) ) / 2.0;
|
||||
mRadius = minRadius + minRadius / 10.0;
|
||||
recalculateCircularString();
|
||||
createRadiusSpinBox();
|
||||
if ( mRadiusSpinBox )
|
||||
{
|
||||
mRadiusSpinBox->setMinimum( minRadius );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QgsPointV2 result;
|
||||
if ( QgsGeometryUtils::segmentMidPoint( mPoints.last(), QgsPointV2( mTemporaryEndPointX, mTemporaryEndPointY ), result, mRadius, QgsPointV2( mapPoint.x(), mapPoint.y() ) ) )
|
||||
{
|
||||
mPoints.append( result );
|
||||
mPoints.append( QgsPointV2( mTemporaryEndPointX, mTemporaryEndPointY ) );
|
||||
}
|
||||
mRadiusMode = false;
|
||||
deleteRadiusSpinBox();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//can we get there?
|
||||
}
|
||||
}
|
||||
else if ( e->button() == Qt::RightButton )
|
||||
{
|
||||
deactivate();
|
||||
if ( mParentTool )
|
||||
{
|
||||
mParentTool->canvasReleaseEvent( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolCircularStringRadius::canvasMapMoveEvent( QgsMapMouseEvent* e )
|
||||
{
|
||||
if ( mPoints.size() > 0 && mRadiusMode )
|
||||
{
|
||||
mLastMouseMapPos.setX( e->mapPoint().x() );
|
||||
mLastMouseMapPos.setY( e->mapPoint().y() );
|
||||
recalculateCircularString();
|
||||
}
|
||||
}
|
||||
|
||||
void QgsMapToolCircularStringRadius::recalculateCircularString()
|
||||
{
|
||||
//new midpoint on circle segment
|
||||
QgsPointV2 midPoint;
|
||||
if ( !QgsGeometryUtils::segmentMidPoint( mPoints.last(), QgsPointV2( mTemporaryEndPointX, mTemporaryEndPointY ), midPoint, mRadius,
|
||||
mLastMouseMapPos ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QList<QgsPointV2> rubberBandPoints = mPoints; rubberBandPoints.append( midPoint ); rubberBandPoints.append( QgsPointV2( mTemporaryEndPointX, mTemporaryEndPointY ) );
|
||||
QgsCircularStringV2* cString = new QgsCircularStringV2();
|
||||
cString->setPoints( rubberBandPoints );
|
||||
delete mRubberBand;
|
||||
mRubberBand = createGeometryRubberBand(( mCaptureMode == CapturePolygon ) ? QGis::Polygon : QGis::Line );
|
||||
mRubberBand->setGeometry( cString );
|
||||
mRubberBand->show();
|
||||
}
|
||||
|
||||
void QgsMapToolCircularStringRadius::createRadiusSpinBox()
|
||||
{
|
||||
deleteRadiusSpinBox();
|
||||
mRadiusSpinBox = new QDoubleSpinBox();
|
||||
mRadiusSpinBox->setMaximum( 99999999 );
|
||||
mRadiusSpinBox->setDecimals( 2 );
|
||||
mRadiusSpinBox->setPrefix( tr( "Radius: " ) );
|
||||
mRadiusSpinBox->setValue( mRadius );
|
||||
QgisApp::instance()->addUserInputWidget( mRadiusSpinBox );
|
||||
QObject::connect( mRadiusSpinBox, SIGNAL( valueChanged( double ) ), this, SLOT( updateRadiusFromSpinBox( double ) ) );
|
||||
mRadiusSpinBox->setFocus( Qt::TabFocusReason );
|
||||
}
|
||||
|
||||
void QgsMapToolCircularStringRadius::deleteRadiusSpinBox()
|
||||
{
|
||||
if ( !mRadiusSpinBox )
|
||||
{
|
||||
return;
|
||||
}
|
||||
QgisApp::instance()->statusBar()->removeWidget( mRadiusSpinBox );
|
||||
delete mRadiusSpinBox; mRadiusSpinBox = 0;
|
||||
}
|
||||
|
||||
void QgsMapToolCircularStringRadius::updateRadiusFromSpinBox( double radius )
|
||||
{
|
||||
mRadius = radius;
|
||||
recalculateCircularString();
|
||||
}
|
52
src/app/qgsmaptoolcircularstringradius.h
Normal file
52
src/app/qgsmaptoolcircularstringradius.h
Normal file
@ -0,0 +1,52 @@
|
||||
/***************************************************************************
|
||||
qgsmaptoolcircularstringradius.h - map tool for adding circular strings
|
||||
by two points and radius
|
||||
---------------------
|
||||
begin : Feb 2015
|
||||
copyright : (C) 2015 by Marco Hugentobler
|
||||
email : marco dot hugentobler at sourcepole dot ch
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSMAPTOOLCIRCULARSTRINGRADIUS_H
|
||||
#define QGSMAPTOOLCIRCULARSTRINGRADIUS_H
|
||||
|
||||
#include "qgsmaptooladdcircularstring.h"
|
||||
#include "qgspointv2.h"
|
||||
|
||||
class QDoubleSpinBox;
|
||||
|
||||
class QgsMapToolCircularStringRadius: public QgsMapToolAddCircularString
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QgsMapToolCircularStringRadius( QgsMapToolCapture* parentTool, QgsMapCanvas* canvas, CaptureMode mode = CaptureLine );
|
||||
~QgsMapToolCircularStringRadius();
|
||||
|
||||
virtual void canvasMapReleaseEvent( QgsMapMouseEvent* e ) override;
|
||||
virtual void canvasMapMoveEvent( QgsMapMouseEvent* e ) override;
|
||||
|
||||
private slots:
|
||||
void updateRadiusFromSpinBox( double radius );
|
||||
|
||||
private:
|
||||
double mTemporaryEndPointX;
|
||||
double mTemporaryEndPointY;
|
||||
bool mRadiusMode;
|
||||
double mRadius;
|
||||
QgsPointV2 mLastMouseMapPos;
|
||||
QDoubleSpinBox* mRadiusSpinBox;
|
||||
|
||||
//recalculate circular string and rubber band depending on mRadius/mLeft and endpoints
|
||||
void recalculateCircularString();
|
||||
void createRadiusSpinBox();
|
||||
void deleteRadiusSpinBox();
|
||||
};
|
||||
|
||||
#endif // QGSMAPTOOLCIRCULARSTRINGRADIUS_H
|
@ -16,6 +16,7 @@
|
||||
#include "qgsmaptooledit.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsmapcanvas.h"
|
||||
#include "qgsgeometryrubberband.h"
|
||||
#include "qgsrubberband.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
@ -97,6 +98,21 @@ int QgsMapToolEdit::addTopologicalPoints( const QList<QgsPoint>& geom )
|
||||
return 0;
|
||||
}
|
||||
|
||||
QgsGeometryRubberBand* QgsMapToolEdit::createGeometryRubberBand( QGis::GeometryType geometryType ) const
|
||||
{
|
||||
QSettings settings;
|
||||
QgsGeometryRubberBand* rb = new QgsGeometryRubberBand( mCanvas, geometryType );
|
||||
QColor color( settings.value( "/qgis/digitizing/line_color_red", 255 ).toInt(),
|
||||
settings.value( "/qgis/digitizing/line_color_green", 0 ).toInt(),
|
||||
settings.value( "/qgis/digitizing/line_color_blue", 0 ).toInt() );
|
||||
double myAlpha = settings.value( "/qgis/digitizing/line_color_alpha", 200 ).toInt() / 255.0 ;
|
||||
color.setAlphaF( myAlpha );
|
||||
rb->setOutlineColor( color );
|
||||
rb->setFillColor( color );
|
||||
rb->show();
|
||||
return rb;
|
||||
}
|
||||
|
||||
void QgsMapToolEdit::notifyNotVectorLayer()
|
||||
{
|
||||
emit messageEmitted( tr( "No active vector layer" ) );
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "qgsmaptooladvanceddigitizing.h"
|
||||
|
||||
class QgsRubberBand;
|
||||
class QgsGeometryRubberBand;
|
||||
class QgsVectorLayer;
|
||||
class QKeyEvent;
|
||||
|
||||
@ -44,6 +45,9 @@ class APP_EXPORT QgsMapToolEdit: public QgsMapToolAdvancedDigitizing
|
||||
*/
|
||||
QgsRubberBand* createRubberBand( QGis::GeometryType geometryType = QGis::Line, bool alternativeBand = false );
|
||||
|
||||
|
||||
QgsGeometryRubberBand* createGeometryRubberBand( QGis::GeometryType geometryType = QGis::Line ) const;
|
||||
|
||||
/** Returns the current vector layer of the map canvas or 0*/
|
||||
QgsVectorLayer* currentVectorLayer();
|
||||
|
||||
|
@ -16,6 +16,7 @@ email : marco.hugentobler at sourcepole dot com
|
||||
#ifndef QGSABSTRACTGEOMETRYV2
|
||||
#define QGSABSTRACTGEOMETRYV2
|
||||
|
||||
#include "qgscoordinatetransform.h"
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgswkbtypes.h"
|
||||
#include <QString>
|
||||
@ -216,8 +217,9 @@ class CORE_EXPORT QgsAbstractGeometryV2
|
||||
|
||||
/** Transforms the geometry using a coordinate transform
|
||||
* @param ct coordinate transform
|
||||
@param d transformation direction
|
||||
*/
|
||||
virtual void transform( const QgsCoordinateTransform& ct ) = 0;
|
||||
virtual void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) = 0;
|
||||
|
||||
/** Transforms the geometry using a QTransform object
|
||||
* @param t QTransform transformation
|
||||
|
@ -577,7 +577,7 @@ void QgsCircularStringV2::draw( QPainter& p ) const
|
||||
p.drawPath( path );
|
||||
}
|
||||
|
||||
void QgsCircularStringV2::transform( const QgsCoordinateTransform& ct )
|
||||
void QgsCircularStringV2::transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d )
|
||||
{
|
||||
double* zArray = mZ.data();
|
||||
|
||||
@ -591,7 +591,7 @@ void QgsCircularStringV2::transform( const QgsCoordinateTransform& ct )
|
||||
zArray[i] = 0;
|
||||
}
|
||||
}
|
||||
ct.transformCoords( nPoints, mX.data(), mY.data(), zArray );
|
||||
ct.transformCoords( nPoints, mX.data(), mY.data(), zArray, d );
|
||||
if ( !hasZ )
|
||||
{
|
||||
delete[] zArray;
|
||||
|
@ -68,7 +68,11 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
|
||||
virtual QgsLineStringV2* curveToLine() const override;
|
||||
|
||||
void draw( QPainter& p ) const override;
|
||||
void transform( const QgsCoordinateTransform& ct ) override;
|
||||
/** Transforms the geometry using a coordinate transform
|
||||
* @param ct coordinate transform
|
||||
@param d transformation direction
|
||||
*/
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override;
|
||||
void transform( const QTransform& t ) override;
|
||||
#if 0
|
||||
void clip( const QgsRectangle& rect ) override;
|
||||
|
@ -410,12 +410,12 @@ void QgsCompoundCurveV2::draw( QPainter& p ) const
|
||||
}
|
||||
}
|
||||
|
||||
void QgsCompoundCurveV2::transform( const QgsCoordinateTransform& ct )
|
||||
void QgsCompoundCurveV2::transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d )
|
||||
{
|
||||
QList< QgsCurveV2* >::iterator it = mCurves.begin();
|
||||
for ( ; it != mCurves.end(); ++it )
|
||||
{
|
||||
( *it )->transform( ct );
|
||||
( *it )->transform( ct, d );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,11 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2
|
||||
void addVertex( const QgsPointV2& pt );
|
||||
|
||||
void draw( QPainter& p ) const override;
|
||||
void transform( const QgsCoordinateTransform& ct ) override;
|
||||
/** Transforms the geometry using a coordinate transform
|
||||
* @param ct coordinate transform
|
||||
@param d transformation direction
|
||||
*/
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override;
|
||||
void transform( const QTransform& t ) override;
|
||||
void addToPainterPath( QPainterPath& path ) const override;
|
||||
void drawAsPolygon( QPainter& p ) const override;
|
||||
|
@ -474,17 +474,17 @@ void QgsCurvePolygonV2::draw( QPainter& p ) const
|
||||
}
|
||||
}
|
||||
|
||||
void QgsCurvePolygonV2::transform( const QgsCoordinateTransform& ct )
|
||||
void QgsCurvePolygonV2::transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d )
|
||||
{
|
||||
if ( mExteriorRing )
|
||||
{
|
||||
mExteriorRing->transform( ct );
|
||||
mExteriorRing->transform( ct, d );
|
||||
}
|
||||
|
||||
QList<QgsCurveV2*>::iterator it = mInteriorRings.begin();
|
||||
for ( ; it != mInteriorRings.end(); ++it )
|
||||
{
|
||||
( *it )->transform( ct );
|
||||
( *it )->transform( ct, d );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,11 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
|
||||
bool removeInteriorRing( int nr );
|
||||
|
||||
virtual void draw( QPainter& p ) const override;
|
||||
void transform( const QgsCoordinateTransform& ct ) override;
|
||||
/** Transforms the geometry using a coordinate transform
|
||||
* @param ct coordinate transform
|
||||
@param d transformation direction
|
||||
*/
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override;
|
||||
void transform( const QTransform& t ) override;
|
||||
|
||||
virtual bool insertVertex( const QgsVertexId& position, const QgsPointV2& vertex ) override;
|
||||
|
@ -130,12 +130,12 @@ int QgsGeometryCollectionV2::dimension() const
|
||||
return maxDim;
|
||||
}
|
||||
|
||||
void QgsGeometryCollectionV2::transform( const QgsCoordinateTransform& ct )
|
||||
void QgsGeometryCollectionV2::transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d )
|
||||
{
|
||||
QVector< QgsAbstractGeometryV2* >::iterator it = mGeometries.begin();
|
||||
for ( ; it != mGeometries.end(); ++it )
|
||||
{
|
||||
( *it )->transform( ct );
|
||||
( *it )->transform( ct, d );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,11 @@ class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2
|
||||
*/
|
||||
virtual bool removeGeometry( int nr );
|
||||
|
||||
virtual void transform( const QgsCoordinateTransform& ct ) override;
|
||||
/** Transforms the geometry using a coordinate transform
|
||||
* @param ct coordinate transform
|
||||
@param d transformation direction
|
||||
*/
|
||||
virtual void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override;
|
||||
void transform( const QTransform& t ) override;
|
||||
#if 0
|
||||
virtual void clip( const QgsRectangle& rect ) override;
|
||||
|
@ -333,9 +333,9 @@ void QgsLineStringV2::drawAsPolygon( QPainter& p ) const
|
||||
p.drawPolygon( mCoords );
|
||||
}
|
||||
|
||||
void QgsLineStringV2::transform( const QgsCoordinateTransform& ct )
|
||||
void QgsLineStringV2::transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d )
|
||||
{
|
||||
ct.transformPolygon( mCoords );
|
||||
ct.transformPolygon( mCoords, d );
|
||||
}
|
||||
|
||||
void QgsLineStringV2::transform( const QTransform& t )
|
||||
|
@ -64,7 +64,12 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
|
||||
void append( const QgsLineStringV2* line );
|
||||
|
||||
void draw( QPainter& p ) const override;
|
||||
void transform( const QgsCoordinateTransform& ct ) override;
|
||||
|
||||
/** Transforms the geometry using a coordinate transform
|
||||
* @param ct coordinate transform
|
||||
@param d transformation direction
|
||||
*/
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override;
|
||||
void transform( const QTransform& t ) override;
|
||||
|
||||
void addToPainterPath( QPainterPath& path ) const override;
|
||||
|
@ -181,9 +181,9 @@ void QgsPointV2::clear()
|
||||
mX = mY = mZ = mM = 0.;
|
||||
}
|
||||
|
||||
void QgsPointV2::transform( const QgsCoordinateTransform& ct )
|
||||
void QgsPointV2::transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d )
|
||||
{
|
||||
ct.transformInPlace( mX, mY, mZ );
|
||||
ct.transformInPlace( mX, mY, mZ, d );
|
||||
}
|
||||
|
||||
void QgsPointV2::coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord ) const
|
||||
|
@ -67,7 +67,12 @@ class CORE_EXPORT QgsPointV2: public QgsAbstractGeometryV2
|
||||
virtual QgsRectangle calculateBoundingBox() const override { return QgsRectangle( mX, mY, mX, mY );}
|
||||
|
||||
void draw( QPainter& p ) const override;
|
||||
void transform( const QgsCoordinateTransform& ct ) override;
|
||||
|
||||
/** Transforms the geometry using a coordinate transform
|
||||
* @param ct coordinate transform
|
||||
@param d transformation direction
|
||||
*/
|
||||
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override;
|
||||
void transform( const QTransform& t ) override;
|
||||
|
||||
virtual void coordinateSequence( QList< QList< QList< QgsPointV2 > > >& coord ) const override;
|
||||
|
@ -94,7 +94,9 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
|
||||
/** Supports topological simplification of geometries on provider side according to a distance tolerance */
|
||||
SimplifyGeometriesWithTopologicalValidation = 1 << 15,
|
||||
/** Supports transactions*/
|
||||
TransactionSupport = 1 << 16
|
||||
TransactionSupport = 1 << 16,
|
||||
/** Supports circular geometry types (circularstring, compoundcurve, curvepolygon)*/
|
||||
CircularGeometries = 1 << 17
|
||||
};
|
||||
|
||||
/** Bitmask of all provider's editing capabilities */
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "qgsclipper.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgscoordinatetransform.h"
|
||||
#include "qgscurvev2.h"
|
||||
#include "qgsdatasourceuri.h"
|
||||
#include "qgsexpressionfieldbuffer.h"
|
||||
#include "qgsfeature.h"
|
||||
@ -1043,6 +1044,27 @@ int QgsVectorLayer::addRing( const QList<QgsPoint>& ring )
|
||||
return utils.addRing( ring );
|
||||
}
|
||||
|
||||
int QgsVectorLayer::addRing( QgsCurveV2* ring )
|
||||
{
|
||||
if ( !mEditBuffer || !mDataProvider )
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
if ( !ring )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( !ring->isClosed() )
|
||||
{
|
||||
delete ring; return 2;
|
||||
}
|
||||
|
||||
QgsVectorLayerEditUtils utils( this );
|
||||
return utils.addRing( ring );
|
||||
}
|
||||
|
||||
int QgsVectorLayer::addPart( const QList<QgsPoint> &points )
|
||||
{
|
||||
if ( !mEditBuffer || !mDataProvider )
|
||||
@ -1065,6 +1087,27 @@ int QgsVectorLayer::addPart( const QList<QgsPoint> &points )
|
||||
return utils.addPart( points, *mSelectedFeatureIds.constBegin() );
|
||||
}
|
||||
|
||||
int QgsVectorLayer::addPart( QgsCurveV2* ring )
|
||||
{
|
||||
if ( !mEditBuffer || !mDataProvider )
|
||||
return 7;
|
||||
|
||||
//number of selected features must be 1
|
||||
|
||||
if ( mSelectedFeatureIds.size() < 1 )
|
||||
{
|
||||
QgsDebugMsg( "Number of selected features <1" );
|
||||
return 4;
|
||||
}
|
||||
else if ( mSelectedFeatureIds.size() > 1 )
|
||||
{
|
||||
QgsDebugMsg( "Number of selected features >1" );
|
||||
return 5;
|
||||
}
|
||||
|
||||
QgsVectorLayerEditUtils utils( this );
|
||||
return utils.addPart( ring, *mSelectedFeatureIds.constBegin() );
|
||||
}
|
||||
|
||||
int QgsVectorLayer::translateFeature( QgsFeatureId featureId, double dx, double dy )
|
||||
{
|
||||
@ -2229,7 +2272,7 @@ bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
|
||||
|
||||
qSort( attrs.begin(), attrs.end(), qGreater<int>() );
|
||||
|
||||
Q_FOREACH ( int attr, attrs )
|
||||
Q_FOREACH( int attr, attrs )
|
||||
{
|
||||
if ( deleteAttribute( attr ) )
|
||||
{
|
||||
@ -2988,7 +3031,7 @@ void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int
|
||||
if ( mEditBuffer )
|
||||
{
|
||||
QSet<QString> vals;
|
||||
Q_FOREACH ( const QVariant& v, uniqueValues )
|
||||
Q_FOREACH( const QVariant& v, uniqueValues )
|
||||
{
|
||||
vals << v.toString();
|
||||
}
|
||||
@ -3818,7 +3861,7 @@ void QgsVectorLayer::invalidateSymbolCountedFlag()
|
||||
|
||||
void QgsVectorLayer::onRelationsLoaded()
|
||||
{
|
||||
Q_FOREACH ( QgsAttributeEditorElement* elem, mAttributeEditorElements )
|
||||
Q_FOREACH( QgsAttributeEditorElement* elem, mAttributeEditorElements )
|
||||
{
|
||||
if ( elem->type() == QgsAttributeEditorElement::AeTypeContainer )
|
||||
{
|
||||
@ -3827,7 +3870,7 @@ void QgsVectorLayer::onRelationsLoaded()
|
||||
continue;
|
||||
|
||||
QList<QgsAttributeEditorElement*> relations = cont->findElements( QgsAttributeEditorElement::AeTypeRelation );
|
||||
Q_FOREACH ( QgsAttributeEditorElement* relElem, relations )
|
||||
Q_FOREACH( QgsAttributeEditorElement* relElem, relations )
|
||||
{
|
||||
QgsAttributeEditorRelation* rel = dynamic_cast< QgsAttributeEditorRelation* >( relElem );
|
||||
if ( !rel )
|
||||
@ -3896,7 +3939,7 @@ QDomElement QgsAttributeEditorContainer::toDomElement( QDomDocument& doc ) const
|
||||
QDomElement elem = doc.createElement( "attributeEditorContainer" );
|
||||
elem.setAttribute( "name", mName );
|
||||
|
||||
Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
|
||||
Q_FOREACH( QgsAttributeEditorElement* child, mChildren )
|
||||
{
|
||||
elem.appendChild( child->toDomElement( doc ) );
|
||||
}
|
||||
@ -3917,7 +3960,7 @@ QList<QgsAttributeEditorElement*> QgsAttributeEditorContainer::findElements( Qgs
|
||||
{
|
||||
QList<QgsAttributeEditorElement*> results;
|
||||
|
||||
Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
|
||||
Q_FOREACH( QgsAttributeEditorElement* elem, mChildren )
|
||||
{
|
||||
if ( elem->type() == type )
|
||||
{
|
||||
|
@ -42,6 +42,7 @@ class QgsAbstractGeometrySimplifier;
|
||||
class QgsAttributeAction;
|
||||
class QgsFieldUIProperties;
|
||||
class QgsCoordinateTransform;
|
||||
class QgsCurveV2;
|
||||
class QgsDiagramLayerSettings;
|
||||
class QgsDiagramRendererV2;
|
||||
class QgsEditorWidgetWrapper;
|
||||
@ -1170,6 +1171,14 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
6 layer not editable */
|
||||
int addRing( const QList<QgsPoint>& ring );
|
||||
|
||||
/** Adds a ring to polygon/multipolygon features (takes ownership)
|
||||
@return
|
||||
0 in case of success
|
||||
1 problem with feature type
|
||||
2 ring not closed
|
||||
6 layer not editable*/
|
||||
int addRing( QgsCurveV2* ring );
|
||||
|
||||
/** Adds a new part polygon to a multipart feature
|
||||
@return
|
||||
0 in case of success,
|
||||
@ -1182,6 +1191,8 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||
7 layer not editable */
|
||||
int addPart( const QList<QgsPoint>& ring );
|
||||
|
||||
int addPart( QgsCurveV2* ring );
|
||||
|
||||
/** Translates feature by dx, dy
|
||||
@param featureId id of the feature to translate
|
||||
@param dx translation of x-coordinate
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsgeometrycache.h"
|
||||
#include "qgsvectorlayereditbuffer.h"
|
||||
#include "qgslinestringv2.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgspointv2.h"
|
||||
|
||||
@ -103,26 +104,26 @@ bool QgsVectorLayerEditUtils::deleteVertex( QgsFeatureId atFeatureId, int atVert
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int QgsVectorLayerEditUtils::addRing( const QList<QgsPoint>& ring )
|
||||
{
|
||||
QgsLineStringV2* ringLine = new QgsLineStringV2();
|
||||
QList< QgsPointV2 > ringPoints;
|
||||
QList<QgsPoint>::const_iterator ringIt = ring.constBegin();
|
||||
for ( ; ringIt != ring.constEnd(); ++ringIt )
|
||||
{
|
||||
ringPoints.append( QgsPointV2( ringIt->x(), ringIt->y() ) );
|
||||
}
|
||||
ringLine->setPoints( ringPoints );
|
||||
return addRing( ringLine );
|
||||
}
|
||||
|
||||
int QgsVectorLayerEditUtils::addRing( QgsCurveV2* ring )
|
||||
{
|
||||
if ( !L->hasGeometryType() )
|
||||
return 5;
|
||||
|
||||
int addRingReturnCode = 5; //default: return code for 'ring not inserted'
|
||||
double xMin, yMin, xMax, yMax;
|
||||
QgsRectangle bBox;
|
||||
|
||||
if ( boundingBoxFromPointList( ring, xMin, yMin, xMax, yMax ) == 0 )
|
||||
{
|
||||
bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
|
||||
bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
|
||||
}
|
||||
else
|
||||
{
|
||||
return 3; //ring not valid
|
||||
}
|
||||
|
||||
QgsRectangle bBox = ring->boundingBox();
|
||||
QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
|
||||
|
||||
QgsFeature f;
|
||||
@ -141,7 +142,6 @@ int QgsVectorLayerEditUtils::addRing( const QList<QgsPoint>& ring )
|
||||
return addRingReturnCode;
|
||||
}
|
||||
|
||||
|
||||
int QgsVectorLayerEditUtils::addPart( const QList<QgsPoint> &points, QgsFeatureId featureId )
|
||||
{
|
||||
if ( !L->hasGeometryType() )
|
||||
@ -152,10 +152,10 @@ int QgsVectorLayerEditUtils::addPart( const QList<QgsPoint> &points, QgsFeatureI
|
||||
{
|
||||
// it's not in cache: let's fetch it from layer
|
||||
QgsFeature f;
|
||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.constGeometry() )
|
||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
|
||||
return 6; //geometry not found
|
||||
|
||||
geometry = *f.constGeometry();
|
||||
geometry = *f.geometry();
|
||||
}
|
||||
|
||||
int errorCode = geometry.addPart( points, L->geometryType() );
|
||||
@ -166,6 +166,29 @@ int QgsVectorLayerEditUtils::addPart( const QList<QgsPoint> &points, QgsFeatureI
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
int QgsVectorLayerEditUtils::addPart( QgsCurveV2* ring, QgsFeatureId featureId )
|
||||
{
|
||||
if ( !L->hasGeometryType() )
|
||||
return 6;
|
||||
|
||||
QgsGeometry geometry;
|
||||
if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
|
||||
{
|
||||
// it's not in cache: let's fetch it from layer
|
||||
QgsFeature f;
|
||||
if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
|
||||
return 6; //geometry not found
|
||||
|
||||
geometry = *f.geometry();
|
||||
}
|
||||
|
||||
int errorCode = geometry.addPart( ring );
|
||||
if ( errorCode == 0 )
|
||||
{
|
||||
L->editBuffer()->changeGeometry( featureId, &geometry );
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
|
||||
int QgsVectorLayerEditUtils::translateFeature( QgsFeatureId featureId, double dx, double dy )
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
class QgsGeometryCache;
|
||||
class QgsCurveV2;
|
||||
|
||||
class CORE_EXPORT QgsVectorLayerEditUtils
|
||||
{
|
||||
@ -62,6 +63,16 @@ class CORE_EXPORT QgsVectorLayerEditUtils
|
||||
5 no feature found where ring can be inserted*/
|
||||
int addRing( const QList<QgsPoint>& ring );
|
||||
|
||||
/** Adds a ring to polygon/multipolygon features
|
||||
@return
|
||||
0 in case of success,
|
||||
1 problem with feature type,
|
||||
2 ring not closed,
|
||||
3 ring not valid,
|
||||
4 ring crosses existing rings,
|
||||
5 no feature found where ring can be inserted*/
|
||||
int addRing( QgsCurveV2* ring );
|
||||
|
||||
/** Adds a new part polygon to a multipart feature
|
||||
@return
|
||||
0 in case of success,
|
||||
@ -73,6 +84,8 @@ class CORE_EXPORT QgsVectorLayerEditUtils
|
||||
6 if selected geometry not found*/
|
||||
int addPart( const QList<QgsPoint>& ring, QgsFeatureId featureId );
|
||||
|
||||
int addPart( QgsCurveV2* ring, QgsFeatureId featureId );
|
||||
|
||||
/** Translates feature by dx, dy
|
||||
@param featureId id of the feature to translate
|
||||
@param dx translation of x-coordinate
|
||||
|
@ -1095,6 +1095,9 @@ bool QgsPostgresProvider::hasSufficientPermsAndCapabilities()
|
||||
|
||||
//supports transactions
|
||||
mEnabledCapabilities |= QgsVectorDataProvider::TransactionSupport;
|
||||
|
||||
// supports circular geometries
|
||||
mEnabledCapabilities |= QgsVectorDataProvider::CircularGeometries;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1050</width>
|
||||
<height>25</height>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
@ -356,6 +356,8 @@
|
||||
<addaction name="mActionToggleEditing"/>
|
||||
<addaction name="mActionSaveLayerEdits"/>
|
||||
<addaction name="mActionAddFeature"/>
|
||||
<addaction name="mActionCircularStringCurvePoint"/>
|
||||
<addaction name="mActionCircularStringRadius"/>
|
||||
<addaction name="mActionMoveFeature"/>
|
||||
<addaction name="mActionNodeTool"/>
|
||||
<addaction name="mActionDeleteSelected"/>
|
||||
@ -2352,6 +2354,30 @@ Acts on currently active editable layer</string>
|
||||
<string>Align Rasters...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionCircularStringCurvePoint">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionCircularStringCurvePoint.png</normaloff>:/images/themes/default/mActionCircularStringCurvePoint.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add circular string</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionCircularStringRadius">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionCircularStringRadius.png</normaloff>:/images/themes/default/mActionCircularStringRadius.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add circular string by radius</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../images/images.qrc"/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user