QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsfeature.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsfeature.cpp - Spatial Feature Implementation
3  --------------------------------------
4 Date : 09-Sep-2003
5 Copyright : (C) 2003 by Gary E.Sherman
6 email : sherman at mrcc.com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsfeature.h"
17 #include "qgsfeature_p.h"
18 #include "qgsfields.h"
19 #include "qgsgeometry.h"
20 #include "qgsrectangle.h"
21 
22 #include "qgsmessagelog.h"
23 
24 #include <QDataStream>
25 
26 /***************************************************************************
27  * This class is considered CRITICAL and any change MUST be accompanied with
28  * full unit tests in testqgsfeature.cpp.
29  * See details in QEP #17
30  ****************************************************************************/
31 
32 
33 //
34 // QgsFeature
35 //
36 
38 {
39  d = new QgsFeaturePrivate( id );
40 }
41 
43 {
44  d = new QgsFeaturePrivate( id );
45  d->fields = fields;
46  initAttributes( d->fields.count() );
47 }
48 
49 QgsFeature::QgsFeature( const QgsFeature &rhs ) //NOLINT
50  : d( rhs.d )
51 {
52 }
53 
55 {
56  d = rhs.d;
57  return *this;
58 }
59 
60 bool QgsFeature::operator ==( const QgsFeature &other ) const
61 {
62  if ( d == other.d )
63  return true;
64 
65  if ( d->fid == other.d->fid
66  && d->valid == other.d->valid
67  && d->fields == other.d->fields
68  && d->attributes == other.d->attributes
69  && d->geometry.equals( other.d->geometry ) )
70  return true;
71 
72  return false;
73 }
74 
75 bool QgsFeature::operator!=( const QgsFeature &other ) const
76 {
77  return !( *this == other );
78 }
79 
81 {
82 }
83 
84 /***************************************************************************
85  * This class is considered CRITICAL and any change MUST be accompanied with
86  * full unit tests in testqgsfeature.cpp.
87  * See details in QEP #17
88  ****************************************************************************/
89 
91 {
92  return d->fid;
93 }
94 
95 void QgsFeature::deleteAttribute( int field )
96 {
97  d.detach();
98  d->attributes.remove( field );
99 }
100 
102 {
103  return d->geometry;
104 }
105 
106 /***************************************************************************
107  * This class is considered CRITICAL and any change MUST be accompanied with
108  * full unit tests in testqgsfeature.cpp.
109  * See details in QEP #17
110  ****************************************************************************/
111 
113 {
114  if ( id == d->fid )
115  return;
116 
117  d.detach();
118  d->fid = id;
119  d->valid = true;
120 }
121 
123 {
124  return d->attributes;
125 }
126 
128 {
129  if ( attrs == d->attributes )
130  return;
131 
132  d.detach();
133  d->attributes = attrs;
134  d->valid = true;
135 }
136 
138 {
139  d.detach();
140  d->geometry = geometry;
141  d->valid = true;
142 }
143 
144 void QgsFeature::setGeometry( std::unique_ptr<QgsAbstractGeometry> geometry )
145 {
146  d.detach();
147  d->geometry = QgsGeometry( std::move( geometry ) );
148  d->valid = true;
149 }
150 
152 {
154 }
155 
156 /***************************************************************************
157  * This class is considered CRITICAL and any change MUST be accompanied with
158  * full unit tests in testqgsfeature.cpp.
159  * See details in QEP #17
160  ****************************************************************************/
161 
162 void QgsFeature::setFields( const QgsFields &fields, bool init )
163 {
164  d.detach();
165  d->fields = fields;
166  if ( init )
167  {
168  initAttributes( d->fields.count() );
169  }
170 }
171 
173 {
174  return d->fields;
175 }
176 
177 /***************************************************************************
178  * This class is considered CRITICAL and any change MUST be accompanied with
179  * full unit tests in testqgsfeature.cpp.
180  * See details in QEP #17
181  ****************************************************************************/
182 
184 {
185  return d->valid;
186 }
187 
188 void QgsFeature::setValid( bool validity )
189 {
190  if ( d->valid == validity )
191  return;
192 
193  d.detach();
194  d->valid = validity;
195 }
196 
198 {
199  return !d->geometry.isNull();
200 }
201 
202 void QgsFeature::initAttributes( int fieldCount )
203 {
204  d.detach();
205  d->attributes.resize( 0 ); // clears existing elements, while still preserving the currently allocated capacity of the list (unlike clear)
206  // ensures ALL attributes, including previously existing ones are default constructed.
207  // doing it this way also avoids clearing individual QVariants -- which can trigger a detachment. Cheaper just to make a new one.
208  d->attributes.resize( fieldCount );
209 }
210 
211 bool QgsFeature::setAttribute( int idx, const QVariant &value )
212 {
213  if ( idx < 0 || idx >= d->attributes.size() )
214  {
215  QgsMessageLog::logMessage( QObject::tr( "Attribute index %1 out of bounds [0;%2]" ).arg( idx ).arg( d->attributes.size() ), QString(), Qgis::Warning );
216  return false;
217  }
218 
219  d.detach();
220  d->attributes[idx] = value;
221  d->valid = true;
222  return true;
223 }
224 
225 /***************************************************************************
226  * This class is considered CRITICAL and any change MUST be accompanied with
227  * full unit tests in testqgsfeature.cpp.
228  * See details in QEP #17
229  ****************************************************************************/
230 
231 bool QgsFeature::setAttribute( const QString &name, const QVariant &value )
232 {
233  int fieldIdx = fieldNameIndex( name );
234  if ( fieldIdx == -1 )
235  return false;
236 
237  d.detach();
238  d->attributes[fieldIdx] = value;
239  d->valid = true;
240  return true;
241 }
242 
243 bool QgsFeature::deleteAttribute( const QString &name )
244 {
245  int fieldIdx = fieldNameIndex( name );
246  if ( fieldIdx == -1 )
247  return false;
248 
249  d.detach();
250  d->attributes[fieldIdx].clear();
251  return true;
252 }
253 
254 QVariant QgsFeature::attribute( int fieldIdx ) const
255 {
256  if ( fieldIdx < 0 || fieldIdx >= d->attributes.count() )
257  return QVariant();
258 
259  return d->attributes.at( fieldIdx );
260 }
261 
262 QVariant QgsFeature::attribute( const QString &name ) const
263 {
264  int fieldIdx = fieldNameIndex( name );
265  if ( fieldIdx == -1 )
266  return QVariant();
267 
268  return d->attributes.at( fieldIdx );
269 }
270 
271 /***************************************************************************
272  * This class is considered CRITICAL and any change MUST be accompanied with
273  * full unit tests in testqgsfeature.cpp.
274  * See details in QEP #17
275  ****************************************************************************/
276 
277 int QgsFeature::fieldNameIndex( const QString &fieldName ) const
278 {
279  return d->fields.lookupField( fieldName );
280 }
281 
282 /***************************************************************************
283  * This class is considered CRITICAL and any change MUST be accompanied with
284  * full unit tests in testqgsfeature.cpp.
285  * See details in QEP #17
286  ****************************************************************************/
287 
288 QDataStream &operator<<( QDataStream &out, const QgsFeature &feature )
289 {
290  out << feature.id();
291  out << feature.attributes();
292  if ( feature.hasGeometry() )
293  {
294  out << ( feature.geometry() );
295  }
296  else
297  {
299  out << geometry;
300  }
301  out << feature.isValid();
302  return out;
303 }
304 
305 QDataStream &operator>>( QDataStream &in, QgsFeature &feature )
306 {
309  bool valid;
310  QgsAttributes attr;
311  in >> id >> attr >> geometry >> valid;
312  feature.setId( id );
313  feature.setGeometry( geometry );
314  feature.setAttributes( attr );
315  feature.setValid( valid );
316  return in;
317 }
318 
319 uint qHash( const QgsFeature &key, uint seed )
320 {
321  uint hash = seed;
322  Q_FOREACH ( const QVariant &attr, key.attributes() )
323  {
324  hash ^= qHash( attr.toString() );
325  }
326 
327  hash ^= qHash( key.geometry().asWkt() );
328  hash ^= qHash( key.id() );
329 
330  return hash;
331 }
332 
QgsFeatureId id() const
Gets the feature ID for this feature.
QgsFeatureId id
Definition: qgsfeature.h:64
void setFields(const QgsFields &fields, bool initAttributes=false)
Assign a field map with the feature to allow attribute access by attribute name.
Definition: qgsfeature.cpp:162
bool isValid() const
Returns the validity of this feature.
Definition: qgsfeature.cpp:183
int fieldNameIndex(const QString &fieldName) const
Utility method to get attribute index from name.
Definition: qgsfeature.cpp:277
virtual ~QgsFeature()
Definition: qgsfeature.cpp:80
QgsFeature & operator=(const QgsFeature &rhs)
Assignment operator.
Definition: qgsfeature.cpp:54
uint qHash(const QgsFeature &key, uint seed)
Definition: qgsfeature.cpp:319
qint64 QgsFeatureId
Definition: qgsfeatureid.h:25
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:127
bool setAttribute(int field, const QVariant &attr)
Set an attribute&#39;s value by field index.
Definition: qgsfeature.cpp:211
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
QDataStream & operator>>(QDataStream &in, QgsFeature &feature)
Reads a feature from stream in into feature. QGIS version compatibility is not guaranteed.
Definition: qgsfeature.cpp:305
QgsFields fields() const
Returns the field map associated with the feature.
void deleteAttribute(int field)
Deletes an attribute and its value.
Definition: qgsfeature.cpp:95
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
QDataStream & operator<<(QDataStream &out, const QgsFeature &feature)
Writes the feature to stream out. QGIS version compatibility is not guaranteed.
Definition: qgsfeature.cpp:288
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:202
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
void seed(uint32_t value)
void setId(QgsFeatureId id)
Sets the feature ID for this feature.
Definition: qgsfeature.cpp:112
QgsGeometry geometry() const
Returns the geometry associated with this feature.
QgsFeature(QgsFeatureId id=QgsFeatureId())
Constructor for QgsFeature.
Definition: qgsfeature.cpp:37
bool operator!=(const QgsFeature &other) const
Compares two features.
Definition: qgsfeature.cpp:75
void setValid(bool validity)
Sets the validity of the feature.
Definition: qgsfeature.cpp:188
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:151
QString asWkt(int precision=17) const
Exports the geometry to WKT.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:262
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
bool operator==(const QgsFeature &other) const
Compares two features.
Definition: qgsfeature.cpp:60
QgsGeometry geometry
Definition: qgsfeature.h:67
A vector of attributes.
Definition: qgsattributes.h:57
QgsAttributes attributes
Definition: qgsfeature.h:65