Quantum GIS API Documentation  master-693a1fe
src/analysis/vector/qgsoverlayanalyzer.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002     qgsoverlayanalyzer.cpp - QGIS Tools for vector geometry analysis
00003                              -------------------
00004     begin                : 8 Nov 2009
00005     copyright            : (C) Carson J. Q. Farmer
00006     email                : carson.farmer@gmail.com
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "qgsoverlayanalyzer.h"
00019 
00020 #include "qgsapplication.h"
00021 #include "qgsfield.h"
00022 #include "qgsfeature.h"
00023 #include "qgslogger.h"
00024 #include "qgscoordinatereferencesystem.h"
00025 #include "qgsvectorfilewriter.h"
00026 #include "qgsvectordataprovider.h"
00027 #include "qgsdistancearea.h"
00028 #include <QProgressDialog>
00029 
00030 bool QgsOverlayAnalyzer::intersection( QgsVectorLayer* layerA, QgsVectorLayer* layerB,
00031                                        const QString& shapefileName, bool onlySelectedFeatures,
00032                                        QProgressDialog* p )
00033 {
00034   if ( !layerA && !layerB )
00035   {
00036     return false;
00037   }
00038 
00039   QgsVectorDataProvider* dpA = layerA->dataProvider();
00040   QgsVectorDataProvider* dpB = layerB->dataProvider();
00041   if ( !dpA && !dpB )
00042   {
00043     return false;
00044   }
00045 
00046   QGis::WkbType outputType = dpA->geometryType();
00047   const QgsCoordinateReferenceSystem crs = layerA->crs();
00048   QgsFields fieldsA = layerA->pendingFields();
00049   QgsFields fieldsB = layerB->pendingFields();
00050   combineFieldLists( fieldsA, fieldsB );
00051 
00052   QgsVectorFileWriter vWriter( shapefileName, dpA->encoding(), fieldsA, outputType, &crs );
00053   QgsFeature currentFeature;
00054   QgsSpatialIndex index;
00055 
00056   //take only selection
00057   if ( onlySelectedFeatures )
00058   {
00059     const QgsFeatureIds selectionB = layerB->selectedFeaturesIds();
00060     QgsFeatureIds::const_iterator it = selectionB.constBegin();
00061     for ( ; it != selectionB.constEnd(); ++it )
00062     {
00063       if ( !layerB->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) )
00064       {
00065         continue;
00066       }
00067       index.insertFeature( currentFeature );
00068     }
00069     //use QgsVectorLayer::featureAtId
00070     const QgsFeatureIds selectionA = layerA->selectedFeaturesIds();
00071     if ( p )
00072     {
00073       p->setMaximum( selectionA.size() );
00074     }
00075     QgsFeature currentFeature;
00076     int processedFeatures = 0;
00077     it = selectionA.constBegin();
00078     for ( ; it != selectionA.constEnd(); ++it )
00079     {
00080       if ( p )
00081       {
00082         p->setValue( processedFeatures );
00083       }
00084 
00085       if ( p && p->wasCanceled() )
00086       {
00087         break;
00088       }
00089       if ( !layerA->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) )
00090       {
00091         continue;
00092       }
00093       intersectFeature( currentFeature, &vWriter, layerB, &index );
00094       ++processedFeatures;
00095     }
00096 
00097     if ( p )
00098     {
00099       p->setValue( selectionA.size() );
00100     }
00101   }
00102   //take all features
00103   else
00104   {
00105     QgsFeatureIterator fit = layerB->getFeatures();
00106     while ( fit.nextFeature( currentFeature ) )
00107     {
00108       index.insertFeature( currentFeature );
00109     }
00110 
00111     int featureCount = layerA->featureCount();
00112     if ( p )
00113     {
00114       p->setMaximum( featureCount );
00115     }
00116     int processedFeatures = 0;
00117 
00118     fit = layerA->getFeatures();
00119 
00120     QgsFeature currentFeature;
00121     while ( fit.nextFeature( currentFeature ) )
00122     {
00123       if ( p )
00124       {
00125         p->setValue( processedFeatures );
00126       }
00127       if ( p && p->wasCanceled() )
00128       {
00129         break;
00130       }
00131       intersectFeature( currentFeature, &vWriter, layerB, &index );
00132       ++processedFeatures;
00133     }
00134     if ( p )
00135     {
00136       p->setValue( featureCount );
00137     }
00138   }
00139   return true;
00140 }
00141 
00142 void QgsOverlayAnalyzer::intersectFeature( QgsFeature& f, QgsVectorFileWriter* vfw,
00143     QgsVectorLayer* vl, QgsSpatialIndex* index )
00144 {
00145   QgsGeometry* featureGeometry = f.geometry();
00146   QgsGeometry* intersectGeometry = 0;
00147   QgsFeature overlayFeature;
00148 
00149   if ( !featureGeometry )
00150   {
00151     return;
00152   }
00153 
00154   QList<QgsFeatureId> intersects;
00155   intersects = index->intersects( featureGeometry->boundingBox() );
00156   QList<QgsFeatureId>::const_iterator it = intersects.constBegin();
00157   QgsFeature outFeature;
00158   for ( ; it != intersects.constEnd(); ++it )
00159   {
00160     if ( !vl->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( overlayFeature ) )
00161     {
00162       continue;
00163     }
00164 
00165     if ( featureGeometry->intersects( overlayFeature.geometry() ) )
00166     {
00167       intersectGeometry = featureGeometry->intersection( overlayFeature.geometry() );
00168 
00169       outFeature.setGeometry( intersectGeometry );
00170       QgsAttributes attributesA = f.attributes();
00171       QgsAttributes attributesB = overlayFeature.attributes();
00172       combineAttributeMaps( attributesA, attributesB );
00173       outFeature.setAttributes( attributesA );
00174 
00175       //add it to vector file writer
00176       if ( vfw )
00177       {
00178         vfw->addFeature( outFeature );
00179       }
00180     }
00181   }
00182 }
00183 
00184 void QgsOverlayAnalyzer::combineFieldLists( QgsFields& fieldListA, const QgsFields& fieldListB )
00185 {
00186   QList<QString> names;
00187   for ( int idx = 0; idx < fieldListA.count(); ++idx )
00188     names.append( fieldListA[idx].name() );
00189 
00190   for ( int idx = 0; idx < fieldListB.count(); ++idx )
00191   {
00192     QgsField field = fieldListB[idx];
00193     int count = 0;
00194     while ( names.contains( field.name() ) )
00195     {
00196       QString name = QString( "%1_%2" ).arg( field.name() ).arg( count );
00197       field = QgsField( name, field.type() );
00198       ++count;
00199     }
00200     fieldListA.append( field );
00201     names.append( field.name() );
00202   }
00203 }
00204 
00205 void QgsOverlayAnalyzer::combineAttributeMaps( QgsAttributes& attributesA, const QgsAttributes& attributesB )
00206 {
00207   attributesA += attributesB;
00208 }
00209 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines