QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
qgsoverlayanalyzer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsoverlayanalyzer.cpp - QGIS Tools for vector geometry analysis
3  -------------------
4  begin : 8 Nov 2009
5  copyright : (C) Carson J. Q. Farmer
6  email : carson.farmer@gmail.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgsoverlayanalyzer.h"
19 
20 #include "qgsapplication.h"
21 #include "qgsfield.h"
22 #include "qgsfeature.h"
23 #include "qgslogger.h"
25 #include "qgsvectorfilewriter.h"
26 #include "qgsvectordataprovider.h"
27 #include "qgsdistancearea.h"
28 #include <QProgressDialog>
29 
31  const QString& shapefileName, bool onlySelectedFeatures,
32  QProgressDialog* p )
33 {
34  if ( !layerA && !layerB )
35  {
36  return false;
37  }
38 
39  QgsVectorDataProvider* dpA = layerA->dataProvider();
40  QgsVectorDataProvider* dpB = layerB->dataProvider();
41  if ( !dpA && !dpB )
42  {
43  return false;
44  }
45 
46  QGis::WkbType outputType = dpA->geometryType();
47  const QgsCoordinateReferenceSystem crs = layerA->crs();
48  QgsFields fieldsA = layerA->pendingFields();
49  QgsFields fieldsB = layerB->pendingFields();
50  combineFieldLists( fieldsA, fieldsB );
51 
52  QgsVectorFileWriter vWriter( shapefileName, dpA->encoding(), fieldsA, outputType, &crs );
53  QgsFeature currentFeature;
55 
56  //take only selection
57  if ( onlySelectedFeatures )
58  {
59  const QgsFeatureIds selectionB = layerB->selectedFeaturesIds();
60  QgsFeatureIds::const_iterator it = selectionB.constBegin();
61  for ( ; it != selectionB.constEnd(); ++it )
62  {
63  if ( !layerB->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) )
64  {
65  continue;
66  }
67  index.insertFeature( currentFeature );
68  }
69  //use QgsVectorLayer::featureAtId
70  const QgsFeatureIds selectionA = layerA->selectedFeaturesIds();
71  if ( p )
72  {
73  p->setMaximum( selectionA.size() );
74  }
75  QgsFeature currentFeature;
76  int processedFeatures = 0;
77  it = selectionA.constBegin();
78  for ( ; it != selectionA.constEnd(); ++it )
79  {
80  if ( p )
81  {
82  p->setValue( processedFeatures );
83  }
84 
85  if ( p && p->wasCanceled() )
86  {
87  break;
88  }
89  if ( !layerA->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( currentFeature ) )
90  {
91  continue;
92  }
93  intersectFeature( currentFeature, &vWriter, layerB, &index );
94  ++processedFeatures;
95  }
96 
97  if ( p )
98  {
99  p->setValue( selectionA.size() );
100  }
101  }
102  //take all features
103  else
104  {
105  QgsFeatureIterator fit = layerB->getFeatures();
106  while ( fit.nextFeature( currentFeature ) )
107  {
108  index.insertFeature( currentFeature );
109  }
110 
111  int featureCount = layerA->featureCount();
112  if ( p )
113  {
114  p->setMaximum( featureCount );
115  }
116  int processedFeatures = 0;
117 
118  fit = layerA->getFeatures();
119 
120  QgsFeature currentFeature;
121  while ( fit.nextFeature( currentFeature ) )
122  {
123  if ( p )
124  {
125  p->setValue( processedFeatures );
126  }
127  if ( p && p->wasCanceled() )
128  {
129  break;
130  }
131  intersectFeature( currentFeature, &vWriter, layerB, &index );
132  ++processedFeatures;
133  }
134  if ( p )
135  {
136  p->setValue( featureCount );
137  }
138  }
139  return true;
140 }
141 
142 void QgsOverlayAnalyzer::intersectFeature( QgsFeature& f, QgsVectorFileWriter* vfw,
144 {
145  QgsGeometry* featureGeometry = f.geometry();
146  QgsGeometry* intersectGeometry = 0;
147  QgsFeature overlayFeature;
148 
149  if ( !featureGeometry )
150  {
151  return;
152  }
153 
154  QList<QgsFeatureId> intersects;
155  intersects = index->intersects( featureGeometry->boundingBox() );
156  QList<QgsFeatureId>::const_iterator it = intersects.constBegin();
157  QgsFeature outFeature;
158  for ( ; it != intersects.constEnd(); ++it )
159  {
160  if ( !vl->getFeatures( QgsFeatureRequest().setFilterFid( *it ) ).nextFeature( overlayFeature ) )
161  {
162  continue;
163  }
164 
165  if ( featureGeometry->intersects( overlayFeature.geometry() ) )
166  {
167  intersectGeometry = featureGeometry->intersection( overlayFeature.geometry() );
168 
169  outFeature.setGeometry( intersectGeometry );
170  QgsAttributes attributesA = f.attributes();
171  QgsAttributes attributesB = overlayFeature.attributes();
172  combineAttributeMaps( attributesA, attributesB );
173  outFeature.setAttributes( attributesA );
174 
175  //add it to vector file writer
176  if ( vfw )
177  {
178  vfw->addFeature( outFeature );
179  }
180  }
181  }
182 }
183 
184 void QgsOverlayAnalyzer::combineFieldLists( QgsFields& fieldListA, const QgsFields& fieldListB )
185 {
186  QList<QString> names;
187  for ( int idx = 0; idx < fieldListA.count(); ++idx )
188  names.append( fieldListA[idx].name() );
189 
190  for ( int idx = 0; idx < fieldListB.count(); ++idx )
191  {
192  QgsField field = fieldListB[idx];
193  int count = 0;
194  while ( names.contains( field.name() ) )
195  {
196  QString name = QString( "%1_%2" ).arg( field.name() ).arg( count );
197  field = QgsField( name, field.type() );
198  ++count;
199  }
200  fieldListA.append( field );
201  names.append( field.name() );
202  }
203 }
204 
205 void QgsOverlayAnalyzer::combineAttributeMaps( QgsAttributes& attributesA, const QgsAttributes& attributesB )
206 {
207  attributesA += attributesB;
208 }
209 
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:59
Wrapper for iterator of features from vector data provider or vector layer.
static unsigned index
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:317
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
Container of fields for a vector layer.
Definition: qgsfield.h:172
void setAttributes(const QgsAttributes &attrs)
Definition: qgsfeature.h:144
WkbType
Used for symbology operations.
Definition: qgis.h:53
A convenience class for writing vector files to disk.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
QList< QgsFeatureId > intersects(QgsRectangle rect) const
returns features that intersect the specified rectangle
QString encoding() const
Get encoding which is used for accessing data.
void setGeometry(const QgsGeometry &geom)
Set this feature's geometry from another QgsGeometry object (deep copy)
Definition: qgsfeature.cpp:134
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
const QgsAttributes & attributes() const
Definition: qgsfeature.h:142
bool addFeature(QgsFeature &feature, QgsFeatureRendererV2 *renderer=0, QGis::UnitType outputUnit=QGis::Meters)
add feature to the currently opened shapefile
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Append a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfield.cpp:162
int count() const
Return number of items.
Definition: qgsfield.h:214
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:33
virtual QGis::WkbType geometryType() const =0
Get feature type.
QgsGeometry * intersection(QgsGeometry *geometry)
Returns a geometry representing the points shared by this geometry and other.
QgsRectangle boundingBox()
Returns the bounding box of this feature.
virtual long featureCount() const
Number of features in the layer.
bool insertFeature(const QgsFeature &f)
add feature to index
QVector< QVariant > QgsAttributes
Definition: qgsfeature.h:100
Class for storing a coordinate reference system (CRS)
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QgsVectorDataProvider * dataProvider()
Returns the data provider.
bool nextFeature(QgsFeature &f)
This is the base class for vector data providers.
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
Represents a vector layer which manages a vector based data sets.
bool intersection(QgsVectorLayer *layerA, QgsVectorLayer *layerB, const QString &shapefileName, bool onlySelectedFeatures=false, QProgressDialog *p=0)
Perform an intersection on two input vector layers and write output to a new shape file...
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:64