Skip to content
Permalink
Browse files

New functionality for merging features

git-svn-id: http://svn.osgeo.org/qgis/trunk@10879 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent
mhugent committed Jun 3, 2009
1 parent aa18385 commit dbaf7bd4546bbda676aaaa7718f5baec35efae8e
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -41,6 +41,7 @@ SET(QGIS_APP_SRCS
qgsmaptoolvertexedit.cpp
qgsmeasuredialog.cpp
qgsmeasuretool.cpp
qgsmergeattributesdialog.cpp
qgsnewhttpconnection.cpp
qgsnumericsortlistviewitem.cpp
qgsogrsublayersdialog.cpp
@@ -129,6 +130,7 @@ SET (QGIS_APP_MOC_HDRS

qgsmeasuretool.h
qgsmeasuredialog.h
qgsmergeattributesdialog.h
qgsnewhttpconnection.h
qgsoptions.h
qgsogrsublayersdialog.h
@@ -114,6 +114,7 @@
#include "qgsmapoverviewcanvas.h"
#include "qgsmaprenderer.h"
#include "qgsmaptip.h"
#include "qgsmergeattributesdialog.h"
#include "qgsmessageviewer.h"
#include "qgsoptions.h"
#include "qgspastetransformations.h"
@@ -703,6 +704,12 @@ void QgisApp::createActions()
connect( mActionDeletePart, SIGNAL( triggered() ), this, SLOT( deletePart() ) );
mActionDeletePart->setEnabled( false );

mActionMergeFeatures = new QAction( getThemeIcon("mActionMergeFeatures.png"), tr("Merge selected features"), this);
shortcuts->registerAction(mActionMergeFeatures);
mActionMergeFeatures->setStatusTip( tr("Merge selected features"));
connect( mActionMergeFeatures, SIGNAL(triggered()), this, SLOT(mergeSelectedFeatures()));
mActionMergeFeatures->setEnabled(false);


// View Menu Items

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

void QgisApp::createMenus()
@@ -1141,6 +1149,7 @@ void QgisApp::createMenus()
mEditMenu->addAction( mActionAddIsland );
mEditMenu->addAction( mActionDeleteRing );
mEditMenu->addAction( mActionDeletePart );
mEditMenu->addAction( mActionMergeFeatures );

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


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

QgsGeometry* QgisApp::unionGeometries(const QgsVectorLayer* vl, QgsFeatureList& featureList) const
{
if(!vl || featureList.size() < 2)
{
return 0;
}

QgsGeometry* unionGeom = featureList[0].geometry();
QgsGeometry* backupPtr = 0; //pointer to delete intermediate results
if(!unionGeom)
{
return 0;
}

for(int i = 1; i < featureList.size(); ++i)
{
QgsGeometry* currentGeom = featureList[i].geometry();
if(currentGeom)
{
backupPtr = unionGeom;
unionGeom = unionGeom->combine(currentGeom);
if(i > 1) //delete previous intermediate results
{
delete backupPtr;
backupPtr = 0;
}
}
}
return unionGeom;
}

void QgisApp::mergeSelectedFeatures()
{
//get active layer (hopefully vector)
QgsMapLayer* activeMapLayer = activeLayer();
if(!activeMapLayer)
{
QMessageBox::information(0, tr("No active layer"), tr("No active layer found. Please select a layer in the layer list"));
return;
}
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>(activeMapLayer);
if(!vl)
{
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"));
return;
}
if(!vl->isEditable())
{
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"));
return;
}

//get selected feature ids (as a QSet<int> )
const QgsFeatureIds& featureIdSet = vl->selectedFeaturesIds();
if(featureIdSet.size() < 2)
{
QMessageBox::information(0, "Not enough features selected", tr("The merge tool requires at least two selected features"));
return;
}

//get initial selection (may be altered by attribute merge dialog later)
QgsFeatureList featureList = vl->selectedFeatures(); //get QList<QgsFeature>
QgsGeometry* unionGeom = unionGeometries(vl, featureList);
if(!unionGeom)
{
return;
}

//make a first geometry union and notify the user straight away if the union geometry type does not match the layer one
QGis::WkbType originalType = vl->wkbType();
QGis::WkbType newType = unionGeom->wkbType();
if(unionGeom->wkbType() != vl->wkbType())
{
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"));
delete unionGeom;
return;
}

//merge the attributes together
QgsMergeAttributesDialog d(featureList, vl, mapCanvas());
if(d.exec() == QDialog::Rejected)
{
return;
}

QgsFeatureList featureListAfter = vl->selectedFeatures();

if(featureListAfter.size() < 2)
{
QMessageBox::information(0, "Not enough features selected", tr("The merge tool requires at least two selected features"));
delete unionGeom;
return;
}

//if the user changed the feature selection in the merge dialog, we need to repead the union and check the type
if(featureList.size() != featureListAfter.size())
{
delete unionGeom;
unionGeom = unionGeometries(vl, featureListAfter);
if(!unionGeom)
{
return;
}

originalType = vl->wkbType();
newType = unionGeom->wkbType();
if(unionGeom->wkbType() != vl->wkbType())
{
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"));
delete unionGeom;
return;
}
}

//create new feature
QgsFeature newFeature;
newFeature.setGeometry(unionGeom);
newFeature.setAttributeMap(d.mergedAttributesMap());

QgsFeatureList::const_iterator feature_it = featureListAfter.constBegin();
for(; feature_it != featureListAfter.constEnd(); ++feature_it)
{
vl->deleteFeature(feature_it->id());
}

vl->addFeature(newFeature, false);

if(mapCanvas())
{
mapCanvas()->refresh();
}
}

void QgisApp::splitFeatures()
{
mMapCanvas->setMapTool( mMapTools.mSplitFeatures );
@@ -5314,6 +5457,17 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
mActionCutFeatures->setEnabled( false );
}

//merge tool needs editable layer and provider with the capability of adding and deleting features
if ( vlayer->isEditable() && (dprovider->capabilities() & QgsVectorDataProvider::DeleteFeatures) \
&& QgsVectorDataProvider::AddFeatures)
{
mActionMergeFeatures->setEnabled(layerHasSelection);
}
else
{
mActionMergeFeatures->setEnabled( false );
}

// moving enabled if geometry changes are supported
if ( vlayer->isEditable() && dprovider->capabilities() & QgsVectorDataProvider::ChangeGeometries )
{
@@ -5366,6 +5520,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
mActionSplitFeatures->setEnabled( true );
mActionSimplifyFeature->setEnabled( true );
mActionDeletePart->setEnabled( true );

}
else
{
@@ -41,6 +41,7 @@ class QValidator;
class QgisAppInterface;
class QgsClipboard;
class QgsComposer;
class QgsGeometry;
class QgsHelpViewer;
class QgsFeature;

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

#include "qgsconfig.h"
#include "qgsfeature.h"
#include "qgspoint.h"

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

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

/// QgisApp aren't copyable
QgisApp( QgisApp const & );
@@ -719,6 +726,7 @@ class QgisApp : public QMainWindow
QAction *mActionSimplifyFeature;
QAction *mActionDeleteRing;
QAction *mActionDeletePart;
QAction *mActionMergeFeatures;
QAction *mActionEditSeparator3;

QAction *mActionPan;

0 comments on commit dbaf7bd

Please sign in to comment.
You can’t perform that action at this time.