QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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  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  Q_FOREACH ( const QgsField& field, fieldListA )
188  names.append( field.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 
QString encoding() const
Get encoding which is used for accessing data.
Wrapper for iterator of features from vector data provider or vector layer.
static unsigned index
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
QString name
Definition: qgsfield.h:52
void setMaximum(int maximum)
int size() const
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QList< QgsFeatureId > intersects(const QgsRectangle &rect) const
Returns features that intersect the specified rectangle.
const QgsCoordinateReferenceSystem & crs() const
Returns layer&#39;s spatial reference system.
Container of fields for a vector layer.
Definition: qgsfield.h:252
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:61
const QgsGeometry * constGeometry() const
Gets a const pointer to the geometry object associated with this feature.
Definition: qgsfeature.cpp:82
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
int count() const
Return number of items.
Definition: qgsfield.cpp:402
QgsFields fields() const
Returns the list of fields of this layer.
long featureCount(QgsSymbolV2 *symbol)
Number of features rendered with specified symbol.
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)
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:346
const_iterator constEnd() const
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
virtual QGis::WkbType geometryType() const =0
Get feature type.
bool contains(const T &value) const
const_iterator constBegin() const
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
bool insertFeature(const QgsFeature &f)
Add feature to index.
QgsRectangle boundingBox() const
Returns the bounding box of this feature.
Class for storing a coordinate reference system (CRS)
QgsGeometry * intersection(const QgsGeometry *geometry) const
Returns a geometry representing the points shared by this geometry and other.
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
Represents a vector layer which manages a vector based data sets.
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:97
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const