Skip to content

Commit dbaf7bd

Browse files
author
mhugent
committedJun 3, 2009
New functionality for merging features
git-svn-id: http://svn.osgeo.org/qgis/trunk@10879 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent aa18385 commit dbaf7bd

9 files changed

+909
-0
lines changed
 
Loading
1.68 KB
Loading
Loading

‎src/app/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ SET(QGIS_APP_SRCS
4141
qgsmaptoolvertexedit.cpp
4242
qgsmeasuredialog.cpp
4343
qgsmeasuretool.cpp
44+
qgsmergeattributesdialog.cpp
4445
qgsnewhttpconnection.cpp
4546
qgsnumericsortlistviewitem.cpp
4647
qgsogrsublayersdialog.cpp
@@ -129,6 +130,7 @@ SET (QGIS_APP_MOC_HDRS
129130

130131
qgsmeasuretool.h
131132
qgsmeasuredialog.h
133+
qgsmergeattributesdialog.h
132134
qgsnewhttpconnection.h
133135
qgsoptions.h
134136
qgsogrsublayersdialog.h

‎src/app/qgisapp.cpp

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
#include "qgsmapoverviewcanvas.h"
115115
#include "qgsmaprenderer.h"
116116
#include "qgsmaptip.h"
117+
#include "qgsmergeattributesdialog.h"
117118
#include "qgsmessageviewer.h"
118119
#include "qgsoptions.h"
119120
#include "qgspastetransformations.h"
@@ -703,6 +704,12 @@ void QgisApp::createActions()
703704
connect( mActionDeletePart, SIGNAL( triggered() ), this, SLOT( deletePart() ) );
704705
mActionDeletePart->setEnabled( false );
705706

707+
mActionMergeFeatures = new QAction( getThemeIcon("mActionMergeFeatures.png"), tr("Merge selected features"), this);
708+
shortcuts->registerAction(mActionMergeFeatures);
709+
mActionMergeFeatures->setStatusTip( tr("Merge selected features"));
710+
connect( mActionMergeFeatures, SIGNAL(triggered()), this, SLOT(mergeSelectedFeatures()));
711+
mActionMergeFeatures->setEnabled(false);
712+
706713

707714
// View Menu Items
708715

@@ -1053,6 +1060,7 @@ void QgisApp::createActionGroups()
10531060
mMapToolGroup->addAction( mActionDeleteRing );
10541061
mActionDeletePart->setCheckable( true );
10551062
mMapToolGroup->addAction( mActionDeletePart );
1063+
mMapToolGroup->addAction( mActionMergeFeatures);
10561064
}
10571065

10581066
void QgisApp::createMenus()
@@ -1141,6 +1149,7 @@ void QgisApp::createMenus()
11411149
mEditMenu->addAction( mActionAddIsland );
11421150
mEditMenu->addAction( mActionDeleteRing );
11431151
mEditMenu->addAction( mActionDeletePart );
1152+
mEditMenu->addAction( mActionMergeFeatures );
11441153

11451154
if ( layout == QDialogButtonBox::GnomeLayout || layout == QDialogButtonBox::MacLayout )
11461155
{
@@ -1345,6 +1354,7 @@ void QgisApp::createToolBars()
13451354
mAdvancedDigitizeToolBar->addAction( mActionAddIsland );
13461355
mAdvancedDigitizeToolBar->addAction( mActionDeleteRing );
13471356
mAdvancedDigitizeToolBar->addAction( mActionDeletePart );
1357+
mAdvancedDigitizeToolBar->addAction( mActionMergeFeatures );
13481358
mToolbarMenu->addAction( mAdvancedDigitizeToolBar->toggleViewAction() );
13491359

13501360

@@ -4085,6 +4095,139 @@ void QgisApp::deletePart()
40854095
mMapCanvas->setMapTool( mMapTools.mDeletePart );
40864096
}
40874097

4098+
QgsGeometry* QgisApp::unionGeometries(const QgsVectorLayer* vl, QgsFeatureList& featureList) const
4099+
{
4100+
if(!vl || featureList.size() < 2)
4101+
{
4102+
return 0;
4103+
}
4104+
4105+
QgsGeometry* unionGeom = featureList[0].geometry();
4106+
QgsGeometry* backupPtr = 0; //pointer to delete intermediate results
4107+
if(!unionGeom)
4108+
{
4109+
return 0;
4110+
}
4111+
4112+
for(int i = 1; i < featureList.size(); ++i)
4113+
{
4114+
QgsGeometry* currentGeom = featureList[i].geometry();
4115+
if(currentGeom)
4116+
{
4117+
backupPtr = unionGeom;
4118+
unionGeom = unionGeom->combine(currentGeom);
4119+
if(i > 1) //delete previous intermediate results
4120+
{
4121+
delete backupPtr;
4122+
backupPtr = 0;
4123+
}
4124+
}
4125+
}
4126+
return unionGeom;
4127+
}
4128+
4129+
void QgisApp::mergeSelectedFeatures()
4130+
{
4131+
//get active layer (hopefully vector)
4132+
QgsMapLayer* activeMapLayer = activeLayer();
4133+
if(!activeMapLayer)
4134+
{
4135+
QMessageBox::information(0, tr("No active layer"), tr("No active layer found. Please select a layer in the layer list"));
4136+
return;
4137+
}
4138+
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>(activeMapLayer);
4139+
if(!vl)
4140+
{
4141+
QMessageBox::information(0, tr("Active layer is not vector"), tr("The merge features tool only works on vector layers. Please select a vector layer from the layer list"));
4142+
return;
4143+
}
4144+
if(!vl->isEditable())
4145+
{
4146+
QMessageBox::information(0, tr("Layer not editable"), tr("Merging features can only be done for layers in editing mode. To use the merge tool, go to Layer->Toggle editing"));
4147+
return;
4148+
}
4149+
4150+
//get selected feature ids (as a QSet<int> )
4151+
const QgsFeatureIds& featureIdSet = vl->selectedFeaturesIds();
4152+
if(featureIdSet.size() < 2)
4153+
{
4154+
QMessageBox::information(0, "Not enough features selected", tr("The merge tool requires at least two selected features"));
4155+
return;
4156+
}
4157+
4158+
//get initial selection (may be altered by attribute merge dialog later)
4159+
QgsFeatureList featureList = vl->selectedFeatures(); //get QList<QgsFeature>
4160+
QgsGeometry* unionGeom = unionGeometries(vl, featureList);
4161+
if(!unionGeom)
4162+
{
4163+
return;
4164+
}
4165+
4166+
//make a first geometry union and notify the user straight away if the union geometry type does not match the layer one
4167+
QGis::WkbType originalType = vl->wkbType();
4168+
QGis::WkbType newType = unionGeom->wkbType();
4169+
if(unionGeom->wkbType() != vl->wkbType())
4170+
{
4171+
QMessageBox::critical(0, "Union operation canceled", tr("The union operation would result in a geometry type that is not compatible with the current layer and therefore is canceled"));
4172+
delete unionGeom;
4173+
return;
4174+
}
4175+
4176+
//merge the attributes together
4177+
QgsMergeAttributesDialog d(featureList, vl, mapCanvas());
4178+
if(d.exec() == QDialog::Rejected)
4179+
{
4180+
return;
4181+
}
4182+
4183+
QgsFeatureList featureListAfter = vl->selectedFeatures();
4184+
4185+
if(featureListAfter.size() < 2)
4186+
{
4187+
QMessageBox::information(0, "Not enough features selected", tr("The merge tool requires at least two selected features"));
4188+
delete unionGeom;
4189+
return;
4190+
}
4191+
4192+
//if the user changed the feature selection in the merge dialog, we need to repead the union and check the type
4193+
if(featureList.size() != featureListAfter.size())
4194+
{
4195+
delete unionGeom;
4196+
unionGeom = unionGeometries(vl, featureListAfter);
4197+
if(!unionGeom)
4198+
{
4199+
return;
4200+
}
4201+
4202+
originalType = vl->wkbType();
4203+
newType = unionGeom->wkbType();
4204+
if(unionGeom->wkbType() != vl->wkbType())
4205+
{
4206+
QMessageBox::critical(0, "Union operation canceled", tr("The union operation would result in a geometry type that is not compatible with the current layer and therefore is canceled"));
4207+
delete unionGeom;
4208+
return;
4209+
}
4210+
}
4211+
4212+
//create new feature
4213+
QgsFeature newFeature;
4214+
newFeature.setGeometry(unionGeom);
4215+
newFeature.setAttributeMap(d.mergedAttributesMap());
4216+
4217+
QgsFeatureList::const_iterator feature_it = featureListAfter.constBegin();
4218+
for(; feature_it != featureListAfter.constEnd(); ++feature_it)
4219+
{
4220+
vl->deleteFeature(feature_it->id());
4221+
}
4222+
4223+
vl->addFeature(newFeature, false);
4224+
4225+
if(mapCanvas())
4226+
{
4227+
mapCanvas()->refresh();
4228+
}
4229+
}
4230+
40884231
void QgisApp::splitFeatures()
40894232
{
40904233
mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
@@ -5314,6 +5457,17 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
53145457
mActionCutFeatures->setEnabled( false );
53155458
}
53165459

5460+
//merge tool needs editable layer and provider with the capability of adding and deleting features
5461+
if ( vlayer->isEditable() && (dprovider->capabilities() & QgsVectorDataProvider::DeleteFeatures) \
5462+
&& QgsVectorDataProvider::AddFeatures)
5463+
{
5464+
mActionMergeFeatures->setEnabled(layerHasSelection);
5465+
}
5466+
else
5467+
{
5468+
mActionMergeFeatures->setEnabled( false );
5469+
}
5470+
53175471
// moving enabled if geometry changes are supported
53185472
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
53195473
{
@@ -5366,6 +5520,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
53665520
mActionSplitFeatures->setEnabled( true );
53675521
mActionSimplifyFeature->setEnabled( true );
53685522
mActionDeletePart->setEnabled( true );
5523+
53695524
}
53705525
else
53715526
{

‎src/app/qgisapp.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class QValidator;
4141
class QgisAppInterface;
4242
class QgsClipboard;
4343
class QgsComposer;
44+
class QgsGeometry;
4445
class QgsHelpViewer;
4546
class QgsFeature;
4647

@@ -63,6 +64,7 @@ class QgsVectorLayer;
6364
#include <QPointer>
6465

6566
#include "qgsconfig.h"
67+
#include "qgsfeature.h"
6668
#include "qgspoint.h"
6769

6870
/*! \class QgisApp
@@ -509,6 +511,8 @@ class QgisApp : public QMainWindow
509511
void deleteRing();
510512
//! deletes part of polygon
511513
void deletePart();
514+
//! merges the selected features together
515+
void mergeSelectedFeatures();
512516

513517
//! activates the selection tool
514518
void select();
@@ -655,6 +659,9 @@ class QgisApp : public QMainWindow
655659
void pasteTransformations();
656660
//! check to see if file is dirty and if so, prompt the user th save it
657661
bool saveDirty();
662+
/** Helper function to union several geometries together (used in function mergeSelectedFeatures)
663+
@return 0 in case of error*/
664+
QgsGeometry* unionGeometries(const QgsVectorLayer* vl, QgsFeatureList& featureList) const;
658665

659666
/// QgisApp aren't copyable
660667
QgisApp( QgisApp const & );
@@ -719,6 +726,7 @@ class QgisApp : public QMainWindow
719726
QAction *mActionSimplifyFeature;
720727
QAction *mActionDeleteRing;
721728
QAction *mActionDeletePart;
729+
QAction *mActionMergeFeatures;
722730
QAction *mActionEditSeparator3;
723731

724732
QAction *mActionPan;

0 commit comments

Comments
 (0)
Please sign in to comment.