QGIS API Documentation  2.11.0-Master
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->fields();
49  QgsFields fieldsB = layerB->fields();
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  if ( !f.constGeometry() )
146  {
147  return;
148  }
149 
150  const QgsGeometry* featureGeometry = f.constGeometry();
151  QgsGeometry* intersectGeometry = 0;
152  QgsFeature overlayFeature;
153 
154  QList<QgsFeatureId> intersects;
155  intersects = index->intersects( featureGeometry->boundingBox() );
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.constGeometry() ) )
166  {
167  intersectGeometry = featureGeometry->intersection( overlayFeature.constGeometry() );
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:70
Wrapper for iterator of features from vector data provider or vector layer.
static unsigned index
void setMaximum(int maximum)
QgsFields fields() const
Returns the list of fields of this layer.
int size() const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
Container of fields for a vector layer.
Definition: qgsfield.h:177
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:75
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:95
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:162
QList< QgsFeatureId > intersects(QgsRectangle rect) const
Returns features that intersect the specified rectangle.
long featureCount(QgsSymbolV2 *symbol)
Number of features rendered with specified symbol.
QString encoding() const
Get encoding which is used for accessing data.
void setValue(int progress)
void setGeometry(const QgsGeometry &geom)
Set this feature's geometry from another QgsGeometry object.
Definition: qgsfeature.cpp:104
void append(const T &value)
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
QgsAttributes attributes() const
Returns the feature's attributes.
Definition: qgsfeature.cpp:90
This class wraps a request for features to a vector layer (or directly its vector data provider)...
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:235
const_iterator constEnd() const
int count() const
Return number of items.
Definition: qgsfield.cpp:285
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:40
virtual QGis::WkbType geometryType() const =0
Get feature type.
bool contains(const T &value) const
const_iterator constBegin() const
QgsGeometry * intersection(const QgsGeometry *geometry) const
Returns a geometry representing the points shared by this geometry and other.
bool insertFeature(const QgsFeature &f)
Add feature to index.
Class for storing a coordinate reference system (CRS)
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:68
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
QgsVectorDataProvider * dataProvider()
Returns the data provider.
const_iterator constEnd() const
bool nextFeature(QgsFeature &f)
const_iterator constBegin() const
This is the base class for vector data providers.
A vector of attributes.
Definition: qgsfeature.h:109
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.
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
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:75