00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgsoverlayanalyzer.h"
00020
00021 #include "qgsapplication.h"
00022 #include "qgsfield.h"
00023 #include "qgsfeature.h"
00024 #include "qgslogger.h"
00025 #include "qgscoordinatereferencesystem.h"
00026 #include "qgsvectorfilewriter.h"
00027 #include "qgsvectordataprovider.h"
00028 #include "qgsdistancearea.h"
00029 #include <QProgressDialog>
00030
00031 bool QgsOverlayAnalyzer::intersection( QgsVectorLayer* layerA, QgsVectorLayer* layerB,
00032 const QString& shapefileName, bool onlySelectedFeatures,
00033 QProgressDialog* p )
00034 {
00035 if ( !layerA && !layerB )
00036 {
00037 return false;
00038 }
00039
00040 QgsVectorDataProvider* dpA = layerA->dataProvider();
00041 QgsVectorDataProvider* dpB = layerB->dataProvider();
00042 if ( !dpA && !dpB )
00043 {
00044 return false;
00045 }
00046
00047 QGis::WkbType outputType = dpA->geometryType();
00048 const QgsCoordinateReferenceSystem crs = layerA->srs();
00049 QgsFieldMap fieldsA = dpA->fields();
00050 QgsFieldMap fieldsB = dpB->fields();
00051 combineFieldLists( fieldsA, fieldsB );
00052
00053 QgsVectorFileWriter vWriter( shapefileName, dpA->encoding(), fieldsA, outputType, &crs );
00054 QgsFeature currentFeature;
00055 QgsSpatialIndex index;
00056
00057
00058 if ( onlySelectedFeatures )
00059 {
00060 const QgsFeatureIds selectionB = layerB->selectedFeaturesIds();
00061 QgsFeatureIds::const_iterator it = selectionB.constBegin();
00062 for ( ; it != selectionB.constEnd(); ++it )
00063 {
00064 if ( !layerB->featureAtId( *it, currentFeature, true, true ) )
00065 {
00066 continue;
00067 }
00068 index.insertFeature( currentFeature );
00069 }
00070
00071 const QgsFeatureIds selectionA = layerA->selectedFeaturesIds();
00072 if ( p )
00073 {
00074 p->setMaximum( selectionA.size() );
00075 }
00076 QgsFeature currentFeature;
00077 int processedFeatures = 0;
00078 it = selectionA.constBegin();
00079 for ( ; it != selectionA.constEnd(); ++it )
00080 {
00081 if ( p )
00082 {
00083 p->setValue( processedFeatures );
00084 }
00085
00086 if ( p && p->wasCanceled() )
00087 {
00088 break;
00089 }
00090 if ( !layerA->featureAtId( *it, currentFeature, true, true ) )
00091 {
00092 continue;
00093 }
00094 intersectFeature( currentFeature, &vWriter, layerB, &index );
00095 ++processedFeatures;
00096 }
00097
00098 if ( p )
00099 {
00100 p->setValue( selectionA.size() );
00101 }
00102 }
00103
00104 else
00105 {
00106 layerB->select( layerB->pendingAllAttributesList(), QgsRectangle(), true, false );
00107 while ( layerB->nextFeature( currentFeature ) )
00108 {
00109 index.insertFeature( currentFeature );
00110 }
00111 QgsFeature currentFeature;
00112 layerA->select( layerA->pendingAllAttributesList(), QgsRectangle(), true, false );
00113
00114 int featureCount = layerA->featureCount();
00115 if ( p )
00116 {
00117 p->setMaximum( featureCount );
00118 }
00119 int processedFeatures = 0;
00120
00121 while ( layerA->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<int> intersects;
00155 intersects = index->intersects( featureGeometry->boundingBox() );
00156 QList<int>::const_iterator it = intersects.constBegin();
00157 QgsFeature outFeature;
00158 for ( ; it != intersects.constEnd(); ++it )
00159 {
00160 if ( !vl->featureAtId( *it, overlayFeature, true, true ) )
00161 {
00162 continue;
00163 }
00164
00165 if ( featureGeometry->intersects( overlayFeature.geometry() ) )
00166 {
00167 intersectGeometry = featureGeometry->intersection( overlayFeature.geometry() );
00168
00169 outFeature.setGeometry( intersectGeometry );
00170 QgsAttributeMap attributeMapA = f.attributeMap();
00171 QgsAttributeMap attributeMapB = overlayFeature.attributeMap();
00172 combineAttributeMaps( attributeMapA, attributeMapB );
00173 outFeature.setAttributeMap( attributeMapA );
00174
00175
00176 if ( vfw )
00177 {
00178 vfw->addFeature( outFeature );
00179 }
00180 }
00181 }
00182 }
00183
00184 void QgsOverlayAnalyzer::combineFieldLists( QgsFieldMap& fieldListA, QgsFieldMap fieldListB )
00185 {
00186 QList<QString> names;
00187 QMap<int, QgsField>::const_iterator j = fieldListA.constBegin();
00188 while ( j != fieldListA.constEnd() )
00189 {
00190 names.append( j.value().name() );
00191 ++j;
00192 }
00193 QMap<int, QgsField>::const_iterator i = fieldListB.constBegin();
00194 int count = 0;
00195 int fcount = fieldListA.size();
00196 QgsField field;
00197 while ( i != fieldListB.constEnd() )
00198 {
00199 field = i.value();
00200 while ( names.contains( field.name() ) )
00201 {
00202 QString name = field.name();
00203 name.append( "_" ).append( QString( count ) );
00204 field = QgsField( name, field.type() );
00205 ++count;
00206 }
00207 fieldListA.insert( fcount, field );
00208 count = 0;
00209 ++fcount;
00210 ++i;
00211 }
00212 }
00213
00214 void QgsOverlayAnalyzer::combineAttributeMaps( QgsAttributeMap& attributeMapA, QgsAttributeMap attributeMapB )
00215 {
00216 QMap<int, QVariant>::const_iterator i = attributeMapB.constBegin();
00217 QVariant attribute;
00218 int fcount = attributeMapA.size();
00219 while ( i != attributeMapB.constEnd() )
00220 {
00221 attribute = i.value();
00222 attributeMapA.insert( fcount, attribute );
00223 ++i;
00224 ++fcount;
00225 }
00226 }
00227