Skip to content

Commit 44554e1

Browse files
committed
Offset curve tool: convert multiline features in both directions
1 parent df25981 commit 44554e1

File tree

2 files changed

+58
-5
lines changed

2 files changed

+58
-5
lines changed

src/app/qgsmaptooloffsetcurve.cpp

+53-5
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "qgisapp.h"
2626

2727
QgsMapToolOffsetCurve::QgsMapToolOffsetCurve( QgsMapCanvas* canvas ): QgsMapToolEdit( canvas ), mRubberBand( 0 ),
28-
mOriginalGeometry( 0 ), mGeometryModified( false ), mDistanceItem( 0 ), mDistanceSpinBox( 0 ), mSnapVertexMarker( 0 ), mForceCopy( false )
28+
mOriginalGeometry( 0 ), mGeometryModified( false ), mDistanceItem( 0 ), mDistanceSpinBox( 0 ), mSnapVertexMarker( 0 ), mForceCopy( false ), mMultiPartGeometry( false )
2929
{
3030
}
3131

@@ -90,6 +90,11 @@ void QgsMapToolOffsetCurve::canvasReleaseEvent( QMouseEvent * e )
9090
return;
9191
}
9292

93+
if ( mMultiPartGeometry )
94+
{
95+
mModifiedGeometry.convertToMultiType();
96+
}
97+
9398
vlayer->beginEditCommand( tr( "Offset curve" ) );
9499

95100
bool editOk;
@@ -218,27 +223,30 @@ QgsGeometry* QgsMapToolOffsetCurve::createOriginGeometry( QgsVectorLayer* vl, co
218223
{
219224
return 0;
220225
}
226+
mMultiPartGeometry = false;
227+
//assign feature part by vertex number (snap to vertex) or by before vertex number (snap to segment)
228+
int partVertexNr = ( sr.snappedVertexNr == -1 ? sr.beforeVertexNr : sr.snappedVertexNr );
221229

222230
if ( vl == currentVectorLayer() && !mForceCopy )
223231
{
224232
//don't consider selected geometries, only the snap result
225-
return snappedFeature.geometryAndOwnership();
233+
return convertToSingleLine( snappedFeature.geometryAndOwnership(), partVertexNr, mMultiPartGeometry );
226234
}
227235
else //snapped to a background layer
228236
{
229237
//if source layer is polygon / multipolygon, create a linestring from the snapped ring
230238
if ( vl->geometryType() == QGis::Polygon )
231239
{
232240
//make linestring from polygon ring and return this geometry
233-
return linestringFromPolygon( snappedFeature.geometry(), sr.snappedVertexNr );
241+
return linestringFromPolygon( snappedFeature.geometry(), partVertexNr );
234242
}
235243

236244

237245
//for background layers, try to merge selected entries together if snapped feature is contained in selection
238246
const QgsFeatureIds& selection = vl->selectedFeaturesIds();
239247
if ( selection.size() < 1 || !selection.contains( sr.snappedAtGeometry ) )
240248
{
241-
return snappedFeature.geometryAndOwnership();
249+
return convertToSingleLine( snappedFeature.geometryAndOwnership(), partVertexNr, mMultiPartGeometry );
242250
}
243251
else
244252
{
@@ -256,7 +264,7 @@ QgsGeometry* QgsMapToolOffsetCurve::createOriginGeometry( QgsVectorLayer* vl, co
256264
if ( geom->isMultipart() )
257265
{
258266
delete geom;
259-
return snappedFeature.geometryAndOwnership();
267+
return convertToSingleLine( snappedFeature.geometryAndOwnership(), sr.snappedVertexNr, mMultiPartGeometry );
260268
}
261269

262270
return geom;
@@ -416,3 +424,43 @@ void QgsMapToolOffsetCurve::configureSnapper( QgsSnapper& s )
416424
s.setSnapLayers( snapLayers );
417425
s.setSnapMode( QgsSnapper::SnapWithOneResult );
418426
}
427+
428+
QgsGeometry* QgsMapToolOffsetCurve::convertToSingleLine( QgsGeometry* geom, int vertex, bool& isMulti )
429+
{
430+
if ( !geom )
431+
{
432+
return 0;
433+
}
434+
435+
isMulti = false;
436+
QGis::WkbType geomType = geom->wkbType();
437+
if ( geomType == QGis::WKBLineString || geomType == QGis::WKBLineString25D )
438+
{
439+
return geom;
440+
}
441+
else if ( geomType == QGis::WKBMultiLineString || geomType == QGis::WKBMultiLineString25D )
442+
{
443+
//search vertex
444+
isMulti = true;
445+
int currentVertex = 0;
446+
QgsMultiPolyline multiLine = geom->asMultiPolyline();
447+
QgsMultiPolyline::const_iterator it = multiLine.constBegin();
448+
for ( ; it != multiLine.constEnd(); ++it )
449+
{
450+
currentVertex += it->size();
451+
if ( vertex < currentVertex )
452+
{
453+
QgsGeometry* g = QgsGeometry::fromPolyline( *it );
454+
delete geom;
455+
return g;
456+
}
457+
}
458+
}
459+
delete geom;
460+
return 0;
461+
}
462+
463+
QgsGeometry* QgsMapToolOffsetCurve::convertToMultiLine( QgsGeometry* geom )
464+
{
465+
return 0;
466+
}

src/app/qgsmaptooloffsetcurve.h

+5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class QgsMapToolOffsetCurve: public QgsMapToolEdit
6161
QgsVertexMarker* mSnapVertexMarker;
6262
/**Forces geometry copy (no modification of geometry in current layer)*/
6363
bool mForceCopy;
64+
bool mMultiPartGeometry;
6465

6566

6667
void deleteRubberBandAndGeometry();
@@ -72,6 +73,10 @@ class QgsMapToolOffsetCurve: public QgsMapToolEdit
7273
QgsGeometry* linestringFromPolygon( QgsGeometry* featureGeom, int vertex );
7374
/**Sets snapping with default vertex search tolerance to all layers (to vertex and segment)*/
7475
void configureSnapper( QgsSnapper& s );
76+
/**Returns a single line from a multiline (or does nothing if geometry is already a single line). Deletes the input geometry*/
77+
QgsGeometry* convertToSingleLine( QgsGeometry* geom, int vertex, bool& isMulti );
78+
/**Converts offset line back to a multiline if necessary*/
79+
QgsGeometry* convertToMultiLine( QgsGeometry* geom );
7580
};
7681

7782
#endif // QGSMAPTOOLOFFSETCURVE_H

0 commit comments

Comments
 (0)