mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Allow selection of a subset of fields to keep for hub lines algorithm
This commit is contained in:
parent
cc19d0a70d
commit
bd24c8b664
70
python/plugins/processing/tests/testdata/expected/hub_lines_field_subset.gml
vendored
Normal file
70
python/plugins/processing/tests/testdata/expected/hub_lines_field_subset.gml
vendored
Normal file
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ hub_lines_field_subset.xsd"
|
||||
xmlns:ogr="http://ogr.maptools.org/"
|
||||
xmlns:gml="http://www.opengis.net/gml">
|
||||
<gml:boundedBy>
|
||||
<gml:Box>
|
||||
<gml:coord><gml:X>1</gml:X><gml:Y>-4.1675</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>7</gml:X><gml:Y>3.8825</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines_field_subset fid="hub_lines_field_subset.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1,1 5.07625,-2.1725</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>1</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:name>point 1</ogr:name>
|
||||
</ogr:hub_lines_field_subset>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines_field_subset fid="hub_lines_field_subset.1">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,3 5.82,3.8825</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>2</ogr:id>
|
||||
<ogr:id2>1</ogr:id2>
|
||||
<ogr:name>point 2</ogr:name>
|
||||
</ogr:hub_lines_field_subset>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines_field_subset fid="hub_lines_field_subset.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,2 1.62,1.4675</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>3</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:name>point 3</ogr:name>
|
||||
</ogr:hub_lines_field_subset>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines_field_subset fid="hub_lines_field_subset.3">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5,2 6.68625,1.23125</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:name>point 4</ogr:name>
|
||||
</ogr:hub_lines_field_subset>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines_field_subset fid="hub_lines_field_subset.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5,2 1.27875,-3.66875</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:name>point 4a</ogr:name>
|
||||
</ogr:hub_lines_field_subset>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines_field_subset fid="hub_lines_field_subset.5">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5,2 3.81625,-4.1675</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>4</ogr:id>
|
||||
<ogr:id2>2</ogr:id2>
|
||||
<ogr:name>point 4b</ogr:name>
|
||||
</ogr:hub_lines_field_subset>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:hub_lines_field_subset fid="hub_lines_field_subset.6">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-1 6.82625,-2.79375</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
<ogr:id>8</ogr:id>
|
||||
<ogr:id2>0</ogr:id2>
|
||||
<ogr:name>point 8</ogr:name>
|
||||
</ogr:hub_lines_field_subset>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
44
python/plugins/processing/tests/testdata/expected/hub_lines_field_subset.xsd
vendored
Normal file
44
python/plugins/processing/tests/testdata/expected/hub_lines_field_subset.xsd
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
|
||||
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
|
||||
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
|
||||
<xs:complexType name="FeatureCollectionType">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureCollectionType">
|
||||
<xs:attribute name="lockId" type="xs:string" use="optional"/>
|
||||
<xs:attribute name="scope" type="xs:string" use="optional"/>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
<xs:element name="hub_lines_field_subset" type="ogr:hub_lines_field_subset_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="hub_lines_field_subset_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="id" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:integer">
|
||||
<xs:totalDigits value="10"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="id2" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:integer">
|
||||
<xs:totalDigits value="10"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:maxLength value="8"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
@ -2500,6 +2500,27 @@ tests:
|
||||
fid: skip
|
||||
fid_2: skip
|
||||
|
||||
- algorithm: native:hublines
|
||||
name: Hub lines subset of fields
|
||||
params:
|
||||
HUBS:
|
||||
name: points.gml
|
||||
type: vector
|
||||
HUB_FIELD: id
|
||||
HUB_FIELDS:
|
||||
- id
|
||||
- id2
|
||||
SPOKES:
|
||||
name: custom/spoke_points.gml
|
||||
type: vector
|
||||
SPOKE_FIELD: id
|
||||
SPOKE_FIELDS:
|
||||
- name
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/hub_lines_field_subset.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: qgis:pointstopath
|
||||
name: Points to path (non grouped)
|
||||
params:
|
||||
|
@ -2885,11 +2885,22 @@ void QgsJoinWithLinesAlgorithm::initAlgorithm( const QVariantMap & )
|
||||
QObject::tr( "Hub layer" ) ) );
|
||||
addParameter( new QgsProcessingParameterField( QStringLiteral( "HUB_FIELD" ),
|
||||
QObject::tr( "Hub ID field" ), QVariant(), QStringLiteral( "HUBS" ) ) );
|
||||
|
||||
addParameter( new QgsProcessingParameterField( QStringLiteral( "HUB_FIELDS" ),
|
||||
QObject::tr( "Hub layer fields to copy (leave empty to copy all fields)" ),
|
||||
QVariant(), QStringLiteral( "HUBS" ), QgsProcessingParameterField::Any,
|
||||
true, true ) );
|
||||
|
||||
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "SPOKES" ),
|
||||
QObject::tr( "Spoke layer" ) ) );
|
||||
addParameter( new QgsProcessingParameterField( QStringLiteral( "SPOKE_FIELD" ),
|
||||
QObject::tr( "Spoke ID field" ), QVariant(), QStringLiteral( "SPOKES" ) ) );
|
||||
|
||||
addParameter( new QgsProcessingParameterField( QStringLiteral( "SPOKE_FIELDS" ),
|
||||
QObject::tr( "Spoke layer fields to copy (leave empty to copy all fields)" ),
|
||||
QVariant(), QStringLiteral( "SPOKES" ), QgsProcessingParameterField::Any,
|
||||
true, true ) );
|
||||
|
||||
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Hub lines" ), QgsProcessing::TypeVectorLine ) );
|
||||
}
|
||||
|
||||
@ -2917,13 +2928,69 @@ QVariantMap QgsJoinWithLinesAlgorithm::processAlgorithm( const QVariantMap ¶
|
||||
|
||||
QString fieldHubName = parameterAsString( parameters, QStringLiteral( "HUB_FIELD" ), context );
|
||||
int fieldHubIndex = hubSource->fields().lookupField( fieldHubName );
|
||||
const QStringList hubFieldsToCopy = parameterAsFields( parameters, QStringLiteral( "HUB_FIELDS" ), context );
|
||||
|
||||
QString fieldSpokeName = parameterAsString( parameters, QStringLiteral( "SPOKE_FIELD" ), context );
|
||||
int fieldSpokeIndex = spokeSource->fields().lookupField( fieldSpokeName );
|
||||
const QStringList spokeFieldsToCopy = parameterAsFields( parameters, QStringLiteral( "SPOKE_FIELDS" ), context );
|
||||
|
||||
if ( fieldHubIndex < 0 || fieldSpokeIndex < 0 )
|
||||
throw QgsProcessingException( QObject::tr( "Invalid ID field" ) );
|
||||
|
||||
QgsFields fields = QgsProcessingUtils::combineFields( hubSource->fields(), spokeSource->fields() );
|
||||
QgsFields hubOutFields;
|
||||
QgsAttributeList hubFieldIndices;
|
||||
if ( hubFieldsToCopy.empty() )
|
||||
{
|
||||
hubOutFields = hubSource->fields();
|
||||
for ( int i = 0; i < hubOutFields.count(); ++i )
|
||||
{
|
||||
hubFieldIndices << i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( const QString &field : hubFieldsToCopy )
|
||||
{
|
||||
int index = hubSource->fields().lookupField( field );
|
||||
if ( index >= 0 )
|
||||
{
|
||||
hubFieldIndices << index;
|
||||
hubOutFields.append( hubSource->fields().at( index ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QgsAttributeList hubFields2Fetch = hubFieldIndices;
|
||||
hubFields2Fetch << fieldHubIndex;
|
||||
|
||||
QgsFields spokeOutFields;
|
||||
QgsAttributeList spokeFieldIndices;
|
||||
if ( spokeFieldsToCopy.empty() )
|
||||
{
|
||||
spokeOutFields = spokeSource->fields();
|
||||
for ( int i = 0; i < spokeOutFields.count(); ++i )
|
||||
{
|
||||
spokeFieldIndices << i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( const QString &field : spokeFieldsToCopy )
|
||||
{
|
||||
int index = spokeSource->fields().lookupField( field );
|
||||
if ( index >= 0 )
|
||||
{
|
||||
spokeFieldIndices << index;
|
||||
spokeOutFields.append( spokeSource->fields().at( index ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QgsAttributeList spokeFields2Fetch = spokeFieldIndices;
|
||||
spokeFields2Fetch << fieldSpokeIndex;
|
||||
|
||||
|
||||
QgsFields fields = QgsProcessingUtils::combineFields( hubOutFields, spokeOutFields );
|
||||
|
||||
QgsWkbTypes::Type outType = QgsWkbTypes::LineString;
|
||||
bool hasZ = false;
|
||||
@ -2959,7 +3026,7 @@ QVariantMap QgsJoinWithLinesAlgorithm::processAlgorithm( const QVariantMap ¶
|
||||
return p;
|
||||
};
|
||||
|
||||
QgsFeatureIterator hubFeatures = hubSource->getFeatures();
|
||||
QgsFeatureIterator hubFeatures = hubSource->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( hubFields2Fetch ) );
|
||||
double step = hubSource->featureCount() > 0 ? 100.0 / hubSource->featureCount() : 1;
|
||||
int i = 0;
|
||||
QgsFeature hubFeature;
|
||||
@ -2977,9 +3044,18 @@ QVariantMap QgsJoinWithLinesAlgorithm::processAlgorithm( const QVariantMap ¶
|
||||
continue;
|
||||
|
||||
QgsPoint hubPoint = getPointFromFeature( hubFeature );
|
||||
QgsAttributes hubAttributes = hubFeature.attributes();
|
||||
|
||||
// only keep selected attributes
|
||||
QgsAttributes hubAttributes;
|
||||
for ( int j = 0; j < hubFeature.attributes().count(); ++j )
|
||||
{
|
||||
if ( !hubFieldIndices.contains( j ) )
|
||||
continue;
|
||||
hubAttributes << hubFeature.attribute( j );
|
||||
}
|
||||
|
||||
QgsFeatureRequest spokeRequest = QgsFeatureRequest().setDestinationCrs( hubSource->sourceCrs() );
|
||||
spokeRequest.setSubsetOfAttributes( spokeFields2Fetch );
|
||||
spokeRequest.setFilterExpression( QgsExpression::createFieldEqualityExpression( fieldSpokeName, hubFeature.attribute( fieldHubIndex ) ) );
|
||||
|
||||
QgsFeatureIterator spokeFeatures = spokeSource->getFeatures( spokeRequest );
|
||||
@ -2990,13 +3066,25 @@ QVariantMap QgsJoinWithLinesAlgorithm::processAlgorithm( const QVariantMap ¶
|
||||
{
|
||||
break;
|
||||
}
|
||||
if ( !spokeFeature.hasGeometry() )
|
||||
continue;
|
||||
|
||||
QgsPoint spokePoint = getPointFromFeature( spokeFeature );
|
||||
QgsGeometry line( new QgsLineString( QVector< QgsPoint >() << hubPoint << spokePoint ) );
|
||||
|
||||
QgsFeature outFeature;
|
||||
QgsAttributes outAttributes = hubAttributes;
|
||||
outAttributes.append( spokeFeature.attributes() );
|
||||
|
||||
// only keep selected attributes
|
||||
QgsAttributes spokeAttributes;
|
||||
for ( int j = 0; j < spokeFeature.attributes().count(); ++j )
|
||||
{
|
||||
if ( !spokeFieldIndices.contains( j ) )
|
||||
continue;
|
||||
spokeAttributes << spokeFeature.attribute( j );
|
||||
}
|
||||
|
||||
outAttributes.append( spokeAttributes );
|
||||
outFeature.setAttributes( outAttributes );
|
||||
outFeature.setGeometry( line );
|
||||
sink->addFeature( outFeature, QgsFeatureSink::FastInsert );
|
||||
|
Loading…
x
Reference in New Issue
Block a user