Skip to content

Commit

Permalink
[FEATURE]: Avoid intersections for polygons is now also possible to b…
Browse files Browse the repository at this point in the history
…ackground layers

git-svn-id: http://svn.osgeo.org/qgis/trunk@11839 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Oct 25, 2009
1 parent 9dba0ae commit a24884c
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 37 deletions.
2 changes: 2 additions & 0 deletions src/app/CMakeLists.txt
Expand Up @@ -9,6 +9,7 @@ SET(QGIS_APP_SRCS
qgsattributeeditor.cpp
qgsattributetypedialog.cpp
qgsattributetypeloaddialog.cpp
qgsavoidintersectionsdialog.cpp
qgsbookmarkitem.cpp
qgsbookmarks.cpp
qgsclipboard.cpp
Expand Down Expand Up @@ -119,6 +120,7 @@ SET (QGIS_APP_MOC_HDRS
qgsattributeeditor.h
qgsattributetypedialog.h
qgsattributetypeloaddialog.h
qgsavoidintersectionsdialog.h
qgsbookmarks.h
qgscontinuouscolordialog.h
qgsconfigureshortcutsdialog.h
Expand Down
60 changes: 60 additions & 0 deletions src/app/qgsavoidintersectionsdialog.cpp
@@ -0,0 +1,60 @@
#include "qgsavoidintersectionsdialog.h"
#include "qgsmapcanvas.h"
#include "qgsvectorlayer.h"

QgsAvoidIntersectionsDialog::QgsAvoidIntersectionsDialog( QgsMapCanvas* canvas, const QSet<QString>& enabledLayers, QWidget * parent, Qt::WindowFlags f ): \
QDialog( parent, f ), mMapCanvas( canvas )
{
setupUi( this );

int nLayers = mMapCanvas->layerCount();
QgsVectorLayer* currentLayer = 0;
QListWidgetItem* newItem = 0;

for ( int i = 0; i < nLayers; ++i )
{
currentLayer = dynamic_cast<QgsVectorLayer*>( mMapCanvas->layer( i ) );
if ( currentLayer )
{
//only consider polygon or multipolygon layers
if ( currentLayer->geometryType() == QGis::Polygon )
{
newItem = new QListWidgetItem( mLayersListWidget );
newItem->setText( currentLayer->name() );
newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
newItem->setData( Qt::UserRole, currentLayer->getLayerID() );
if ( enabledLayers.contains( currentLayer->getLayerID() ) )
{
newItem->setCheckState( Qt::Checked );
}
else
{
newItem->setCheckState( Qt::Unchecked );
}
}
}
}
}

QgsAvoidIntersectionsDialog::~QgsAvoidIntersectionsDialog()
{

}

void QgsAvoidIntersectionsDialog::enabledLayers( QSet<QString>& enabledLayers )
{
enabledLayers.clear();

int itemCount = mLayersListWidget->count();
QListWidgetItem* currentItem = 0;

for ( int i = 0; i < itemCount; ++i )
{
currentItem = mLayersListWidget->item( i );
if ( currentItem->checkState() == Qt::Checked )
{
enabledLayers.insert( currentItem->data( Qt::UserRole ).toString() );
}
}
}

21 changes: 21 additions & 0 deletions src/app/qgsavoidintersectionsdialog.h
@@ -0,0 +1,21 @@
#ifndef QGSAVOIDINTERSECTIONSDIALOG_H
#define QGSAVOIDINTERSECTIONSDIALOG_H

#include "ui_qgsavoidintersectionsdialogbase.h"

class QgsMapCanvas;

class QgsAvoidIntersectionsDialog: public QDialog, private Ui::QgsAvoidIntersectionsDialogBase
{
Q_OBJECT
public:
QgsAvoidIntersectionsDialog( QgsMapCanvas* canvas, const QSet<QString>& enabledLayers, QWidget * parent = 0, Qt::WindowFlags f = 0 );
~QgsAvoidIntersectionsDialog();
/**Returns ids of layers that are considered for the avoid intersection function*/
void enabledLayers( QSet<QString>& enabledLayers );

private:
QgsMapCanvas* mMapCanvas;
};

#endif // QGSAVOIDINTERSECTIONSDIALOG_H
72 changes: 64 additions & 8 deletions src/app/qgsmaptooladdfeature.cpp
Expand Up @@ -21,6 +21,7 @@
#include "qgsfield.h"
#include "qgsgeometry.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayerregistry.h"
#include "qgsproject.h"
#include "qgsrubberband.h"
#include "qgsvectordataprovider.h"
Expand Down Expand Up @@ -442,16 +443,27 @@ void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )
}
f->setGeometryAndOwnership( &wkb[0], size );

