| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| /*************************************************************************** | ||
| checkDock.h | ||
| TOPOLogy checker | ||
| ------------------- | ||
| date : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef CHECKDOCK_H | ||
| #define CHECKDOCK_H | ||
|
|
||
| #include <QDockWidget> | ||
|
|
||
| #include <qgsvectorlayer.h> | ||
| #include <qgsgeometry.h> | ||
| //#include <qgsvertexmarker.h> | ||
| #include "qgsspatialindex.h" | ||
| //#include <spatialindex/qgsspatialindex.h> | ||
|
|
||
| #include "ui_checkDock.h" | ||
| #include "rulesDialog.h" | ||
| #include "topolError.h" | ||
| #include "topolTest.h" | ||
| #include "dockModel.h" | ||
|
|
||
| class QgsMapLayerRegistry; | ||
| class QgsRubberBand; | ||
| class QgsVertexMarker; | ||
| class QgisApp; | ||
| class QgisInterface; | ||
| class checkDock; | ||
|
|
||
| class checkDock : public QDockWidget, public Ui::checkDock | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| public: | ||
| /** | ||
| * Constructor | ||
| * @param qIface pointer to QgisInterface instance that is passed to the rulesDialog | ||
| * @param parent parent object | ||
| */ | ||
| checkDock( QgisInterface* qIface, QWidget *parent = 0 ); | ||
| ~checkDock(); | ||
|
|
||
| private slots: | ||
| /** | ||
| * Launches the configuration dialog | ||
| */ | ||
| void configure(); | ||
| /** | ||
| * Launches fixing routine | ||
| */ | ||
| void fix(); | ||
| /** | ||
| * Validates the whole layer | ||
| */ | ||
| void validateAll(); | ||
| /** | ||
| * Validates the current extent | ||
| */ | ||
| void validateExtent(); | ||
| /** | ||
| * Validates only selected features | ||
| */ | ||
| void validateSelected(); | ||
| /** | ||
| * toggles the visibility of rubber band error markers | ||
| */ | ||
| void toggleErrorMarkers(); | ||
| /** | ||
| * Handles error selection | ||
| * @param index clicked index in the table | ||
| */ | ||
| void errorListClicked( const QModelIndex& index ); | ||
| /** | ||
| * Deletes allocated errors' data | ||
| */ | ||
| void deleteErrors(); | ||
| /** | ||
| * Filters all errors involving features from specified layer | ||
| * @param layerId layer ID | ||
| */ | ||
| void parseErrorListByLayer( QString layerId ); | ||
| /** | ||
| * Clears rubberbands when window is hidden | ||
| * @param visible true if the window is visible | ||
| */ | ||
| void updateRubberBands( bool visible ); | ||
|
|
||
|
|
||
| private: | ||
| rulesDialog* mConfigureDialog; | ||
| QgisApp* mQgisApp; | ||
|
|
||
| QgsRubberBand* mRBConflict; | ||
| QgsRubberBand* mRBFeature1; | ||
| QgsRubberBand* mRBFeature2; | ||
| QgsVertexMarker* mVMConflict; | ||
| QgsVertexMarker* mVMFeature1; | ||
| QgsVertexMarker* mVMFeature2; | ||
| QList<QgsRubberBand*> mRbErrorMarkers; | ||
| bool mMarkersVisible; | ||
|
|
||
| ErrorList mErrorList; | ||
| DockModel* mErrorListModel; | ||
|
|
||
| QgisInterface* qgsInterface; | ||
|
|
||
| //pointer to topology tests table | ||
| QTableWidget* mTestTable; | ||
|
|
||
| topolTest* mTest; | ||
| QgsMapLayerRegistry* mLayerRegistry; | ||
|
|
||
| /** | ||
| * Runs tests from the test table | ||
| * @param type validation type - what features to check | ||
| */ | ||
| void runTests( ValidateType type ); | ||
| /** | ||
| * Validates topology | ||
| * @param type validation type - what features to check | ||
| */ | ||
| void validate( ValidateType type ); | ||
| /** | ||
| * Filters all errors involving specified feature | ||
| * @param featureId feature ID | ||
| */ | ||
| void parseErrorListByFeature( int featureId ); | ||
| /** | ||
| * Deletes vertex markers | ||
| */ | ||
| void clearVertexMarkers(); | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <ui version="4.0"> | ||
| <class>checkDock</class> | ||
| <widget class="QDockWidget" name="checkDock"> | ||
| <property name="geometry"> | ||
| <rect> | ||
| <x>0</x> | ||
| <y>0</y> | ||
| <width>436</width> | ||
| <height>439</height> | ||
| </rect> | ||
| </property> | ||
| <property name="windowTitle"> | ||
| <string>Topology Checker</string> | ||
| </property> | ||
| <widget class="QWidget" name="dockWidgetContents"> | ||
| <layout class="QGridLayout" name="gridLayout"> | ||
| <item row="0" column="0"> | ||
| <layout class="QVBoxLayout" name="verticalLayout"> | ||
| <item> | ||
| <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| <item> | ||
| <widget class="QPushButton" name="mValidateAllButton"> | ||
| <property name="text"> | ||
| <string>Validate All</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QPushButton" name="mValidateExtentButton"> | ||
| <property name="text"> | ||
| <string>Validate Extent</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| </layout> | ||
| </item> | ||
| <item> | ||
| <widget class="QPushButton" name="mToggleRubberbands"> | ||
| <property name="text"> | ||
| <string>Toggle Error Markers</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QTableView" name="mErrorTableView"/> | ||
| </item> | ||
| <item> | ||
| <widget class="QLabel" name="mComment"> | ||
| <property name="text"> | ||
| <string>Topology not checked yet</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| <item> | ||
| <widget class="QPushButton" name="mConfigureButton"> | ||
| <property name="text"> | ||
| <string>Configure</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QComboBox" name="mFixBox"> | ||
| <item> | ||
| <property name="text"> | ||
| <string>Select automatic fix</string> | ||
| </property> | ||
| </item> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QPushButton" name="mFixButton"> | ||
| <property name="text"> | ||
| <string>Fix!</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| </layout> | ||
| </item> | ||
| </layout> | ||
| </item> | ||
| </layout> | ||
| </widget> | ||
| </widget> | ||
| <resources/> | ||
| <connections/> | ||
| </ui> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| /*************************************************************************** | ||
| dockModel.cpp | ||
| TOPOLogy checker | ||
| ------------------- | ||
| date : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "dockModel.h" | ||
| #include "topolError.h" | ||
|
|
||
| DockModel::DockModel( ErrorList& theErrorList, QObject *parent = 0 ) : mErrorlist( theErrorList ) | ||
| { | ||
| mHeader << "Error" << "Layer" << "Feature ID"; | ||
|
|
||
| } | ||
|
|
||
| int DockModel::rowCount( const QModelIndex &parent ) const | ||
| { | ||
| return mErrorlist.count(); | ||
| } | ||
|
|
||
| int DockModel::columnCount( const QModelIndex &parent ) const | ||
| { | ||
| return 3; | ||
| } | ||
|
|
||
| QVariant DockModel::headerData( int section, Qt::Orientation orientation, int role ) const | ||
| { | ||
| if ( role == Qt::DisplayRole ) | ||
| { | ||
| if ( orientation == Qt::Vertical ) //row | ||
| { | ||
| return QVariant( section ); | ||
| } | ||
| else | ||
| { | ||
| return mHeader[section]; | ||
| } | ||
| } | ||
| else return QVariant(); | ||
| } | ||
|
|
||
| QVariant DockModel::data( const QModelIndex &index, int role ) const | ||
| { | ||
| if ( !index.isValid() || ( role != Qt::TextAlignmentRole && role != Qt::DisplayRole && role != Qt::EditRole ) ) | ||
| return QVariant(); | ||
|
|
||
| int row = index.row(); | ||
| // if(!row) | ||
| // { | ||
| // return QVariant(); | ||
| // } | ||
| int column = index.column(); | ||
|
|
||
| if ( role == Qt::TextAlignmentRole ) | ||
| { | ||
| if ( column ) | ||
| return QVariant( Qt::AlignRight ); | ||
| else | ||
| return QVariant( Qt::AlignLeft ); | ||
| } | ||
|
|
||
| QVariant val; | ||
| switch ( column ) | ||
| { | ||
| case 0: | ||
| val = mErrorlist[row]->name(); | ||
| break; | ||
| case 1: | ||
| if ( !mErrorlist[row]->featurePairs().first().layer ) | ||
| val = QString( "Unkown" ); | ||
| else | ||
| val = mErrorlist[row]->featurePairs().first().layer->name(); | ||
| break; | ||
| case 2: | ||
| val = mErrorlist[row]->featurePairs().first().feature.id(); | ||
| break; | ||
| default: | ||
| val = QVariant(); | ||
| } | ||
|
|
||
| if ( val.isNull() ) | ||
| { | ||
| return QVariant(); | ||
| } | ||
|
|
||
| // convert to QString from some other representation | ||
| // this prevents displaying greater numbers in exponential format | ||
| return val.toString(); | ||
| } | ||
|
|
||
| bool DockModel::setData( const QModelIndex &index, const QVariant &value, int role ) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| Qt::ItemFlags DockModel::flags( const QModelIndex &index ) const | ||
| { | ||
| if ( !index.isValid() ) | ||
| return Qt::ItemIsEnabled; | ||
|
|
||
| Qt::ItemFlags flags = QAbstractItemModel::flags( index ); | ||
| return flags; | ||
| } | ||
|
|
||
| void DockModel::resetModel() | ||
| { | ||
| reset(); | ||
| } | ||
|
|
||
| void DockModel::reload( const QModelIndex &index1, const QModelIndex &index2 ) | ||
|
|
||
| { | ||
| emit dataChanged( index1, index2 ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| /*************************************************************************** | ||
| dockModel.h | ||
| TOPOLogy checker | ||
| ------------------- | ||
| date : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef DOCKMODEL_H | ||
| #define DOCKMODEL_H | ||
|
|
||
| #include <QAbstractTableModel> | ||
| #include <QModelIndex> | ||
| #include <QObject> | ||
|
|
||
| #include "topolError.h" | ||
|
|
||
| class DockModel: public QAbstractTableModel | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| public: | ||
| /** | ||
| * Constructor | ||
| * @param theErrorList reference to the ErrorList where errors will be stored | ||
| * @param parent parent object | ||
| */ | ||
| DockModel(ErrorList& theErrorList, QObject *parent); | ||
| /** | ||
| * Returns header data | ||
| * @param section required section | ||
| * @param orientation horizontal or vertical orientation | ||
| * @param role data role | ||
| */ | ||
| QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; | ||
| /** | ||
| * Returns data on the given index | ||
| * @param index model index | ||
| * @param role data role | ||
| */ | ||
| virtual QVariant data(const QModelIndex &index, int role) const; | ||
| /** | ||
| * Updates data on given index | ||
| * @param index model index | ||
| * @param value new data value | ||
| * @param role data role | ||
| */ | ||
| virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); | ||
| /** | ||
| * Returns item flags for the index | ||
| * @param index model index | ||
| */ | ||
| Qt::ItemFlags flags(const QModelIndex &index) const; | ||
|
|
||
| /** | ||
| * Returns the number of rows | ||
| * @param parent parent index | ||
| */ | ||
| int rowCount(const QModelIndex &parent) const; | ||
| /** | ||
| * Returns the number of columns | ||
| * @param parent parent index | ||
| */ | ||
| int columnCount(const QModelIndex &parent) const; | ||
|
|
||
| /** | ||
| * Reloads the model data between indices | ||
| * @param index1 start index | ||
| * @param index2 end index | ||
| */ | ||
| void reload(const QModelIndex &index1, const QModelIndex &index2); | ||
| /** | ||
| * Resets the model | ||
| */ | ||
| void resetModel(); | ||
|
|
||
| private: | ||
| ErrorList& mErrorlist; | ||
| QList<QString> mHeader; | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,123 @@ | ||
| #ifndef GEOSFUNCTIONS_H | ||
| #define GEOSFUNCTIONS_H | ||
|
|
||
| #include <geos_c.h> | ||
| #include <qgsgeometry.h> | ||
|
|
||
| class GEOSException | ||
| { | ||
| public: | ||
| GEOSException( const char *theMsg ) | ||
| { | ||
| if ( strcmp( theMsg, "Unknown exception thrown" ) == 0 && lastMsg ) | ||
| { | ||
| delete [] theMsg; | ||
| char *aMsg = new char[strlen( lastMsg )+1]; | ||
| strcpy( aMsg, lastMsg ); | ||
| msg = aMsg; | ||
| } | ||
| else | ||
| { | ||
| msg = theMsg; | ||
| lastMsg = msg; | ||
| } | ||
| } | ||
|
|
||
| // copy constructor | ||
| GEOSException( const GEOSException &rhs ) | ||
| { | ||
| *this = rhs; | ||
| } | ||
|
|
||
| ~GEOSException() | ||
| { | ||
| if ( lastMsg == msg ) | ||
| lastMsg = NULL; | ||
| delete [] msg; | ||
| } | ||
|
|
||
| const char *what() | ||
| { | ||
| return msg; | ||
| } | ||
|
|
||
| private: | ||
| const char *msg; | ||
| static const char *lastMsg; | ||
| }; | ||
|
|
||
| /** | ||
| * Checks whether two geometries touch each other | ||
| * @param g1 first geometry | ||
| * @param g2 second geometry | ||
| */ | ||
| bool geosTouches(QgsGeometry* g1, QgsGeometry* g2) | ||
| { | ||
| try | ||
| { | ||
| if (1 == GEOSTouches(g1->asGeos(), g2->asGeos())) | ||
| return true; | ||
| } | ||
| catch (GEOSException &e) | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Checks whether two geometries are identical in all respect(duplicates) | ||
| * @param g1 first geometry | ||
| * @param g2 second geometry | ||
| */ | ||
| bool geosEquals(QgsGeometry* g1, QgsGeometry* g2) | ||
| { | ||
| try | ||
| { | ||
| if (1 == GEOSEquals(g1->asGeos(), g2->asGeos())) | ||
| return true; | ||
| } | ||
| catch (GEOSException &e) | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
| /** | ||
| * Checks whether two geometries overlap | ||
| * @param g1 first geometry | ||
| * @param g2 second geometry | ||
| */ | ||
| bool geosOverlaps(QgsGeometry* g1, QgsGeometry* g2) | ||
| { | ||
| try | ||
| { | ||
| if (1 == GEOSOverlaps(g1->asGeos(), g2->asGeos())) | ||
| return true; | ||
| } | ||
| catch (GEOSException &e) | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Checks whether the first geometry contains the second geometry | ||
| * @param g1 first geometry | ||
| * @param g2 second geometry | ||
| */ | ||
| bool geosContains(QgsGeometry* g1, QgsGeometry* g2) | ||
| { | ||
| try | ||
| { | ||
| if (1 == GEOSContains(g1->asGeos(), g2->asGeos())) | ||
| return true; | ||
| } | ||
| catch (GEOSException &e) | ||
| { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,274 @@ | ||
| /*************************************************************************** | ||
| rulesDialog.cpp | ||
| TOPOLogy checker | ||
| ------------------- | ||
| date : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include <QtGui> | ||
|
|
||
| #include <qgsvectordataprovider.h> | ||
| #include <qgsvectorlayer.h> | ||
| //#include <qgssearchstring.h> | ||
| //#include <qgssearchtreenode.h> | ||
| #include <qgsmaplayer.h> | ||
| #include <qgsmaplayerregistry.h> | ||
|
|
||
| #include <qgsproviderregistry.h> | ||
| #include <qgslogger.h> | ||
| #include <qgisinterface.h> | ||
| #include <qgsproject.h> | ||
|
|
||
| //#include "../../app/qgisapp.h" | ||
|
|
||
| #include "rulesDialog.h" | ||
| #include "topolTest.h" | ||
|
|
||
| rulesDialog::rulesDialog( QList<QString> layerList, QMap<QString, TopologyRule> testMap, QgisInterface* theQgisIface, QWidget *parent ) | ||
| : QDialog( parent ), Ui::rulesDialog() | ||
| { | ||
| setupUi( this ); | ||
|
|
||
| mQgisIface = theQgisIface; | ||
|
|
||
| //setHorizontalHeaderItems(); | ||
| mTestTable->hideColumn( 4 ); | ||
| mTestTable->hideColumn( 5 ); | ||
|
|
||
| mTestConfMap = testMap; | ||
| mTestTable->setSelectionBehavior( QAbstractItemView::SelectRows ); | ||
| mTestBox->addItems( mTestConfMap.keys() ); | ||
|
|
||
| QgsMapLayerRegistry* layerRegistry = QgsMapLayerRegistry::instance(); | ||
|
|
||
| for ( int i = 0; i < layerList.size(); ++i ) | ||
| { | ||
| // add layer ID to the layerId list | ||
| mLayerIds << layerList[i]; | ||
|
|
||
| //QgsVectorLayer* v1 = ( QgsVectorLayer* )layerRegistry->mapLayers()[layerList[i]]; | ||
|
|
||
| // add layer name to the layer combo boxes | ||
| mLayer1Box->addItem((( QgsVectorLayer* )layerRegistry->mapLayers()[layerList[i]] )->name() ); | ||
| mLayer2Box->addItem((( QgsVectorLayer* )layerRegistry->mapLayers()[layerList[i]] )->name() ); | ||
| } | ||
|
|
||
| connect( mAddTestButton, SIGNAL( clicked() ), this, SLOT( addTest() ) ); | ||
| connect( mAddTestButton, SIGNAL( clicked() ), mTestTable, SLOT( resizeColumnsToContents() ) ); | ||
| // attempt to add new test when Ok clicked | ||
| connect( buttonBox, SIGNAL( accepted() ), this, SLOT( addTest() ) ); | ||
| connect( mDeleteTestButton, SIGNAL( clicked() ), this, SLOT( deleteTest() ) ); | ||
| connect( mTestBox, SIGNAL( currentIndexChanged( const QString& ) ), this, SLOT( showControls( const QString& ) ) ); | ||
| mTestBox->setCurrentIndex( 4 ); | ||
|
|
||
| //this resets this plugin up if a project is loaded | ||
| connect( mQgisIface->mainWindow(), SIGNAL( projectRead() ), this, SLOT( projectRead() ) ); | ||
| projectRead(); | ||
| } | ||
|
|
||
| rulesDialog::~rulesDialog() | ||
| { | ||
| } | ||
|
|
||
| void rulesDialog::setHorizontalHeaderItems() | ||
| { | ||
| QStringList labels; | ||
| labels << "Test" << "Layer #1" << "Layer #2" << "Tolerance" << "" << ""; | ||
| mTestTable->setHorizontalHeaderLabels( labels ); | ||
| } | ||
|
|
||
| void rulesDialog::readTest( int index, QgsMapLayerRegistry* layerRegistry ) | ||
| { | ||
| QString testName; | ||
| QString layer1Id; | ||
| QString layer2Id; | ||
| QString tolerance; | ||
| QgsProject* project = QgsProject::instance(); | ||
| QString postfix = QString( "%1" ).arg( index ); | ||
|
|
||
| testName = project->readEntry( "Topol", "/testname_" + postfix, "" ); | ||
| tolerance = project->readEntry( "Topol", "/tolerance_" + postfix, "" ); | ||
| layer1Id = project->readEntry( "Topol", "/layer1_" + postfix, "" ); | ||
| layer2Id = project->readEntry( "Topol", "/layer2_" + postfix, "" ); | ||
|
|
||
| QgsVectorLayer* l1; | ||
| if ( !( QgsVectorLayer* )layerRegistry->mapLayers().contains( layer1Id ) ) | ||
| return; | ||
|
|
||
| l1 = ( QgsVectorLayer* )layerRegistry->mapLayers()[layer1Id]; | ||
| if ( !l1 ) | ||
| return; | ||
|
|
||
| QString layer1Name = l1->name(); | ||
| QString layer2Name; | ||
| QgsVectorLayer* l2; | ||
|
|
||
| if ( mTestConfMap[testName].useSecondLayer ) | ||
| { | ||
| if ( !( QgsVectorLayer* )layerRegistry->mapLayers().contains( layer2Id ) ) | ||
| return; | ||
| else | ||
| { | ||
| l2 = ( QgsVectorLayer* )layerRegistry->mapLayers()[layer2Id]; | ||
| layer2Name = l2->name(); | ||
| } | ||
| } | ||
| else | ||
| layer2Name = "No layer"; | ||
|
|
||
| int row = index; | ||
| mTestTable->insertRow( row ); | ||
|
|
||
| QTableWidgetItem* newItem; | ||
| newItem = new QTableWidgetItem( testName ); | ||
| newItem->setFlags( newItem->flags() & ~Qt::ItemIsEditable ); | ||
| mTestTable->setItem( row, 0, newItem ); | ||
|
|
||
| newItem = new QTableWidgetItem( layer1Name ); | ||
| newItem->setFlags( newItem->flags() & ~Qt::ItemIsEditable ); | ||
| mTestTable->setItem( row, 1, newItem ); | ||
|
|
||
| newItem = new QTableWidgetItem( layer2Name ); | ||
| newItem->setFlags( newItem->flags() & ~Qt::ItemIsEditable ); | ||
| mTestTable->setItem( row, 2, newItem ); | ||
|
|
||
| if ( mTestConfMap[testName].useTolerance ) | ||
| newItem = new QTableWidgetItem( tolerance ); | ||
| else | ||
| newItem = new QTableWidgetItem( QString( "No tolerance" ) ); | ||
|
|
||
| newItem->setFlags( newItem->flags() & ~Qt::ItemIsEditable ); | ||
| mTestTable->setItem( row, 3, newItem ); | ||
|
|
||
| // add layer ids to hidden columns | ||
| newItem = new QTableWidgetItem( layer1Id ); | ||
| mTestTable->setItem( row, 4, newItem ); | ||
| newItem = new QTableWidgetItem( layer2Id ); | ||
| mTestTable->setItem( row, 5, newItem ); | ||
| } | ||
|
|
||
| void rulesDialog::projectRead() | ||
| { | ||
| QgsMapLayerRegistry* layerRegistry = QgsMapLayerRegistry::instance(); | ||
| int testCount = QgsProject::instance()->readNumEntry( "Topol", "/testCount" ); | ||
| mTestTable->clearContents(); | ||
|
|
||
| for ( int i = 0; i < testCount; ++i ) | ||
| readTest( i, layerRegistry ); | ||
| } | ||
|
|
||
| void rulesDialog::showControls( const QString& testName ) | ||
| { | ||
| mLayer2Box->setVisible( mTestConfMap[testName].useSecondLayer ); | ||
|
|
||
| bool useTolerance = mTestConfMap[testName].useTolerance; | ||
| mToleranceBox->setVisible( useTolerance ); | ||
| mToleranceLabel->setVisible( useTolerance ); | ||
| } | ||
|
|
||
| void rulesDialog::addLayer( QgsMapLayer* layer ) | ||
| { | ||
| mLayerIds << layer->id(); | ||
|
|
||
| // add layer name to the layer combo boxes | ||
| mLayer1Box->addItem( layer->name() ); | ||
| mLayer2Box->addItem( layer->name() ); | ||
| } | ||
|
|
||
| void rulesDialog::removeLayer( QString layerId ) | ||
| { | ||
| int index = mLayerIds.indexOf( layerId ); | ||
|
|
||
| mLayerIds.removeAt( index ); | ||
| // + 1 for "No layer" string | ||
| mLayer1Box->removeItem( index + 1 ); | ||
| mLayer2Box->removeItem( index + 1 ); | ||
|
|
||
| // TODO: Maybe tell the dock that we have no layers under | ||
| //if (mLayer1Box->size() == 1) do something | ||
| } | ||
|
|
||
| void rulesDialog::addTest() | ||
| { | ||
| //sanity checks | ||
| QString test = mTestBox->currentText(); | ||
| QString layer1 = mLayer1Box->currentText(); | ||
| if ( layer1 == "No layer" ) | ||
| return; | ||
|
|
||
| QString layer2 = mLayer2Box->currentText(); | ||
| if ( layer2 == "No layer" && mTestConfMap[test].useSecondLayer ) | ||
| return; | ||
|
|
||
| int row = mTestTable->rowCount(); | ||
| mTestTable->insertRow( row ); | ||
|
|
||
| QTableWidgetItem* newItem; | ||
| newItem = new QTableWidgetItem( test ); | ||
| mTestTable->setItem( row, 0, newItem ); | ||
| newItem = new QTableWidgetItem( layer1 ); | ||
| mTestTable->setItem( row, 1, newItem ); | ||
|
|
||
| if ( mTestConfMap[test].useSecondLayer ) | ||
| newItem = new QTableWidgetItem( layer2 ); | ||
| else | ||
| newItem = new QTableWidgetItem( "No layer" ); | ||
|
|
||
| mTestTable->setItem( row, 2, newItem ); | ||
|
|
||
| if ( mTestConfMap[test].useTolerance ) | ||
| newItem = new QTableWidgetItem( QString( "%1" ).arg( mToleranceBox->value() ) ); | ||
| else | ||
| newItem = new QTableWidgetItem( QString( "No tolerance" ) ); | ||
|
|
||
| mTestTable->setItem( row, 3, newItem ); | ||
|
|
||
| QString layer1ID, layer2ID; | ||
| // add layer ids to hidden columns | ||
| // -1 for "No layer" string | ||
| if ( mTestConfMap[test].useSecondLayer ) | ||
| layer2ID = mLayerIds[mLayer2Box->currentIndex() - 1]; | ||
| else | ||
| layer2ID = "No layer"; | ||
|
|
||
| layer1ID = mLayerIds[mLayer1Box->currentIndex() - 1]; | ||
|
|
||
| //TODO: use setItemData (or something like that) instead of hidden columns | ||
| newItem = new QTableWidgetItem( layer1ID ); | ||
| mTestTable->setItem( row, 4, newItem ); | ||
| newItem = new QTableWidgetItem( layer2ID ); | ||
| mTestTable->setItem( row, 5, newItem ); | ||
|
|
||
| // save state to the project file..... | ||
| QString postfix = QString( "%1" ).arg( row ); | ||
| QgsProject* project = QgsProject::instance(); | ||
|
|
||
| project->writeEntry( "Topol", "/testCount", row + 1 ); | ||
| project->writeEntry( "Topol", "/testname_" + postfix, test ); | ||
| project->writeEntry( "Topol", "/tolerance_" + postfix, QString( "%1" ).arg( mToleranceBox->value() ) ); | ||
| project->writeEntry( "Topol", "/layer1_" + postfix, layer1ID ); | ||
| project->writeEntry( "Topol", "/layer2_" + postfix, layer2ID ); | ||
|
|
||
| // reset controls to default | ||
| mTestBox->setCurrentIndex( 0 ); | ||
| mLayer1Box->setCurrentIndex( 0 ); | ||
| mLayer2Box->setCurrentIndex( 0 ); | ||
| mToleranceBox->setValue( 0 ); | ||
| } | ||
|
|
||
| void rulesDialog::deleteTest() | ||
| { | ||
| int row = mTestTable->currentRow(); | ||
| if ( 0 <= row && row < mTestTable->rowCount() ) | ||
| mTestTable->removeRow( row ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| /*************************************************************************** | ||
| rulesDialog.h | ||
| TOPOLogy checker | ||
| ------------------- | ||
| date : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef RULESDIALOG_H_ | ||
| #define RULESDIALOG_H_ | ||
|
|
||
| #include <QDialog> | ||
|
|
||
| #include <qgsvectorlayer.h> | ||
|
|
||
| #include "ui_rulesDialog.h" | ||
| #include "topolTest.h" | ||
|
|
||
| class QgisInterface; | ||
| class QgsMapLayerRegistry; | ||
|
|
||
| class rulesDialog : public QDialog, public Ui::rulesDialog | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| public: | ||
| /* | ||
| * Constructor | ||
| * @param layerList List of layer IDs | ||
| * @param testMap maps test names to test routines | ||
| * @param theQgisIface pointer to a QgisInterface instance | ||
| * @param parent parent widget | ||
| */ | ||
| rulesDialog( QList<QString> layerList, QMap<QString, TopologyRule> testMap, QgisInterface* theQgisIface, QWidget *parent ); | ||
| ~rulesDialog(); | ||
| /* | ||
| * Returns pointer to the test table | ||
| */ | ||
| QTableWidget* testTable() { return mTestTable; } | ||
| /* | ||
| * Returns pointer to the test combobox | ||
| */ | ||
| QComboBox* testBox() { return mTestBox; } | ||
|
|
||
| private: | ||
| QMap<QString, TopologyRule> mTestConfMap; | ||
| QList<QString> mLayerIds; | ||
| QgisInterface* mQgisIface; | ||
|
|
||
| /* | ||
| * Reads a test from the project | ||
| * @param index test index | ||
| * @param layerRegistry pointer to a QgsMapLayerRegistry instance | ||
| */ | ||
| void readTest( int index, QgsMapLayerRegistry* layerRegistry ); | ||
| /* | ||
| * Sets the horizontal header for tet table | ||
| */ | ||
| void setHorizontalHeaderItems(); | ||
|
|
||
| private slots: | ||
| /* | ||
| * Shows or hides controls according to test settings | ||
| * @param testName name of the test | ||
| */ | ||
| void showControls( const QString& testName ); | ||
| /* | ||
| * Adds test to the table | ||
| */ | ||
| void addTest(); | ||
| /* | ||
| * Deletes test from the table | ||
| */ | ||
| void deleteTest(); | ||
| /* | ||
| * Reads tests from the project | ||
| */ | ||
| void projectRead(); | ||
| /* | ||
| * Adds layer to layer comboboxes | ||
| * @param layer layer pointer | ||
| */ | ||
| void addLayer( QgsMapLayer* layer ); | ||
| /* | ||
| * Deletes layer to layer comboboxes | ||
| * @param layerId layer ID | ||
| */ | ||
| void removeLayer( QString layerId ); | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <ui version="4.0"> | ||
| <class>rulesDialog</class> | ||
| <widget class="QDialog" name="rulesDialog"> | ||
| <property name="geometry"> | ||
| <rect> | ||
| <x>0</x> | ||
| <y>0</y> | ||
| <width>739</width> | ||
| <height>545</height> | ||
| </rect> | ||
| </property> | ||
| <property name="windowTitle"> | ||
| <string>Test settings</string> | ||
| </property> | ||
| <layout class="QGridLayout" name="gridLayout"> | ||
| <item row="0" column="0"> | ||
| <layout class="QVBoxLayout" name="verticalLayout"> | ||
| <item> | ||
| <widget class="QLabel" name="label"> | ||
| <property name="text"> | ||
| <string>Current Rules</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QTableWidget" name="mTestTable"> | ||
| <column> | ||
| <property name="text"> | ||
| <string>Rule</string> | ||
| </property> | ||
| </column> | ||
| <column> | ||
| <property name="text"> | ||
| <string>Layer #1</string> | ||
| </property> | ||
| </column> | ||
| <column> | ||
| <property name="text"> | ||
| <string>Layer #2</string> | ||
| </property> | ||
| </column> | ||
| <column> | ||
| <property name="text"> | ||
| <string>Tolerance</string> | ||
| </property> | ||
| </column> | ||
| <column> | ||
| <property name="text"> | ||
| <string>Layer1ID</string> | ||
| </property> | ||
| </column> | ||
| <column> | ||
| <property name="text"> | ||
| <string>Layer2ID</string> | ||
| </property> | ||
| </column> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| <item> | ||
| <widget class="QComboBox" name="mTestBox"> | ||
| <property name="sizeAdjustPolicy"> | ||
| <enum>QComboBox::AdjustToContents</enum> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QComboBox" name="mLayer1Box"> | ||
| <property name="sizeAdjustPolicy"> | ||
| <enum>QComboBox::AdjustToContents</enum> | ||
| </property> | ||
| <item> | ||
| <property name="text"> | ||
| <string>No layer</string> | ||
| </property> | ||
| </item> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QComboBox" name="mLayer2Box"> | ||
| <property name="sizeAdjustPolicy"> | ||
| <enum>QComboBox::AdjustToContents</enum> | ||
| </property> | ||
| <item> | ||
| <property name="text"> | ||
| <string>No layer</string> | ||
| </property> | ||
| </item> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <spacer name="horizontalSpacer_2"> | ||
| <property name="orientation"> | ||
| <enum>Qt::Horizontal</enum> | ||
| </property> | ||
| <property name="sizeHint" stdset="0"> | ||
| <size> | ||
| <width>40</width> | ||
| <height>20</height> | ||
| </size> | ||
| </property> | ||
| </spacer> | ||
| </item> | ||
| <item> | ||
| <widget class="QLabel" name="mToleranceLabel"> | ||
| <property name="text"> | ||
| <string>Tolerance</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QDoubleSpinBox" name="mToleranceBox"/> | ||
| </item> | ||
| </layout> | ||
| </item> | ||
| <item> | ||
| <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| <item> | ||
| <widget class="QPushButton" name="mAddTestButton"> | ||
| <property name="text"> | ||
| <string>Add New Rule</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <widget class="QPushButton" name="mDeleteTestButton"> | ||
| <property name="text"> | ||
| <string>Delete Rule</string> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| <item> | ||
| <spacer name="horizontalSpacer"> | ||
| <property name="orientation"> | ||
| <enum>Qt::Horizontal</enum> | ||
| </property> | ||
| <property name="sizeHint" stdset="0"> | ||
| <size> | ||
| <width>198</width> | ||
| <height>20</height> | ||
| </size> | ||
| </property> | ||
| </spacer> | ||
| </item> | ||
| <item> | ||
| <widget class="QDialogButtonBox" name="buttonBox"> | ||
| <property name="orientation"> | ||
| <enum>Qt::Horizontal</enum> | ||
| </property> | ||
| <property name="standardButtons"> | ||
| <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> | ||
| </property> | ||
| </widget> | ||
| </item> | ||
| </layout> | ||
| </item> | ||
| </layout> | ||
| </item> | ||
| </layout> | ||
| </widget> | ||
| <resources/> | ||
| <connections> | ||
| <connection> | ||
| <sender>buttonBox</sender> | ||
| <signal>accepted()</signal> | ||
| <receiver>rulesDialog</receiver> | ||
| <slot>accept()</slot> | ||
| <hints> | ||
| <hint type="sourcelabel"> | ||
| <x>506</x> | ||
| <y>369</y> | ||
| </hint> | ||
| <hint type="destinationlabel"> | ||
| <x>289</x> | ||
| <y>194</y> | ||
| </hint> | ||
| </hints> | ||
| </connection> | ||
| <connection> | ||
| <sender>buttonBox</sender> | ||
| <signal>rejected()</signal> | ||
| <receiver>rulesDialog</receiver> | ||
| <slot>reject()</slot> | ||
| <hints> | ||
| <hint type="sourcelabel"> | ||
| <x>506</x> | ||
| <y>369</y> | ||
| </hint> | ||
| <hint type="destinationlabel"> | ||
| <x>289</x> | ||
| <y>194</y> | ||
| </hint> | ||
| </hints> | ||
| </connection> | ||
| </connections> | ||
| </ui> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| /*************************************************************************** | ||
| topol.cpp | ||
| TOPOLogy checker | ||
| ------------------- | ||
| begin : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| // QGIS Specific includes | ||
| #include <qgsmaplayer.h> | ||
| #include <qgsapplication.h> | ||
| #include <qgisinterface.h> | ||
| #include <qgisgui.h> | ||
|
|
||
| // Qt4 Related Includes | ||
| #include <QAction> | ||
| #include <QToolBar> | ||
| #include <QFile> | ||
| #include <QMessageBox> | ||
|
|
||
| #include "topol.h" | ||
| #include "checkDock.h" | ||
|
|
||
| static const char * const sIdent = "$Id: plugin.cpp 8053 2008-01-26 13:59:53Z timlinux $"; | ||
| static const QString sName = QObject::tr( "Topology Checker" ); | ||
| static const QString sDescription = QObject::tr( "A Plugin for finding topological errors in vector layers" ); | ||
| static const QString sCategory = QObject::tr( "Vector" ); | ||
| static const QString sPluginVersion = QObject::tr( "Version 0.1" ); | ||
| static const QgisPlugin::PLUGINTYPE sPluginType = QgisPlugin::UI; | ||
| static const QString sPluginIcon = ":/topology/topol.png"; | ||
|
|
||
| ////////////////////////////////////////////////////////////////////// | ||
| // | ||
| // THE FOLLOWING METHODS ARE MANDATORY FOR ALL PLUGINS | ||
| // | ||
| ////////////////////////////////////////////////////////////////////// | ||
|
|
||
| /** | ||
| * Constructor for the plugin. The plugin is passed a pointer | ||
| * an interface object that provides access to exposed functions in QGIS. | ||
| * @param theQGisInterface - Pointer to the QGIS interface object | ||
| */ | ||
| Topol::Topol( QgisInterface * theQgisInterface ): | ||
| QgisPlugin( sName, sDescription, sCategory, sPluginVersion, sPluginType ), | ||
| mQGisIface( theQgisInterface ) | ||
| { | ||
| mDock = 0; | ||
| } | ||
|
|
||
| Topol::~Topol() | ||
| { | ||
| } | ||
|
|
||
| /* | ||
| * Initialize the GUI interface for the plugin - this is only called once when the plugin is | ||
| * added to the plugin registry in the QGIS application. | ||
| */ | ||
| void Topol::initGui() | ||
| { | ||
| mQActionPointer = new QAction( QIcon( ":/topology/topol.png" ), tr( "TopologyChecker" ), this ); | ||
| //mQActionPointer = new QAction( QIcon(), tr( "Topology Checker" ), this ); | ||
| mQActionPointer->setCheckable( true ); | ||
|
|
||
|
|
||
| // Create the action for tool | ||
| //mQActionPointer = new QAction(QIcon(":/topol_c/topol.png"),tr("Topology Checker"), this); | ||
| // Set the what's this text | ||
| mQActionPointer->setWhatsThis( tr( "Topology Checker for vector layer" ) ); | ||
| // Connect the action to the run | ||
| connect( mQActionPointer, SIGNAL( triggered() ), this, SLOT( showOrHide() ) ); | ||
| // Add the icon to the toolbar | ||
| mQGisIface->addToolBarIcon( mQActionPointer ); | ||
| mQGisIface->addPluginToMenu( tr( "&Topol" ), mQActionPointer ); | ||
| //run(); | ||
| } | ||
| //method defined in interface | ||
| void Topol::help() | ||
| { | ||
| //implement me! | ||
| } | ||
|
|
||
| void Topol::showOrHide() | ||
| { | ||
| if ( !mDock ) | ||
| run(); | ||
| else | ||
| if ( mQActionPointer->isChecked() ) | ||
| mDock->show(); | ||
| else | ||
| mDock->hide(); | ||
| } | ||
|
|
||
| // Slot called when the menu item is triggered | ||
| // If you created more menu items / toolbar buttons in initiGui, you should | ||
| // create a separate handler for each action - this single run() method will | ||
| // not be enough | ||
| void Topol::run() | ||
| { | ||
| mDock = new checkDock( mQGisIface ); | ||
| mQGisIface->addDockWidget( Qt::RightDockWidgetArea, mDock ); | ||
| connect( mDock, SIGNAL( visibilityChanged( bool ) ), mQActionPointer, SLOT( setChecked( bool ) ) ); | ||
| //mDock->show(); | ||
| } | ||
|
|
||
| // Unload the plugin by cleaning up the GUI | ||
| void Topol::unload() | ||
| { | ||
| // remove the GUI | ||
| mQGisIface->removePluginMenu( "&Topol", mQActionPointer ); | ||
| mQGisIface->removeToolBarIcon( mQActionPointer ); | ||
| delete mQActionPointer; | ||
| } | ||
|
|
||
| ////////////////////////////////////////////////////////////////////////// | ||
| // | ||
| // | ||
| // THE FOLLOWING CODE IS AUTOGENERATED BY THE PLUGIN BUILDER SCRIPT | ||
| // YOU WOULD NORMALLY NOT NEED TO MODIFY THIS, AND YOUR PLUGIN | ||
| // MAY NOT WORK PROPERLY IF YOU MODIFY THIS INCORRECTLY | ||
| // | ||
| // | ||
| ////////////////////////////////////////////////////////////////////////// | ||
|
|
||
|
|
||
| /** | ||
| * Required extern functions needed for every plugin | ||
| * These functions can be called prior to creating an instance | ||
| * of the plugin class | ||
| */ | ||
| // Class factory to return a new instance of the plugin class | ||
| QGISEXTERN QgisPlugin * classFactory( QgisInterface * theQgisInterfacePointer ) | ||
| { | ||
| return new Topol( theQgisInterfacePointer ); | ||
| } | ||
| // Return the name of the plugin - note that we do not user class members as | ||
| // the class may not yet be insantiated when this method is called. | ||
| QGISEXTERN QString name() | ||
| { | ||
| return sName; | ||
| } | ||
|
|
||
| // Return the description | ||
| QGISEXTERN QString description() | ||
| { | ||
| return sDescription; | ||
| } | ||
|
|
||
| // Return the type (either UI or MapLayer plugin) | ||
| QGISEXTERN int type() | ||
| { | ||
| return sPluginType; | ||
| } | ||
|
|
||
| // Return the version number for the plugin | ||
| QGISEXTERN QString version() | ||
| { | ||
| return sPluginVersion; | ||
| } | ||
|
|
||
| QGISEXTERN QString icon() | ||
| { | ||
| return sPluginIcon; | ||
| } | ||
|
|
||
| // Delete ourself | ||
| QGISEXTERN void unload( QgisPlugin * thePluginPointer ) | ||
| { | ||
| delete thePluginPointer; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| /*************************************************************************** | ||
| topol.h | ||
| ------------------- | ||
| begin : Jan 21, 2004 | ||
| copyright : (C) 2004 by Tim Sutton | ||
| email : tim@linfiniti.com | ||
| ***************************************************************************/ | ||
|
|
||
| /*************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
| /* $Id: plugin.h 7796 2007-12-16 22:11:38Z homann $ */ | ||
| /*************************************************************************** | ||
| * QGIS Programming conventions: | ||
| * | ||
| * mVariableName - a class level member variable | ||
| * sVariableName - a static class level member variable | ||
| * variableName() - accessor for a class member (no 'get' in front of name) | ||
| * setVariableName() - mutator for a class member (prefix with 'set') | ||
| * | ||
| * Additional useful conventions: | ||
| * | ||
| * theVariableName - a method parameter (prefix with 'the') | ||
| * myVariableName - a locally declared variable within a method ('my' prefix) | ||
| * | ||
| * DO: Use mixed case variable names - myVariableName | ||
| * DON'T: separate variable names using underscores: my_variable_name (NO!) | ||
| * | ||
| * **************************************************************************/ | ||
| #ifndef TOPOL_H | ||
| #define TOPOL_H | ||
|
|
||
| //QT4 includes | ||
| #include <QObject> | ||
|
|
||
| //QGIS includes | ||
| #include "../qgisplugin.h" | ||
|
|
||
| //forward declarations | ||
| class QAction; | ||
| class QToolBar; | ||
|
|
||
| class QgisInterface; | ||
| class checkDock; | ||
|
|
||
| /** | ||
| * \class Plugin | ||
| * \brief [name] plugin for QGIS | ||
| * [description] | ||
| */ | ||
| class Topol:public QObject, public QgisPlugin | ||
| { | ||
| Q_OBJECT; | ||
| public: | ||
|
|
||
| ////////////////////////////////////////////////////////////////////// | ||
| // | ||
| // MANDATORY PLUGIN METHODS FOLLOW | ||
| // | ||
| ////////////////////////////////////////////////////////////////////// | ||
|
|
||
| /** | ||
| * Constructor for a plugin. The QgisInterface pointer is passed by | ||
| * QGIS when it attempts to instantiate the plugin. | ||
| * @param theInterface Pointer to the QgisInterface object. | ||
| */ | ||
| Topol(QgisInterface * theInterface); | ||
| //! Destructor | ||
| virtual ~Topol(); | ||
|
|
||
| public slots: | ||
| //! init the gui | ||
| virtual void initGui(); | ||
| //! Create and show the dialog box | ||
| void run(); | ||
| //! Show/hide the dialog box | ||
| void showOrHide(); | ||
| //! unload the plugin | ||
| void unload(); | ||
| //! show the help document | ||
| void help(); | ||
|
|
||
| private: | ||
|
|
||
| //////////////////////////////////////////////////////////////////// | ||
| // | ||
| // MANDATORY PLUGIN PROPERTY DECLARATIONS ..... | ||
| // | ||
| //////////////////////////////////////////////////////////////////// | ||
|
|
||
| int mPluginType; | ||
| //! Pointer to the QGIS interface object | ||
| QgisInterface *mQGisIface; | ||
| //!pointer to the qaction for this plugin | ||
| QAction * mQActionPointer; | ||
| checkDock* mDock; | ||
|
|
||
| //////////////////////////////////////////////////////////////////// | ||
| // | ||
| // ADD YOUR OWN PROPERTY DECLARATIONS AFTER THIS POINT..... | ||
| // | ||
| //////////////////////////////////////////////////////////////////// | ||
| }; | ||
|
|
||
| #endif //Topol_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| <RCC> | ||
| <qresource prefix="/topology" > | ||
| <file>topol.png</file> | ||
| <file>configureRules.png</file> | ||
| <file>validateAll.png</file> | ||
| <file>validateExtent.png</file> | ||
| </qresource> | ||
| </RCC> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,229 @@ | ||
| /*************************************************************************** | ||
| topolError.h | ||
| TOPOLogy checker | ||
| ------------------- | ||
| date : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #include "topolError.h" | ||
|
|
||
| //TODO: tell dock to parse errorlist when feature is deleted | ||
| bool TopolError::fix( QString fixName ) | ||
| { | ||
| std::cout << "fix: \"" << fixName.toStdString() << "\"\n"; | ||
| ( this->*mFixMap[fixName] )(); | ||
| } | ||
|
|
||
| bool TopolError::fixMove( FeatureLayer fl1, FeatureLayer fl2 ) | ||
| { | ||
| bool ok; | ||
| QgsFeature f1, f2; | ||
|
|
||
| ok = fl1.layer->getFeatures( QgsFeatureRequest().setFilterFid( fl1.feature.id() ) ).nextFeature( f1 ); | ||
| ok = ok && fl2.layer->getFeatures(( QgsFeatureRequest().setFilterFid( fl2.feature.id() ) ) ).nextFeature( f2 ); | ||
|
|
||
| if ( !ok ) | ||
| return false; | ||
|
|
||
|
|
||
| QgsGeometry* g2, *g1 = f1.geometry(); | ||
| // 0 means success | ||
| if ( !f1.geometry()->makeDifference( f2.geometry() ) ) | ||
| return fl1.layer->changeGeometry( f1.id(), f1.geometry() ); | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| bool TopolError::fixMoveFirst() | ||
| { | ||
| return fixMove( mFeaturePairs.first(), mFeaturePairs[1] ); | ||
| } | ||
|
|
||
| bool TopolError::fixMoveSecond() | ||
| { | ||
| return fixMove( mFeaturePairs[1], mFeaturePairs.first() ); | ||
| } | ||
|
|
||
| bool TopolError::fixUnion( FeatureLayer fl1, FeatureLayer fl2 ) | ||
| { | ||
| bool ok; | ||
| QgsFeature f1, f2; | ||
|
|
||
| ok = fl1.layer->getFeatures( QgsFeatureRequest().setFilterFid( fl1.feature.id() ) ).nextFeature( f1 ); | ||
| ok = ok && fl2.layer->getFeatures(( QgsFeatureRequest().setFilterFid( fl2.feature.id() ) ) ).nextFeature( f2 ); | ||
|
|
||
| if ( !ok ) | ||
| return false; | ||
|
|
||
| QgsGeometry* g = f1.geometry()->combine( f2.geometry() ); | ||
| if ( !g ) | ||
| return false; | ||
|
|
||
| if ( fl2.layer->deleteFeature( f2.id() ) ) | ||
| return fl1.layer->changeGeometry( f1.id(), g ); | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| bool TopolError::fixSnap() | ||
| { | ||
| bool ok; | ||
| QgsFeature f1, f2; | ||
| FeatureLayer fl = mFeaturePairs[1]; | ||
| ok = fl.layer->getFeatures(( QgsFeatureRequest().setFilterFid( fl.feature.id() ) ) ).nextFeature( f2 ); | ||
| fl = mFeaturePairs.first(); | ||
| ok = ok && fl.layer->getFeatures( QgsFeatureRequest().setFilterFid( fl.feature.id() ) ).nextFeature( f1 ); | ||
|
|
||
| if ( !ok ) | ||
| return false; | ||
|
|
||
| QgsGeometry* ge = f1.geometry(); | ||
|
|
||
| QgsPolyline line = ge->asPolyline(); | ||
| line.last() = mConflict->asPolyline().last(); | ||
|
|
||
| QgsGeometry* newG = QgsGeometry::fromPolyline( line ); | ||
| bool ret = fl.layer->changeGeometry( f1.id(), newG ); | ||
| delete newG; | ||
|
|
||
| return ret; | ||
| } | ||
|
|
||
| bool TopolError::fixUnionFirst() | ||
| { | ||
| return fixUnion( mFeaturePairs.first(), mFeaturePairs[1] ); | ||
| } | ||
|
|
||
| bool TopolError::fixUnionSecond() | ||
| { | ||
| return fixUnion( mFeaturePairs[1], mFeaturePairs.first() ); | ||
| } | ||
|
|
||
| bool TopolError::fixDeleteFirst() | ||
| { | ||
| FeatureLayer fl = mFeaturePairs.first(); | ||
| return fl.layer->deleteFeature( fl.feature.id() ); | ||
| } | ||
|
|
||
| bool TopolError::fixDeleteSecond() | ||
| { | ||
| FeatureLayer fl = mFeaturePairs[1]; | ||
| return fl.layer->deleteFeature( fl.feature.id() ); | ||
| } | ||
|
|
||
| TopolError::TopolError( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ): | ||
| mFeaturePairs( theFeaturePairs ), | ||
| mBoundingBox( theBoundingBox ), | ||
| mConflict( theConflict ) | ||
| { | ||
| mFixMap["Select automatic fix"] = &TopolError::fixDummy; | ||
| } | ||
|
|
||
| TopolErrorIntersection::TopolErrorIntersection( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "intersecting geometries"; | ||
|
|
||
| mFixMap["Move blue feature"] = &TopolErrorIntersection::fixMoveFirst; | ||
| mFixMap["Move red feature"] = &TopolErrorIntersection::fixMoveSecond; | ||
| mFixMap["Delete blue feature"] = &TopolErrorIntersection::fixDeleteFirst; | ||
| mFixMap["Delete red feature"] = &TopolErrorIntersection::fixDeleteSecond; | ||
|
|
||
| // allow union only when both features have the same geometry type | ||
| if ( theFeaturePairs.first().feature.geometry()->type() == theFeaturePairs[1].feature.geometry()->type() ) | ||
| { | ||
| mFixMap["Union to blue feature"] = &TopolErrorIntersection::fixUnionFirst; | ||
| mFixMap["Union to red feature"] = &TopolErrorIntersection::fixUnionSecond; | ||
| } | ||
| } | ||
|
|
||
| TopolErrorClose::TopolErrorClose( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "features too close"; | ||
|
|
||
| mFixMap["Move blue feature"] = &TopolErrorClose::fixMoveFirst; | ||
| mFixMap["Move red feature"] = &TopolErrorClose::fixMoveSecond; | ||
| mFixMap["Snap to segment"] = &TopolErrorClose::fixSnap; | ||
| } | ||
|
|
||
| TopolErrorCovered::TopolErrorCovered( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "point not covered by segment"; | ||
| mFixMap["Delete point"] = &TopolErrorCovered::fixDeleteFirst; | ||
| } | ||
|
|
||
| TopolErrorShort::TopolErrorShort( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "segment too short"; | ||
| mFixMap["Delete feature"] = &TopolErrorShort::fixDeleteFirst; | ||
| } | ||
|
|
||
| TopolErrorValid::TopolErrorValid( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "invalid geometry"; | ||
| mFixMap["Delete feature"] = &TopolErrorValid::fixDeleteFirst; | ||
| } | ||
|
|
||
| TopolErrorDangle::TopolErrorDangle( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "dangling end"; | ||
| mFixMap["Delete feature"] = &TopolErrorDangle::fixDeleteFirst; | ||
| } | ||
|
|
||
| TopolErrorDuplicates::TopolErrorDuplicates( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "duplicate geometry"; | ||
| //mFixMap["Delete feature"] = &TopolErrorDuplicates::fixDeleteFirst; | ||
| } | ||
|
|
||
| TopolErrorPseudos::TopolErrorPseudos( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "pseudo node"; | ||
| //mFixMap["Delete feature"] = &TopolErrorDuplicates::fixDeleteFirst; | ||
| } | ||
|
|
||
| TopolErrorOverlaps::TopolErrorOverlaps( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "overlaps"; | ||
| //mFixMap["Delete feature"] = &TopolErrorDuplicates::fixDeleteFirst; | ||
| } | ||
|
|
||
| TopolErrorGaps::TopolErrorGaps( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "gaps"; | ||
| //mFixMap["Delete feature"] = &TopolErrorDuplicates::fixDeleteFirst; | ||
| } | ||
|
|
||
| TopolErrorPointNotCoveredByLineEnds::TopolErrorPointNotCoveredByLineEnds( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "point not covered"; | ||
| } | ||
|
|
||
| TopolErrorLineEndsNotCoveredByPoints::TopolErrorLineEndsNotCoveredByPoints( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "line ends not covered by point"; | ||
| } | ||
|
|
||
| TopolErrorPointNotInPolygon::TopolErrorPointNotInPolygon( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "point not in polygon"; | ||
| } | ||
|
|
||
| TopolErrorPolygonContainsPoint::TopolErrorPolygonContainsPoint( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "polygon does not contain point"; | ||
| } | ||
|
|
||
| TopolErroMultiPart::TopolErroMultiPart( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ) : TopolError( theBoundingBox, theConflict, theFeaturePairs ) | ||
| { | ||
| mName = "multipart feature"; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,233 @@ | ||
| /*************************************************************************** | ||
| topolError.h | ||
| TOPOLogy checker | ||
| ------------------- | ||
| begin : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef TOPOLERROR_H | ||
| #define TOPOLERROR_H | ||
|
|
||
| #include <qgsvectorlayer.h> | ||
| #include <qgsgeometry.h> | ||
| #include <qgsrectangle.h> | ||
|
|
||
| class TopolError; | ||
| typedef QList<TopolError*> ErrorList; | ||
| typedef bool ( TopolError::*fixFunction )(); | ||
|
|
||
| class FeatureLayer | ||
| { | ||
| public: | ||
| FeatureLayer() : | ||
| layer( 0 ), feature( QgsFeature() ) {}; | ||
| /** | ||
| * Constructor | ||
| * @param theLayer layer pointer | ||
| * @param theFeature QgsFeature | ||
| */ | ||
| FeatureLayer( QgsVectorLayer* theLayer, QgsFeature theFeature ) : | ||
| layer( theLayer ), feature( theFeature ) {}; | ||
|
|
||
| QgsVectorLayer* layer; | ||
| QgsFeature feature; | ||
| }; | ||
|
|
||
| class TopolError | ||
| { | ||
| protected: | ||
| QString mName; | ||
| QgsRectangle mBoundingBox; | ||
| QgsGeometry* mConflict; | ||
| QList<FeatureLayer> mFeaturePairs; | ||
| QMap<QString, fixFunction> mFixMap; | ||
|
|
||
| /** | ||
| * A dummy fix - does nothing | ||
| */ | ||
| bool fixDummy() { return false; } | ||
| /** | ||
| * Snaps to a feature | ||
| */ | ||
| bool fixSnap(); | ||
| /** | ||
| * Moves first feature | ||
| */ | ||
| bool fixMoveFirst(); | ||
| /** | ||
| * Moves second feature | ||
| */ | ||
| bool fixMoveSecond(); | ||
| /** | ||
| * Unions features to the first | ||
| */ | ||
| bool fixUnionFirst(); | ||
| /** | ||
| * Unions features to the first | ||
| */ | ||
| bool fixUnionSecond(); | ||
| /** | ||
| * Deletes first feature | ||
| */ | ||
| bool fixDeleteFirst(); | ||
| /** | ||
| * Deletes second feature | ||
| */ | ||
| bool fixDeleteSecond(); | ||
|
|
||
| //helper fix functions | ||
|
|
||
| /** | ||
| * Makes geometry difference | ||
| * @param fl1 first FeatureLayer pair | ||
| * @param fl2 second FeatureLayer pair | ||
| */ | ||
| bool fixMove( FeatureLayer fl1, FeatureLayer fl2 ); | ||
| /** | ||
| * Unions features to the first one | ||
| * @param fl1 first FeatureLayer pair | ||
| * @param fl2 second FeatureLayer pair | ||
| */ | ||
| bool fixUnion( FeatureLayer fl1, FeatureLayer fl2 ); | ||
|
|
||
| public: | ||
| /** | ||
| * Constructor | ||
| * @param theBoundingBox bounding box of the two features | ||
| * @param theConflict geometry representation of the conflict | ||
| * @param theFeaturePairs FeatureLayer pairs of the two features | ||
| */ | ||
| TopolError( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
|
|
||
| /** | ||
| * Destructor | ||
| */ | ||
| virtual ~TopolError() { delete mConflict; } | ||
| /** | ||
| * Runs fixing function | ||
| * @param fixName name of the fix | ||
| */ | ||
| virtual bool fix( QString fixName ); | ||
| /** | ||
| * Returns error's name | ||
| */ | ||
| virtual QString name() { return mName; } | ||
| /** | ||
| * Returns topology conflict | ||
| */ | ||
| virtual QgsGeometry* conflict() { return mConflict; } | ||
| /** | ||
| * Returns bounding box of the error | ||
| */ | ||
| virtual QgsRectangle boundingBox() { return mBoundingBox; } | ||
| /** | ||
| * Returns FeatureLayer pairs from the error | ||
| */ | ||
| virtual QList<FeatureLayer> featurePairs() { return mFeaturePairs; } | ||
| /** | ||
| * Returns the names of posible fixes | ||
| */ | ||
| virtual QStringList fixNames() { return mFixMap.keys(); } | ||
| }; | ||
|
|
||
| class TopolErrorIntersection : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorIntersection( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorClose : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorClose( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorCovered : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorCovered( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorShort : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorShort( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorValid : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorValid( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorDangle : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorDangle( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorDuplicates : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorDuplicates( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorPseudos : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorPseudos( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorOverlaps : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorOverlaps( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorGaps : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorGaps( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorPointNotCoveredByLineEnds : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorPointNotCoveredByLineEnds( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorLineEndsNotCoveredByPoints : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorLineEndsNotCoveredByPoints( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorPointNotInPolygon : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorPointNotInPolygon( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErrorPolygonContainsPoint : public TopolError | ||
| { | ||
| public: | ||
| TopolErrorPolygonContainsPoint( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| class TopolErroMultiPart : public TopolError | ||
| { | ||
| public: | ||
| TopolErroMultiPart( QgsRectangle theBoundingBox, QgsGeometry* theConflict, QList<FeatureLayer> theFeaturePairs ); | ||
| }; | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,280 @@ | ||
| /*************************************************************************** | ||
| topolTest.h | ||
| TOPOLogy checker | ||
| ------------------- | ||
| date : May 2009 | ||
| copyright : Vita Cizek | ||
| email : weetya (at) gmail.com | ||
| *************************************************************************** | ||
| * * | ||
| * This program is free software; you can redistribute it and/or modify * | ||
| * it under the terms of the GNU General Public License as published by * | ||
| * the Free Software Foundation; either version 2 of the License, or * | ||
| * (at your option) any later version. * | ||
| * * | ||
| ***************************************************************************/ | ||
|
|
||
| #ifndef TOPOLTEST_H | ||
| #define TOPOLTEST_H | ||
|
|
||
| #include <QObject> | ||
|
|
||
| #include <qgsvectorlayer.h> | ||
| #include <qgsgeometry.h> | ||
| #include "qgsspatialindex.h" | ||
|
|
||
| #include "topolError.h" | ||
|
|
||
| class topolTest; | ||
| class QgisInterface; | ||
| class WKTReader; | ||
|
|
||
| enum ValidateType { ValidateAll, ValidateExtent, ValidateSelected }; | ||
|
|
||
| typedef ErrorList( topolTest::*testFunction )( double, QgsVectorLayer*, QgsVectorLayer*,bool ); | ||
|
|
||
| class TopologyRule | ||
| { | ||
| public: | ||
| bool useSecondLayer; | ||
| bool useTolerance; | ||
| bool useSpatialIndex; | ||
| testFunction f; | ||
|
|
||
| /** | ||
| * Constructor | ||
| * initializes the test to use both layers and not to use the tolerance | ||
| */ | ||
| TopologyRule() | ||
| { | ||
| useSecondLayer = true; | ||
| useTolerance = false; | ||
| f = 0; | ||
| } | ||
| }; | ||
|
|
||
| /** | ||
| helper class to pass as comparator to map,set etc.. | ||
| */ | ||
| class PointComparer | ||
| { | ||
| public: | ||
| bool operator()( QgsPoint p1, QgsPoint p2 )const | ||
| { | ||
| if ( p1.x() < p2.x() ) | ||
| { | ||
| return true; | ||
| } | ||
|
|
||
| if ( p1.x() == p2.x() ) | ||
| { | ||
| if ( p1.y() < p2.y() ) | ||
| { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
| }; | ||
|
|
||
|
|
||
| class topolTest: public QObject | ||
| { | ||
| Q_OBJECT | ||
|
|
||
| public: | ||
| topolTest( QgisInterface* qgsIface ); | ||
| ~topolTest(); | ||
|
|
||
| /** | ||
| * Returns copy of the test map | ||
| */ | ||
| QMap<QString, TopologyRule> testMap() { return mTopologyRuleMap; } | ||
| /** | ||
| * Runs the test and returns all found errors | ||
| * @param testName name of the test | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 pointer to the second layer | ||
| * @param type type what features to validate | ||
| * @param tolerance possible tolerance | ||
| */ | ||
| ErrorList runTest( QString testName, QgsVectorLayer* layer1, QgsVectorLayer* layer2, ValidateType type, double tolerance ); | ||
|
|
||
| /** | ||
| * Checks for intersections of the two layers | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 pointer to the second layer | ||
| */ | ||
| ErrorList checkOverlapWithLayer( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2 , bool isExtent); | ||
| /** | ||
| * Checks for self-intersections in the layer | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| ErrorList checkSelfIntersections( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
| /** | ||
| * Checks for features that are too close | ||
| * @param tolerance allowed tolerance | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 pointer to the second layer | ||
| */ | ||
| ErrorList checkCloseFeature( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
| /** | ||
| * Checks for short segments | ||
| * @param tolerance tolerance - not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 pointer to the second layer | ||
| */ | ||
| ErrorList checkSegmentLength( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
| /** | ||
| * Checks for dangling lines | ||
| * @param tolerance allowed tolerance | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| ErrorList checkDanglingLines( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2 , bool isExtent); | ||
| /** | ||
| * Checks for points not covered by any segment | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 pointer to the second layer | ||
| */ | ||
| ErrorList checkPointCoveredBySegment( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
| /** | ||
| * Checks for invalid geometries | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| ErrorList checkValid( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for duplicate geometries | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| ErrorList checkDuplicates( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for pseudo nodes | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| ErrorList checkPseudos( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for overlaps of polygons from same layer | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| ErrorList checkOverlaps( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for gaps among polygons from same layer | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| ErrorList checkGaps( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for points form one layer that are not covered by line ends form another layer | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first point layer | ||
| * @param layer2 pointer to the second line layer | ||
| */ | ||
| ErrorList checkPointCoveredByLineEnds( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for points that are not inside any polygons from another layer | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first point layer | ||
| * @param layer2 pointer to the second polygon layer | ||
| */ | ||
| ErrorList checkPointInPolygon( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2, bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for polygons that do not contain any points form another layer | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first polygon layer | ||
| * @param layer2 pointer to the second point layer | ||
| */ | ||
| ErrorList checkPolygonContainsPoint( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2,bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for multipart features | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| ErrorList checkMultipart( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2,bool isExtent ); | ||
|
|
||
| /** | ||
| * Checks for line features that do not have both ends covered by points from another layer | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first linelayer | ||
| * @param layer2 pointer to the second point layer | ||
| */ | ||
| ErrorList checkyLineEndsCoveredByPoints( double tolerance, QgsVectorLayer* layer1, QgsVectorLayer* layer2,bool isExtent ); | ||
|
|
||
|
|
||
| public slots: | ||
| /** | ||
| * Checks for invalid geometries | ||
| * @param tolerance not used | ||
| * @param layer1 pointer to the first layer | ||
| * @param layer2 not used | ||
| */ | ||
| void setTestCancelled(); | ||
|
|
||
| private: | ||
| QMap<QString, QgsSpatialIndex*> mLayerIndexes; | ||
| QMap<QString, TopologyRule> mTopologyRuleMap; | ||
|
|
||
| QList<FeatureLayer> mFeatureList1; | ||
| QMap<int, FeatureLayer> mFeatureMap2; | ||
|
|
||
| QgisInterface* theQgsInterface; | ||
| bool mTestCancelled; | ||
|
|
||
| /** | ||
| * Builds spatial index for the layer | ||
| * @param layer pointer to the layer | ||
| */ | ||
| QgsSpatialIndex* createIndex( QgsVectorLayer* layer, QgsRectangle extent ); | ||
|
|
||
| /** | ||
| * Fills the feature list with features from the layer | ||
| * @param layer pointer to the layer | ||
| * @param extent of the layer to add features | ||
| */ | ||
| void fillFeatureList( QgsVectorLayer* layer, QgsRectangle extent ); | ||
|
|
||
| /** | ||
| * Fills the feature map with features from the layer | ||
| * @param layer pointer to the layer | ||
| * @param extent of the layer to create index | ||
| */ | ||
| void fillFeatureMap( QgsVectorLayer* layer, QgsRectangle extent ); | ||
|
|
||
| /** | ||
| * Returns true if the test was cancelled | ||
| */ | ||
| bool testCancelled(); | ||
|
|
||
| signals: | ||
| /** | ||
| * Informs progress dialog about current status | ||
| * @param value process status | ||
| */ | ||
| void progress( int value ); | ||
| }; | ||
|
|
||
| #endif |