void RgShortestPathWidget::exportPath() { RgExportDlg dlg( this ); if ( !dlg.exec() ) return; QgsVectorLayer *vl = dlg.mapLayer(); if ( vl == NULL ) return; QgsPoint p1, p2; QgsGraph *path = getPath( p1, p2 ); if ( path == NULL ) return; QgsCoordinateTransform ct( mPlugin->iface()->mapCanvas()->mapSettings().destinationCrs(), vl->crs() ); int startVertexIdx = path->findVertex( p1 ); int stopVertexIdx = path->findVertex( p2 ); double time = 0.0; double cost = 0.0; Unit timeUnit = Unit::byName( mPlugin->timeUnitName() ); Unit distanceUnit = Unit::byName( mPlugin->distanceUnitName() ); QgsPolyline p; while ( startVertexIdx != stopVertexIdx ) { if ( stopVertexIdx < 0 ) break; QgsGraphArcIdList l = path->vertex( stopVertexIdx ).inArc(); if ( l.empty() ) break; const QgsGraphArc& e = path->arc( l.front() ); cost += e.property( 0 ).toDouble(); time += e.property( 1 ).toDouble(); p.push_front( ct.transform( path->vertex( e.inVertex() ).point() ) ); stopVertexIdx = e.outVertex(); } p.push_front( ct.transform( p1 ) ); QgsFeature f; f.initAttributes( vl->pendingFields().count() ); f.setGeometry( QgsGeometry::fromPolyline( p ) ); f.setAttribute( 0, cost / distanceUnit.multipler() ); f.setAttribute( 1, time / timeUnit.multipler() ); QgsFeatureList features; features << f; vl->dataProvider()->addFeatures( features ); vl->updateExtents(); mPlugin->iface()->mapCanvas()->update(); delete path; }
void QgsGPXFeatureIterator::readAttributes( QgsFeature& feature, const QgsWaypoint& wpt ) { // add attributes if they are wanted for ( int i = 0; i < mSource->mFields.count(); ++i ) { switch ( mSource->indexToAttr[i] ) { case QgsGPXProvider::NameAttr: feature.setAttribute( i, QVariant( wpt.name ) ); break; case QgsGPXProvider::EleAttr: if ( wpt.ele != -std::numeric_limits<double>::max() ) feature.setAttribute( i, QVariant( wpt.ele ) ); break; case QgsGPXProvider::SymAttr: feature.setAttribute( i, QVariant( wpt.sym ) ); break; case QgsGPXProvider::CmtAttr: feature.setAttribute( i, QVariant( wpt.cmt ) ); break; case QgsGPXProvider::DscAttr: feature.setAttribute( i, QVariant( wpt.desc ) ); break; case QgsGPXProvider::SrcAttr: feature.setAttribute( i, QVariant( wpt.src ) ); break; case QgsGPXProvider::URLAttr: feature.setAttribute( i, QVariant( wpt.url ) ); break; case QgsGPXProvider::URLNameAttr: feature.setAttribute( i, QVariant( wpt.urlname ) ); break; } } }
void eval_columns() { QgsFields fields; fields.append( QgsField( "x1" ) ); fields.append( QgsField( "x2" ) ); fields.append( QgsField( "foo", QVariant::Int ) ); QgsFeature f; f.initAttributes( 3 ); f.setAttribute( 2, QVariant( 20 ) ); // good exp QgsExpression exp( "foo + 1" ); bool prepareRes = exp.prepare( fields ); QCOMPARE( prepareRes, true ); QCOMPARE( exp.hasEvalError(), false ); QVariant res = exp.evaluate( &f ); QCOMPARE( res.type(), QVariant::Int ); QCOMPARE( res.toInt(), 21 ); // bad exp QgsExpression exp2( "bar + 1" ); bool prepareRes2 = exp2.prepare( fields ); QCOMPARE( prepareRes2, false ); QCOMPARE( exp2.hasEvalError(), true ); QVariant res2 = exp2.evaluate( &f ); QCOMPARE( res2.type(), QVariant::Invalid ); }
void QgsOgrFeatureIterator::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex ) const { if ( mSource->mFirstFieldIsFid && attindex == 0 ) { f.setAttribute( 0, static_cast<qint64>( OGR_F_GetFID( ogrFet ) ) ); return; } int attindexWithoutFid = ( mSource->mFirstFieldIsFid ) ? attindex - 1 : attindex; bool ok = false; QVariant value = QgsOgrUtils::getOgrFeatureAttribute( ogrFet, mSource->mFieldsWithoutFid, attindexWithoutFid, mSource->mEncoding, &ok ); if ( !ok ) return; f.setAttribute( attindex, value ); }
bool QgsVectorLayerImport::addFeature( QgsFeature& feat ) { QgsAttributes attrs = feat.attributes(); QgsFeature newFeat; if ( feat.constGeometry() ) newFeat.setGeometry( *feat.constGeometry() ); newFeat.initAttributes( mAttributeCount ); for ( int i = 0; i < attrs.count(); ++i ) { // add only mapped attributes (un-mapped ones will not be present in the // destination layer) int dstIdx = mOldToNewAttrIdx.value( i, -1 ); if ( dstIdx < 0 ) continue; QgsDebugMsgLevel( QString( "moving field from pos %1 to %2" ).arg( i ).arg( dstIdx ), 3 ); newFeat.setAttribute( dstIdx, attrs.at( i ) ); } mFeatureBuffer.append( newFeat ); if ( mFeatureBuffer.count() >= FEATURE_BUFFER_SIZE ) { return flushBuffer(); } return true; }
void QgsOgrFeatureIterator::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex ) { OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attindex ); if ( ! fldDef ) { QgsDebugMsg( "ogrFet->GetFieldDefnRef(attindex) returns NULL" ); return; } QVariant value; if ( OGR_F_IsFieldSet( ogrFet, attindex ) ) { switch ( P->mAttributeFields[attindex].type() ) { case QVariant::String: value = QVariant( P->mEncoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attindex ) ) ); break; case QVariant::Int: value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attindex ) ); break; case QVariant::Double: value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attindex ) ); break; //case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break; default: assert( NULL && "unsupported field type" ); } } else { value = QVariant( QString::null ); } f.setAttribute( attindex, value ); }
void QgsGPXFeatureIterator::readAttributes( QgsFeature& feature, const QgsTrack& trk ) { // add attributes if they are wanted for ( int i = 0; i < mSource->mFields.count(); ++i ) { switch ( mSource->indexToAttr[i] ) { case QgsGPXProvider::NameAttr: feature.setAttribute( i, QVariant( trk.name ) ); break; case QgsGPXProvider::NumAttr: if ( trk.number != std::numeric_limits<int>::max() ) feature.setAttribute( i, QVariant( trk.number ) ); break; case QgsGPXProvider::CmtAttr: feature.setAttribute( i, QVariant( trk.cmt ) ); break; case QgsGPXProvider::DscAttr: feature.setAttribute( i, QVariant( trk.desc ) ); break; case QgsGPXProvider::SrcAttr: feature.setAttribute( i, QVariant( trk.src ) ); break; case QgsGPXProvider::URLAttr: feature.setAttribute( i, QVariant( trk.url ) ); break; case QgsGPXProvider::URLNameAttr: feature.setAttribute( i, QVariant( trk.urlname ) ); break; } } }
void QgsWFSFeatureIterator::copyFeature( const QgsFeature* f, QgsFeature& feature, bool fetchGeometry ) { Q_UNUSED( fetchGeometry ); if ( !f ) { return; } //copy the geometry const QgsGeometry* geometry = f->constGeometry(); if ( geometry && fetchGeometry ) { const unsigned char *geom = geometry->asWkb(); int geomSize = geometry->wkbSize(); unsigned char* copiedGeom = new unsigned char[geomSize]; memcpy( copiedGeom, geom, geomSize ); QgsGeometry *g = new QgsGeometry(); g->fromWkb( copiedGeom, geomSize ); feature.setGeometry( g ); } else { feature.setGeometry( nullptr ); } //and the attributes feature.initAttributes( mSource->mFields.size() ); for ( int i = 0; i < mSource->mFields.size(); i++ ) { const QVariant &v = f->attributes().value( i ); if ( v.type() != mSource->mFields.at( i ).type() ) feature.setAttribute( i, QgsVectorDataProvider::convertValue( mSource->mFields.at( i ).type(), v.toString() ) ); else feature.setAttribute( i, v ); } //id and valid feature.setValid( true ); feature.setFeatureId( f->id() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups }
bool QgsVectorLayerTools::copyMoveFeatures( QgsVectorLayer* layer, QgsFeatureRequest& request, double dx, double dy, QString* errorMsg ) const { bool res = false; if ( !layer || !layer->isEditable() ) { return false; } QgsFeatureIterator fi = layer->getFeatures( request ); QgsFeature f; QgsAttributeList pkAttrList = layer->pkAttributeList(); int browsedFeatureCount = 0; int couldNotWriteCount = 0; int noGeometryCount = 0; QgsFeatureIds fidList; while ( fi.nextFeature( f ) ) { browsedFeatureCount++; // remove pkey values Q_FOREACH ( auto idx, pkAttrList ) { f.setAttribute( idx, QVariant() ); } // translate if ( f.hasGeometry() ) { QgsGeometry geom = f.geometry(); geom.translate( dx, dy ); f.setGeometry( geom ); #ifdef QGISDEBUG const QgsFeatureId fid = f.id(); #endif // paste feature if ( !layer->addFeature( f, false ) ) { couldNotWriteCount++; QgsDebugMsg( QString( "Could not add new feature. Original copied feature id: %1" ).arg( fid ) ); } else { fidList.insert( f.id() ); } } else { noGeometryCount++; } }
void QgsDelimitedTextFeatureIterator::fetchAttribute( QgsFeature& feature, int fieldIdx, const QStringList& tokens ) { if ( fieldIdx < 0 || fieldIdx >= mSource->attributeColumns.count() ) return; int column = mSource->attributeColumns[fieldIdx]; if ( column < 0 || column >= tokens.count() ) return; const QString &value = tokens[column]; QVariant val; switch ( mSource->mFields[fieldIdx].type() ) { case QVariant::Int: { int ivalue = 0; bool ok = false; if ( ! value.isEmpty() ) ivalue = value.toInt( &ok ); if ( ok ) val = QVariant( ivalue ); else val = QVariant( mSource->mFields[fieldIdx].type() ); break; } case QVariant::Double: { double dvalue = 0.0; bool ok = false; if ( ! value.isEmpty() ) { if ( mSource->mDecimalPoint.isEmpty() ) { dvalue = value.toDouble( &ok ); } else { dvalue = QString( value ).replace( mSource->mDecimalPoint, "." ).toDouble( &ok ); } } if ( ok ) { val = QVariant( dvalue ); } else { val = QVariant( mSource->mFields[fieldIdx].type() ); } break; } default: val = QVariant( value ); break; } feature.setAttribute( fieldIdx, val ); }
void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesDirect( QgsFeature& f, const QVariant& joinValue ) const { // no memory cache, query the joined values by setting substring QString subsetString = joinLayer->dataProvider()->subsetString(); // provider might already have a subset string QString bkSubsetString = subsetString; if ( !subsetString.isEmpty() ) { subsetString.append( " AND " ); } QString joinFieldName; if ( joinInfo->joinFieldName.isEmpty() && joinInfo->joinFieldIndex >= 0 && joinInfo->joinFieldIndex < joinLayer->pendingFields().count() ) joinFieldName = joinLayer->pendingFields().field( joinInfo->joinFieldIndex ).name(); // for compatibility with 1.x else joinFieldName = joinInfo->joinFieldName; subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + joinValue.toString() + "\"" ); joinLayer->dataProvider()->setSubsetString( subsetString, false ); // select (no geometry) QgsFeatureRequest request; request.setFlags( QgsFeatureRequest::NoGeometry ); request.setSubsetOfAttributes( attributes ); QgsFeatureIterator fi = joinLayer->getFeatures( request ); // get first feature QgsFeature fet; if ( fi.nextFeature( fet ) ) { int index = indexOffset; const QgsAttributes& attr = fet.attributes(); for ( int i = 0; i < attr.count(); ++i ) { if ( i == joinField ) continue; f.setAttribute( index++, attr[i] ); } } else { // no suitable join feature found, keeping empty (null) attributes } joinLayer->dataProvider()->setSubsetString( bkSubsetString, false ); }
void QgsOgrFeatureIterator::getFeatureAttribute( OGRFeatureH ogrFet, QgsFeature & f, int attindex ) { OGRFieldDefnH fldDef = OGR_F_GetFieldDefnRef( ogrFet, attindex ); if ( ! fldDef ) { QgsDebugMsg( "ogrFet->GetFieldDefnRef(attindex) returns NULL" ); return; } QVariant value; if ( OGR_F_IsFieldSet( ogrFet, attindex ) ) { switch ( mSource->mFields.at( attindex ).type() ) { case QVariant::String: value = QVariant( mSource->mEncoding->toUnicode( OGR_F_GetFieldAsString( ogrFet, attindex ) ) ); break; case QVariant::Int: value = QVariant( OGR_F_GetFieldAsInteger( ogrFet, attindex ) ); break; #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 2000000 case QVariant::LongLong: value = QVariant( OGR_F_GetFieldAsInteger64( ogrFet, attindex ) ); break; #endif case QVariant::Double: value = QVariant( OGR_F_GetFieldAsDouble( ogrFet, attindex ) ); break; case QVariant::Date: case QVariant::DateTime: { int year, month, day, hour, minute, second, tzf; OGR_F_GetFieldAsDateTime( ogrFet, attindex, &year, &month, &day, &hour, &minute, &second, &tzf ); if ( mSource->mFields.at( attindex ).type() == QVariant::Date ) value = QDate( year, month, day ); else value = QDateTime( QDate( year, month, day ), QTime( hour, minute, second ) ); } break; default: assert( 0 && "unsupported field type" ); } } else { value = QVariant( QString::null ); } f.setAttribute( attindex, value ); }
bool QgsMssqlFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); if ( !mQuery ) return false; if ( !mQuery->isActive() ) { QgsDebugMsg( "Read attempt on inactive query" ); return false; } if ( mQuery->next() ) { feature.initAttributes( mSource->mFields.count() ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups for ( int i = 0; i < mAttributesToFetch.count(); i++ ) { QVariant v = mQuery->value( i ); feature.setAttribute( mAttributesToFetch[i], mQuery->value( i ) ); } if ( mFidCol >= 0 ) { feature.setFeatureId( mQuery->value( mFidCol ).toLongLong() ); } if ( mGeometryCol >= 0 ) { QByteArray ar = mQuery->value( mGeometryCol ).toByteArray(); unsigned char* wkb = mParser.ParseSqlGeometry(( unsigned char* )ar.data(), ar.size() ); if ( wkb ) { feature.setGeometryAndOwnership( wkb, mParser.GetWkbLen() ); } } feature.setValid( true ); return true; } return false; }
void QgsVectorLayerFeatureIterator::FetchJoinInfo::addJoinedAttributesCached( QgsFeature& f, const QVariant& joinValue ) const { const QHash<QString, QgsAttributes>& memoryCache = joinInfo->cachedAttributes; QHash<QString, QgsAttributes>::const_iterator it = memoryCache.find( joinValue.toString() ); if ( it == memoryCache.constEnd() ) return; // joined value not found -> leaving the attributes empty (null) int index = indexOffset; const QgsAttributes& featureAttributes = it.value(); for ( int i = 0; i < featureAttributes.count(); ++i ) { // skip the join field to avoid double field names (fields often have the same name) if ( i == joinField ) continue; f.setAttribute( index++, featureAttributes[i] ); } }
bool QgsOgrUtils::readOgrFeatureAttributes( OGRFeatureH ogrFet, const QgsFields& fields, QgsFeature& feature, QTextCodec* encoding ) { // read all attributes feature.initAttributes( fields.count() ); feature.setFields( fields ); if ( !ogrFet ) return false; bool ok = false; for ( int idx = 0; idx < fields.count(); ++idx ) { QVariant value = getOgrFeatureAttribute( ogrFet, fields, idx, encoding, &ok ); if ( ok ) { feature.setAttribute( idx, value ); } } return true; }
bool QgsOracleFeatureIterator::fetchFeature( QgsFeature& feature ) { feature.setValid( false ); if ( !mQry.isActive() ) return false; for ( ;; ) { feature.initAttributes( mSource->mFields.count() ); feature.setGeometry( 0 ); if ( mRewind ) { mRewind = false; if ( !mQry.first() ) return true; } else if ( !mQry.next() ) { return false; } int col = 0; if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) == 0 || (( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 && !mConnection->hasSpatial() ) ) { QByteArray *ba = static_cast<QByteArray*>( mQry.value( col++ ).data() ); unsigned char *copy = new unsigned char[ba->size()]; memcpy( copy, ba->constData(), ba->size() ); feature.setGeometryAndOwnership( copy, ba->size() ); if ( !mConnection->hasSpatial() && mRequest.filterType() == QgsFeatureRequest::FilterRect && ( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) != 0 && ( !feature.geometry() || !feature.geometry()->intersects( mRequest.filterRect() ) ) ) { // skip feature that don't intersect with our rectangle QgsDebugMsg( "no intersect" ); continue; } if (( mRequest.flags() & QgsFeatureRequest::NoGeometry ) != 0 ) { feature.setGeometryAndOwnership( 0, 0 ); } } QgsFeatureId fid = 0; switch ( mSource->mPrimaryKeyType ) { case pktInt: // get 64bit integer from result fid = mQry.value( col++ ).toLongLong(); if ( mAttributeList.contains( mSource->mPrimaryKeyAttrs[0] ) ) feature.setAttribute( mSource->mPrimaryKeyAttrs[0], fid ); break; case pktRowId: case pktFidMap: { QList<QVariant> primaryKeyVals; if ( mSource->mPrimaryKeyType == pktFidMap ) { foreach ( int idx, mSource->mPrimaryKeyAttrs ) { const QgsField &fld = mSource->mFields[idx]; QVariant v = mQry.value( col ); if ( v.type() != fld.type() ) v = QgsVectorDataProvider::convertValue( fld.type(), v.toString() ); primaryKeyVals << v; if ( mAttributeList.contains( idx ) ) feature.setAttribute( idx, v ); col++; } } else { primaryKeyVals << mQry.value( col++ ); } fid = mSource->mShared->lookupFid( QVariant( primaryKeyVals ) ); } break; case pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; }
bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature ) { try { feature.initAttributes( P->fields().count() ); int col = 0; if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { int returnedLength = ::PQgetlength( queryResult.result(), row, col ); if ( returnedLength > 0 ) { unsigned char *featureGeom = new unsigned char[returnedLength + 1]; memset( featureGeom, 0, returnedLength + 1 ); memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength ); feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else { feature.setGeometryAndOwnership( 0, 0 ); } col++; } QgsFeatureId fid = 0; bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; const QgsAttributeList& fetchAttributes = mRequest.subsetOfAttributes(); switch ( P->mPrimaryKeyType ) { case QgsPostgresProvider::pktOid: case QgsPostgresProvider::pktTid: case QgsPostgresProvider::pktInt: fid = P->mConnectionRO->getBinaryInt( queryResult, row, col++ ); if ( P->mPrimaryKeyType == QgsPostgresProvider::pktInt && ( !subsetOfAttributes || fetchAttributes.contains( P->mPrimaryKeyAttrs[0] ) ) ) feature.setAttribute( P->mPrimaryKeyAttrs[0], fid ); break; case QgsPostgresProvider::pktFidMap: { QList<QVariant> primaryKeyVals; foreach ( int idx, P->mPrimaryKeyAttrs ) { const QgsField &fld = P->field( idx ); QVariant v = P->convertValue( fld.type(), queryResult.PQgetvalue( row, col ) ); primaryKeyVals << v; if ( !subsetOfAttributes || fetchAttributes.contains( idx ) ) feature.setAttribute( idx, v ); col++; } fid = P->lookupFid( QVariant( primaryKeyVals ) ); } break; case QgsPostgresProvider::pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; } feature.setFeatureId( fid ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 4 ); // iterate attributes if ( subsetOfAttributes ) { foreach ( int idx, fetchAttributes ) getFeatureAttribute( idx, queryResult, row, col, feature ); } else { for ( int idx = 0; idx < P->mAttributeFields.count(); ++idx ) getFeatureAttribute( idx, queryResult, row, col, feature ); } return true; }
bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature ) { try { feature.initAttributes( P->fields().count() ); int col = 0; if ( !( mRequest.flags() & QgsFeatureRequest::NoGeometry ) ) { int returnedLength = ::PQgetlength( queryResult.result(), row, col ); if ( returnedLength > 0 ) { unsigned char *featureGeom = new unsigned char[returnedLength + 1]; memset( featureGeom, 0, returnedLength + 1 ); memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength ); // modify 2.5D WKB types to make them compliant with OGR unsigned int wkbType; memcpy( &wkbType, featureGeom + 1, sizeof( wkbType ) ); // convert unsupported types to supported ones switch ( wkbType ) { case 15: // 2D polyhedral => multipolygon wkbType = 6; break; case 1015: // 3D polyhedral => multipolygon wkbType = 1006; break; case 17: // 2D triangle => polygon wkbType = 3; break; case 1017: // 3D triangle => polygon wkbType = 1003; break; case 16: // 2D TIN => multipolygon wkbType = 6; break; case 1016: // TIN => multipolygon wkbType = 1006; break; } // convert from postgis types to qgis types if ( wkbType >= 1000 ) { wkbType = wkbType - 1000 + QGis::WKBPoint25D - 1; } memcpy( featureGeom + 1, &wkbType, sizeof( wkbType ) ); // change wkb type of inner geometries if ( wkbType == QGis::WKBMultiPoint25D || wkbType == QGis::WKBMultiLineString25D || wkbType == QGis::WKBMultiPolygon25D ) { unsigned int numGeoms = *(( int* )( featureGeom + 5 ) ); unsigned char* wkb = featureGeom + 9; for ( unsigned int i = 0; i < numGeoms; ++i ) { unsigned int localType; memcpy( &localType, wkb + 1, sizeof( localType ) ); switch ( localType ) { case 15: // 2D polyhedral => multipolygon localType = 6; break; case 1015: // 3D polyhedral => multipolygon localType = 1006; break; case 17: // 2D triangle => polygon localType = 3; break; case 1017: // 3D triangle => polygon localType = 1003; break; case 16: // 2D TIN => multipolygon localType = 6; break; case 1016: // TIN => multipolygon localType = 1006; break; } if ( localType >= 1000 ) { localType = localType - 1000 + QGis::WKBPoint25D - 1; } memcpy( wkb + 1, &localType, sizeof( localType ) ); // skip endian and type info wkb += sizeof( unsigned int ) + 1; // skip coordinates switch ( wkbType ) { case QGis::WKBMultiPoint25D: wkb += sizeof( double ) * 3; break; case QGis::WKBMultiLineString25D: { unsigned int nPoints = *(( int* ) wkb ); wkb += sizeof( nPoints ); wkb += sizeof( double ) * 3 * nPoints; } break; default: case QGis::WKBMultiPolygon25D: { unsigned int nRings = *(( int* ) wkb ); wkb += sizeof( nRings ); for ( unsigned int j = 0; j < nRings; ++j ) { unsigned int nPoints = *(( int* ) wkb ); wkb += sizeof( nPoints ); wkb += sizeof( double ) * 3 * nPoints; } } break; } } } feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else { feature.setGeometryAndOwnership( 0, 0 ); } col++; } QgsFeatureId fid = 0; bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; const QgsAttributeList& fetchAttributes = mRequest.subsetOfAttributes(); switch ( P->mPrimaryKeyType ) { case QgsPostgresProvider::pktOid: case QgsPostgresProvider::pktTid: case QgsPostgresProvider::pktInt: fid = P->mConnectionRO->getBinaryInt( queryResult, row, col++ ); if ( P->mPrimaryKeyType == QgsPostgresProvider::pktInt && ( !subsetOfAttributes || fetchAttributes.contains( P->mPrimaryKeyAttrs[0] ) ) ) feature.setAttribute( P->mPrimaryKeyAttrs[0], fid ); break; case QgsPostgresProvider::pktFidMap: { QList<QVariant> primaryKeyVals; foreach ( int idx, P->mPrimaryKeyAttrs ) { const QgsField &fld = P->field( idx ); QVariant v = P->convertValue( fld.type(), queryResult.PQgetvalue( row, col ) ); primaryKeyVals << v; if ( !subsetOfAttributes || fetchAttributes.contains( idx ) ) feature.setAttribute( idx, v ); col++; } fid = P->lookupFid( QVariant( primaryKeyVals ) ); } break; case QgsPostgresProvider::pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; } feature.setFeatureId( fid ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 4 ); // iterate attributes if ( subsetOfAttributes ) { foreach ( int idx, fetchAttributes ) getFeatureAttribute( idx, queryResult, row, col, feature ); } else { for ( int idx = 0; idx < P->mAttributeFields.count(); ++idx ) getFeatureAttribute( idx, queryResult, row, col, feature ); } return true; }
bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature ) { feature.initAttributes( mSource->mFields.count() ); int col = 0; if ( mFetchGeometry ) { int returnedLength = ::PQgetlength( queryResult.result(), row, col ); if ( returnedLength > 0 ) { unsigned char *featureGeom = new unsigned char[returnedLength + 1]; memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength ); memset( featureGeom + returnedLength, 0, 1 ); unsigned int wkbType; memcpy( &wkbType, featureGeom + 1, sizeof( wkbType ) ); QgsWKBTypes::Type newType = QgsPostgresConn::wkbTypeFromOgcWkbType( wkbType ); if (( unsigned int )newType != wkbType ) { // overwrite type unsigned int n = newType; memcpy( featureGeom + 1, &n, sizeof( n ) ); } // PostGIS stores TIN as a collection of Triangles. // Since Triangles are not supported, they have to be converted to Polygons const int nDims = 2 + ( QgsWKBTypes::hasZ( newType ) ? 1 : 0 ) + ( QgsWKBTypes::hasM( newType ) ? 1 : 0 ); if ( wkbType % 1000 == 16 ) { unsigned int numGeoms; memcpy( &numGeoms, featureGeom + 5, sizeof( unsigned int ) ); unsigned char *wkb = featureGeom + 9; for ( unsigned int i = 0; i < numGeoms; ++i ) { const unsigned int localType = QgsWKBTypes::singleType( newType ); // polygon(Z|M) memcpy( wkb + 1, &localType, sizeof( localType ) ); // skip endian and type info wkb += sizeof( unsigned int ) + 1; // skip coordinates unsigned int nRings; memcpy( &nRings, wkb, sizeof( int ) ); wkb += sizeof( int ); for ( unsigned int j = 0; j < nRings; ++j ) { unsigned int nPoints; memcpy( &nPoints, wkb, sizeof( int ) ); wkb += sizeof( nPoints ) + sizeof( double ) * nDims * nPoints; } } } feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else { feature.setGeometryAndOwnership( 0, 0 ); } col++; } QgsFeatureId fid = 0; bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; const QgsAttributeList& fetchAttributes = mRequest.subsetOfAttributes(); switch ( mSource->mPrimaryKeyType ) { case pktOid: case pktTid: case pktInt: fid = mConn->getBinaryInt( queryResult, row, col++ ); if ( mSource->mPrimaryKeyType == pktInt && ( !subsetOfAttributes || fetchAttributes.contains( mSource->mPrimaryKeyAttrs[0] ) ) ) feature.setAttribute( mSource->mPrimaryKeyAttrs[0], fid ); break; case pktFidMap: { QList<QVariant> primaryKeyVals; Q_FOREACH ( int idx, mSource->mPrimaryKeyAttrs ) { const QgsField &fld = mSource->mFields.at( idx ); QVariant v = QgsPostgresProvider::convertValue( fld.type(), queryResult.PQgetvalue( row, col ) ); primaryKeyVals << v; if ( !subsetOfAttributes || fetchAttributes.contains( idx ) ) feature.setAttribute( idx, v ); col++; } fid = mSource->mShared->lookupFid( QVariant( primaryKeyVals ) ); } break; case pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; } feature.setFeatureId( fid ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 4 ); // iterate attributes if ( subsetOfAttributes ) { Q_FOREACH ( int idx, fetchAttributes ) getFeatureAttribute( idx, queryResult, row, col, feature ); } else { for ( int idx = 0; idx < mSource->mFields.count(); ++idx )
bool QgsVirtualLayerFeatureIterator::fetchFeature( QgsFeature &feature ) { feature.setValid( false ); if ( mClosed ) { return false; } bool skipFeature = false; do { if ( mQuery->step() != SQLITE_ROW ) { return false; } feature.setFields( mSource->mFields, /* init */ true ); if ( mSource->mDefinition.uid().isNull() && mRequest.filterType() != QgsFeatureRequest::FilterFid ) { // no id column => autoincrement feature.setId( mFid++ ); } else { // first column: uid feature.setId( mQuery->columnInt64( 0 ) ); } int n = mQuery->columnCount(); int i = 0; const auto constMAttributes = mAttributes; for ( int idx : constMAttributes ) { int type = mQuery->columnType( i + 1 ); switch ( type ) { case SQLITE_INTEGER: feature.setAttribute( idx, mQuery->columnInt64( i + 1 ) ); break; case SQLITE_FLOAT: feature.setAttribute( idx, mQuery->columnDouble( i + 1 ) ); break; case SQLITE_TEXT: default: feature.setAttribute( idx, mQuery->columnText( i + 1 ) ); break; }; i++; } if ( n > mAttributes.size() + 1 ) { // geometry field QByteArray blob( mQuery->columnBlob( n - 1 ) ); if ( blob.size() > 0 ) { feature.setGeometry( spatialiteBlobToQgsGeometry( blob.constData(), blob.size() ) ); } else { feature.clearGeometry(); } } feature.setValid( true ); geometryToDestinationCrs( feature, mTransform ); // if the FilterRect has not been applied on the query // apply it here by skipping features until they intersect if ( mSource->mDefinition.uid().isNull() && feature.hasGeometry() && mSource->mDefinition.hasDefinedGeometry() && !mFilterRect.isNull() ) { if ( mRequest.flags() & QgsFeatureRequest::ExactIntersect ) { // using exact test when checking for intersection skipFeature = !mRectEngine->intersects( feature.geometry().constGet() ); } else { // check just bounding box against rect when not using intersection skipFeature = !feature.geometry().boundingBox().intersects( mFilterRect ); } } } while ( skipFeature ); return true; }
bool QgsGrassFeatureIterator::fetchFeature( QgsFeature& feature ) { if ( mClosed ) return false; feature.setValid( false ); int cat = -1, type = -1, id = -1; QgsFeatureId featureId = -1; QgsDebugMsgLevel( "entered.", 3 ); /* TODO: handle editing if ( P->isEdited() || P->isFrozen() || !P->mValid ) { close(); return false; } */ // TODO: is this necessary? the same is checked below if ( !QgsGrassProvider::isTopoType( mSource->mLayerType ) && ( mSource->mCidxFieldIndex < 0 || mNextCidx >= mSource->mCidxFieldNumCats ) ) { close(); return false; // No features, no features in this layer } bool filterById = mRequest.filterType() == QgsFeatureRequest::FilterFid; // Get next line/area id int found = 0; while ( true ) { QgsDebugMsgLevel( QString( "mNextTopoId = %1" ).arg( mNextTopoId ), 3 ); if ( mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { if ( mNextTopoId > Vect_get_num_lines( mSource->mMap ) ) break; id = mNextTopoId; type = Vect_read_line( mSource->mMap, 0, 0, mNextTopoId++ ); if ( !( type & mSource->mGrassType ) ) continue; featureId = id; } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { if ( mNextTopoId > Vect_get_num_nodes( mSource->mMap ) ) break; id = mNextTopoId; type = 0; mNextTopoId++; featureId = id; } else { if ( mNextCidx >= mSource->mCidxFieldNumCats ) break; Vect_cidx_get_cat_by_index( mSource->mMap, mSource->mCidxFieldIndex, mNextCidx++, &cat, &type, &id ); // Warning: selection array is only of type line/area of current layer -> check type first if ( !( type & mSource->mGrassType ) ) continue; // The 'id' is a unique id of a GRASS geometry object (point, line, area) // but it cannot be used as QgsFeatureId because one geometry object may // represent more features because it may have more categories. featureId = makeFeatureId( id, cat ); } if ( filterById && featureId != mRequest.filterFid() ) continue; // it is correct to use id with mSelection because mSelection is only used // for geometry selection if ( !mSelection[id] ) continue; found = 1; break; } if ( !found ) { close(); return false; // No more features } QgsDebugMsgLevel( QString( "cat = %1 type = %2 id = %3 fatureId = %4" ).arg( cat ).arg( type ).arg( id ).arg( featureId ), 3 ); feature.setFeatureId( featureId ); feature.initAttributes( mSource->mFields.count() ); feature.setFields( &mSource->mFields ); // allow name-based attribute lookups if ( mRequest.flags() & QgsFeatureRequest::NoGeometry ) feature.setGeometry( 0 ); else setFeatureGeometry( feature, id, type ); if ( ! QgsGrassProvider::isTopoType( mSource->mLayerType ) ) { if ( mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes ) setFeatureAttributes( cat, &feature, mRequest.subsetOfAttributes() ); else setFeatureAttributes( cat, &feature ); } else { feature.setAttribute( 0, id ); #if GRASS_VERSION_MAJOR < 7 if ( mSource->mLayerType == QgsGrassProvider::TOPO_POINT || mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) #else /* No more topo points in GRASS 7 */ if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) #endif { feature.setAttribute( 1, QgsGrassProvider::primitiveTypeName( type ) ); int node1, node2; Vect_get_line_nodes( mSource->mMap, id, &node1, &node2 ); feature.setAttribute( 2, node1 ); if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { feature.setAttribute( 3, node2 ); } } if ( mSource->mLayerType == QgsGrassProvider::TOPO_LINE ) { if ( type == GV_BOUNDARY ) { int left, right; Vect_get_line_areas( mSource->mMap, id, &left, &right ); feature.setAttribute( 4, left ); feature.setAttribute( 5, right ); } } else if ( mSource->mLayerType == QgsGrassProvider::TOPO_NODE ) { QString lines; int nlines = Vect_get_node_n_lines( mSource->mMap, id ); for ( int i = 0; i < nlines; i++ ) { int line = Vect_get_node_line( mSource->mMap, id, i ); if ( i > 0 ) lines += ","; lines += QString::number( line ); } feature.setAttribute( 1, lines ); } } feature.setValid( true ); return true; }
int QgsTransectSample::createSample( QProgressDialog* pd ) { Q_UNUSED( pd ); if ( !mStrataLayer || !mStrataLayer->isValid() ) { return 1; } if ( !mBaselineLayer || !mBaselineLayer->isValid() ) { return 2; } //stratum id is not necessarily an integer QVariant::Type stratumIdType = QVariant::Int; if ( !mStrataIdAttribute.isEmpty() ) { stratumIdType = mStrataLayer->pendingFields().field( mStrataIdAttribute ).type(); } //create vector file writers for output QgsFields outputPointFields; outputPointFields.append( QgsField( "id", stratumIdType ) ); outputPointFields.append( QgsField( "station_id", QVariant::Int ) ); outputPointFields.append( QgsField( "stratum_id", stratumIdType ) ); outputPointFields.append( QgsField( "station_code", QVariant::String ) ); outputPointFields.append( QgsField( "start_lat", QVariant::Double ) ); outputPointFields.append( QgsField( "start_long", QVariant::Double ) ); QgsVectorFileWriter outputPointWriter( mOutputPointLayer, "utf-8", outputPointFields, QGis::WKBPoint, &( mStrataLayer->crs() ) ); if ( outputPointWriter.hasError() != QgsVectorFileWriter::NoError ) { return 3; } outputPointFields.append( QgsField( "bearing", QVariant::Double ) ); //add bearing attribute for lines QgsVectorFileWriter outputLineWriter( mOutputLineLayer, "utf-8", outputPointFields, QGis::WKBLineString, &( mStrataLayer->crs() ) ); if ( outputLineWriter.hasError() != QgsVectorFileWriter::NoError ) { return 4; } QgsFields usedBaselineFields; usedBaselineFields.append( QgsField( "stratum_id", stratumIdType ) ); usedBaselineFields.append( QgsField( "ok", QVariant::String ) ); QgsVectorFileWriter usedBaselineWriter( mUsedBaselineLayer, "utf-8", usedBaselineFields, QGis::WKBLineString, &( mStrataLayer->crs() ) ); if ( usedBaselineWriter.hasError() != QgsVectorFileWriter::NoError ) { return 5; } //debug: write clipped buffer bounds with stratum id to same directory as out_point QFileInfo outputPointInfo( mOutputPointLayer ); QString bufferClipLineOutput = outputPointInfo.absolutePath() + "/out_buffer_clip_line.shp"; QgsFields bufferClipLineFields; bufferClipLineFields.append( QgsField( "id", stratumIdType ) ); QgsVectorFileWriter bufferClipLineWriter( bufferClipLineOutput, "utf-8", bufferClipLineFields, QGis::WKBLineString, &( mStrataLayer->crs() ) ); //configure distanceArea depending on minDistance units and output CRS QgsDistanceArea distanceArea; distanceArea.setSourceCrs( mStrataLayer->crs().srsid() ); if ( mMinDistanceUnits == Meters ) { distanceArea.setEllipsoidalMode( true ); } else { distanceArea.setEllipsoidalMode( false ); } //possibility to transform output points to lat/long QgsCoordinateTransform toLatLongTransform( mStrataLayer->crs(), QgsCoordinateReferenceSystem( 4326, QgsCoordinateReferenceSystem::EpsgCrsId ) ); //init random number generator mt_srand( QTime::currentTime().msec() ); QgsFeatureRequest fr; fr.setSubsetOfAttributes( QStringList() << mStrataIdAttribute << mMinDistanceAttribute << mNPointsAttribute, mStrataLayer->pendingFields() ); QgsFeatureIterator strataIt = mStrataLayer->getFeatures( fr ); QgsFeature fet; int nTotalTransects = 0; int nFeatures = 0; if ( pd ) { pd->setMaximum( mStrataLayer->featureCount() ); } while ( strataIt.nextFeature( fet ) ) { if ( pd ) { pd->setValue( nFeatures ); } if ( pd && pd->wasCanceled() ) { break; } if ( !fet.constGeometry() ) { continue; } const QgsGeometry* strataGeom = fet.constGeometry(); //find baseline for strata QVariant strataId = fet.attribute( mStrataIdAttribute ); QgsGeometry* baselineGeom = findBaselineGeometry( strataId.isValid() ? strataId : -1 ); if ( !baselineGeom ) { continue; } double minDistance = fet.attribute( mMinDistanceAttribute ).toDouble(); double minDistanceLayerUnits = minDistance; //if minDistance is in meters and the data in degrees, we need to apply a rough conversion for the buffer distance double bufferDist = bufferDistance( minDistance ); if ( mMinDistanceUnits == Meters && mStrataLayer->crs().mapUnits() == QGis::DecimalDegrees ) { minDistanceLayerUnits = minDistance / 111319.9; } QgsGeometry* clippedBaseline = strataGeom->intersection( baselineGeom ); if ( !clippedBaseline || clippedBaseline->wkbType() == QGis::WKBUnknown ) { delete clippedBaseline; continue; } QgsGeometry* bufferLineClipped = clipBufferLine( strataGeom, clippedBaseline, bufferDist ); if ( !bufferLineClipped ) { delete clippedBaseline; continue; } //save clipped baseline to file QgsFeature blFeature; blFeature.setGeometry( *clippedBaseline ); blFeature.setAttribute( "stratum_id", strataId ); blFeature.setAttribute( "ok", "f" ); usedBaselineWriter.addFeature( blFeature ); //start loop to create random points along the baseline int nTransects = fet.attribute( mNPointsAttribute ).toInt(); int nCreatedTransects = 0; int nIterations = 0; int nMaxIterations = nTransects * 50; QgsSpatialIndex sIndex; //to check minimum distance QMap< QgsFeatureId, QgsGeometry* > lineFeatureMap; while ( nCreatedTransects < nTransects && nIterations < nMaxIterations ) { double randomPosition = (( double )mt_rand() / MD_RAND_MAX ) * clippedBaseline->length(); QgsGeometry* samplePoint = clippedBaseline->interpolate( randomPosition ); ++nIterations; if ( !samplePoint ) { continue; } QgsPoint sampleQgsPoint = samplePoint->asPoint(); QgsPoint latLongSamplePoint = toLatLongTransform.transform( sampleQgsPoint ); QgsFeature samplePointFeature; samplePointFeature.setGeometry( samplePoint ); samplePointFeature.setAttribute( "id", nTotalTransects + 1 ); samplePointFeature.setAttribute( "station_id", nCreatedTransects + 1 ); samplePointFeature.setAttribute( "stratum_id", strataId ); samplePointFeature.setAttribute( "station_code", strataId.toString() + "_" + QString::number( nCreatedTransects + 1 ) ); samplePointFeature.setAttribute( "start_lat", latLongSamplePoint.y() ); samplePointFeature.setAttribute( "start_long", latLongSamplePoint.x() ); //find closest point on clipped buffer line QgsPoint minDistPoint; int afterVertex; if ( bufferLineClipped->closestSegmentWithContext( sampleQgsPoint, minDistPoint, afterVertex ) < 0 ) { continue; } //bearing between sample point and min dist point (transect direction) double bearing = distanceArea.bearing( sampleQgsPoint, minDistPoint ) / M_PI * 180.0; QgsPolyline sampleLinePolyline; QgsPoint ptFarAway( sampleQgsPoint.x() + ( minDistPoint.x() - sampleQgsPoint.x() ) * 1000000, sampleQgsPoint.y() + ( minDistPoint.y() - sampleQgsPoint.y() ) * 1000000 ); QgsPolyline lineFarAway; lineFarAway << sampleQgsPoint << ptFarAway; QgsGeometry* lineFarAwayGeom = QgsGeometry::fromPolyline( lineFarAway ); QgsGeometry* lineClipStratum = lineFarAwayGeom->intersection( strataGeom ); if ( !lineClipStratum ) { delete lineFarAwayGeom; delete lineClipStratum; continue; } //cancel if distance between sample point and line is too large (line does not start at point if ( lineClipStratum->distance( *samplePoint ) > 0.000001 ) { delete lineFarAwayGeom; delete lineClipStratum; continue; } //if lineClipStratum is a multiline, take the part line closest to sampleQgsPoint if ( lineClipStratum->wkbType() == QGis::WKBMultiLineString || lineClipStratum->wkbType() == QGis::WKBMultiLineString25D ) { QgsGeometry* singleLine = closestMultilineElement( sampleQgsPoint, lineClipStratum ); if ( singleLine ) { delete lineClipStratum; lineClipStratum = singleLine; } } //cancel if length of lineClipStratum is too small double transectLength = distanceArea.measure( lineClipStratum ); if ( transectLength < mMinTransectLength ) { delete lineFarAwayGeom; delete lineClipStratum; continue; } //search closest existing profile. Cancel if dist < minDist if ( otherTransectWithinDistance( lineClipStratum, minDistanceLayerUnits, minDistance, sIndex, lineFeatureMap, distanceArea ) ) { delete lineFarAwayGeom; delete lineClipStratum; continue; } QgsFeatureId fid( nCreatedTransects ); QgsFeature sampleLineFeature( fid ); sampleLineFeature.setGeometry( lineClipStratum ); sampleLineFeature.setAttribute( "id", nTotalTransects + 1 ); sampleLineFeature.setAttribute( "station_id", nCreatedTransects + 1 ); sampleLineFeature.setAttribute( "stratum_id", strataId ); sampleLineFeature.setAttribute( "station_code", strataId.toString() + "_" + QString::number( nCreatedTransects + 1 ) ); sampleLineFeature.setAttribute( "start_lat", latLongSamplePoint.y() ); sampleLineFeature.setAttribute( "start_long", latLongSamplePoint.x() ); sampleLineFeature.setAttribute( "bearing", bearing ); outputLineWriter.addFeature( sampleLineFeature ); //add point to file writer here. //It can only be written if the corresponding transect has been as well outputPointWriter.addFeature( samplePointFeature ); sIndex.insertFeature( sampleLineFeature ); Q_NOWARN_DEPRECATED_PUSH lineFeatureMap.insert( fid, sampleLineFeature.geometryAndOwnership() ); Q_NOWARN_DEPRECATED_POP delete lineFarAwayGeom; ++nTotalTransects; ++nCreatedTransects; } delete clippedBaseline; QgsFeature bufferClipFeature; bufferClipFeature.setGeometry( bufferLineClipped ); bufferClipFeature.setAttribute( "id", strataId ); bufferClipLineWriter.addFeature( bufferClipFeature ); //delete bufferLineClipped; //delete all line geometries in spatial index QMap< QgsFeatureId, QgsGeometry* >::iterator featureMapIt = lineFeatureMap.begin(); for ( ; featureMapIt != lineFeatureMap.end(); ++featureMapIt ) { delete( featureMapIt.value() ); } lineFeatureMap.clear(); delete baselineGeom; ++nFeatures; } if ( pd ) { pd->setValue( mStrataLayer->featureCount() ); } return 0; }
bool QgsSpatiaLiteFeatureIterator::getFeature( sqlite3_stmt *stmt, QgsFeature &feature ) { bool subsetAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; int ret = sqlite3_step( stmt ); if ( ret == SQLITE_DONE ) { // there are no more rows to fetch return false; } if ( ret != SQLITE_ROW ) { // some unexpected error occurred QgsMessageLog::logMessage( QObject::tr( "SQLite error getting feature: %1" ).arg( QString::fromUtf8( sqlite3_errmsg( mHandle->handle() ) ) ), QObject::tr( "SpatiaLite" ) ); return false; } // one valid row has been fetched from the result set if ( !mFetchGeometry ) { // no geometry was required feature.setGeometryAndOwnership( 0, 0 ); } feature.initAttributes( mSource->mFields.count() ); feature.setFields( mSource->mFields ); // allow name-based attribute lookups int ic; int n_columns = sqlite3_column_count( stmt ); for ( ic = 0; ic < n_columns; ic++ ) { if ( ic == 0 ) { if ( mHasPrimaryKey ) { // first column always contains the ROWID (or the primary key) QgsFeatureId fid = sqlite3_column_int64( stmt, ic ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 3 ); feature.setFeatureId( fid ); } else { // autoincrement a row number mRowNumber++; feature.setFeatureId( mRowNumber ); } } else if ( mFetchGeometry && ic == mGeomColIdx ) { getFeatureGeometry( stmt, ic, feature ); } else { if ( subsetAttributes ) { if ( ic <= mRequest.subsetOfAttributes().size() ) { int attrIndex = mRequest.subsetOfAttributes()[ic-1]; feature.setAttribute( attrIndex, getFeatureAttribute( stmt, ic, mSource->mFields.at( attrIndex ).type() ) ); } } else { int attrIndex = ic - 1; feature.setAttribute( attrIndex, getFeatureAttribute( stmt, ic, mSource->mFields.at( attrIndex ).type() ) ); } } } return true; }
bool QgsPostgresFeatureIterator::getFeature( QgsPostgresResult &queryResult, int row, QgsFeature &feature ) { feature.initAttributes( mSource->mFields.count() ); int col = 0; if ( mFetchGeometry ) { int returnedLength = ::PQgetlength( queryResult.result(), row, col ); if ( returnedLength > 0 ) { unsigned char *featureGeom = new unsigned char[returnedLength + 1]; memcpy( featureGeom, PQgetvalue( queryResult.result(), row, col ), returnedLength ); memset( featureGeom + returnedLength, 0, 1 ); // modify 2.5D WKB types to make them compliant with OGR unsigned int wkbType; memcpy( &wkbType, featureGeom + 1, sizeof( wkbType ) ); wkbType = QgsPostgresConn::wkbTypeFromOgcWkbType( wkbType ); memcpy( featureGeom + 1, &wkbType, sizeof( wkbType ) ); // change wkb type of inner geometries if ( wkbType == QGis::WKBMultiPoint25D || wkbType == QGis::WKBMultiLineString25D || wkbType == QGis::WKBMultiPolygon25D ) { unsigned int numGeoms; memcpy( &numGeoms, featureGeom + 5, sizeof( unsigned int ) ); unsigned char *wkb = featureGeom + 9; for ( unsigned int i = 0; i < numGeoms; ++i ) { unsigned int localType; memcpy( &localType, wkb + 1, sizeof( localType ) ); localType = QgsPostgresConn::wkbTypeFromOgcWkbType( localType ); memcpy( wkb + 1, &localType, sizeof( localType ) ); // skip endian and type info wkb += sizeof( unsigned int ) + 1; // skip coordinates switch ( wkbType ) { case QGis::WKBMultiPoint25D: wkb += sizeof( double ) * 3; break; case QGis::WKBMultiLineString25D: { unsigned int nPoints; memcpy( &nPoints, wkb, sizeof( int ) ); wkb += sizeof( int ) + sizeof( double ) * 3 * nPoints; } break; default: case QGis::WKBMultiPolygon25D: { unsigned int nRings; memcpy( &nRings, wkb, sizeof( int ) ); wkb += sizeof( int ); for ( unsigned int j = 0; j < nRings; ++j ) { unsigned int nPoints; memcpy( &nPoints, wkb, sizeof( int ) ); wkb += sizeof( nPoints ) + sizeof( double ) * 3 * nPoints; } } break; } } } feature.setGeometryAndOwnership( featureGeom, returnedLength + 1 ); } else { feature.setGeometryAndOwnership( 0, 0 ); } col++; } QgsFeatureId fid = 0; bool subsetOfAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; const QgsAttributeList& fetchAttributes = mRequest.subsetOfAttributes(); switch ( mSource->mPrimaryKeyType ) { case pktOid: case pktTid: case pktInt: fid = mConn->getBinaryInt( queryResult, row, col++ ); if ( mSource->mPrimaryKeyType == pktInt && ( !subsetOfAttributes || fetchAttributes.contains( mSource->mPrimaryKeyAttrs[0] ) ) ) feature.setAttribute( mSource->mPrimaryKeyAttrs[0], fid ); break; case pktFidMap: { QList<QVariant> primaryKeyVals; Q_FOREACH ( int idx, mSource->mPrimaryKeyAttrs ) { const QgsField &fld = mSource->mFields[idx]; QVariant v = QgsPostgresProvider::convertValue( fld.type(), queryResult.PQgetvalue( row, col ) ); primaryKeyVals << v; if ( !subsetOfAttributes || fetchAttributes.contains( idx ) ) feature.setAttribute( idx, v ); col++; } fid = mSource->mShared->lookupFid( QVariant( primaryKeyVals ) ); } break; case pktUnknown: Q_ASSERT( !"FAILURE: cannot get feature with unknown primary key" ); return false; } feature.setFeatureId( fid ); QgsDebugMsgLevel( QString( "fid=%1" ).arg( fid ), 4 ); // iterate attributes if ( subsetOfAttributes ) { Q_FOREACH ( int idx, fetchAttributes ) getFeatureAttribute( idx, queryResult, row, col, feature ); } else { for ( int idx = 0; idx < mSource->mFields.count(); ++idx )
bool QgsSqlAnywhereFeatureIterator::nextFeature( QgsFeature& feature, SqlAnyStatement *stmt ) { feature.setValid( false ); bool fetchGeometry = !( mRequest.flags() & QgsFeatureRequest::NoGeometry ); bool subsetAttributes = mRequest.flags() & QgsFeatureRequest::SubsetOfAttributes; if ( mClosed ) return false; if ( !P->mConnRO || !P->mConnRO->isAlive() ) { SaDebugMsg( "No database connection." ); return false; } bool ok; int id; a_sqlany_data_value geom; unsigned char *geomBuf = NULL; ok = ( stmt != NULL && stmt->fetchNext() ); // if no more rows... if ( !ok ) return false; if ( !fetchGeometry ) feature.setGeometryAndOwnership( 0, 0 ); int numAttributes = P->fields().count(); // also used later for sanity check feature.initAttributes( numAttributes ); feature.setFields( &P->mAttributeFields ); // allow name-based attribute lookups int i = 0; int numcols = stmt->numCols(); int colidx = 0; // Refers to which column we're on in "feature" (the row) for ( i = 0; i < numcols; i++ ) { if ( i == 0 ) { // first column always contains primary key ok = stmt->getInt( i, id ); if ( !ok ) break; QgsDebugMsgLevel( QString( "pid=%1" ).arg( id ), 3 ); feature.setFeatureId( id ); } else if ( i == 1 && fetchGeometry ) { // second column contains QKB geometry value ok = stmt->getColumn( i, &geom ); if ( !ok ) break; QgsDebugMsgLevel( QString( "retrieved geometry column" ), 3 ); geomBuf = new unsigned char[ *geom.length + 1 ]; memset( geomBuf, '\0', *geom.length ); memcpy( geomBuf, geom.buffer, *geom.length ); feature.setGeometryAndOwnership( geomBuf, *geom.length + 1 ); } else { if ( i == 1 ) { feature.setGeometryAndOwnership( 0, 0 ); // no geometry to fetch } int attrIndex = subsetAttributes ? mRequest.subsetOfAttributes()[colidx++] : colidx++; QVariant val; ok = stmt->getQVariant( i, val ); // ok may be false if value was NULL, but this is a valid return // Sanity check before setting the attribute value if ( colidx - 1 == i // First column is always pk, so colidx should be at least 1 behind || ( colidx - 1 == i - 1 && fetchGeometry ) // if fetchGeometry is true, colidx should be 2 behind || attrIndex >= numAttributes ) // index should always be less than the count { SaDebugMsg( QString( "Error retrieving feature column %1 with attribute index %2" ).arg( i ).arg( attrIndex ) ); return false; } // So now this should not crash. feature.setAttribute( attrIndex, val ); } } feature.setValid( true ); return true; }