diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 26a6ecf54e5c..1442718aa9ef 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -2,38 +2,45 @@ SUBDIRS(plugins) IF (WIN32) SET(BINDINGS_CORE_LIB ${CMAKE_CURRENT_BINARY_DIR}/core/core.pyd) SET(BINDINGS_GUI_LIB ${CMAKE_CURRENT_BINARY_DIR}/gui/gui.pyd) + SET(BINDINGS_ANALYSIS_LIB ${CMAKE_CURRENT_BINARY_DIR}/analysis/analysis.pyd) IF (NOT MSVC) SET(QGIS_CORE_LIB ${CMAKE_BINARY_DIR}/src/core/libqgis_core.dll) SET(QGIS_GUI_LIB ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.dll) + SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/libqgis_analysis.dll) ELSE (NOT MSVC) - SET(QGIS_CORE_LIB ${CMAKE_BINARY_DIR}/src/core/${CMAKE_CFG_INTDIR}/qgis_core.lib) - SET(QGIS_GUI_LIB ${CMAKE_BINARY_DIR}/src/gui/${CMAKE_CFG_INTDIR}/qgis_gui.lib) + SET(QGIS_CORE_LIB ${CMAKE_BINARY_DIR}/src/core/${CMAKE_CFG_INTDIR}/qgis_core.lib) + SET(QGIS_GUI_LIB ${CMAKE_BINARY_DIR}/src/gui/${CMAKE_CFG_INTDIR}/qgis_gui.lib) + SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/${CMAKE_CFG_INTDIR}/qgis_analysis.lib) ENDIF (NOT MSVC) ELSE (WIN32) - SET(BINDINGS_CORE_LIB ${CMAKE_CURRENT_BINARY_DIR}/core/core.so) - SET(BINDINGS_GUI_LIB ${CMAKE_CURRENT_BINARY_DIR}/gui/gui.so) + SET(BINDINGS_CORE_LIB ${CMAKE_CURRENT_BINARY_DIR}/core/core.so) + SET(BINDINGS_GUI_LIB ${CMAKE_CURRENT_BINARY_DIR}/gui/gui.so) + SET(BINDINGS_ANALYSIS_LIB ${CMAKE_CURRENT_BINARY_DIR}/analysis/analysis.so) IF (APPLE) - SET(QGIS_CORE_LIB ${CMAKE_BINARY_DIR}/src/core/libqgis_core.dylib) - SET(QGIS_GUI_LIB ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.dylib) + SET(QGIS_CORE_LIB ${CMAKE_BINARY_DIR}/src/core/libqgis_core.dylib) + SET(QGIS_GUI_LIB ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.dylib) + SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/libqgis_analysis.dylib) ELSE (APPLE) - SET(QGIS_CORE_LIB ${CMAKE_BINARY_DIR}/src/core/libqgis_core.so) - SET(QGIS_GUI_LIB ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.so) + SET(QGIS_CORE_LIB ${CMAKE_BINARY_DIR}/src/core/libqgis_core.so) + SET(QGIS_GUI_LIB ${CMAKE_BINARY_DIR}/src/gui/libqgis_gui.so) + SET(QGIS_ANALYSIS_LIB ${CMAKE_BINARY_DIR}/src/analysis/libqgis_analysis.so) ENDIF (APPLE) ENDIF (WIN32) -SET (BINDINGS_LIBS ${BINDINGS_CORE_LIB} ${BINDINGS_GUI_LIB}) - -SET (BINDINGS_CORE_MAKEFILE ${CMAKE_CURRENT_BINARY_DIR}/core/Makefile) -SET (BINDINGS_GUI_MAKEFILE ${CMAKE_CURRENT_BINARY_DIR}/gui/Makefile) +SET (BINDINGS_LIBS ${BINDINGS_CORE_LIB} ${BINDINGS_GUI_LIB} ${BINDINGS_ANALYSIS_LIB}) +SET (BINDINGS_CORE_MAKEFILE ${CMAKE_CURRENT_BINARY_DIR}/core/Makefile) +SET (BINDINGS_GUI_MAKEFILE ${CMAKE_CURRENT_BINARY_DIR}/gui/Makefile) +SET (BINDINGS_ANALYSIS_MAKEFILE ${CMAKE_CURRENT_BINARY_DIR}/analysis/Makefile) # 'python' target will force to build bindings libs for core and gui -ADD_CUSTOM_TARGET (python ALL DEPENDS ${BINDINGS_CORE_LIB} ${BINDINGS_GUI_LIB}) +ADD_CUSTOM_TARGET (python ALL DEPENDS ${BINDINGS_CORE_LIB} ${BINDINGS_GUI_LIB} ${BINDINGS_ANALYSIS_LIB}) # don't run python before the libs are built -ADD_DEPENDENCIES (python qgis_core qgis_gui) +ADD_DEPENDENCIES (python qgis_core qgis_gui qgis_analysis) -FILE(GLOB CORE_SIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/core/*.sip") -FILE(GLOB GUI_SIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/gui/*.sip") +FILE(GLOB CORE_SIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/core/*.sip") +FILE(GLOB GUI_SIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/gui/*.sip") +FILE(GLOB ANALYSIS_SIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/analysis/*.sip") # Step 1: during configuration # create file configure.py from configure.py.in @@ -50,12 +57,12 @@ ENDIF (MSVC) # run python configure.py # it will run SIP utility to generate sources and will prepare makefiles # should be run everytime core or gui library has been changed -ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_CORE_MAKEFILE} ${BINDINGS_GUI_MAKEFILE} PRE_BUILD +ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_CORE_MAKEFILE} ${BINDINGS_GUI_MAKEFILE} ${BINDINGS_ANALYSIS_MAKEFILE} PRE_BUILD COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_BINARY_DIR}/configure.py ${CMAKE_CFG_INTDIR} ${EXPORT} - DEPENDS ${QGIS_CORE_LIB} ${QGIS_GUI_LIB} + DEPENDS ${QGIS_CORE_LIB} ${QGIS_GUI_LIB} ${QGIS_ANALYSIS_LIB} ${CMAKE_CURRENT_BINARY_DIR}/configure.py - ${CORE_SIP_FILES} ${GUI_SIP_FILES}) + ${CORE_SIP_FILES} ${GUI_SIP_FILES} ${ANALYSIS_SIP_FILES}) # Step 3: run make in core and gui subdirs ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_CORE_LIB} PRE_LINK @@ -66,6 +73,10 @@ ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_GUI_LIB} PRE_LINK COMMAND ${SIP_MAKE_PROGRAM} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/gui DEPENDS ${BINDINGS_GUI_MAKEFILE}) +ADD_CUSTOM_COMMAND(OUTPUT ${BINDINGS_ANALYSIS_LIB} PRE_LINK + COMMAND ${SIP_MAKE_PROGRAM} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/analysis + DEPENDS ${BINDINGS_ANALYSIS_MAKEFILE}) IF (BINDINGS_GLOBAL_INSTALL) diff --git a/python/analysis/analysis.sip b/python/analysis/analysis.sip new file mode 100644 index 000000000000..c4594a60d990 --- /dev/null +++ b/python/analysis/analysis.sip @@ -0,0 +1,11 @@ + +%Module qgis.analysis 0 + +%Import QtCore/QtCoremod.sip +%Import QtGui/QtGuimod.sip +%Import QtXml/QtXmlmod.sip + +%Import core/core.sip + +%Include qgsgeometryanalyzer.sip + diff --git a/python/analysis/qgsgeometryanalyzer.sip b/python/analysis/qgsgeometryanalyzer.sip new file mode 100644 index 000000000000..1f559c10a38b --- /dev/null +++ b/python/analysis/qgsgeometryanalyzer.sip @@ -0,0 +1,67 @@ +/** \ingroup analysis + * The QGis class provides vector geometry analysis functions + */ + +class QgsGeometryAnalyzer +{ +%TypeHeaderCode +#include +%End + + public: + + /** + * Simplify vector layer using (a modified) Douglas-Peucker algorithm + * and write it to a new shape file + */ + bool simplify( QgsVectorLayer* layer, const QString& shapefileName, double tolerance, + bool onlySelectedFeatures = false ); + + /**Calculate the true centroids, or 'center of mass' for a vector layer and + write it to a new shape file + */ + bool centroids( QgsVectorLayer* layer, const QString& shapefileName, + bool onlySelectedFeatures = false ); + + /**Create a polygon based on the extent of all (selected) features and write it to a new shape file + */ + bool extent( QgsVectorLayer* layer, const QString& shapefileName, + bool onlySelectedFeatures = false ); + + /**Create buffers for a vector layer and write it to a new shape file + */ + bool buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance, + bool onlySelectedFeatures = false, bool dissolve = false, + int bufferDistanceField = -1 ); + + /**Create convex hull(s) of a vector layer and write it to a new shape file + */ + bool convexHull( QgsVectorLayer* layer, const QString& shapefileName, + bool onlySelectedFeatures = false, + int uniqueIdField = -1 ); + + /**Dissolve a vector layer and write it to a new shape file + */ + bool dissolve( QgsVectorLayer* layer, const QString& shapefileName, + bool onlySelectedFeatures = false, + int uniqueIdField = -1 ); + + private: + + QList simpleMeasure( QgsGeometry* geometry ); + double perimeterMeasure( QgsGeometry* geometry, QgsDistanceArea& measure ); + /**Helper function to simplify an individual feature*/ + void simplifyFeature( QgsFeature& f, QgsVectorFileWriter* vfw, double tolerance ); + /**Helper function to get the cetroid of an individual feature*/ + void centroidFeature( QgsFeature& f, QgsVectorFileWriter* vfw ); + /**Helper function to buffer an individual feature*/ + void bufferFeature( QgsFeature& f, int nProcessedFeatures, QgsVectorFileWriter* vfw, + bool dissolve, QgsGeometry** dissolveGeometry, + double bufferDistance, int bufferDistanceField ); + /**Helper function to get the convex hull of feature(s)*/ + void convexFeature( QgsFeature& f, int nProcessedFeatures, + QgsGeometry** dissolveGeometry ); + /**Helper function to dissolve feature(s)*/ + void dissolveFeature( QgsFeature& f, int nProcessedFeatures, + QgsGeometry** dissolveGeometry ); +}; diff --git a/python/configure.py.in b/python/configure.py.in index c328a345c0e7..1648e03ba4c4 100644 --- a/python/configure.py.in +++ b/python/configure.py.in @@ -38,6 +38,8 @@ if not os.path.isdir("./core"): os.mkdir("./core") if not os.path.isdir("./gui"): os.mkdir("./gui") +if not os.path.isdir("./analysis"): + os.mkdir("./analysis") ########################################################################## # SIP -> *.CPP + *.H @@ -46,6 +48,7 @@ if not os.path.isdir("./gui"): # system. build_file_core = build_path + "/python/core/core.sbf" build_file_gui = build_path + "/python/gui/gui.sbf" +build_file_analysis = build_path + "/python/analysis/analysis.sbf" # Get the SIP configuration information. config = PyQt4.pyqtconfig.Configuration() @@ -61,6 +64,7 @@ mod_dir = os.path.join(config.default_mod_dir, "qgis") # directory where sip files will be installed sip_dir_core = os.path.join(config.default_sip_dir, "qgis/core") sip_dir_gui = os.path.join(config.default_sip_dir, "qgis/gui") +sip_dir_analysis = os.path.join(config.default_sip_dir, "qgis/analysis") # Run SIP to generate the code. print "Parsing SIP files for 'core' library..." @@ -73,6 +77,11 @@ cmd = " ".join([config.sip_bin, "-c", "gui", "-b", build_file_gui, "-I", python_ print cmd os.system(cmd) +print "Parsing SIP files for 'analysis' library..." +cmd = " ".join([config.sip_bin, "-c", "analysis", "-b", build_file_analysis, "-I", python_path, "-I", config.pyqt_sip_dir, qt_sip_flags, python_path + "/analysis/analysis.sip"]) +print cmd +os.system(cmd) + ########################################################################## # MAKEFILES @@ -83,12 +92,13 @@ print "Creating makefiles..." # its configuration module. installs = [] -# directories relative to core (gui) directories +# directories relative to core (gui, analysis) directories installs.append([[python_path + "__init__.py", python_path + "qgisconfig.py"], mod_dir]) installs_core = copy.copy(installs) installs_gui = copy.copy(installs) +installs_analysis = copy.copy(installs) # install all sip files sips_core = glob.glob(python_path + "/core/*.sip") @@ -98,6 +108,10 @@ for sip in sips_core: sips_gui = glob.glob(python_path + "/gui/*.sip") for sip in sips_gui: installs_gui.append([os.path.basename(sip), sip_dir_gui]) + +sips_analysis = glob.glob(python_path + "/analysis/*.sip") +for sip in sips_analysis: + installs_analysis.append([os.path.basename(sip), sip_dir_analysis]) # Create the Makefile. The QtModuleMakefile class provided by the @@ -120,9 +134,18 @@ makefile_gui = sipconfig.ModuleMakefile( install_dir=mod_dir, dir="gui", universal=osx_universal) + +makefile_analysis = sipconfig.ModuleMakefile( + configuration=config, + qt=qt_libs, + build_file=build_file_analysis, + installs=installs_analysis, + install_dir=mod_dir, + dir="analysis", + universal=osx_universal) -# common settings for both core and gui libs -for mk in [ makefile_core, makefile_gui ]: +# common settings for core, gui and analysis libs +for mk in [ makefile_core, makefile_gui, makefile_analysis ]: mk.extra_lflags.extend( "@CMAKE_MODULE_LINKER_FLAGS@".strip(' ').split(' ') ) mk.extra_libs = ["qgis_core"] mk.extra_lib_dirs = [build_path+"/src/core"+intdir] @@ -145,9 +168,18 @@ makefile_gui.extra_include_dirs.append(build_path+"/src/ui") makefile_gui.extra_include_dirs.append(src_path+"/src/plugins") # because of qgisplugin.h TODO: sort out makefile_gui.extra_cxxflags.append("-DGUI_EXPORT="+export) +# more settings for analysis lib +makefile_analysis.extra_libs.append("qgis_analysis") +makefile_analysis.extra_lib_dirs.append(build_path+"/src/analysis/vector"+intdir) +makefile_analysis.extra_include_dirs.append(src_path+"/src/analysis/vector") +makefile_analysis.extra_include_dirs.append(build_path+"/src/analysis/vector") +makefile_analysis.extra_include_dirs.append(src_path+"/src/plugins") # because of qgisplugin.h TODO: sort out +makefile_analysis.extra_cxxflags.append("-DANALYSIS_EXPORT="+export) + # Generate the Makefile itself. makefile_core.generate() makefile_gui.generate() +makefile_analysis.generate() ########################################################################## # QGIS CONFIG diff --git a/python/qgisconfig.py.in b/python/qgisconfig.py.in index cab56f1548e0..931aa27bcae8 100644 --- a/python/qgisconfig.py.in +++ b/python/qgisconfig.py.in @@ -34,6 +34,7 @@ class QgisModuleMakefile(pyqtconfig.QtModuleMakefile): # Make sure our C++ library is linked. self.extra_libs.append("qgis_core") self.extra_libs.append("qgis_gui") + self.extra_libs.append("qgis_analysis") # Let the super-class do what it needs to. pyqtconfig.QtModuleMakefile.finalise(self) diff --git a/src/analysis/vector/qgsgeometryanalyzer.cpp b/src/analysis/vector/qgsgeometryanalyzer.cpp index cd2a5031d04e..761723f3794a 100644 --- a/src/analysis/vector/qgsgeometryanalyzer.cpp +++ b/src/analysis/vector/qgsgeometryanalyzer.cpp @@ -28,262 +28,251 @@ #include "qgsdistancearea.h" #include +bool QgsGeometryAnalyzer::simplify( QgsVectorLayer* layer, const QString& shapefileName, \ + double tolerance, bool onlySelectedFeatures, QProgressDialog* p ) +{ + if ( !layer ) + { + return false; + } + QgsVectorDataProvider* dp = layer->dataProvider(); + if ( !dp ) + { + return false; + } -bool QgsGeometryAnalyzer::singlepartsToMultipart( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding, - const int fieldIndex ) -{ - return false; - /* - QgsVectorDataProvider* provider = layer->dataProvider(); - QgsAttributeList allAttrs = provider->attributeIndexes(); - provider->select( allAttrs, QgsRectangle(), true ); - const QgsCoordinateReferenceSystem* outputCRS; - outputCRS = &layer->srs(); - QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName, - fileEncoding, provider->fields(), provider->geometryType(), outputCRS ); - - QgsGeometry inGeom; - QgsGeometry outGeom; - QList unique; - provider->uniqueValues( index, unique ) - if ( unique->size() < layer->featureCount() ) + QGis::WkbType outputType = dp->geometryType(); + const QgsCoordinateReferenceSystem crs = layer->srs(); + + QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); + QgsFeature currentFeature; + + //take only selection + if ( onlySelectedFeatures ) + { + //use QgsVectorLayer::featureAtId + const QgsFeatureIds selection = layer->selectedFeaturesIds(); + if ( p ) { - QList multiGeom; - bool first; - QgsAttributeMap atMap; + p->setMaximum( selection.size() ); + } - for ( int it = unique.begin(); it != unique.end(); ++it ) + int processedFeatures = 0; + QgsFeatureIds::const_iterator it = selection.constBegin(); + for ( ; it != selection.constEnd(); ++it ) + { + if ( p ) { - provider->select( allAttrs, QgsRectangle(), true ); - first = true; - while ( provider->nextFeature( inFeat ) ) - { - if ( inFeat.attributeMap()[ index ].toString().trimmed() == it.toString().trimmed() ) - { - if (first) - { - atMap = inFeat.attributeMap(); - first = false; - } - inGeom = inFeat.geometry(); - multiGeom << inGeom.asGeometryCollection() - } - outFeat.setAttributeMap( atMap ); - outGeom = convertGeometry( multifeature, vtype ); - outFeat.setGeometry( outGeom ); - writer.addFeature( outFeat ); - } + p->setValue( processedFeatures ); } - delete writer; - return true; - */ -} -bool QgsGeometryAnalyzer::multipartToSingleparts( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ) -{ - return false; - /* - QgsVectorDataProvider* provider = layer->dataProvider(); - QgsAttributeList allAttrs = provider->attributeIndexes(); - provider->select( allAttrs, QgsRectangle(), true ); - const QgsCoordinateReferenceSystem* outputCRS; - outputCRS = &layer->srs(); - QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName, - fileEncoding, provider->fields(), provider->geometryType(), outputCRS ); - inFeat = QgsFeature() - outFeat = QgsFeature() - inGeom = QgsGeometry() - outGeom = QgsGeometry() - nFeat = vprovider.featureCount() - nElement = 0 - self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), 0 ) - self.emit( SIGNAL( "runRange(PyQt_PyObject)" ), ( 0, nFeat ) ) - while vprovider.nextFeature( inFeat ) - nElement += 1 - self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), nElement ) - inGeom = inFeat.geometry() - atMap = inFeat.attributeMap() - featList = self.extractAsSingle( inGeom ) - outFeat.setAttributeMap( atMap ) - for i in featList: - outFeat.setGeometry( i ) - writer.addFeature( outFeat ) - del writer - return True - - */ -} - -bool QgsGeometryAnalyzer::extractNodes( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ) -{ - return false; - /* - QgsVectorDataProvider* provider = layer->dataProvider(); - QgsAttributeList allAttrs = provider->attributeIndexes(); - provider->select( allAttrs, QgsRectangle(), true ); - const QgsCoordinateReferenceSystem* outputCRS; - outputCRS = &layer->srs(); - QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName, - fileEncoding, provider->fields(), provider->geometryType(), outputCRS ); - - QgsFeature inFeat; - QgsFeature outFeat; - - QgsGeometry outGeom; - QList pointList; - QgsPoint geomPoint; - QList::iterator it; - while ( provider->nextFeature( inFeat ) ) - { - pointList = extractPoints( inFeat.geometry() ); - outFeat.setAttributeMap( inFeat.attributeMap() ); - for (it = pointList.begin(); it != pointList.end(); ++it ) + if ( p && p->wasCanceled() ) + { + break; + } + if ( !layer->featureAtId( *it, currentFeature, true, true ) ) { - geomPoint = QgsGeometry::fromPoint( it ); - outFeat.setGeometry( geomPoint ); - writer.addFeature( outFeat ); + continue; } + simplifyFeature( currentFeature, &vWriter, tolerance ); + ++processedFeatures; } - delete writer; - return true; - */ -} - -bool QgsGeometryAnalyzer::polygonsToLines( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ) -{ - return false; - /* - QgsVectorDataProvider* provider = layer->dataProvider(); - QgsAttributeList allAttrs = provider->attributeIndexes(); - provider->select( allAttrs, QgsRectangle(), true ); - QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName, - fileEncoding, provider->fields(), QGis::WKBPoint, provider->crs() ); + if ( p ) + { + p->setValue( selection.size() ); + } + } + //take all features + else + { + layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false ); - QgsFeature inFeat; - QgsFeature outFeat; - QgsGeometry inGeom; - QgsGeometry outGeom; - QList lineList; + int featureCount = layer->featureCount(); + if ( p ) + { + p->setMaximum( featureCount ); + } + int processedFeatures = 0; - while ( provider->nextFeature( inFeat ) ) + while ( layer->nextFeature( currentFeature ) ) { - lineList = QgsGeometryAnalyzer::extractLines( inFeat.geometry() ); - outFeat.setAttributeMap( inFeat.attributeMap() ); - for ( line = lineList.begin(); line != lineList.end(); line++ ) + if ( p ) { - outFeat.setGeometry( outGeom.fromPolyline( line ) ); - writer.addFeature( outFeat ); + p->setValue( processedFeatures ); } + if ( p && p->wasCanceled() ) + { + break; + } + simplifyFeature( currentFeature, &vWriter, tolerance ); + ++processedFeatures; + } + if ( p ) + { + p->setValue( featureCount ); } - delete writer; - return true; - */ + } + + return true; } -bool QgsGeometryAnalyzer::exportGeometryInformation( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ) +void QgsGeometryAnalyzer::simplifyFeature( QgsFeature& f, QgsVectorFileWriter* vfw, double tolerance ) { - return false; -#if 0 - QgsVectorDataProvider* provider = layer->dataProvider(); - QgsAttributeList allAttrs = provider->attributeIndexes(); - provider->select( allAttrs, QgsRectangle(), true ); - QgsCoordinateReferenceSystem outputCRS = layer->srs(); - int index1; - int index2; - //( fields, index1, index2 ) = self.checkGeometryFields( self.vlayer ) - - QgsVectorFileWriter writer = QgsVectorFileWriter( shapefileName, - fileEncoding, provider->fields(), provider->geometryType(), &outputCRS ); - - QgsFeature inFeat; - QgsFeature outFeat; - QgsGeometry* inGeom; - QList attrs; - - while ( provider->nextFeature( inFeat ) ) - { - inGeom = inFeat.geometry(); - outFeat.setAttributeMap( inFeat.attributeMap() ); - attrs = QgsGeometryAnalyzer::simpleMeasure( inGeom ); - outFeat.setGeometry( inGeom ); - outFeat.setAttributeMap( inFeat.attributeMap() ); - outFeat.addAttribute( index1, QVariant( attrs[0] ) ); // FIXME: index1 unset - outFeat.addAttribute( index2, QVariant( attrs[1] ) ); // FIXME: index2 unset - writer.addFeature( outFeat ); + QgsGeometry* featureGeometry = f.geometry(); + QgsGeometry* tmpGeometry = 0; + + if ( !featureGeometry ) + { + return; + } + // simplify feature + tmpGeometry = featureGeometry->simplify( tolerance ); + + QgsFeature newFeature; + newFeature.setGeometry( tmpGeometry ); + newFeature.setAttributeMap( f.attributeMap() ); + + //add it to vector file writer + if ( vfw ) + { + vfw->addFeature( newFeature ); } - return true; -#endif } -bool QgsGeometryAnalyzer::simplifyGeometry( QgsVectorLayer* layer, - const QString shapefileName, - const QString fileEncoding, - const double tolerance ) + +bool QgsGeometryAnalyzer::centroids( QgsVectorLayer* layer, const QString& shapefileName, \ + bool onlySelectedFeatures, QProgressDialog* p ) { - QgsVectorDataProvider* provider = layer->dataProvider(); - QgsAttributeList allAttrs = provider->attributeIndexes(); - provider->select( allAttrs, QgsRectangle(), true ); - QgsCoordinateReferenceSystem outputCRS = layer->srs(); - QgsVectorFileWriter writer = QgsVectorFileWriter( shapefileName, - fileEncoding, provider->fields(), provider->geometryType(), &outputCRS ); + if ( !layer ) + { + return false; + } + + QgsVectorDataProvider* dp = layer->dataProvider(); + if ( !dp ) + { + return false; + } + + QGis::WkbType outputType = QGis::WKBPoint; + const QgsCoordinateReferenceSystem crs = layer->srs(); + + QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); + QgsFeature currentFeature; + + //take only selection + if ( onlySelectedFeatures ) + { + //use QgsVectorLayer::featureAtId + const QgsFeatureIds selection = layer->selectedFeaturesIds(); + if ( p ) + { + p->setMaximum( selection.size() ); + } + + int processedFeatures = 0; + QgsFeatureIds::const_iterator it = selection.constBegin(); + for ( ; it != selection.constEnd(); ++it ) + { + if ( p ) + { + p->setValue( processedFeatures ); + } - QgsFeature inFeat; - QgsFeature outFeat; - QgsGeometry* inGeom; + if ( p && p->wasCanceled() ) + { + break; + } + if ( !layer->featureAtId( *it, currentFeature, true, true ) ) + { + continue; + } + centroidFeature( currentFeature, &vWriter ); + ++processedFeatures; + } - while ( provider->nextFeature( inFeat ) ) + if ( p ) + { + p->setValue( selection.size() ); + } + } + //take all features + else { - inGeom = inFeat.geometry(); - outFeat.setAttributeMap( inFeat.attributeMap() ); - outFeat.setGeometry( inGeom->simplify( tolerance ) ); - writer.addFeature( outFeat ); + layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false ); + + int featureCount = layer->featureCount(); + if ( p ) + { + p->setMaximum( featureCount ); + } + int processedFeatures = 0; + + while ( layer->nextFeature( currentFeature ) ) + { + if ( p ) + { + p->setValue( processedFeatures ); + } + if ( p && p->wasCanceled() ) + { + break; + } + centroidFeature( currentFeature, &vWriter ); + ++processedFeatures; + } + if ( p ) + { + p->setValue( featureCount ); + } } return true; - } -bool QgsGeometryAnalyzer::polygonCentroids( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ) + +void QgsGeometryAnalyzer::centroidFeature( QgsFeature& f, QgsVectorFileWriter* vfw ) { - QgsVectorDataProvider* provider = layer->dataProvider(); - QgsAttributeList allAttrs = provider->attributeIndexes(); - provider->select( allAttrs, QgsRectangle(), true ); - QgsCoordinateReferenceSystem outputCRS = layer->srs(); - QgsVectorFileWriter writer = QgsVectorFileWriter( shapefileName, - fileEncoding, provider->fields(), provider->geometryType(), &outputCRS ); + QgsGeometry* featureGeometry = f.geometry(); + QgsGeometry* tmpGeometry = 0; - QgsFeature inFeat; - QgsFeature outFeat; - QgsGeometry* inGeom; + if ( !featureGeometry ) + { + return; + } + + tmpGeometry = featureGeometry->centroid(); - while ( provider->nextFeature( inFeat ) ) + QgsFeature newFeature; + newFeature.setGeometry( tmpGeometry ); + newFeature.setAttributeMap( f.attributeMap() ); + + //add it to vector file writer + if ( vfw ) { - inGeom = inFeat.geometry(); - outFeat.setAttributeMap( inFeat.attributeMap() ); - outFeat.setGeometry( inGeom->centroid() ); - writer.addFeature( outFeat ); + vfw->addFeature( newFeature ); } - return true; } -bool QgsGeometryAnalyzer::layerExtent( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ) +bool QgsGeometryAnalyzer::extent( QgsVectorLayer* layer, const QString& shapefileName, \ + bool onlySelectedFeatures, QProgressDialog* p ) { + if ( !layer ) + { + return false; + } + + QgsVectorDataProvider* dp = layer->dataProvider(); + if ( !dp ) + { + return false; + } + + QGis::WkbType outputType = QGis::WKBPolygon; + const QgsCoordinateReferenceSystem crs = layer->srs(); + QgsFieldMap fields; fields.insert( 0 , QgsField( QString( "MINX" ), QVariant::Double ) ); fields.insert( 1 , QgsField( QString( "MINY" ), QVariant::Double ) ); @@ -296,40 +285,44 @@ bool QgsGeometryAnalyzer::layerExtent( QgsVectorLayer* layer, fields.insert( 8 , QgsField( QString( "HEIGHT" ), QVariant::Double ) ); fields.insert( 9 , QgsField( QString( "WIDTH" ), QVariant::Double ) ); - QgsVectorDataProvider* provider = layer->dataProvider(); - QgsCoordinateReferenceSystem outputCRS = layer->srs(); - QgsVectorFileWriter writer = QgsVectorFileWriter( shapefileName, - fileEncoding, provider->fields(), provider->geometryType(), &outputCRS ); + QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), fields, outputType, &crs ); QgsRectangle rect; - rect = layer->extent(); + if ( onlySelectedFeatures ) // take only selection + { + rect = layer->boundingBoxOfSelected(); + } + else + { + rect = layer->extent(); + } + double minx = rect.xMinimum(); double miny = rect.yMinimum(); double maxx = rect.xMaximum(); double maxy = rect.yMaximum(); double height = rect.height(); double width = rect.width(); - double cntx = minx + ( width / 2.0 ); double cnty = miny + ( height / 2.0 ); double area = width * height; double perim = ( 2 * width ) + ( 2 * height ); QgsFeature feat; - QgsAttributeMap atMap; - atMap.insert( 0 , QVariant( minx ) ); - atMap.insert( 1 , QVariant( miny ) ); - atMap.insert( 2 , QVariant( maxx ) ); - atMap.insert( 3 , QVariant( maxy ) ); - atMap.insert( 4 , QVariant( cntx ) ); - atMap.insert( 5 , QVariant( cnty ) ); - atMap.insert( 6 , QVariant( area ) ); - atMap.insert( 7 , QVariant( perim ) ); - atMap.insert( 8 , QVariant( height ) ); - atMap.insert( 9 , QVariant( width ) ); - feat.setAttributeMap( atMap ); + QgsAttributeMap map; + map.insert( 0 , QVariant( minx ) ); + map.insert( 1 , QVariant( miny ) ); + map.insert( 2 , QVariant( maxx ) ); + map.insert( 3 , QVariant( maxy ) ); + map.insert( 4 , QVariant( cntx ) ); + map.insert( 5 , QVariant( cnty ) ); + map.insert( 6 , QVariant( area ) ); + map.insert( 7 , QVariant( perim ) ); + map.insert( 8 , QVariant( height ) ); + map.insert( 9 , QVariant( width ) ); + feat.setAttributeMap( map ); feat.setGeometry( QgsGeometry::fromRect( rect ) ); - writer.addFeature( feat ); + vWriter.addFeature( feat ); return true; } @@ -383,232 +376,277 @@ double QgsGeometryAnalyzer::perimeterMeasure( QgsGeometry* geometry, QgsDistance return value; } -QgsFieldMap QgsGeometryAnalyzer::checkGeometryFields( QgsVectorLayer* layer, int& index1, int& index2 ) +bool QgsGeometryAnalyzer::convexHull( QgsVectorLayer* layer, const QString& shapefileName, + bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p ) { - return QgsFieldMap(); - /* QgsVectorDataProvider* provider = layer->dataProvider(); - QgsAttributeList allAttrs = provider->attributeIndexes(); - // provider->select( allAttrs, QgsRectangle(), true ); - QgsFieldMap fields = provider->fields() - QGis::GeometryType geomType = layer->geometryType(); - - for i in fieldList.keys() - nameList.append( fieldList[ i ].name().toLower() ) - if geomType == QGis.Polygon: - plp = "Poly" - ( found, index1 ) = self.checkForField( nameList, "AREA" ) - if not found: - field = QgsField( "AREA", QVariant.Double, "double", 10, 6, "Polygon area" ) - index1 = len( fieldList.keys() ) - fieldList[ index1 ] = field - ( found, index2 ) = self.checkForField( nameList, "PERIMETER" ) - - if not found: - field = QgsField( "PERIMETER", QVariant.Double, "double", 10, 6, "Polygon perimeter" ) - index2 = len( fieldList.keys() ) - fieldList[ index2 ] = field - elif geomType == QGis.Line: - plp = "Line" - (found, index1) = self.checkForField(nameList, "LENGTH") - if not found: - field = QgsField("LENGTH", QVariant.Double, "double", 10, 6, "Line length") - index1 = len(fieldList.keys()) - fieldList[index1] = field - index2 = index1 - else: - plp = "Point" - (found, index1) = self.checkForField(nameList, "XCOORD") - if not found: - field = QgsField("XCOORD", QVariant.Double, "double", 10, 6, "Point x coordinate") - index1 = len(fieldList.keys()) - fieldList[index1] = field - (found, index2) = self.checkForField(nameList, "YCOORD") - if not found: - field = QgsField("YCOORD", QVariant.Double, "double", 10, 6, "Point y coordinate") - index2 = len(fieldList.keys()) - fieldList[index2] = field - return (fieldList, index1, index2) - */ -} + if ( !layer ) + { + return false; + } -QgsGeometry* QgsGeometryAnalyzer::extractLines( QgsGeometry* geometry ) -{ - return NULL; - /* - QGis::WkbType wkbType = geometry.wkbType(); - QList lineList; - QgsMultiPolygon polyList - if ( geometry.type() == QGis::Polygon ) + QgsVectorDataProvider* dp = layer->dataProvider(); + if ( !dp ) + { + return false; + } + + QGis::WkbType outputType = QGis::WKBPolygon; + const QgsCoordinateReferenceSystem crs = layer->srs(); + + QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); + QgsFeature currentFeature; + QgsGeometry* dissolveGeometry; //dissolve geometry + QMultiMap map; + bool useField = false; + + if ( uniqueIdField == -1 ) + { + uniqueIdField = 0; + } + else + { + useField = true; + layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false ); + while ( layer->nextFeature( currentFeature ) ) { - if ( geometry.isMultipart() ) - { - polyList = geometry.asMultiPolygon(); - for ( polygon = polyList.begin(); polygon != polyList.end(); polygon++ ) + map.insert( currentFeature.attributeMap()[uniqueIdField].toString(), currentFeature.id() ); + } + } + QMultiMap::const_iterator jt; + for (jt = map.constBegin(); jt != map.constEnd(); ++jt) + { + QString currentKey = jt.key(); + int processedFeatures = 0; + //take only selection + if ( onlySelectedFeatures ) + { + //use QgsVectorLayer::featureAtId + const QgsFeatureIds selection = layer->selectedFeaturesIds(); + if ( p ) + { + p->setMaximum( selection.size() ); + } + processedFeatures = 0; + while ( jt != map.end() && ( jt.key() == currentKey || !useField ) ) { - for ( lines = polygon.begin(); lines != polygon.end(); lines++ ) + if ( p && p->wasCanceled() ) { - lineList << lines; + break; } + if ( selection.contains( jt.value() ) ) + { + if ( p ) + { + p->setValue( processedFeatures ); + } + if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) ) + { + continue; + } + convexFeature( currentFeature, processedFeatures, &dissolveGeometry ); + ++processedFeatures; + } + ++jt; + } + QgsFeature dissolveFeature; + dissolveFeature.setGeometry( dissolveGeometry ); + vWriter.addFeature( dissolveFeature ); + } + //take all features + else + { + int featureCount = layer->featureCount(); + if ( p ) + { + p->setMaximum( featureCount ); + } + processedFeatures = 0; + while ( jt != map.end() && ( jt.key() == currentKey || !useField ) ) + { + if ( p ) + { + p->setValue( processedFeatures ); } - else + + if ( p && p->wasCanceled() ) { - lineList = geometry.asPolygon(); + break; } + if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) ) + { + continue; + } + convexFeature( currentFeature, processedFeatures, &dissolveGeometry ); + ++processedFeatures; + ++jt; } + QgsFeature dissolveFeature; + dissolveFeature.setGeometry( dissolveGeometry ); + vWriter.addFeature( dissolveFeature ); } - return lineList - */ -} -QgsGeometry* QgsGeometryAnalyzer::extractAsSingle( QgsGeometry* geometry ) -{ - return NULL; - /* - multi_geom = QgsGeometry() - temp_geom = [] - if geom.type() == 0: - if geom.isMultipart() - multi_geom = geom.asMultiPoint() - for i in multi_geom: - temp_geom.append( QgsGeometry().fromPoint ( i ) ) - else: - temp_geom.append( geom ) - elif geom.type() == 1: - if geom.isMultipart() - multi_geom = geom.asMultiPolyline() - for i in multi_geom: - temp_geom.append( QgsGeometry().fromPolyline( i ) ) - else: - temp_geom.append( geom ) - elif geom.type() == 2: - if geom.isMultipart() - multi_geom = geom.asMultiPolygon() - for i in multi_geom: - temp_geom.append( QgsGeometry().fromPolygon( i ) ) - else: - temp_geom.append( geom ) - return temp_geom - - */ + } + return true; } -QgsGeometry* QgsGeometryAnalyzer::extractAsMulti( QgsGeometry* geometry ) -{ - return NULL; - /* - if ( geometry->mGeos == NULL ) - { - geometry->exportWkbToGeos(); - } - if ( !geometry->mGeos ) - { - return 0; - } - return fromGeosGeom( GEOSIntersection( mGeos, geometry->mGeos ) ); - - for ( int i = 0; i < geometry.size(); i++ ) - geomarr[i] = geometry->mGeos[i]; - GEOSGeometry *geom = 0; +void QgsGeometryAnalyzer::convexFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry) +{ + QgsGeometry* featureGeometry = f.geometry(); + QgsGeometry* tmpGeometry = 0; + QgsGeometry* convexGeometry = 0; - try - { - geom = GEOSGeom_createCollection( typeId, geomarr, geoms.size() ); - } - catch ( GEOSException &e ) - { - Q_UNUSED( e ); - } + if ( !featureGeometry ) + { + return; + } - delete [] geomarr; + convexGeometry = featureGeometry->convexHull(); - return geom; + if ( nProcessedFeatures == 0 ) + { + *dissolveGeometry = convexGeometry; + } + else + { + tmpGeometry = *dissolveGeometry; + *dissolveGeometry = ( *dissolveGeometry )->combine( convexGeometry ); + delete tmpGeometry; + delete convexGeometry; } +} - temp_geom = [] - if geom.type() == 0: - if geom.isMultipart() - return geom.asMultiPoint() - else: - return [ geom.asPoint() ] - elif geom.type() == 1: - if geom.isMultipart() - return geom.asMultiPolyline() - else: - return [ geom.asPolyline() ] - else: - if geom.isMultipart() - return geom.asMultiPolygon() - else: - return [ geom.asPolygon() ] +bool QgsGeometryAnalyzer::dissolve( QgsVectorLayer* layer, const QString& shapefileName, + bool onlySelectedFeatures, int uniqueIdField, QProgressDialog* p ) +{ + if ( !layer ) + { + return false; + } - */ + QgsVectorDataProvider* dp = layer->dataProvider(); + if ( !dp ) + { + return false; + } -} + QGis::WkbType outputType = dp->geometryType(); + const QgsCoordinateReferenceSystem crs = layer->srs(); -QgsGeometry* QgsGeometryAnalyzer::convertGeometry( QgsGeometry* geometry ) -{ - return NULL; - /* - if vType == 0: - return QgsGeometry().fromMultiPoint(geom_list) - elif vType == 1: - return QgsGeometry().fromMultiPolyline(geom_list) - else: - return QgsGeometry().fromMultiPolygon(geom_list) - */ -} + QgsVectorFileWriter vWriter( shapefileName, dp->encoding(), dp->fields(), outputType, &crs ); + QgsFeature currentFeature; + QgsGeometry* dissolveGeometry; //dissolve geometry + QMultiMap map; + bool useField = false; -QList QgsGeometryAnalyzer::extractPoints( QgsGeometry* geometry ) -{ - return QList(); - /* QGis::WkbType wkbType = geometry.wkbType(); - QList pointList; - QList lineList; - switch ( wkbType ) + if ( uniqueIdField == -1 ) + { + uniqueIdField = 0; + } + else + { + useField = true; + layer->select( layer->pendingAllAttributesList(), QgsRectangle(), true, false ); + while ( layer->nextFeature( currentFeature ) ) { - case QGis::WKBPoint25D: - case QGis::WKBPoint: - case QGis::WKBMultiLineString25D: - case QGis::WKBMultiLineString: + map.insert( currentFeature.attributeMap()[uniqueIdField].toString(), currentFeature.id() ); + } + } + QMultiMap::const_iterator jt; + for (jt = map.constBegin(); jt != map.constEnd(); ++jt) + { + QString currentKey = jt.key(); + int processedFeatures = 0; + //take only selection + if ( onlySelectedFeatures ) + { + //use QgsVectorLayer::featureAtId + const QgsFeatureIds selection = layer->selectedFeaturesIds(); + if ( p ) + { + p->setMaximum( selection.size() ); + } + processedFeatures = 0; + while ( jt != map.end() && ( jt.key() == currentKey || !useField ) ) + { + if ( p && p->wasCanceled() ) + { + break; + } + if ( selection.contains( jt.value() ) ) + { + if ( p ) + { + p->setValue( processedFeatures ); + } + if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) ) + { + continue; + } + dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry ); + ++processedFeatures; + } + ++jt; + } + QgsFeature dissolveFeature; + dissolveFeature.setGeometry( dissolveGeometry ); + vWriter.addFeature( dissolveFeature ); + } + //take all features + else + { + int featureCount = layer->featureCount(); + if ( p ) { - geometry->convertToMultitype(); - pointList = geometry.asMultiPoint(); - break; + p->setMaximum( featureCount ); } - case QGis::WKBLineString25D: - case QGis::WKBLineString: - case QGis::WKBMultiLineString25D: - case QGis::WKBMultiLineString: + processedFeatures = 0; + while ( jt != map.end() && ( jt.key() == currentKey || !useField ) ) { - geometry->convertToMultitype(); - lineList = geometry.asMultiPolyline(); - for ( line = lineList.begin(); line != lineList.end(); line++ ) + if ( p ) { - pointList << line; + p->setValue( processedFeatures ); } - break; - } - case QGis::WKBPolygon25D: - case QGis::WKBPolygon: - case QGis::WKBMultiPolygon25D: - case QGis::WKBMultiPolygon: - { - geometry->convertToMultitype(); - QgsPolygon polyList = geometry.asMultiPolygon(); - for ( lineList = polyList.begin(); lineList != polyList.end(); lineList++ ) + + if ( p && p->wasCanceled() ) { - for ( line = lineList.begin(); line != lineList.end(); line++ ) - { - pointList << line; - } + break; } - break; + if ( !layer->featureAtId( jt.value(), currentFeature, true, true ) ) + { + continue; + } + dissolveFeature( currentFeature, processedFeatures, &dissolveGeometry ); + ++processedFeatures; + ++jt; } - default: - break; + QgsFeature dissolveFeature; + dissolveFeature.setGeometry( dissolveGeometry ); + vWriter.addFeature( dissolveFeature ); } - return pointList; - */ + } + return true; +} + +void QgsGeometryAnalyzer::dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry ) +{ + QgsGeometry* featureGeometry = f.geometry(); + QgsGeometry* tmpGeometry = 0; + + if ( !featureGeometry ) + { + return; + } + + if ( nProcessedFeatures == 0 ) + { + *dissolveGeometry = featureGeometry; + } + else + { + tmpGeometry = *dissolveGeometry; + *dissolveGeometry = ( *dissolveGeometry )->combine( featureGeometry ); + delete tmpGeometry; + } } bool QgsGeometryAnalyzer::buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance, \ diff --git a/src/analysis/vector/qgsgeometryanalyzer.h b/src/analysis/vector/qgsgeometryanalyzer.h index d201330c732f..14d8c122166b 100644 --- a/src/analysis/vector/qgsgeometryanalyzer.h +++ b/src/analysis/vector/qgsgeometryanalyzer.h @@ -38,72 +38,37 @@ class ANALYSIS_EXPORT QgsGeometryAnalyzer { public: - /** - * Convert a vector layer from single part geometry - * to multipart geometry for a given field - * - * */ - bool singlepartsToMultipart( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding, - const int fieldIndex ); - - /** - * Convert multipart features to multiple singlepart features. Creates - * simple polygons and lines. - */ - bool multipartToSingleparts( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ); - - /** - * Extract nodes from line and polygon vector layers and output them as - * points. - * */ - bool extractNodes( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ); - - /** - * Convert polygon features to line features. Multipart polygons are - * converted to multiple singlepart lines. - */ - bool polygonsToLines( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ); - - /** - * Add vector layer geometry info to point (XCOORD, YCOORD), line (LENGTH), - * or polygon (AREA, PERIMETER) layer. - */ - bool exportGeometryInformation( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ); - - /** - * Simplify (generalise) line or polygon vector layers using (a modified) - * Douglas-Peucker algorithm. - */ - bool simplifyGeometry( QgsVectorLayer* layer, - const QString shapefileName, - const QString fileEncoding, - const double tolerance ); - - /** - * Calculate the true centroids, or 'center of mass' for each polygon in an - * input polygon layer. - */ - bool polygonCentroids( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ); - - /** - * Create a polygon based on the extents of all features (or all - * selected features if applicable) and write it out to a shp. - */ - bool layerExtent( QgsVectorLayer* layer, - const QString& shapefileName, - const QString& fileEncoding ); + /**Simplify vector layer using (a modified) Douglas-Peucker algorithm + and write it to a new shape file + @param layer input vector layer + @param shapefileName path to the output shp + @param fileEncoding encoding of the output file + @param tolerance (level of simplification) + @param onlySelectedFeatures if true, only selected features are considered, else all the features + @param p progress dialog (or 0 if no progress dialog is to be shown) + @note: added in version 1.4*/ + bool simplify( QgsVectorLayer* layer, const QString& shapefileName, double tolerance, \ + bool onlySelectedFeatures = false, QProgressDialog* p = 0 ); + + /**Calculate the true centroids, or 'center of mass' for a vector layer and + write it to a new shape file + @param layer input vector layer + @param shapefileName path to the output shp + @param fileEncoding encoding of the output file + @param onlySelectedFeatures if true, only selected features are considered, else all the features + @param p progress dialog (or 0 if no progress dialog is to be shown) + @note: added in version 1.4*/ + bool centroids( QgsVectorLayer* layer, const QString& shapefileName, \ + bool onlySelectedFeatures = false, QProgressDialog* p = 0 ); + + /**Create a polygon based on the extent of all (selected) features and write it to a new shape file + @param layer input vector layer + @param shapefileName path to the output shp + @param fileEncoding encoding of the output file + @param onlySelectedFeatures if true, only selected features are considered, else all the features + @param p progress dialog (or 0 if no progress dialog is to be shown) + @note: added in version 1.4*/ + bool extent( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures = false, QProgressDialog* p = 0 ); /**Create buffers for a vector layer and write it to a new shape file @param layer input vector layer @@ -118,19 +83,45 @@ class ANALYSIS_EXPORT QgsGeometryAnalyzer bool buffer( QgsVectorLayer* layer, const QString& shapefileName, double bufferDistance, \ bool onlySelectedFeatures = false, bool dissolve = false, int bufferDistanceField = -1, QProgressDialog* p = 0 ); + /**Create convex hull(s) of a vector layer and write it to a new shape file + @param layer input vector layer + @param shapefileName path to the output shp + @param fileEncoding encoding of the output file + @param onlySelectedFeatures if true, only selected features are considered, else all the features + @param uniqueIdField index of the attribute field that contains the unique convex hull id (or -1 if + all features have the same buffer distance) + @param p progress dialog (or 0 if no progress dialog is to be shown) + @note: added in version 1.4*/ + bool convexHull( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures = false, \ + int uniqueIdField = -1, QProgressDialog* p = 0 ); + + /**Dissolve a vector layer and write it to a new shape file + @param layer input vector layer + @param shapefileName path to the output shp + @param fileEncoding encoding of the output file + @param onlySelectedFeatures if true, only selected features are considered, else all the features + @param uniqueIdField index of the attribute field that contains the unique id to dissolve on (or -1 if + all features should be dissolved together) + @param p progress dialog (or 0 if no progress dialog is to be shown) + @note: added in version 1.4*/ + bool dissolve( QgsVectorLayer* layer, const QString& shapefileName, bool onlySelectedFeatures = false, \ + int uniqueIdField = -1, QProgressDialog* p = 0 ); + private: QList simpleMeasure( QgsGeometry* geometry ); double perimeterMeasure( QgsGeometry* geometry, QgsDistanceArea& measure ); - QgsFieldMap checkGeometryFields( QgsVectorLayer* layer, int& index1, int& index2 ); - QgsGeometry* extractLines( QgsGeometry* geometry ); - QgsGeometry* extractAsSingle( QgsGeometry* geometry ); - QgsGeometry* extractAsMulti( QgsGeometry* geometry ); - QgsGeometry* convertGeometry( QgsGeometry* geometry ); - QList extractPoints( QgsGeometry* geometry ); + /**Helper function to simplify an individual feature*/ + void simplifyFeature( QgsFeature& f, QgsVectorFileWriter* vfw, double tolerance ); + /**Helper function to get the cetroid of an individual feature*/ + void centroidFeature( QgsFeature& f, QgsVectorFileWriter* vfw ); /**Helper function to buffer an individual feature*/ void bufferFeature( QgsFeature& f, int nProcessedFeatures, QgsVectorFileWriter* vfw, bool dissolve, QgsGeometry** dissolveGeometry, \ double bufferDistance, int bufferDistanceField ); + /**Helper function to get the convex hull of feature(s)*/ + void convexFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry ); + /**Helper function to dissolve feature(s)*/ + void dissolveFeature( QgsFeature& f, int nProcessedFeatures, QgsGeometry** dissolveGeometry ); }; #endif //QGSVECTORANALYZER