[FEATURE]: Tool to add circular strings with start point, curve point and end point

This commit is contained in:
Marco Hugentobler 2015-08-17 17:14:05 +02:00
parent 9b31f34a26
commit c39ffe9fc2
37 changed files with 309 additions and 119 deletions

View File

@ -504,6 +504,7 @@
<file>themes/default/mIconClear.png</file>
<file>flags/zh.png</file>
<file>themes/default/mIconPaintEffects.svg</file>
<file>themes/default/mActionCircularStringCurvePoint.png</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 );

View File

@ -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;

View File

@ -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;

View File

@ -117,6 +117,8 @@ SET(QGIS_APP_SRCS
qgsvectorlayerproperties.cpp
qgsvisibilitypresets.cpp
qgshandlebadlayers.cpp
qgsmaptooladdcircularstring.cpp
qgsmaptoolcircularstringcurvepoint.cpp
composer/qgsattributeselectiondialog.cpp
composer/qgscomposer.cpp
@ -240,6 +242,7 @@ SET (QGIS_APP_MOC_HDRS
qgsmaptoolsimplify.h
qgsmaptoolsplitfeatures.h
qgsmaptoolsplitparts.h
qgsmaptooladdcircularstring.h
nodetool/qgsmaptoolnodetool.h
nodetool/qgsselectedfeature.h

View File

@ -250,6 +250,7 @@
#include "qgsmaptooladdring.h"
#include "qgsmaptoolfillring.h"
#include "qgsmaptoolannotation.h"
#include "qgsmaptoolcircularstringcurvepoint.h"
#include "qgsmaptooldeletering.h"
#include "qgsmaptooldeletepart.h"
#include "qgsmaptoolfeatureaction.h"
@ -1170,6 +1171,7 @@ 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( mActionMoveFeature, SIGNAL( triggered() ), this, SLOT( moveFeature() ) );
connect( mActionRotateFeature, SIGNAL( triggered() ), this, SLOT( rotateFeature() ) );
@ -1444,6 +1446,7 @@ void QgisApp::createActionGroups()
mMapToolGroup->addAction( mActionMeasureArea );
mMapToolGroup->addAction( mActionMeasureAngle );
mMapToolGroup->addAction( mActionAddFeature );
mMapToolGroup->addAction( mActionCircularStringCurvePoint );
mMapToolGroup->addAction( mActionMoveFeature );
mMapToolGroup->addAction( mActionRotateFeature );
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
@ -2293,6 +2296,8 @@ 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.mMoveFeature = new QgsMapToolMoveFeature( mMapCanvas );
mMapTools.mMoveFeature->setAction( mActionMoveFeature );
mMapTools.mRotateFeature = new QgsMapToolRotateFeature( mMapCanvas );
@ -6159,6 +6164,11 @@ void QgisApp::addFeature()
mMapCanvas->setMapTool( mMapTools.mAddFeature );
}
void QgisApp::circularStringCurvePoint()
{
mMapCanvas->setMapTool( mMapTools.mCircularStringCurvePoint );
}
void QgisApp::selectFeatures()
{
mMapCanvas->setMapTool( mMapTools.mSelectFeatures );

View File

@ -966,6 +966,8 @@ 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 move feature tool
void moveFeature();
//! activates the offset curve tool
@ -1471,6 +1473,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
QgsMapTool *mMeasureArea;
QgsMapTool *mMeasureAngle;
QgsMapTool *mAddFeature;
QgsMapTool *mCircularStringCurvePoint;
QgsMapTool *mMoveFeature;
QgsMapTool *mOffsetCurve;
QgsMapTool *mReshapeFeatures;

View File

@ -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 )

View File

@ -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"
@ -118,33 +121,52 @@ 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() );
int errorCode = 0;
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;

View File

@ -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;

View File

@ -169,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 )
@ -219,9 +226,6 @@ int QgsMapToolCapture::addVertex( const QgsPoint& point )
int QgsMapToolCapture::addCurve( QgsCurveV2* c )
{
return 1; //todo...
#if 0
if ( !c )
{
return 1;
@ -253,12 +257,16 @@ int QgsMapToolCapture::addCurve( QgsCurveV2* c )
QgsPointV2 endPt = c->endPoint();
mTempRubberBand->addPoint( QgsPoint( endPt.x(), endPt.y() ) ); //add last point of c
//const QgsCoordinateTransform* ct = mapCanvas()->mapSettings()->layerTransform( QgsMapLayer *layer ) const
//c->transform( ct, QgsCoordinateTransform::ReverseTransform);
//mCaptureCurve.addCurve( transformed curve );
//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;
#endif //0
}

View File

@ -53,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 );
@ -60,14 +65,12 @@ 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*/
int addVertex( const QgsPoint& point );
/** Adds a whole curve (e.g. circularstring) to the captured geometry. Curve must be in map CRS*/
int addCurve( QgsCurveV2* c );
/** Removes the last vertex from mRubberBand and mCaptureList*/
void undo();