//is automatic polygon intersection removal activated?
int avoidPolygonIntersections = QgsProject::instance()->readNumEntry( "Digitizing", "/AvoidPolygonIntersections", 0 );

if ( avoidPolygonIntersections != 0 )
int avoidIntersectionsReturn = avoidIntersectons( f->geometry() );
if ( avoidIntersectionsReturn == 1 )
{
if ( vlayer->removePolygonIntersections( f->geometry() ) != 0 )
{
QMessageBox::critical( 0, tr( "Error" ), tr( "Could not remove polygon intersection" ) );
}
//not a polygon type. Impossible to get there
}
else if ( avoidIntersectionsReturn == 2 )
{
//bail out...
QMessageBox::critical( 0, tr( "Error" ), tr( "The feature could not be added because removing the polygon intersections would change the geometry type" ) );
delete f;
delete mRubberBand;
mRubberBand = 0;
mCaptureList.clear();
return;
}
else if ( avoidIntersectionsReturn == 3 )
{
QMessageBox::critical( 0, tr( "Error" ), tr( "An error was reported during intersection removal" ) );
}


}

// add the fields to the QgsFeature
Expand Down Expand Up @@ -507,3 +519,47 @@ void QgsMapToolAddFeature::canvasReleaseEvent( QMouseEvent * e )
}
}
}

int QgsMapToolAddFeature::avoidIntersectons( QgsGeometry* g )
{
int returnValue = 0;

//check if g has polygon type
if ( !g || g->type() != QGis::Polygon )
{
return 1;
}

QGis::WkbType geomTypeBeforeModification = g->wkbType();

//read avoid intersections list from project properties
bool listReadOk;
QStringList avoidIntersectionsList = QgsProject::instance()->readListEntry( "Digitizing", "/AvoidIntersectionsList", &listReadOk );
if ( !listReadOk )
{
return true; //no intersections stored in project does not mean error
}

//go through list, convert each layer to vector layer and call QgsVectorLayer::removePolygonIntersections for each
QgsVectorLayer* currentLayer = 0;
QStringList::const_iterator aIt = avoidIntersectionsList.constBegin();
for ( ; aIt != avoidIntersectionsList.constEnd(); ++aIt )
{
currentLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( *aIt ) );
if ( currentLayer )
{
if ( currentLayer->removePolygonIntersections( g ) != 0 )
{
returnValue = 3;
}
}
}

//make sure the geometry still has the same type (e.g. no change from polygon to multipolygon)
if ( g->wkbType() != geomTypeBeforeModification )
{
return 2;
}

return returnValue;
}
5 changes: 5 additions & 0 deletions src/app/qgsmaptooladdfeature.h
Expand Up @@ -24,4 +24,9 @@ class QgsMapToolAddFeature: public QgsMapToolCapture
QgsMapToolAddFeature( QgsMapCanvas* canvas, enum CaptureTool tool );
virtual ~QgsMapToolAddFeature();
void canvasReleaseEvent( QMouseEvent * e );
private:
/**Modifies geometry to avoid intersections with the layers specified in project properties
@return 0 in case of success, 1 if geometry is not of polygon type, 2 if avoid intersection would change the geometry type, \
3 other error during intersection removal*/
int avoidIntersectons( QgsGeometry* g );
};
38 changes: 29 additions & 9 deletions src/app/qgsprojectproperties.cpp
Expand Up @@ -20,6 +20,7 @@
#include "qgsprojectproperties.h"

//qgis includes
#include "qgsavoidintersectionsdialog.h"
#include "qgscontexthelp.h"
#include "qgscoordinatetransform.h"
#include "qgslogger.h"
Expand Down Expand Up @@ -113,14 +114,16 @@ QgsProjectProperties::QgsProjectProperties( QgsMapCanvas* mapCanvas, QWidget *pa
mEnableTopologicalEditingCheckBox->setCheckState( Qt::Unchecked );
}

int avoidPolygonIntersections = QgsProject::instance()->readNumEntry( "Digitizing", "/AvoidPolygonIntersections", 0 );
if ( avoidPolygonIntersections != 0 )
bool avoidIntersectionListOk;
mAvoidIntersectionsSettings.clear();
QStringList avoidIntersectionsList = QgsProject::instance()->readListEntry( "Digitizing", "/AvoidIntersectionsList", &avoidIntersectionListOk );
if ( avoidIntersectionListOk )
{
mAvoidIntersectionsCheckBox->setCheckState( Qt::Checked );
}
else
{
mAvoidIntersectionsCheckBox->setCheckState( Qt::Unchecked );
QStringList::const_iterator avoidIt = avoidIntersectionsList.constBegin();
for ( ; avoidIt != avoidIntersectionsList.constEnd(); ++avoidIt )
{
mAvoidIntersectionsSettings.insert( *avoidIt );
}
}

bool layerIdListOk, enabledListOk, toleranceListOk, toleranceUnitListOk, snapToListOk;
Expand Down Expand Up @@ -399,8 +402,16 @@ void QgsProjectProperties::apply()
//write the digitizing settings
int topologicalEditingEnabled = ( mEnableTopologicalEditingCheckBox->checkState() == Qt::Checked ) ? 1 : 0;
QgsProject::instance()->writeEntry( "Digitizing", "/TopologicalEditing", topologicalEditingEnabled );
int avoidPolygonIntersectionsEnabled = ( mAvoidIntersectionsCheckBox->checkState() == Qt::Checked ) ? 1 : 0;
QgsProject::instance()->writeEntry( "Digitizing", "/AvoidPolygonIntersections", avoidPolygonIntersectionsEnabled );

//store avoid intersection layers
QStringList avoidIntersectionList;
QSet<QString>::const_iterator avoidIt = mAvoidIntersectionsSettings.constBegin();
for ( ; avoidIt != mAvoidIntersectionsSettings.constEnd(); ++avoidIt )
{
avoidIntersectionList.append( *avoidIt );
}
QgsProject::instance()->writeEntry( "Digitizing", "/AvoidIntersectionsList", avoidIntersectionList );


QMap<QString, LayerEntry>::const_iterator layerEntryIt;

Expand Down Expand Up @@ -498,6 +509,15 @@ void QgsProjectProperties::on_buttonBox_helpRequested()
QgsContextHelp::run( context_id );
}

void QgsProjectProperties::on_mAvoidIntersectionsPushButton_clicked()
{
QgsAvoidIntersectionsDialog d( mMapCanvas, mAvoidIntersectionsSettings );
if ( d.exec() == QDialog::Accepted )
{
d.enabledLayers( mAvoidIntersectionsSettings );
}
}

void QgsProjectProperties::on_mSnappingOptionsPushButton_clicked()
{
QgsSnappingDialog d( mMapCanvas, mSnappingLayerSettings );
Expand Down
10 changes: 9 additions & 1 deletion src/app/qgsprojectproperties.h
Expand Up @@ -89,7 +89,12 @@ class QgsProjectProperties : public QDialog, private Ui::QgsProjectPropertiesBas
void on_buttonBox_helpRequested();

/*!
* Slot to show dialog for advanced editing options
*
*/
void on_mAvoidIntersectionsPushButton_clicked();

/*!
* Slot to show dialog for the layer snapping options
*/
void on_mSnappingOptionsPushButton_clicked();

Expand All @@ -114,6 +119,9 @@ class QgsProjectProperties : public QDialog, private Ui::QgsProjectPropertiesBas
snapping tolerance*/
QMap<QString, LayerEntry> mSnappingLayerSettings;

/**Stores ids of layers where intersections of new polygons is considered. Is passed to / read from QgsAvoidIntersectionsDialog*/
QSet<QString> mAvoidIntersectionsSettings;


/*!
* Function to save dialog window state
Expand Down
66 changes: 66 additions & 0 deletions src/ui/qgsavoidintersectionsdialogbase.ui
@@ -0,0 +1,66 @@
<ui version="4.0" >
<class>QgsAvoidIntersectionsDialogBase</class>
<widget class="QDialog" name="QgsAvoidIntersectionsDialogBase" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>365</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle" >
<string>Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<item row="0" column="0" >
<widget class="QListWidget" name="mLayersListWidget" />
</item>
<item row="1" column="0" >
<widget class="QDialogButtonBox" name="mButtonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>mButtonBox</sender>
<signal>accepted()</signal>
<receiver>QgsAvoidIntersectionsDialogBase</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>mButtonBox</sender>
<signal>rejected()</signal>
<receiver>QgsAvoidIntersectionsDialogBase</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

0 comments on commit a24884c

Please sign in to comment.