Skip to content

Commit 3ae2297

Browse files
committedApr 3, 2017
Correctly show rubber bands when dragging vertices of circular edges
1 parent ab58413 commit 3ae2297

File tree

2 files changed

+150
-18
lines changed

2 files changed

+150
-18
lines changed
 

‎src/app/nodetool/qgsnodetool2.cpp

Lines changed: 133 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "qgsadvanceddigitizingdockwidget.h"
1919
#include "qgscurve.h"
2020
#include "qgscurvepolygon.h"
21+
#include "qgsgeometryutils.h"
2122
#include "qgslogger.h"
2223
#include "qgsmapcanvas.h"
2324
#include "qgsmulticurve.h"
@@ -236,6 +237,24 @@ void QgsNodeTool2::addDragMiddleBand( const QgsPoint &v1, const QgsPoint &v2, co
236237
mDragMiddleBandsOffset << qMakePair( offset1, offset2 );
237238
}
238239

240+
void QgsNodeTool2::addDragCircularBand( const QgsPoint &v0, const QgsPoint &v1, const QgsPoint &v2, bool moving0, bool moving1, bool moving2, const QgsPoint &mapPoint )
241+
{
242+
CircularBand b;
243+
b.band = createRubberBand( QgsWkbTypes::LineGeometry, true );
244+
b.p0 = v0;
245+
b.p1 = v1;
246+
b.p2 = v2;
247+
b.moving0 = moving0;
248+
b.moving1 = moving1;
249+
b.moving2 = moving2;
250+
b.offset0 = v0 - mapPoint;
251+
b.offset1 = v1 - mapPoint;
252+
b.offset2 = v2 - mapPoint;
253+
b.updateRubberBand( mapPoint );
254+
255+
mDragCircularBands << b;
256+
}
257+
239258
void QgsNodeTool2::clearDragBands()
240259
{
241260
qDeleteAll( mDragBands );
@@ -249,6 +268,10 @@ void QgsNodeTool2::clearDragBands()
249268
qDeleteAll( mDragPointMarkers );
250269
mDragPointMarkers.clear();
251270
mDragPointMarkersOffset.clear();
271+
272+
Q_FOREACH ( const CircularBand &b, mDragCircularBands )
273+
delete b.band;
274+
mDragCircularBands.clear();
252275
}
253276

254277
void QgsNodeTool2::cadCanvasPressEvent( QgsMapMouseEvent *e )
@@ -445,6 +468,12 @@ void QgsNodeTool2::mouseMoveDraggingVertex( QgsMapMouseEvent *e )
445468
band->movePoint( 1, e->mapPoint() + offset.second );
446469
}
447470

