Quantum GIS API Documentation  1.8
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   QgsFieldMap fieldsA = dpA->fields();
00049   QgsFieldMap fieldsB = dpB->fields();
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->featureAtId( *it, currentFeature, true, true ) )
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->featureAtId( *it, currentFeature, true, true ) )
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     layerB->select( layerB->pendingAllAttributesList(), QgsRectangle(), true, false );
00106     while ( layerB->nextFeature( currentFeature ) )
00107     {
00108       index.insertFeature( currentFeature );
00109     }
00110     QgsFeature currentFeature;
00111     layerA->select( layerA->pendingAllAttributesList(), QgsRectangle(), true, false );
00112 
00113     int featureCount = layerA->featureCount();
00114     if ( p )
00115     {
00116       p->setMaximum( featureCount );
00117     }
00118     int processedFeatures = 0;
00119 
00120     while ( layerA->nextFeature( currentFeature ) )
00121     {
00122       if ( p )
00123       {
00124         p->setValue( processedFeatures );
00125       }
00126       if ( p && p->wasCanceled() )
00127       {
00128         break;
00129       }
00130       intersectFeature( currentFeature, &vWriter, layerB, &index );
00131       ++processedFeatures;
00132     }
00133     if ( p )
00134     {
00135       p->setValue( featureCount );
00136     }
00137   }
00138   return true;
00139 }
00140 
00141 void QgsOverlayAnalyzer::intersectFeature( QgsFeature& f, QgsVectorFileWriter* vfw,
00142     QgsVectorLayer* vl, QgsSpatialIndex* index )
00143 {
00144   QgsGeometry* featureGeometry = f.geometry();
00145   QgsGeometry* intersectGeometry = 0;
00146   QgsFeature overlayFeature;
00147 
00148   if ( !featureGeometry )
00149   {
00150     return;
00151   }
00152 
00153   QList<QgsFeatureId> intersects;
00154   intersects = index->intersects( featureGeometry->boundingBox() );
00155   QList<QgsFeatureId>::const_iterator it = intersects.constBegin();
00156   QgsFeature outFeature;
00157   for ( ; it != intersects.constEnd(); ++it )
00158   {
00159     if ( !vl->featureAtId( *it, overlayFeature, true, true ) )
00160     {
00161       continue;
00162     }
00163 
00164     if ( featureGeometry->intersects( overlayFeature.geometry() ) )
00165     {
00166       intersectGeometry = featureGeometry->intersection( overlayFeature.geometry() );
00167 
00168       outFeature.setGeometry( intersectGeometry );
00169       QgsAttributeMap attributeMapA = f.attributeMap();
00170       QgsAttributeMap attributeMapB = overlayFeature.attributeMap();
00171       combineAttributeMaps( attributeMapA, attributeMapB );
00172       outFeature.setAttributeMap( attributeMapA );
00173 
00174       //add it to vector file writer
00175       if ( vfw )
00176       {
00177         vfw->addFeature( outFeature );
00178       }
00179     }
00180   }
00181 }
00182 
00183 void QgsOverlayAnalyzer::combineFieldLists( QgsFieldMap& fieldListA, QgsFieldMap fieldListB )
00184 {
00185   QList<QString> names;
00186   QMap<int, QgsField>::const_iterator j = fieldListA.constBegin();
00187   while ( j != fieldListA.constEnd() )
00188   {
00189     names.append( j.value().name() );
00190     ++j;
00191   }
00192   QMap<int, QgsField>::const_iterator i = fieldListB.constBegin();
00193   int count = 0;
00194   int fcount = fieldListA.size();
00195   QgsField field;
00196   while ( i != fieldListB.constEnd() )
00197   {
00198     field = i.value();
00199     while ( names.contains( field.name() ) )
00200     {
00201       QString name = field.name();
00202       name.append( "_" ).append( QString( count ) );
00203       field = QgsField( name, field.type() );
00204       ++count;
00205     }
00206     fieldListA.insert( fcount, field );
00207     count = 0;
00208     ++fcount;
00209     ++i;
00210   }
00211 }
00212 
00213 void QgsOverlayAnalyzer::combineAttributeMaps( QgsAttributeMap& attributeMapA, QgsAttributeMap attributeMapB )
00214 {
00215   QMap<int, QVariant>::const_iterator i = attributeMapB.constBegin();
00216   QVariant attribute;
00217   int fcount = attributeMapA.size();
00218   while ( i != attributeMapB.constEnd() )
00219   {
00220     attribute = i.value();
00221     attributeMapA.insert( fcount, attribute );
00222     ++i;
00223     ++fcount;
00224   }
00225 }
00226 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines