bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer* eventLayer, int lineField, int eventField, QgsFeatureIds &unlocatedFeatureIds, const QString& outputLayer, const QString& outputFormat, int locationField1, int locationField2, int offsetField, double offsetScale, bool forceSingleGeometry, QgsVectorDataProvider* memoryProvider, QProgressDialog* p ) { if ( !lineLayer || !eventLayer || !lineLayer->isValid() || !eventLayer->isValid() ) { return false; } //create line field / id map for line layer QMultiHash< QString, QgsFeature > lineLayerIdMap; //1:n possible (e.g. several linear reference geometries for one feature in the event layer) QgsFeatureIterator fit = lineLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() << lineField ) ); QgsFeature fet; while ( fit.nextFeature( fet ) ) { lineLayerIdMap.insert( fet.attribute( lineField ).toString(), fet ); } //create output datasource or attributes in memory provider QgsVectorFileWriter* fileWriter = nullptr; QgsFeatureList memoryProviderFeatures; if ( !memoryProvider ) { QgsWkbTypes::Type memoryProviderType = QgsWkbTypes::MultiLineString; if ( locationField2 == -1 ) { memoryProviderType = forceSingleGeometry ? QgsWkbTypes::Point : QgsWkbTypes::MultiPoint; } else { memoryProviderType = forceSingleGeometry ? QgsWkbTypes::LineString : QgsWkbTypes::MultiLineString; } fileWriter = new QgsVectorFileWriter( outputLayer, eventLayer->dataProvider()->encoding(), eventLayer->fields(), memoryProviderType, lineLayer->crs(), outputFormat ); } else { memoryProvider->addAttributes( eventLayer->fields().toList() ); } //iterate over eventLayer and write new features to output file or layer fit = eventLayer->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) ); QgsGeometry lrsGeom; double measure1, measure2 = 0.0; int nEventFeatures = eventLayer->featureCount(); int featureCounter = 0; int nOutputFeatures = 0; //number of output features for the current event feature if ( p ) { p->setWindowModality( Qt::WindowModal ); p->setMinimum( 0 ); p->setMaximum( nEventFeatures ); p->show(); } while ( fit.nextFeature( fet ) ) { nOutputFeatures = 0; //update progress dialog if ( p ) { if ( p->wasCanceled() ) { break; } p->setValue( featureCounter ); ++featureCounter; } measure1 = fet.attribute( locationField1 ).toDouble(); if ( locationField2 != -1 ) { measure2 = fet.attribute( locationField2 ).toDouble(); if ( qgsDoubleNear(( measure2 - measure1 ), 0.0 ) ) { continue; } } QList<QgsFeature> featureIdList = lineLayerIdMap.values( fet.attribute( eventField ).toString() ); QList<QgsFeature>::iterator featureIdIt = featureIdList.begin(); for ( ; featureIdIt != featureIdList.end(); ++featureIdIt ) { if ( locationField2 == -1 ) { lrsGeom = locateAlongMeasure( measure1, featureIdIt->geometry() ); } else { lrsGeom = locateBetweenMeasures( measure1, measure2, featureIdIt->geometry() ); } if ( !lrsGeom.isEmpty() ) { ++nOutputFeatures; addEventLayerFeature( fet, lrsGeom, featureIdIt->geometry(), fileWriter, memoryProviderFeatures, offsetField, offsetScale, forceSingleGeometry ); } } if ( nOutputFeatures < 1 ) { unlocatedFeatureIds.insert( fet.id() ); } } if ( p ) { p->setValue( nEventFeatures ); } if ( memoryProvider ) { memoryProvider->addFeatures( memoryProviderFeatures ); } delete fileWriter; return true; }
bool QgsGeometryAnalyzer::eventLayer( QgsVectorLayer* lineLayer, QgsVectorLayer* eventLayer, int lineField, int eventField, QList<int>& unlocatedFeatureIds, const QString& outputLayer, const QString& outputFormat, int locationField1, int locationField2, int offsetField, double offsetScale, bool forceSingleGeometry, QgsVectorDataProvider* memoryProvider, QProgressDialog* p ) { if ( !lineLayer || !eventLayer || !lineLayer->isValid() || !eventLayer->isValid() ) { return false; } //create line field / id map for line layer QMultiHash< QString, QgsFeatureId > lineLayerIdMap; //1:n possible (e.g. several linear reference geometries for one feature in the event layer) lineLayer->select( QgsAttributeList() << lineField, QgsRectangle(), false, false ); QgsFeature fet; while ( lineLayer->nextFeature( fet ) ) { lineLayerIdMap.insert( fet.attributeMap()[lineField].toString(), fet.id() ); } //create output datasource or attributes in memory provider QgsVectorFileWriter* fileWriter = 0; QgsFeatureList memoryProviderFeatures; if ( !memoryProvider ) { QGis::WkbType memoryProviderType = QGis::WKBMultiLineString; if ( locationField2 == -1 ) { memoryProviderType = forceSingleGeometry ? QGis::WKBPoint : QGis::WKBMultiPoint; } else { memoryProviderType = forceSingleGeometry ? QGis::WKBLineString : QGis::WKBMultiLineString; } fileWriter = new QgsVectorFileWriter( outputLayer, eventLayer->dataProvider()->encoding(), eventLayer->pendingFields(), memoryProviderType, &( lineLayer->crs() ), outputFormat ); } else { memoryProvider->addAttributes( eventLayer->pendingFields().values() ); } //iterate over eventLayer and write new features to output file or layer eventLayer->select( eventLayer->pendingAllAttributesList(), QgsRectangle(), false, false ); QgsGeometry* lrsGeom = 0; QgsFeature lineFeature; double measure1, measure2; int nEventFeatures = eventLayer->pendingFeatureCount(); int featureCounter = 0; int nOutputFeatures = 0; //number of output features for the current event feature if ( p ) { p->setWindowModality( Qt::WindowModal ); p->setMinimum( 0 ); p->setMaximum( nEventFeatures ); p->show(); } while ( eventLayer->nextFeature( fet ) ) { nOutputFeatures = 0; //update progress dialog if ( p ) { if ( p->wasCanceled() ) { break; } p->setValue( featureCounter ); ++featureCounter; } measure1 = fet.attributeMap()[locationField1].toDouble(); if ( locationField2 != -1 ) { measure2 = fet.attributeMap()[locationField2].toDouble(); } QList<QgsFeatureId> featureIdList = lineLayerIdMap.values( fet.attributeMap()[eventField].toString() ); QList<QgsFeatureId>::const_iterator featureIdIt = featureIdList.constBegin(); for ( ; featureIdIt != featureIdList.constEnd(); ++featureIdIt ) { if ( !lineLayer->featureAtId( *featureIdIt, lineFeature, true, false ) ) { continue; } if ( locationField2 == -1 ) { lrsGeom = locateAlongMeasure( measure1, lineFeature.geometry() ); } else { lrsGeom = locateBetweenMeasures( measure1, measure2, lineFeature.geometry() ); } if ( lrsGeom ) { ++nOutputFeatures; addEventLayerFeature( fet, lrsGeom, lineFeature.geometry(), fileWriter, memoryProviderFeatures, offsetField, offsetScale, forceSingleGeometry ); } } if ( nOutputFeatures < 1 ) { unlocatedFeatureIds.push_back( fet.id() ); } } if ( p ) { p->setValue( nEventFeatures ); } if ( memoryProvider ) { memoryProvider->addFeatures( memoryProviderFeatures ); } delete fileWriter; return true; }