471+
for ( int i = 0; i < mDragCircularBands.count(); ++i )
472+
{
473+
CircularBand &b = mDragCircularBands[i];
474+
b.updateRubberBand( e->mapPoint() );
475+
}
476+
448477
// in case of moving of standalone point geometry
449478
for ( int i = 0; i < mDragPointMarkers.count(); ++i )
450479
{
@@ -867,44 +896,117 @@ void QgsNodeTool2::startDraggingMoveVertex( const QgsPoint &mapPoint, const QgsP
867896

868897
QgsPoint dragVertexMapPoint = m.point();
869898

899+
// set of middle vertices that are already in a circular rubber band
900+
// i.e. every circular band is defined by its middle circular vertex
901+
QSet<Vertex> verticesInCircularBands;
902+
870903
Q_FOREACH ( const Vertex &v, movingVertices )
871904
{
872905
int v0idx, v1idx;
873906
QgsGeometry geom = cachedGeometry( v.layer, v.fid );
874907
QgsPoint pt = geom.vertexAt( v.vertexId );
908+
875909
geom.adjacentVertices( v.vertexId, v0idx, v1idx );
910+
911+
QgsVertexId vid;
912+
if ( v0idx != -1 && v1idx != -1 && geom.vertexIdFromVertexNr( v.vertexId, vid ) && vid.type == QgsVertexId::CurveVertex )
913+
{
914+
// the vertex is in the middle of a curved segment
915+
qDebug( "middle point curve vertex" );
916+
if ( !verticesInCircularBands.contains( v ) )
917+
{
918+
addDragCircularBand( geom.vertexAt( v0idx ),
919+
pt,
920+
geom.vertexAt( v1idx ),
921+
movingVertices.contains( Vertex( v.layer, v.fid, v0idx ) ),
922+
true,
923+
movingVertices.contains( Vertex( v.layer, v.fid, v1idx ) ),
924+
dragVertexMapPoint );
925+
verticesInCircularBands << v;
926+
}
927+
928+
// skip the rest - no need for further straight of circular bands for this vertex
929+
// because our circular rubber band spans both towards left and right
930+
continue;
931+
}
932+
876933
if ( v0idx != -1 )
877934
{
878-
Vertex v0( v.layer, v.fid, v0idx );
879-
QgsPoint otherPoint0 = geom.vertexAt( v0idx );
880-
QgsPoint otherMapPoint0 = toMapCoordinates( v.layer, otherPoint0 );
881-
if ( !movingVertices.contains( v0 ) )
935+
// there is another vertex to the left - let's build a rubber band for it
936+
QgsVertexId v0id;
937+
if ( geom.vertexIdFromVertexNr( v0idx, v0id ) && v0id.type == QgsVertexId::CurveVertex )
882938
{
883-
// rubber band that is fixed on one side and moving with mouse cursor on the other
884-
addDragBand( otherMapPoint0, pt, pt - dragVertexMapPoint );
939+
// circular segment to the left
940+
Vertex v0( v.layer, v.fid, v0idx );
941+
if ( !verticesInCircularBands.contains( v0 ) )
942+
{
943+
addDragCircularBand( geom.vertexAt( v0idx - 1 ),
944+
geom.vertexAt( v0idx ),
945+
pt,
946+
movingVertices.contains( Vertex( v.layer, v.fid, v0idx - 1 ) ),
947+
movingVertices.contains( Vertex( v.layer, v.fid, v0idx ) ),
948+
true,
949+
dragVertexMapPoint );
950+
verticesInCircularBands << v0;
951+
}
885952
}
886953
else
887954
{
888-
// rubber band that has both endpoints moving with mouse cursor
889-
if ( v0idx > v.vertexId )
890-
addDragMiddleBand( otherMapPoint0, pt, otherMapPoint0 - dragVertexMapPoint, pt - dragVertexMapPoint );
955+
// straight segment to the left
956+
Vertex v0( v.layer, v.fid, v0idx );
957+
QgsPoint otherPoint0 = geom.vertexAt( v0idx );
958+
QgsPoint otherMapPoint0 = toMapCoordinates( v.layer, otherPoint0 );
959+
if ( !movingVertices.contains( v0 ) )
960+
{
961+
// rubber band that is fixed on one side and moving with mouse cursor on the other
962+
addDragBand( otherMapPoint0, pt, pt - dragVertexMapPoint );
963+
}
964+
else
965+
{
966+
// rubber band that has both endpoints moving with mouse cursor
967+
if ( v0idx > v.vertexId )
968+
addDragMiddleBand( otherMapPoint0, pt, otherMapPoint0 - dragVertexMapPoint, pt - dragVertexMapPoint );
969+
}
891970
}
892971
}
972+
893973
if ( v1idx != -1 )
894974
{
895-
Vertex v1( v.layer, v.fid, v1idx );
896-
QgsPoint otherPoint1 = geom.vertexAt( v1idx );
897-
QgsPoint otherMapPoint1 = toMapCoordinates( v.layer, otherPoint1 );
898-
if ( !movingVertices.contains( v1 ) )
975+
// there is another vertex to the right - let's build a rubber band for it
976+
QgsVertexId v1id;
977+
if ( geom.vertexIdFromVertexNr( v1idx, v1id ) && v1id.type == QgsVertexId::CurveVertex )
899978
{
900-
// rubber band that is fixed on one side and moving with mouse cursor on the other
901-
addDragBand( otherMapPoint1, pt, pt - dragVertexMapPoint );
979+
// circular segment to the right
980+
Vertex v1( v.layer, v.fid, v1idx );
981+
if ( !verticesInCircularBands.contains( v1 ) )
982+
{
983+
addDragCircularBand( pt,
984+
geom.vertexAt( v1idx ),
985+
geom.vertexAt( v1idx + 1 ),
986+
true,
987+
movingVertices.contains( Vertex( v.layer, v.fid, v1idx ) ),
988+
movingVertices.contains( Vertex( v.layer, v.fid, v1idx + 1 ) ),
989+
dragVertexMapPoint );
990+
verticesInCircularBands << v1;
991+
}
902992
}
903993
else
904994
{
905-
// rubber band that has both endpoints moving with mouse cursor
906-
if ( v1idx > v.vertexId )
907-
addDragMiddleBand( otherMapPoint1, pt, otherMapPoint1 - dragVertexMapPoint, pt - dragVertexMapPoint );
995+
// straight segment to the right
996+
Vertex v1( v.layer, v.fid, v1idx );
997+
QgsPoint otherPoint1 = geom.vertexAt( v1idx );
998+
QgsPoint otherMapPoint1 = toMapCoordinates( v.layer, otherPoint1 );
999+
if ( !movingVertices.contains( v1 ) )
1000+
{
1001+
// rubber band that is fixed on one side and moving with mouse cursor on the other
1002+
addDragBand( otherMapPoint1, pt, pt - dragVertexMapPoint );
1003+
}
1004+
else
1005+
{
1006+
// rubber band that has both endpoints moving with mouse cursor
1007+
if ( v1idx > v.vertexId )
1008+
addDragMiddleBand( otherMapPoint1, pt, otherMapPoint1 - dragVertexMapPoint, pt - dragVertexMapPoint );
1009+
}
9081010
}
9091011
}
9101012

@@ -1385,3 +1487,16 @@ bool QgsNodeTool2::matchEdgeCenterTest( const QgsPointLocator::Match &m, const Q
13851487
bool isNearCenter = distFromEdgeCenter < tol;
13861488
return isNearCenter;
13871489
}
1490+
1491+
void QgsNodeTool2::CircularBand::updateRubberBand( const QgsPoint &mapPoint )
1492+
{
1493+
QgsPointSequence points;
1494+
QgsPoint v0 = moving0 ? mapPoint + offset0 : p0;
1495+
QgsPoint v1 = moving1 ? mapPoint + offset1 : p1;
1496+
QgsPoint v2 = moving2 ? mapPoint + offset2 : p2;
1497+
QgsGeometryUtils::segmentizeArc( QgsPointV2( v0 ), QgsPointV2( v1 ), QgsPointV2( v2 ), points );
1498+
// it would be useful to have QgsRubberBand::setPoints() call
1499+
band->reset();
1500+
Q_FOREACH ( const QgsPointV2 &p, points )
1501+
band->addPoint( p );
1502+
}

‎src/app/nodetool/qgsnodetool2.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ class APP_EXPORT QgsNodeTool2 : public QgsMapToolAdvancedDigitizing
112112

113113
void addDragMiddleBand( const QgsPoint &v1, const QgsPoint &v2, const QgsVector &offset1, const QgsVector &offset2 );
114114

115+
void addDragCircularBand( const QgsPoint &v0, const QgsPoint &v1, const QgsPoint &v2, bool moving0, bool moving1, bool moving2, const QgsPoint &mapPoint );
116+
115117
void clearDragBands();
116118

117119
void mouseMoveDraggingVertex( QgsMapMouseEvent *e );
@@ -231,6 +233,21 @@ class APP_EXPORT QgsNodeTool2 : public QgsMapToolAdvancedDigitizing
231233
//! companion array to mDragMiddleBands: for each rubber band it keeps offset of both
232234
//! first and second point (in map units) from the position of the main vertex (mDraggingVertex)
233235
QList< QPair<QgsVector, QgsVector> > mDragMiddleBandsOffset;
236+
237+
//! structure to keep information about a rubber band used for dragging of a circular segment
238+
struct CircularBand
239+
{
240+
QgsRubberBand *band = nullptr; //!< Pointer to the actual rubber band
241+
QgsPoint p0, p1, p2; //!< What are the original positions of points (in map units)
242+
bool moving0, moving1, moving2; //!< Which points of the band are moving with mouse cursor
243+
QgsVector offset0, offset1, offset2; //!< If the point is moving, what is the offset from the mouse cursor
244+
245+
//! update geometry of the rubber band band on the current mouse cursor position (in map units)
246+
void updateRubberBand( const QgsPoint &mapPoint );
247+
};
248+
249+
//! list of active rubber bands for circular segments
250+
QList<CircularBand> mDragCircularBands;
234251
//! instance of Vertex that is being currently moved or nothing
235252
std::unique_ptr<Vertex> mDraggingVertex;
236253
//! whether moving a vertex or adding one

0 commit comments

Comments
 (0)
Please sign in to comment.