Quantum GIS API Documentation
1.8
|
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 : [email protected] 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