Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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 /* $Id: qgis.h 9774 2008-12-12 05:41:24Z timlinux $ */
18 
19 #include "qgsoverlayanalyzer.h"
20 
21 #include "qgsapplication.h"
22 #include "qgsfield.h"
23 #include "qgsfeature.h"
24 #include "qgslogger.h"
26 #include "qgsvectorfilewriter.h"
27 #include "qgsvectordataprovider.h"
28 #include "qgsdistancearea.h"
29 #include <QProgressDialog>
30 
32  const QString& shapefileName, bool onlySelectedFeatures,
33  QProgressDialog* p )
34 {
35  if ( !layerA && !layerB )
36  {
37  return false;
38  }
39 
40  QgsVectorDataProvider* dpA = layerA->dataProvider();
41  QgsVectorDataProvider* dpB = layerB->dataProvider();
42  if ( !dpA && !dpB )
43  {
44  return false;
45  }
46 
47  QGis::WkbType outputType = dpA->geometryType();
48  const QgsCoordinateReferenceSystem crs = layerA->crs();
49  QgsFieldMap fieldsA = dpA->fields();
50  QgsFieldMap fieldsB = dpB->fields();
51  combineFieldLists( fieldsA, fieldsB );
52 
53  QgsVectorFileWriter vWriter( shapefileName, dpA->encoding(), fieldsA, outputType, &crs );
54  QgsFeature currentFeature;
55  QgsSpatialIndex index;
56 
57  //take only selection
58  if ( onlySelectedFeatures )
59  {
60  const QgsFeatureIds selectionB = layerB->selectedFeaturesIds();
61  QgsFeatureIds::const_iterator it = selectionB.constBegin();
62  for ( ; it != selectionB.constEnd(); ++it )
63  {
64  if ( !layerB->featureAtId( *it, currentFeature, true, true ) )
65  {
66  continue;
67  }
68  index.insertFeature( currentFeature );
69  }
70  //use QgsVectorLayer::featureAtId
71  const QgsFeatureIds selectionA = layerA->selectedFeaturesIds();
72  if ( p )
73  {
74  p->setMaximum( selectionA.size() );
75  }
76  QgsFeature currentFeature;
77  int processedFeatures = 0;
78  it = selectionA.constBegin();
79  for ( ; it != selectionA.constEnd(); ++it )
80  {
81  if ( p )
82  {
83  p->setValue( processedFeatures );
84  }
85 
86  if ( p && p->wasCanceled() )
87  {
88  break;
89  }
90  if ( !layerA->featureAtId( *it, currentFeature, true, true ) )
91  {
92  continue;
93  }
94  intersectFeature( currentFeature, &vWriter, layerB, &index );
95  ++processedFeatures;
96  }
97 
98  if ( p )
99  {
100  p->setValue( selectionA.size() );
101  }
102  }
103  //take all features
104  else
105  {
106  layerB->select( layerB->pendingAllAttributesList(), QgsRectangle(), true, false );
107  while ( layerB->nextFeature( currentFeature ) )
108  {
109  index.insertFeature( currentFeature );
110  }
111  QgsFeature currentFeature;
112  layerA->select( layerA->pendingAllAttributesList(), QgsRectangle(), true, false );
113 
114  int featureCount = layerA->featureCount();
115  if ( p )
116  {
117  p->setMaximum( featureCount );
118  }
119  int processedFeatures = 0;
120 
121  while ( layerA->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 
143  QgsVectorLayer* vl, QgsSpatialIndex* index )
144 {
145  QgsGeometry* featureGeometry = f.geometry();
146  QgsGeometry* intersectGeometry = 0;
147  QgsFeature overlayFeature;
148 
149  if ( !featureGeometry )
150  {
151  return;
152  }
153 
154  QList<int> intersects;
155  intersects = index->intersects( featureGeometry->boundingBox() );
156  QList<int>::const_iterator it = intersects.constBegin();
157  QgsFeature outFeature;
158  for ( ; it != intersects.constEnd(); ++it )
159  {
160  if ( !vl->featureAtId( *it, overlayFeature, true, true ) )
161  {
162  continue;
163  }
164 
165  if ( featureGeometry->intersects( overlayFeature.geometry() ) )
166  {
167  intersectGeometry = featureGeometry->intersection( overlayFeature.geometry() );
168 
169  outFeature.setGeometry( intersectGeometry );
170  QgsAttributeMap attributeMapA = f.attributeMap();
171  QgsAttributeMap attributeMapB = overlayFeature.attributeMap();
172  combineAttributeMaps( attributeMapA, attributeMapB );
173  outFeature.setAttributeMap( attributeMapA );
174 
175  //add it to vector file writer
176  if ( vfw )
177  {
178  vfw->addFeature( outFeature );
179  }
180  }
181  }
182 }
183 
185 {
186  QList<QString> names;
187  QMap<int, QgsField>::const_iterator j = fieldListA.constBegin();
188  while ( j != fieldListA.constEnd() )
189  {
190  names.append( j.value().name() );
191  ++j;
192  }
193  QMap<int, QgsField>::const_iterator i = fieldListB.constBegin();
194  int count = 0;
195  int fcount = fieldListA.size();
196  QgsField field;
197  while ( i != fieldListB.constEnd() )
198  {
199  field = i.value();
200  while ( names.contains( field.name() ) )
201  {
202  QString name = field.name();
203  name.append( "_" ).append( QString( count ) );
204  field = QgsField( name, field.type() );
205  ++count;
206  }
207  fieldListA.insert( fcount, field );
208  count = 0;
209  ++fcount;
210  ++i;
211  }
212 }
213 
215 {
216  QMap<int, QVariant>::const_iterator i = attributeMapB.constBegin();
217  QVariant attribute;
218  int fcount = attributeMapA.size();
219  while ( i != attributeMapB.constEnd() )
220  {
221  attribute = i.value();
222  attributeMapA.insert( fcount, attribute );
223  ++i;
224  ++fcount;
225  }
226 }
227