mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-15 00:07:25 -05:00
[FEATURE][processing] New algorithm "Split features by character"
This algorithm splits features into multiple output features by splitting a field's value with a specified character. For instance, if a layer contains features with multiple comma separated values contained in a single field, this algorithm can be used to split these values up across multiple output features. Geometries and other attributes remain unchanged in the output. Optionally, the separator string can be a regular expression for added flexibility. Designed for use in models which need to process input files with multiple concatenated values in a single attribute, e.g. geocoding a table with "address1,address2,address3" format strings
This commit is contained in:
parent
9756345412
commit
c409025409
1
python/plugins/processing/tests/testdata/custom/split_points.cpg
vendored
Normal file
1
python/plugins/processing/tests/testdata/custom/split_points.cpg
vendored
Normal file
@ -0,0 +1 @@
|
||||
UTF-8
|
||||
BIN
python/plugins/processing/tests/testdata/custom/split_points.dbf
vendored
Normal file
BIN
python/plugins/processing/tests/testdata/custom/split_points.dbf
vendored
Normal file
Binary file not shown.
1
python/plugins/processing/tests/testdata/custom/split_points.prj
vendored
Normal file
1
python/plugins/processing/tests/testdata/custom/split_points.prj
vendored
Normal file
@ -0,0 +1 @@
|
||||
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
|
||||
1
python/plugins/processing/tests/testdata/custom/split_points.qpj
vendored
Normal file
1
python/plugins/processing/tests/testdata/custom/split_points.qpj
vendored
Normal file
@ -0,0 +1 @@
|
||||
GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]
|
||||
BIN
python/plugins/processing/tests/testdata/custom/split_points.shp
vendored
Normal file
BIN
python/plugins/processing/tests/testdata/custom/split_points.shp
vendored
Normal file
Binary file not shown.
BIN
python/plugins/processing/tests/testdata/custom/split_points.shx
vendored
Normal file
BIN
python/plugins/processing/tests/testdata/custom/split_points.shx
vendored
Normal file
Binary file not shown.
56
python/plugins/processing/tests/testdata/expected/split_by_char_a.gml
vendored
Normal file
56
python/plugins/processing/tests/testdata/expected/split_by_char_a.gml
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ split_by_char_a.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>1</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>3</gml:X><gml:Y>3</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_a fid="split_by_char_a.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>xyz</ogr:val>
|
||||
<ogr:val2>a</ogr:val2>
|
||||
</ogr:split_by_char_a>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_a fid="split_by_char_a.1">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>a</ogr:val>
|
||||
<ogr:val2>ab1b</ogr:val2>
|
||||
</ogr:split_by_char_a>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_a fid="split_by_char_a.2">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>a</ogr:val>
|
||||
<ogr:val2>ab1b</ogr:val2>
|
||||
</ogr:split_by_char_a>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_a fid="split_by_char_a.3">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>cc</ogr:val>
|
||||
<ogr:val2>ab1b</ogr:val2>
|
||||
</ogr:split_by_char_a>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_a fid="split_by_char_a.4">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>a </ogr:val>
|
||||
<ogr:val2>a</ogr:val2>
|
||||
</ogr:split_by_char_a>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_a fid="split_by_char_a.5">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>c</ogr:val>
|
||||
<ogr:val2>a</ogr:val2>
|
||||
</ogr:split_by_char_a>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
||||
36
python/plugins/processing/tests/testdata/expected/split_by_char_a.xsd
vendored
Normal file
36
python/plugins/processing/tests/testdata/expected/split_by_char_a.xsd
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?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="split_by_char_a" type="ogr:split_by_char_a_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="split_by_char_a_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="val" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="val2" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:maxLength value="30"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
49
python/plugins/processing/tests/testdata/expected/split_by_char_b.gml
vendored
Normal file
49
python/plugins/processing/tests/testdata/expected/split_by_char_b.gml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ split_by_char_b.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>1</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>3</gml:X><gml:Y>3</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_b fid="split_by_char_b.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>xyz</ogr:val>
|
||||
<ogr:val2>a</ogr:val2>
|
||||
</ogr:split_by_char_b>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_b fid="split_by_char_b.1">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val></ogr:val>
|
||||
<ogr:val2>ab1b</ogr:val2>
|
||||
</ogr:split_by_char_b>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_b fid="split_by_char_b.2">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val></ogr:val>
|
||||
<ogr:val2>ab1b</ogr:val2>
|
||||
</ogr:split_by_char_b>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_b fid="split_by_char_b.3">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>cc</ogr:val>
|
||||
<ogr:val2>ab1b</ogr:val2>
|
||||
</ogr:split_by_char_b>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_b fid="split_by_char_b.4">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>a B c</ogr:val>
|
||||
<ogr:val2>a</ogr:val2>
|
||||
</ogr:split_by_char_b>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
||||
36
python/plugins/processing/tests/testdata/expected/split_by_char_b.xsd
vendored
Normal file
36
python/plugins/processing/tests/testdata/expected/split_by_char_b.xsd
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?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="split_by_char_b" type="ogr:split_by_char_b_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="split_by_char_b_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="val" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="val2" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:maxLength value="30"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
42
python/plugins/processing/tests/testdata/expected/split_by_char_regex.gml
vendored
Normal file
42
python/plugins/processing/tests/testdata/expected/split_by_char_regex.gml
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ogr:FeatureCollection
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://ogr.maptools.org/ split_by_char_regex.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>1</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>3</gml:X><gml:Y>3</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_regex fid="split_by_char_regex.0">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>2,2</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>xyz</ogr:val>
|
||||
<ogr:val2>a</ogr:val2>
|
||||
</ogr:split_by_char_regex>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_regex fid="split_by_char_regex.1">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>aBaBcc</ogr:val>
|
||||
<ogr:val2>ab</ogr:val2>
|
||||
</ogr:split_by_char_regex>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_regex fid="split_by_char_regex.2">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>1,1</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>aBaBcc</ogr:val>
|
||||
<ogr:val2>b</ogr:val2>
|
||||
</ogr:split_by_char_regex>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_by_char_regex fid="split_by_char_regex.3">
|
||||
<ogr:geometryProperty><gml:Point srsName="EPSG:4326"><gml:coordinates>3,3</gml:coordinates></gml:Point></ogr:geometryProperty>
|
||||
<ogr:val>a B c</ogr:val>
|
||||
<ogr:val2>a</ogr:val2>
|
||||
</ogr:split_by_char_regex>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
||||
36
python/plugins/processing/tests/testdata/expected/split_by_char_regex.xsd
vendored
Normal file
36
python/plugins/processing/tests/testdata/expected/split_by_char_regex.xsd
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?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="split_by_char_regex" type="ogr:split_by_char_regex_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="split_by_char_regex_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:PointPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
<xs:element name="val" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:maxLength value="10"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
<xs:element name="val2" nillable="true" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
@ -2263,4 +2263,46 @@ tests:
|
||||
custom_overlay3_b.geojson_pc:
|
||||
precision: 3
|
||||
|
||||
- algorithm: native:splitfeaturesbycharacter
|
||||
name: Split features by character
|
||||
params:
|
||||
CHAR: B
|
||||
FIELD: val
|
||||
INPUT:
|
||||
name: custom/split_points.shp|layername=split_points
|
||||
type: vector
|
||||
REGEX: false
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/split_by_char_a.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:splitfeaturesbycharacter
|
||||
name: Split features by character 2
|
||||
params:
|
||||
CHAR: aB
|
||||
FIELD: val
|
||||
INPUT:
|
||||
name: custom/split_points.shp|layername=split_points
|
||||
type: vector
|
||||
REGEX: false
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/split_by_char_b.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:splitfeaturesbycharacter
|
||||
name: Split features by character regex
|
||||
params:
|
||||
CHAR: \d
|
||||
FIELD: val2
|
||||
INPUT:
|
||||
name: custom/split_points.shp|layername=split_points
|
||||
type: vector
|
||||
REGEX: true
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/split_by_char_regex.gml
|
||||
type: vector
|
||||
|
||||
# See ../README.md for a description of the file format
|
||||
|
||||
@ -104,6 +104,7 @@ SET(QGIS_ANALYSIS_SRCS
|
||||
processing/qgsalgorithmsimplify.cpp
|
||||
processing/qgsalgorithmsmooth.cpp
|
||||
processing/qgsalgorithmsnaptogrid.cpp
|
||||
processing/qgsalgorithmsplitfeaturesbyattributecharacter.cpp
|
||||
processing/qgsalgorithmsplitlineantimeridian.cpp
|
||||
processing/qgsalgorithmsplitlinesbylength.cpp
|
||||
processing/qgsalgorithmsplitwithlines.cpp
|
||||
|
||||
@ -0,0 +1,147 @@
|
||||
/***************************************************************************
|
||||
qgsalgorithmsplitfeaturesbyattributecharacter.cpp
|
||||
---------------------
|
||||
begin : September 2019
|
||||
copyright : (C) 2019 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsalgorithmsplitfeaturesbyattributecharacter.h"
|
||||
#include "qgscurve.h"
|
||||
#include "qgslinestring.h"
|
||||
#include "qgscircularstring.h"
|
||||
#include "qgscompoundcurve.h"
|
||||
#include "qgsgeometrycollection.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
QString QgsSplitFeaturesByAttributeCharacterAlgorithm::name() const
|
||||
{
|
||||
return QStringLiteral( "splitfeaturesbycharacter" );
|
||||
}
|
||||
|
||||
QString QgsSplitFeaturesByAttributeCharacterAlgorithm::displayName() const
|
||||
{
|
||||
return QObject::tr( "Split features by character" );
|
||||
}
|
||||
|
||||
QStringList QgsSplitFeaturesByAttributeCharacterAlgorithm::tags() const
|
||||
{
|
||||
return QObject::tr( "separate,attribute,value,string" ).split( ',' );
|
||||
}
|
||||
|
||||
QString QgsSplitFeaturesByAttributeCharacterAlgorithm::group() const
|
||||
{
|
||||
return QObject::tr( "Vector general" );
|
||||
}
|
||||
|
||||
QString QgsSplitFeaturesByAttributeCharacterAlgorithm::groupId() const
|
||||
{
|
||||
return QStringLiteral( "vectorgeneral" );
|
||||
}
|
||||
|
||||
QString QgsSplitFeaturesByAttributeCharacterAlgorithm::shortHelpString() const
|
||||
{
|
||||
return QObject::tr( "This algorithm splits features into multiple output features by splitting a field's value with a specified character.\n\n"
|
||||
"For instance, if a layer contains features with multiple comma separated values contained in a single field, this "
|
||||
"algorithm can be used to split these values up across multiple output features.\n\n"
|
||||
"Geometries and other attributes remain unchanged in the output.\n\n"
|
||||
"Optionally, the separator string can be a regular expression for added flexibility." );
|
||||
}
|
||||
|
||||
QString QgsSplitFeaturesByAttributeCharacterAlgorithm::shortDescription() const
|
||||
{
|
||||
return QObject::tr( "Splits features into multiple output features by splitting a field by a character." );
|
||||
}
|
||||
|
||||
QList<int> QgsSplitFeaturesByAttributeCharacterAlgorithm::inputLayerTypes() const
|
||||
{
|
||||
return QList<int>() << QgsProcessing::TypeVector;
|
||||
}
|
||||
|
||||
void QgsSplitFeaturesByAttributeCharacterAlgorithm::initParameters( const QVariantMap & )
|
||||
{
|
||||
addParameter( new QgsProcessingParameterField( QStringLiteral( "FIELD" ), QObject::tr( "Split using values in field" ), QVariant(), QStringLiteral( "INPUT" ) ) );
|
||||
addParameter( new QgsProcessingParameterString( QStringLiteral( "CHAR" ), QObject::tr( "Split values using character" ) ) );
|
||||
std::unique_ptr< QgsProcessingParameterDefinition > regexParam = qgis::make_unique< QgsProcessingParameterBoolean >( QStringLiteral( "REGEX" ), QObject::tr( "Use regular expression separator" ) );
|
||||
regexParam->setFlags( regexParam->flags() | QgsProcessingParameterDefinition::FlagAdvanced );
|
||||
addParameter( regexParam.release() );
|
||||
}
|
||||
|
||||
QgsProcessing::SourceType QgsSplitFeaturesByAttributeCharacterAlgorithm::outputLayerType() const
|
||||
{
|
||||
return QgsProcessing::TypeVector;
|
||||
}
|
||||
|
||||
QgsSplitFeaturesByAttributeCharacterAlgorithm *QgsSplitFeaturesByAttributeCharacterAlgorithm::createInstance() const
|
||||
{
|
||||
return new QgsSplitFeaturesByAttributeCharacterAlgorithm();
|
||||
}
|
||||
|
||||
QgsFields QgsSplitFeaturesByAttributeCharacterAlgorithm::outputFields( const QgsFields &inputFields ) const
|
||||
{
|
||||
mFieldIndex = inputFields.lookupField( mFieldName );
|
||||
QgsFields outputFields;
|
||||
for ( int i = 0; i < inputFields.count(); ++i )
|
||||
{
|
||||
if ( i != mFieldIndex )
|
||||
{
|
||||
outputFields.append( inputFields.at( i ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// we need to convert the split field to a string field
|
||||
outputFields.append( QgsField( inputFields.at( i ).name(), QVariant::String ) );
|
||||
}
|
||||
}
|
||||
return outputFields;
|
||||
}
|
||||
|
||||
QString QgsSplitFeaturesByAttributeCharacterAlgorithm::outputName() const
|
||||
{
|
||||
return QObject::tr( "Split" );
|
||||
}
|
||||
|
||||
bool QgsSplitFeaturesByAttributeCharacterAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
{
|
||||
mChar = parameterAsString( parameters, QStringLiteral( "CHAR" ), context );
|
||||
mFieldName = parameterAsString( parameters, QStringLiteral( "FIELD" ), context );
|
||||
mUseRegex = parameterAsBoolean( parameters, QStringLiteral( "REGEX" ), context );
|
||||
if ( mUseRegex )
|
||||
mRegex = QRegularExpression( mChar );
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsFeatureList QgsSplitFeaturesByAttributeCharacterAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &, QgsProcessingFeedback * )
|
||||
{
|
||||
QgsFeatureList res;
|
||||
const QString val = f.attribute( mFieldIndex ).toString();
|
||||
const QStringList parts = mUseRegex ? val.split( mRegex ) : val.split( mChar );
|
||||
res.reserve( parts.size() );
|
||||
for ( const QString &p : parts )
|
||||
{
|
||||
QgsFeature out = f;
|
||||
out.setAttribute( mFieldIndex, p );
|
||||
res << out;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
QgsFeatureSink::SinkFlags QgsSplitFeaturesByAttributeCharacterAlgorithm::sinkFlags() const
|
||||
{
|
||||
return QgsFeatureSink::RegeneratePrimaryKey;
|
||||
}
|
||||
|
||||
///@endcond
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
/***************************************************************************
|
||||
qgsalgorithmsplitfeaturesbyattributecharacter.h
|
||||
---------------------
|
||||
begin : September 2019
|
||||
copyright : (C) 2019 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSALGORITHMSPLITFEATURESBYATTRIBUTECHARACTER_H
|
||||
#define QGSALGORITHMSPLITFEATURESBYATTRIBUTECHARACTER_H
|
||||
|
||||
#define SIP_NO_FILE
|
||||
|
||||
#include "qgis_sip.h"
|
||||
#include "qgsprocessingalgorithm.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
/**
|
||||
* Native explode lines algorithm.
|
||||
*/
|
||||
class QgsSplitFeaturesByAttributeCharacterAlgorithm : public QgsProcessingFeatureBasedAlgorithm
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
QgsSplitFeaturesByAttributeCharacterAlgorithm() = default;
|
||||
QString name() const override;
|
||||
QString displayName() const override;
|
||||
QStringList tags() const override;
|
||||
QString group() const override;
|
||||
QString groupId() const override;
|
||||
QString shortHelpString() const override;
|
||||
QString shortDescription() const override;
|
||||
QList<int> inputLayerTypes() const override;
|
||||
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
|
||||
QgsProcessing::SourceType outputLayerType() const override;
|
||||
QgsSplitFeaturesByAttributeCharacterAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
QgsFields outputFields( const QgsFields &inputFields ) const override;
|
||||
|
||||
protected:
|
||||
QString outputName() const override;
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
QgsFeatureSink::SinkFlags sinkFlags() const override;
|
||||
private:
|
||||
QString mFieldName;
|
||||
mutable int mFieldIndex = -1;
|
||||
QString mChar;
|
||||
bool mUseRegex = false;
|
||||
QRegularExpression mRegex;
|
||||
|
||||
};
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
||||
#endif // QGSALGORITHMSPLITFEATURESBYATTRIBUTECHARACTER_H
|
||||
|
||||
|
||||
@ -101,6 +101,7 @@
|
||||
#include "qgsalgorithmsplitlineantimeridian.h"
|
||||
#include "qgsalgorithmsplitlinesbylength.h"
|
||||
#include "qgsalgorithmsplitwithlines.h"
|
||||
#include "qgsalgorithmsplitfeaturesbyattributecharacter.h"
|
||||
#include "qgsalgorithmstringconcatenation.h"
|
||||
#include "qgsalgorithmsubdivide.h"
|
||||
#include "qgsalgorithmswapxy.h"
|
||||
@ -252,6 +253,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
|
||||
addAlgorithm( new QgsSimplifyAlgorithm() );
|
||||
addAlgorithm( new QgsSmoothAlgorithm() );
|
||||
addAlgorithm( new QgsSnapToGridAlgorithm() );
|
||||
addAlgorithm( new QgsSplitFeaturesByAttributeCharacterAlgorithm() );
|
||||
addAlgorithm( new QgsSplitGeometryAtAntimeridianAlgorithm() );
|
||||
addAlgorithm( new QgsSplitLinesByLengthAlgorithm() );
|
||||
addAlgorithm( new QgsSplitWithLinesAlgorithm() );
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user