Skip to content

Commit 76c84f1

Browse files
committed
[FEATURE][processing] "Create parallel lines" algorithm
This algorithm creates copies of line features in a layer, by creating multiple parallel versions of each feature. Each copy is offset by a preset distance.
1 parent b80ad5e commit 76c84f1

File tree

8 files changed

+502
-3
lines changed

8 files changed

+502
-3
lines changed
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://ogr.maptools.org/ create_parallel_lines.xsd"
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-3.6</gml:Y></gml:coord>
10+
<gml:coord><gml:X>11.42426406871193</gml:X><gml:Y>5</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:create_parallel_lines fid="lines.0">
16+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,2 9,2 9,3 11,5</gml:coordinates></gml:LineString></ogr:geometryProperty>
17+
<ogr:instance>0</ogr:instance>
18+
<ogr:offset>0</ogr:offset>
19+
</ogr:create_parallel_lines>
20+
</gml:featureMember>
21+
<gml:featureMember>
22+
<ogr:create_parallel_lines fid="lines.0">
23+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>11.1414213562373,4.85857864376269 9.2,2.91715728752538 9.2,1.8 6.0,1.8</gml:coordinates></gml:LineString></ogr:geometryProperty>
24+
<ogr:instance>1</ogr:instance>
25+
<ogr:offset>-0.2</ogr:offset>
26+
</ogr:create_parallel_lines>
27+
</gml:featureMember>
28+
<gml:featureMember>
29+
<ogr:create_parallel_lines fid="lines.0">
30+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>11.2828427124746,4.71715728752538 9.4,2.83431457505076 9.4,1.6 6.0,1.6</gml:coordinates></gml:LineString></ogr:geometryProperty>
31+
<ogr:instance>2</ogr:instance>
32+
<ogr:offset>-0.4</ogr:offset>
33+
</ogr:create_parallel_lines>
34+
</gml:featureMember>
35+
<gml:featureMember>
36+
<ogr:create_parallel_lines fid="lines.0">
37+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>11.4242640687119,4.57573593128807 9.6,2.75147186257614 9.6,1.4 6.0,1.4</gml:coordinates></gml:LineString></ogr:geometryProperty>
38+
<ogr:instance>3</ogr:instance>
39+
<ogr:offset>-0.6</ogr:offset>
40+
</ogr:create_parallel_lines>
41+
</gml:featureMember>
42+
<gml:featureMember>
43+
<ogr:create_parallel_lines fid="lines.1">
44+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
45+
<ogr:instance>0</ogr:instance>
46+
<ogr:offset>0</ogr:offset>
47+
</ogr:create_parallel_lines>
48+
</gml:featureMember>
49+
<gml:featureMember>
50+
<ogr:create_parallel_lines fid="lines.1">
51+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1.0,-1.2 -1.0,-1.2</gml:coordinates></gml:LineString></ogr:geometryProperty>
52+
<ogr:instance>1</ogr:instance>
53+
<ogr:offset>-0.2</ogr:offset>
54+
</ogr:create_parallel_lines>
55+
</gml:featureMember>
56+
<gml:featureMember>
57+
<ogr:create_parallel_lines fid="lines.1">
58+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1.0,-1.4 -1.0,-1.4</gml:coordinates></gml:LineString></ogr:geometryProperty>
59+
<ogr:instance>2</ogr:instance>
60+
<ogr:offset>-0.4</ogr:offset>
61+
</ogr:create_parallel_lines>
62+
</gml:featureMember>
63+
<gml:featureMember>
64+
<ogr:create_parallel_lines fid="lines.1">
65+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>1.0,-1.6 -1.0,-1.6</gml:coordinates></gml:LineString></ogr:geometryProperty>
66+
<ogr:instance>3</ogr:instance>
67+
<ogr:offset>-0.6</ogr:offset>
68+
</ogr:create_parallel_lines>
69+
</gml:featureMember>
70+
<gml:featureMember>
71+
<ogr:create_parallel_lines fid="lines.2">
72+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2,2 3,2 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
73+
<ogr:instance>0</ogr:instance>
74+
<ogr:offset>0</ogr:offset>
75+
</ogr:create_parallel_lines>
76+
</gml:featureMember>
77+
<gml:featureMember>
78+
<ogr:create_parallel_lines fid="lines.2">
79+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3.2,3.0 3.2,1.8 2.8,1.8 2.2,1.8 2.2,0.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
80+
<ogr:instance>1</ogr:instance>
81+
<ogr:offset>-0.2</ogr:offset>
82+
</ogr:create_parallel_lines>
83+
</gml:featureMember>
84+
<gml:featureMember>
85+
<ogr:create_parallel_lines fid="lines.2">
86+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3.4,3.0 3.4,1.6 2.93333333333333,1.6 2.4,1.6 2.4,0.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
87+
<ogr:instance>2</ogr:instance>
88+
<ogr:offset>-0.4</ogr:offset>
89+
</ogr:create_parallel_lines>
90+
</gml:featureMember>
91+
<gml:featureMember>
92+
<ogr:create_parallel_lines fid="lines.2">
93+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3.6,3.0 3.6,1.4 3.06666666666667,1.4 2.6,1.4 2.6,0.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
94+
<ogr:instance>3</ogr:instance>
95+
<ogr:offset>-0.6</ogr:offset>
96+
</ogr:create_parallel_lines>
97+
</gml:featureMember>
98+
<gml:featureMember>
99+
<ogr:create_parallel_lines fid="lines.3">
100+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
101+
<ogr:instance>0</ogr:instance>
102+
<ogr:offset>0</ogr:offset>
103+
</ogr:create_parallel_lines>
104+
</gml:featureMember>
105+
<gml:featureMember>
106+
<ogr:create_parallel_lines fid="lines.3">
107+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.0,0.8 3.0,0.8</gml:coordinates></gml:LineString></ogr:geometryProperty>
108+
<ogr:instance>1</ogr:instance>
109+
<ogr:offset>-0.2</ogr:offset>
110+
</ogr:create_parallel_lines>
111+
</gml:featureMember>
112+
<gml:featureMember>
113+
<ogr:create_parallel_lines fid="lines.3">
114+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.0,0.6 3.0,0.6</gml:coordinates></gml:LineString></ogr:geometryProperty>
115+
<ogr:instance>2</ogr:instance>
116+
<ogr:offset>-0.4</ogr:offset>
117+
</ogr:create_parallel_lines>
118+
</gml:featureMember>
119+
<gml:featureMember>
120+
<ogr:create_parallel_lines fid="lines.3">
121+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>5.0,0.4 3.0,0.4</gml:coordinates></gml:LineString></ogr:geometryProperty>
122+
<ogr:instance>3</ogr:instance>
123+
<ogr:offset>-0.6</ogr:offset>
124+
</ogr:create_parallel_lines>
125+
</gml:featureMember>
126+
<gml:featureMember>
127+
<ogr:create_parallel_lines fid="lines.4">
128+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-3 10,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
129+
<ogr:instance>0</ogr:instance>
130+
<ogr:offset>0</ogr:offset>
131+
</ogr:create_parallel_lines>
132+
</gml:featureMember>
133+
<gml:featureMember>
134+
<ogr:create_parallel_lines fid="lines.4">
135+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10.0,-3.2 7.0,-3.2</gml:coordinates></gml:LineString></ogr:geometryProperty>
136+
<ogr:instance>1</ogr:instance>
137+
<ogr:offset>-0.2</ogr:offset>
138+
</ogr:create_parallel_lines>
139+
</gml:featureMember>
140+
<gml:featureMember>
141+
<ogr:create_parallel_lines fid="lines.4">
142+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10.0,-3.4 7.0,-3.4</gml:coordinates></gml:LineString></ogr:geometryProperty>
143+
<ogr:instance>2</ogr:instance>
144+
<ogr:offset>-0.4</ogr:offset>
145+
</ogr:create_parallel_lines>
146+
</gml:featureMember>
147+
<gml:featureMember>
148+
<ogr:create_parallel_lines fid="lines.4">
149+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10.0,-3.6 7.0,-3.6</gml:coordinates></gml:LineString></ogr:geometryProperty>
150+
<ogr:instance>3</ogr:instance>
151+
<ogr:offset>-0.6</ogr:offset>
152+
</ogr:create_parallel_lines>
153+
</gml:featureMember>
154+
<gml:featureMember>
155+
<ogr:create_parallel_lines fid="lines.5">
156+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 10,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
157+
<ogr:instance>0</ogr:instance>
158+
<ogr:offset>0</ogr:offset>
159+
</ogr:create_parallel_lines>
160+
</gml:featureMember>
161+
<gml:featureMember>
162+
<ogr:create_parallel_lines fid="lines.5">
163+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10.1414213562373,0.858578643762691 6.14142135623731,-3.14142135623731</gml:coordinates></gml:LineString></ogr:geometryProperty>
164+
<ogr:instance>1</ogr:instance>
165+
<ogr:offset>-0.2</ogr:offset>
166+
</ogr:create_parallel_lines>
167+
</gml:featureMember>
168+
<gml:featureMember>
169+
<ogr:create_parallel_lines fid="lines.5">
170+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10.2828427124746,0.717157287525381 6.28284271247462,-3.28284271247462</gml:coordinates></gml:LineString></ogr:geometryProperty>
171+
<ogr:instance>2</ogr:instance>
172+
<ogr:offset>-0.4</ogr:offset>
173+
</ogr:create_parallel_lines>
174+
</gml:featureMember>
175+
<gml:featureMember>
176+
<ogr:create_parallel_lines fid="lines.5">
177+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>10.4242640687119,0.575735931288071 6.42426406871193,-3.42426406871193</gml:coordinates></gml:LineString></ogr:geometryProperty>
178+
<ogr:instance>3</ogr:instance>
179+
<ogr:offset>-0.6</ogr:offset>
180+
</ogr:create_parallel_lines>
181+
</gml:featureMember>
182+
<gml:featureMember>
183+
<ogr:create_parallel_lines fid="lines.6">
184+
<ogr:instance xsi:nil="true"/>
185+
<ogr:offset xsi:nil="true"/>
186+
</ogr:create_parallel_lines>
187+
</gml:featureMember>
188+
</ogr:FeatureCollection>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<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">
3+
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
4+
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
5+
<xs:complexType name="FeatureCollectionType">
6+
<xs:complexContent>
7+
<xs:extension base="gml:AbstractFeatureCollectionType">
8+
<xs:attribute name="lockId" type="xs:string" use="optional"/>
9+
<xs:attribute name="scope" type="xs:string" use="optional"/>
10+
</xs:extension>
11+
</xs:complexContent>
12+
</xs:complexType>
13+
<xs:element name="create_parallel_lines" type="ogr:create_parallel_lines_Type" substitutionGroup="gml:_Feature"/>
14+
<xs:complexType name="create_parallel_lines_Type">
15+
<xs:complexContent>
16+
<xs:extension base="gml:AbstractFeatureType">
17+
<xs:sequence>
18+
<xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
19+
<xs:element name="instance" nillable="true" minOccurs="0" maxOccurs="1">
20+
<xs:simpleType>
21+
<xs:restriction base="xs:integer">
22+
<xs:totalDigits value="10"/>
23+
</xs:restriction>
24+
</xs:simpleType>
25+
</xs:element>
26+
<xs:element name="offset" nillable="true" minOccurs="0" maxOccurs="1">
27+
<xs:simpleType>
28+
<xs:restriction base="xs:decimal">
29+
</xs:restriction>
30+
</xs:simpleType>
31+
</xs:element>
32+
</xs:sequence>
33+
</xs:extension>
34+
</xs:complexContent>
35+
</xs:complexType>
36+
</xs:schema>

