mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-27 00:33:48 -05:00
[FEATURE][processing] Native "split lines by maximum length" algorithm
This algorithm takes an input (multi)line (or curve) layer, and splits each feature into multiple parts such that no part is longer then the specified maximum length. Supports data-defined maximum length property, and edit in place operation. Credit to @NathanW2 for the inspiration!
This commit is contained in:
parent
19b54ba2f9
commit
b95400806a
83
python/plugins/processing/tests/testdata/expected/split_lines_by_length.gml
vendored
Normal file
83
python/plugins/processing/tests/testdata/expected/split_lines_by_length.gml
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
<?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_lines_by_length.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>-3</gml:Y></gml:coord>
|
||||
<gml:coord><gml:X>11</gml:X><gml:Y>5</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,2 8.2,2.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>8.2,2.0 9,2 9,3 9.28284271247462,3.28284271247462</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>9.28284271247462,3.28284271247462 10.838477631085,4.83847763108502</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.0">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10.838477631085,4.83847763108502 11,5</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.1">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2,2 2.2,2.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.2,2.0 3,2 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.3">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-3 9.2,-3.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>9.2,-3.0 10,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.5">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 7.55563491861041,-1.4443650813896</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.5">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7.55563491861041,-1.4443650813896 9.11126983722081,0.111269837220809</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.5">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>9.11126983722081,0.111269837220809 10,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_lines_by_length fid="lines.6">
|
||||
</ogr:split_lines_by_length>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
23
python/plugins/processing/tests/testdata/expected/split_lines_by_length.xsd
vendored
Normal file
23
python/plugins/processing/tests/testdata/expected/split_lines_by_length.xsd
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?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_lines_by_length" type="ogr:split_lines_by_length_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="split_lines_by_length_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
BIN
python/plugins/processing/tests/testdata/expected/split_linez_by_length.dbf
vendored
Normal file
BIN
python/plugins/processing/tests/testdata/expected/split_linez_by_length.dbf
vendored
Normal file
Binary file not shown.
1
python/plugins/processing/tests/testdata/expected/split_linez_by_length.prj
vendored
Normal file
1
python/plugins/processing/tests/testdata/expected/split_linez_by_length.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/expected/split_linez_by_length.qpj
vendored
Normal file
1
python/plugins/processing/tests/testdata/expected/split_linez_by_length.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/expected/split_linez_by_length.shp
vendored
Normal file
BIN
python/plugins/processing/tests/testdata/expected/split_linez_by_length.shp
vendored
Normal file
Binary file not shown.
BIN
python/plugins/processing/tests/testdata/expected/split_linez_by_length.shx
vendored
Normal file
BIN
python/plugins/processing/tests/testdata/expected/split_linez_by_length.shx
vendored
Normal file
Binary file not shown.
98
python/plugins/processing/tests/testdata/expected/split_multiline_by_length.gml
vendored
Normal file
98
python/plugins/processing/tests/testdata/expected/split_multiline_by_length.gml
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
<?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_multiline_by_length.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>5.58042226487524</gml:X><gml:Y>4.119769673704415</gml:Y></gml:coord>
|
||||
</gml:Box>
|
||||
</gml:boundedBy>
|
||||
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.1">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 0.1,-1.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.1">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>0.1,-1.0 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 4.1,1.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>4.1,1.0 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.02418426103647,2.4147792706334 5.00538358886158,1.3149399484023</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.2">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.00538358886158,1.3149399484023 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.3">
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2.0,1.1</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.0,1.1 2,2 2.2,2.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.2,2.0 3,2 3.0,2.3</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3.0,2.3 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.94433781190019,4.04721689059501 4.04388044198829,4.07893446646294</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>4.04388044198829,4.07893446646294 5.1434230720764,4.11065204233086</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.1434230720764,4.11065204233086 5.4595009596929,4.11976967370441</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,3 4.09976658596272,2.97734042366024</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>4.09976658596272,2.97734042366024 5.19953317192545,2.95468084732049</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
<gml:featureMember>
|
||||
<ogr:split_multiline_by_length fid="lines.4">
|
||||
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.19953317192545,2.95468084732049 5.58042226487524,2.9468330134357</gml:coordinates></gml:LineString></ogr:geometryProperty>
|
||||
</ogr:split_multiline_by_length>
|
||||
</gml:featureMember>
|
||||
</ogr:FeatureCollection>
|
23
python/plugins/processing/tests/testdata/expected/split_multiline_by_length.xsd
vendored
Normal file
23
python/plugins/processing/tests/testdata/expected/split_multiline_by_length.xsd
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
<?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_multiline_by_length" type="ogr:split_multiline_by_length_Type" substitutionGroup="gml:_Feature"/>
|
||||
<xs:complexType name="split_multiline_by_length_Type">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="gml:AbstractFeatureType">
|
||||
<xs:sequence>
|
||||
<xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
|
||||
</xs:sequence>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
@ -6360,4 +6360,41 @@ tests:
|
||||
name: expected/force_rhr_multipolys.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:splitlinesbylength
|
||||
name: Split multilines by length
|
||||
params:
|
||||
INPUT:
|
||||
name: multilines.gml|layername=multilines
|
||||
type: vector
|
||||
LENGTH: 1.1
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/split_multiline_by_length.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:splitlinesbylength
|
||||
name: Split lines by length
|
||||
params:
|
||||
INPUT:
|
||||
name: lines.gml|layername=lines
|
||||
type: vector
|
||||
LENGTH: 2.2
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/split_lines_by_length.gml
|
||||
type: vector
|
||||
|
||||
- algorithm: native:splitlinesbylength
|
||||
name: Split linesz by length
|
||||
params:
|
||||
INPUT:
|
||||
name: lines_z.shp
|
||||
type: vector
|
||||
LENGTH: 3.1
|
||||
results:
|
||||
OUTPUT:
|
||||
name: expected/split_linez_by_length.shp
|
||||
type: vector
|
||||
|
||||
|
||||
# See ../README.md for a description of the file format
|
||||
|
@ -92,6 +92,7 @@ SET(QGIS_ANALYSIS_SRCS
|
||||
processing/qgsalgorithmsimplify.cpp
|
||||
processing/qgsalgorithmsmooth.cpp
|
||||
processing/qgsalgorithmsnaptogrid.cpp
|
||||
processing/qgsalgorithmsplitlinesbylength.cpp
|
||||
processing/qgsalgorithmsplitwithlines.cpp
|
||||
processing/qgsalgorithmstringconcatenation.cpp
|
||||
processing/qgsalgorithmswapxy.cpp
|
||||
|
151
src/analysis/processing/qgsalgorithmsplitlinesbylength.cpp
Normal file
151
src/analysis/processing/qgsalgorithmsplitlinesbylength.cpp
Normal file
@ -0,0 +1,151 @@
|
||||
/***************************************************************************
|
||||
qgsalgorithmsplitlinesbylength.cpp
|
||||
---------------------
|
||||
begin : December 2018
|
||||
copyright : (C) 2018 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 "qgsalgorithmsplitlinesbylength.h"
|
||||
#include "qgscurve.h"
|
||||
#include "qgslinestring.h"
|
||||
#include "qgscircularstring.h"
|
||||
#include "qgscompoundcurve.h"
|
||||
#include "qgsgeometrycollection.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
QString QgsSplitLinesByLengthAlgorithm::name() const
|
||||
{
|
||||
return QStringLiteral( "splitlinesbylength" );
|
||||
}
|
||||
|
||||
QString QgsSplitLinesByLengthAlgorithm::displayName() const
|
||||
{
|
||||
return QObject::tr( "Split lines by maximum length" );
|
||||
}
|
||||
|
||||
QStringList QgsSplitLinesByLengthAlgorithm::tags() const
|
||||
{
|
||||
return QObject::tr( "segments,parts,distance,cut,chop" ).split( ',' );
|
||||
}
|
||||
|
||||
QString QgsSplitLinesByLengthAlgorithm::group() const
|
||||
{
|
||||
return QObject::tr( "Vector geometry" );
|
||||
}
|
||||
|
||||
QString QgsSplitLinesByLengthAlgorithm::groupId() const
|
||||
{
|
||||
return QStringLiteral( "vectorgeometry" );
|
||||
}
|
||||
|
||||
QString QgsSplitLinesByLengthAlgorithm::shortHelpString() const
|
||||
{
|
||||
return QObject::tr( "This algorithm takes a line (or curve) layer and splits each feature into multiple parts, "
|
||||
"where each part is of a specified maximum length.\n\n"
|
||||
"Z and M values at the start and end of the new line substrings are linearly interpolated from existing values." );
|
||||
}
|
||||
|
||||
QString QgsSplitLinesByLengthAlgorithm::shortDescription() const
|
||||
{
|
||||
return QObject::tr( "Splits lines into parts which are no longer than a specified length." );
|
||||
}
|
||||
|
||||
QList<int> QgsSplitLinesByLengthAlgorithm::inputLayerTypes() const
|
||||
{
|
||||
return QList<int>() << QgsProcessing::TypeVectorLine;
|
||||
}
|
||||
|
||||
QgsProcessing::SourceType QgsSplitLinesByLengthAlgorithm::outputLayerType() const
|
||||
{
|
||||
return QgsProcessing::TypeVectorLine;
|
||||
}
|
||||
|
||||
QgsSplitLinesByLengthAlgorithm *QgsSplitLinesByLengthAlgorithm::createInstance() const
|
||||
{
|
||||
return new QgsSplitLinesByLengthAlgorithm();
|
||||
}
|
||||
|
||||
void QgsSplitLinesByLengthAlgorithm::initParameters( const QVariantMap & )
|
||||
{
|
||||
std::unique_ptr< QgsProcessingParameterDistance > length = qgis::make_unique< QgsProcessingParameterDistance >( QStringLiteral( "LENGTH" ),
|
||||
QObject::tr( "Maximum line length" ), 10, QStringLiteral( "INPUT" ), false, 0 );
|
||||
length->setIsDynamic( true );
|
||||
length->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "LENGTH" ), QObject::tr( "Maximum length" ), QgsPropertyDefinition::DoublePositive ) );
|
||||
length->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
|
||||
addParameter( length.release() );
|
||||
}
|
||||
|
||||
bool QgsSplitLinesByLengthAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
{
|
||||
mLength = parameterAsDouble( parameters, QStringLiteral( "LENGTH" ), context );
|
||||
mDynamicLength = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "LENGTH" ) );
|
||||
if ( mDynamicLength )
|
||||
mLengthProperty = parameters.value( QStringLiteral( "LENGTH" ) ).value< QgsProperty >();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString QgsSplitLinesByLengthAlgorithm::outputName() const
|
||||
{
|
||||
return QObject::tr( "Split" );
|
||||
}
|
||||
|
||||
QgsWkbTypes::Type QgsSplitLinesByLengthAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
|
||||
{
|
||||
return QgsWkbTypes::singleType( inputWkbType );
|
||||
}
|
||||
|
||||
QgsFeatureList QgsSplitLinesByLengthAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &context, QgsProcessingFeedback * )
|
||||
{
|
||||
if ( !f.hasGeometry() )
|
||||
{
|
||||
return QgsFeatureList() << f;
|
||||
}
|
||||
else
|
||||
{
|
||||
double distance = mLength;
|
||||
if ( mDynamicLength )
|
||||
distance = mLengthProperty.valueAsDouble( context.expressionContext(), distance );
|
||||
|
||||
QgsFeature outputFeature;
|
||||
outputFeature.setAttributes( f.attributes() );
|
||||
QgsFeatureList features;
|
||||
const QgsGeometry inputGeom = f.geometry();
|
||||
for ( auto it = inputGeom.const_parts_begin(); it != inputGeom.const_parts_end(); ++it )
|
||||
{
|
||||
const QgsCurve *part = qgsgeometry_cast< const QgsCurve * >( *it );
|
||||
if ( !part )
|
||||
continue;
|
||||
|
||||
double start = 0.0;
|
||||
double end = distance;
|
||||
const double length = part->length();
|
||||
while ( start < length )
|
||||
{
|
||||
outputFeature.setGeometry( QgsGeometry( part->curveSubstring( start, end ) ) );
|
||||
start += distance;
|
||||
end += distance;
|
||||
features << outputFeature;
|
||||
}
|
||||
|
||||
}
|
||||
return features;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///@endcond
|
||||
|
||||
|
||||
|
67
src/analysis/processing/qgsalgorithmsplitlinesbylength.h
Normal file
67
src/analysis/processing/qgsalgorithmsplitlinesbylength.h
Normal file
@ -0,0 +1,67 @@
|
||||
/***************************************************************************
|
||||
qgsalgorithmsplitlinesbylength.h
|
||||
---------------------
|
||||
begin : December 2018
|
||||
copyright : (C) 2018 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 QGSALGORITHMSPLITLINESBYLENGTH_H
|
||||
#define QGSALGORITHMSPLITLINESBYLENGTH_H
|
||||
|
||||
#define SIP_NO_FILE
|
||||
|
||||
#include "qgis.h"
|
||||
#include "qgsprocessingalgorithm.h"
|
||||
|
||||
///@cond PRIVATE
|
||||
|
||||
/**
|
||||
* Native split lines by maximum length algorithm.
|
||||
*/
|
||||
class QgsSplitLinesByLengthAlgorithm : public QgsProcessingFeatureBasedAlgorithm
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
QgsSplitLinesByLengthAlgorithm() = 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;
|
||||
QgsProcessing::SourceType outputLayerType() const override;
|
||||
QgsSplitLinesByLengthAlgorithm *createInstance() const override SIP_FACTORY;
|
||||
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
|
||||
bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
protected:
|
||||
QString outputName() const override;
|
||||
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type inputWkbType ) const override;
|
||||
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
|
||||
|
||||
private:
|
||||
|
||||
double mLength = 0.0;
|
||||
bool mDynamicLength = false;
|
||||
QgsProperty mLengthProperty;
|
||||
|
||||
};
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
||||
#endif // QGSALGORITHMSPLITLINESBYLENGTH_H
|
||||
|
||||
|
@ -87,6 +87,7 @@
|
||||
#include "qgsalgorithmsimplify.h"
|
||||
#include "qgsalgorithmsmooth.h"
|
||||
#include "qgsalgorithmsnaptogrid.h"
|
||||
#include "qgsalgorithmsplitlinesbylength.h"
|
||||
#include "qgsalgorithmsplitwithlines.h"
|
||||
#include "qgsalgorithmstringconcatenation.h"
|
||||
#include "qgsalgorithmsubdivide.h"
|
||||
@ -221,6 +222,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
|
||||
addAlgorithm( new QgsSimplifyAlgorithm() );
|
||||
addAlgorithm( new QgsSmoothAlgorithm() );
|
||||
addAlgorithm( new QgsSnapToGridAlgorithm() );
|
||||
addAlgorithm( new QgsSplitLinesByLengthAlgorithm() );
|
||||
addAlgorithm( new QgsSplitWithLinesAlgorithm() );
|
||||
addAlgorithm( new QgsStringConcatenationAlgorithm() );
|
||||
addAlgorithm( new QgsSubdivideAlgorithm() );
|
||||
|
@ -175,6 +175,7 @@ class TestQgsProcessingInPlace(unittest.TestCase):
|
||||
self._support_inplace_edit_tester('native:difference', GEOMETRY_ONLY)
|
||||
self._support_inplace_edit_tester('native:dropgeometries', ALL)
|
||||
self._support_inplace_edit_tester('native:splitwithlines', LINESTRING_AND_POLYGON_ONLY)
|
||||
self._support_inplace_edit_tester('native:splitlinesbylength', LINESTRING_ONLY)
|
||||
self._support_inplace_edit_tester('native:buffer', POLYGON_ONLY_NOT_M_NOT_Z)
|
||||
|
||||
def _make_compatible_tester(self, feature_wkt, layer_wkb_name, attrs=[1]):
|
||||
|
Loading…
x
Reference in New Issue
Block a user