Skip to content

Commit

Permalink
🐛 [BUG] Fix gpx and kml parsing: geom is an empty GeometryCollection …
Browse files Browse the repository at this point in the history
…after invalid MultiLineString merge
  • Loading branch information
justinefricou committed Jan 30, 2025
1 parent 8df192f commit b40a095
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ CHANGELOG
2.113.0+dev (XXXX-XX-XX)
----------------------------

**Bug fixes**

- Fix gpx and kml parsing: geom is an empty GeometryCollection after invalid MultiLineString merge


2.113.0 (2025-01-30)
----------------------------
Expand Down
11 changes: 11 additions & 0 deletions geotrek/common/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ def test_it_raises_error_on_multiple_not_continuous_features(self):
with self.assertRaises(GeomValueError):
get_geom_from_gpx(gpx)

def test_it_raises_error_on_invalid_multilinestring_merge(self):
gpx = self._get_gpx_from('geotrek/trekking/tests/data/apidae_trek_parser/trace_with_only_two_duplicate_track_points.gpx')
with self.assertRaises(GeomValueError):
get_geom_from_gpx(gpx)


class KmlToGeomTests(SimpleTestCase):

Expand Down Expand Up @@ -215,6 +220,12 @@ def test_it_raises_exception_when_no_linear_data(self):
with self.assertRaises(GeomValueError):
get_geom_from_kml(kml)

def test_it_raises_exception_on_invalid_multilinestring_merge(self):
kml = self._get_kml_from('geotrek/trekking/tests/data/apidae_trek_parser/trace_with_only_two_duplicate_coordinates.kml')

with self.assertRaises(GeomValueError):
get_geom_from_kml(kml)


class TestConvertEncodingFiles(TestCase):
data_dir = "geotrek/trekking/tests/data"
Expand Down
9 changes: 6 additions & 3 deletions geotrek/common/utils/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,15 @@ def maybe_get_linestring_from_layer(layer):
geos = convert_to_geos(feat.geom)
if geos.geom_type == 'MultiLineString':
geos = geos.merged # If possible we merge the MultiLineString into a LineString
if geos.geom_type == 'MultiLineString':
if geos.geom_type != 'LineString':
raise GeomValueError(
_("Feature geometry cannot be converted to a single continuous LineString feature"))
geoms.append(geos)

full_geom = MultiLineString(geoms)
full_geom.srid = geoms[0].srid
full_geom = full_geom.merged # If possible we merge the MultiLineString into a LineString
if full_geom.geom_type == 'MultiLineString':
if full_geom.geom_type != 'LineString':
raise GeomValueError(
_("Geometries from various features cannot be converted to a single continuous LineString feature"))

Expand Down Expand Up @@ -109,7 +109,10 @@ def get_geos_linestring(datasource):
geom.coord_dim = 2
geos = geom.geos
if geos.geom_type == 'MultiLineString':
geos = geos.merged
geos = geos.merged # If possible we merge the MultiLineString into a LineString
if geos.geom_type != 'LineString':
raise GeomValueError(
_("Feature geometry cannot be converted to a single continuous LineString feature"))
return geos

def get_first_geom_with_type_in(types, geoms):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
<name>A test trace in KML format</name>
<Style id="roadStyle">
<LineStyle>
<color>9F0000FF</color>
<width>4</width>
</LineStyle>

</Style>
<Placemark>
<name>A trace for my test trek</name>
<LookAt>
<longitude>6.51847</longitude>
<latitude>45.80873</latitude>
</LookAt>
<Point>
<coordinates>6.51847,45.80873,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>route</name>
<styleUrl>#roadStyle</styleUrl>
<MultiGeometry>
<LineString>
<coordinates>6.51847,45.80873,0 6.51847,45.80873,0
</coordinates>
</LineString>
</MultiGeometry>
</Placemark>
</Document>
</kml>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<gpx version="1.1" creator="GDAL 3.3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.topografix.com/GPX/1/1"
xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">

<trk>
<trkseg>
<trkpt lat="45.660127" lon="4.987793">
</trkpt>
<trkpt lat="45.660127" lon="4.987793">
</trkpt>
</trkseg>
</trk>

</gpx>

0 comments on commit b40a095

Please sign in to comment.