View File

@ -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" ) );

View File

@ -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();

View File

@ -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>
@ -217,7 +218,7 @@ class CORE_EXPORT QgsAbstractGeometryV2
/** Transforms the geometry using a coordinate transform
* @param ct coordinate transform
*/
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

View File

@ -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;

View File

@ -68,7 +68,7 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
virtual QgsLineStringV2* curveToLine() const override;
void draw( QPainter& p ) const override;
void transform( const QgsCoordinateTransform& ct ) override;
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;

View File

@ -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 );
}
}

View File

@ -81,7 +81,7 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2
void addVertex( const QgsPointV2& pt );
void draw( QPainter& p ) const override;
void transform( const QgsCoordinateTransform& ct ) override;
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;

View File

@ -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 );
}
}

View File

@ -76,7 +76,7 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
bool removeInteriorRing( int nr );
virtual void draw( QPainter& p ) const override;
void transform( const QgsCoordinateTransform& ct ) override;
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;

View File

@ -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 );
}
}

View File

@ -63,7 +63,7 @@ class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2
*/
virtual bool removeGeometry( int nr );
virtual void transform( const QgsCoordinateTransform& ct ) override;
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;

View File

@ -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 )

View File

@ -64,7 +64,7 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
void append( const QgsLineStringV2* line );
void draw( QPainter& p ) const override;
void transform( const QgsCoordinateTransform& ct ) override;
void transform( const QgsCoordinateTransform& ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform ) override;
void transform( const QTransform& t ) override;
void addToPainterPath( QPainterPath& path ) const override;

View File

@ -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

View File

@ -67,7 +67,7 @@ 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;
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;

View File

@ -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 */

View File

@ -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"
@ -1036,6 +1037,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 )
@ -1058,6 +1080,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 )
{
@ -2182,7 +2225,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 ) )
{
@ -2941,7 +2984,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();
}
@ -3757,7 +3800,7 @@ void QgsVectorLayer::invalidateSymbolCountedFlag()
void QgsVectorLayer::onRelationsLoaded()
{
Q_FOREACH ( QgsAttributeEditorElement* elem, mAttributeEditorElements )
Q_FOREACH( QgsAttributeEditorElement* elem, mAttributeEditorElements )
{
if ( elem->type() == QgsAttributeEditorElement::AeTypeContainer )
{
@ -3766,7 +3809,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 )
@ -3835,7 +3878,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 ) );
}
@ -3856,7 +3899,7 @@ QList<QgsAttributeEditorElement*> QgsAttributeEditorContainer::findElements( Qgs
{
QList<QgsAttributeEditorElement*> results;
Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
Q_FOREACH( QgsAttributeEditorElement* elem, mChildren )
{
if ( elem->type() == type )
{

View File

@ -40,6 +40,7 @@ class QImage;
class QgsAbstractGeometrySimplifier;
class QgsAttributeAction;
class QgsCoordinateTransform;
class QgsCurveV2;
class QgsDiagramLayerSettings;
class QgsDiagramRendererV2;
class QgsEditorWidgetWrapper;
@ -1165,6 +1166,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,
@ -1177,6 +1186,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

View File

@ -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 )

View File

@ -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

View File

@ -1091,6 +1091,9 @@ bool QgsPostgresProvider::hasSufficientPermsAndCapabilities()
//supports transactions
mEnabledCapabilities |= QgsVectorDataProvider::TransactionSupport;
// supports circular geometries
mEnabledCapabilities |= QgsVectorDataProvider::CircularGeometries;
return true;
}

View File

@ -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,7 @@
<addaction name="mActionToggleEditing"/>
<addaction name="mActionSaveLayerEdits"/>
<addaction name="mActionAddFeature"/>
<addaction name="mActionCircularStringCurvePoint"/>
<addaction name="mActionMoveFeature"/>
<addaction name="mActionNodeTool"/>
<addaction name="mActionDeleteSelected"/>
@ -2352,6 +2353,18 @@ 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>
</widget>
<resources>
<include location="../../images/images.qrc"/>