Skip to content

Commit

Permalink
[FEATURE][processing] Native "split lines by maximum length" algorithm
Browse files Browse the repository at this point in the history
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 6, 2018
1 parent 19b54ba commit b954008
Show file tree
Hide file tree
Showing 15 changed files with 488 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -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>
37 changes: 37 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit b954008

Please sign in to comment.