python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5908,5 +5908,20 @@ tests:
59085908
name: expected/feature_array.shp
59095909
type: vector
59105910

5911+
- algorithm: native:parallellines
5912+
name: Create parallel lines
5913+
params:
5914+
COUNT: 3
5915+
INPUT:
5916+
name: lines.gml
5917+
type: vector
5918+
JOIN_STYLE: 1
5919+
MITER_LIMIT: 2.0
5920+
OFFSET: -0.2
5921+
SEGMENTS: 8
5922+
results:
5923+
OUTPUT:
5924+
name: expected/create_parallel_lines.gml
5925+
type: vector
59115926

59125927
# See ../README.md for a description of the file format

src/analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ SET(QGIS_ANALYSIS_SRCS
6161
processing/qgsalgorithmorderbyexpression.cpp
6262
processing/qgsalgorithmorientedminimumboundingbox.cpp
6363
processing/qgsalgorithmpackage.cpp
64+
processing/qgsalgorithmparallellines.cpp
6465
processing/qgsalgorithmpointonsurface.cpp
6566
processing/qgsalgorithmprojectpointcartesian.cpp
6667
processing/qgsalgorithmpromotetomultipart.cpp

src/analysis/processing/qgsalgorithmarrayfeatures.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ QStringList QgsArrayFeaturesAlgorithm::tags() const
3636

3737
QString QgsArrayFeaturesAlgorithm::group() const
3838
{
39-
return QObject::tr( "Vector geometry" );
39+
return QObject::tr( "Vector creation" );
4040
}
4141

4242
QString QgsArrayFeaturesAlgorithm::groupId() const
4343
{
44-
return QStringLiteral( "vectorgeometry" );
44+
return QStringLiteral( "vectorcreation" );
4545
}
4646

4747
QString QgsArrayFeaturesAlgorithm::outputName() const
@@ -69,7 +69,7 @@ void QgsArrayFeaturesAlgorithm::initParameters( const QVariantMap & )
6969
{
7070
std::unique_ptr< QgsProcessingParameterNumber > count = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "COUNT" ),
7171
QObject::tr( "Number of features to create" ), QgsProcessingParameterNumber::Integer,
72-
10, true, 1 );
72+
10, false, 1 );
7373
count->setIsDynamic( true );
7474
count->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "COUNT" ), QObject::tr( "Number of features to create" ), QgsPropertyDefinition::IntegerPositiveGreaterZero ) );
7575
count->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );

0 commit comments

Comments
 (0)