Skip to content

Commit

Permalink
[FEATURE] Native 'Promote to Multipart' algorithm
Browse files Browse the repository at this point in the history
This algorithm is basically the equivalent of the ST_Multi(...)
command - it forces a feature's geometry to become multipart,
regardless of the input geometry type.

If input geometries are singlepart, they will output as
multipart with just 1 part. If they are already multipart,
they will be output unchanged.
  • Loading branch information
nyalldawson committed Sep 5, 2017
1 parent 8776122 commit 3484eb0
Show file tree
Hide file tree
Showing 11 changed files with 429 additions and 0 deletions.
@@ -0,0 +1,32 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>promote_multipart_already_multi</Name>
<ElementPath>promote_multipart_already_multi</ElementPath>
<!--MULTIPOLYGON-->
<GeometryType>6</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>4</FeatureCount>
<ExtentXMin>0.00000</ExtentXMin>
<ExtentXMax>9.00000</ExtentXMax>
<ExtentYMin>-1.00000</ExtentYMin>
<ExtentYMax>6.00000</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>Bname</Name>
<ElementPath>Bname</ElementPath>
<Type>String</Type>
<Width>4</Width>
</PropertyDefn>
<PropertyDefn>
<Name>Bintval</Name>
<ElementPath>Bintval</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>Bfloatval</Name>
<ElementPath>Bfloatval</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0</gml:X><gml:Y>-1</gml:Y></gml:coord>
<gml:coord><gml:X>9</gml:X><gml:Y>6</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:promote_multipart_already_multi fid="multipolys.0">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,1 2,2 3,2 3,3 4,3 4,1 2,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:Bname>Test</ogr:Bname>
<ogr:Bintval>1</ogr:Bintval>
<ogr:Bfloatval>0.123</ogr:Bfloatval>
</ogr:promote_multipart_already_multi>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_already_multi fid="multipolys.1">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7,-1 8,-1 8,3 7,3 7,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7,6 7,5 7,4 8,4 9,5 9,6 7,6</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
</ogr:promote_multipart_already_multi>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_already_multi fid="multipolys.2">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0,0 0,1 1,1 1,0 0,0</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:Bname>Test</ogr:Bname>
<ogr:Bintval>2</ogr:Bintval>
<ogr:Bfloatval>-0.123</ogr:Bfloatval>
</ogr:promote_multipart_already_multi>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_already_multi fid="multipolys.3">
<ogr:Bname>Test</ogr:Bname>
<ogr:Bintval>3</ogr:Bintval>
<ogr:Bfloatval>0</ogr:Bfloatval>
</ogr:promote_multipart_already_multi>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>promote_multipart_lines</Name>
<ElementPath>promote_multipart_lines</ElementPath>
<!--MULTILINESTRING-->
<GeometryType>5</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>7</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>11.00000</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
<ExtentYMax>5.00000</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
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:promote_multipart_lines fid="lines.0">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>6,2 9,2 9,3 11,5</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:promote_multipart_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_lines fid="lines.1">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:promote_multipart_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_lines fid="lines.2">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,0 2,2 3,2 3,3</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:promote_multipart_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_lines fid="lines.3">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:promote_multipart_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_lines fid="lines.4">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>7,-3 10,-3</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:promote_multipart_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_lines fid="lines.5">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>6,-3 10,1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:promote_multipart_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_lines fid="lines.6">
</ogr:promote_multipart_lines>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,26 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>promote_multipart_points</Name>
<ElementPath>promote_multipart_points</ElementPath>
<!--MULTIPOINT-->
<GeometryType>4</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>9</FeatureCount>
<ExtentXMin>0.00000</ExtentXMin>
<ExtentXMax>8.00000</ExtentXMax>
<ExtentYMin>-5.00000</ExtentYMin>
<ExtentYMax>3.00000</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>id</Name>
<ElementPath>id</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>id2</Name>
<ElementPath>id2</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>0</gml:X><gml:Y>-5</gml:Y></gml:coord>
<gml:coord><gml:X>8</gml:X><gml:Y>3</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:promote_multipart_points fid="points.0">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>1,1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>1</ogr:id>
<ogr:id2>2</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_points fid="points.1">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>3,3</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>2</ogr:id>
<ogr:id2>1</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_points fid="points.2">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>2,2</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>3</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_points fid="points.3">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>5,2</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>4</ogr:id>
<ogr:id2>2</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_points fid="points.4">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>4,1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>5</ogr:id>
<ogr:id2>1</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_points fid="points.5">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>0,-5</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>6</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_points fid="points.6">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>8,-1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>7</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_points fid="points.7">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>7,-1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>8</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_points fid="points.8">
<ogr:geometryProperty><gml:MultiPoint srsName="EPSG:4326"><gml:pointMember><gml:Point><gml:coordinates>0,-1</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint></ogr:geometryProperty>
<ogr:id>9</ogr:id>
<ogr:id2>0</ogr:id2>
</ogr:promote_multipart_points>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,32 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>promote_multipart_polys</Name>
<ElementPath>promote_multipart_polys</ElementPath>
<!--MULTIPOLYGON-->
<GeometryType>6</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>6</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>10.00000</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
<ExtentYMax>6.00000</ExtentYMax>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>name</Name>
<ElementPath>name</ElementPath>
<Type>String</Type>
<Width>5</Width>
</PropertyDefn>
<PropertyDefn>
<Name>intval</Name>
<ElementPath>intval</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
<PropertyDefn>
<Name>floatval</Name>
<ElementPath>floatval</ElementPath>
<Type>Real</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
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>10</gml:X><gml:Y>6</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:promote_multipart_polys fid="polys.0">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1,-1 -1,3 3,3 3,2 2,2 2,-1 -1,-1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>aaaaa</ogr:name>
<ogr:intval>33</ogr:intval>
<ogr:floatval>44.123456</ogr:floatval>
</ogr:promote_multipart_polys>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_polys fid="polys.1">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5,5 6,4 4,4 5,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>Aaaaa</ogr:name>
<ogr:intval>-33</ogr:intval>
<ogr:floatval>0</ogr:floatval>
</ogr:promote_multipart_polys>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_polys fid="polys.2">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2,5 2,6 3,6 3,5 2,5</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>bbaaa</ogr:name>
<ogr:floatval>0.123</ogr:floatval>
</ogr:promote_multipart_polys>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_polys fid="polys.3">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6,1 10,1 10,-3 6,-3 6,1</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>7,0 7,-2 9,-2 9,0 7,0</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>ASDF</ogr:name>
<ogr:intval>0</ogr:intval>
</ogr:promote_multipart_polys>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_polys fid="polys.4">
<ogr:intval>120</ogr:intval>
<ogr:floatval>-100291.43213</ogr:floatval>
</ogr:promote_multipart_polys>
</gml:featureMember>
<gml:featureMember>
<ogr:promote_multipart_polys fid="polys.5">
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3,2 6,1 6,-3 2,-1 2,2 3,2</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
<ogr:name>elim</ogr:name>
<ogr:intval>2</ogr:intval>
<ogr:floatval>3.33</ogr:floatval>
</ogr:promote_multipart_polys>
</gml:featureMember>
</ogr:FeatureCollection>
44 changes: 44 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -3393,3 +3393,47 @@ tests:
OUTPUT:
name: expected/convex_hull_by_feature.gml
type: vector

- algorithm: native:promotetomulti
name: Promote to multipart lines
params:
INPUT:
name: lines.gml
type: vector
results:
OUTPUT:
name: expected/promote_multipart_lines.gml
type: vector

- algorithm: native:promotetomulti
name: Promote to multipart lines points
params:
INPUT:
name: points.gml
type: vector
results:
OUTPUT:
name: expected/promote_multipart_points.gml
type: vector

- algorithm: native:promotetomulti
name: Promote to multipart polygons
params:
INPUT:
name: polys.gml
type: vector
results:
OUTPUT:
name: expected/promote_multipart_polys.gml
type: vector

- algorithm: native:promotetomulti
name: Promote to multipart (already multipart)
params:
INPUT:
name: multipolys.gml
type: vector
results:
OUTPUT:
name: expected/promote_multipart_already_multi.gml
type: vector

0 comments on commit 3484eb0

Please sign in to comment.