QGIS API Documentation  2.14.0-Essen
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 : [email protected]
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 = nullptr;
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.at( 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 
Wrapper for iterator of features from vector data provider or vector layer.
static unsigned index
QList< QgsFeatureId > intersects(const QgsRectangle &rect) const
Returns features that intersect the specified rectangle.
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:187
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:76
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:115
bool addFeature(QgsFeature &feature, QgsFeatureRendererV2 *renderer=nullptr, QGis::UnitType outputUnit=QGis::Meters)
Add feature to the currently opened data source.
WkbType
Used for symbology operations.
Definition: qgis.h:57
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:187
long featureCount(QgsSymbolV2 *symbol)
Number of features rendered with specified symbol.
QString encoding() const
Get encoding which is used for accessing data.
bool intersection(QgsVectorLayer *layerA, QgsVectorLayer *layerB, const QString &shapefileName, bool onlySelectedFeatures=false, QProgressDialog *p=nullptr)
Perform an intersection on two input vector layers and write output to a new shape file...
void setValue(int progress)
void setGeometry(const QgsGeometry &geom)
Set this feature&#39;s geometry from another QgsGeometry object.
Definition: qgsfeature.cpp:124
void append(const T &value)
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
QString name() const
Gets the name of the field.
Definition: qgsfield.cpp:84
This class wraps a request for features to a vector layer (or directly its vector data provider)...
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:309
const_iterator constEnd() const
int count() const
Return number of items.
Definition: qgsfield.cpp:365
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
virtual QGis::WkbType geometryType() const =0
Get feature type.
const QgsField & at(int i) const
Get field at particular index (must be in range 0..N-1)
Definition: qgsfield.cpp:385
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:82
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;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:115
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
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:89