Skip to content
Permalink
Browse files

[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!
  • Loading branch information
nyalldawson committed Dec 4, 2018
1 parent 19b54ba commit b95400806a8627e4deec0c70433b8de109cbe7a6
@@ -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>
@@ -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>
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
@@ -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"]]
Binary file not shown.
Binary file not shown.
@@ -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>
@@ -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

0 comments on commit b954008

Please sign in to comment.
You can’t perform that action at this time.