Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/OsmSharp/Complete/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,19 +92,35 @@ public static CompleteWay CreateComplete(this Way way, IOsmGeoSource osmGeoSourc
/// Creates a complete relation.
/// </summary>
public static CompleteRelation CreateComplete(this Relation relation, IOsmGeoSource osmGeoSource)
{
return relation.CreateComplete(osmGeoSource, new Dictionary<long, CompleteRelation>());
}

private static CompleteRelation CreateComplete(this Relation relation, IOsmGeoSource osmGeoSource, Dictionary<long, CompleteRelation> createdRelations)
{
if (relation == null) throw new ArgumentNullException("relation");
if (relation.Id == null) throw new Exception("relation.Id is null");
if (osmGeoSource == null) throw new ArgumentNullException("osmGeoSource");

var completeRelation = new CompleteRelation();
completeRelation.Id = relation.Id.Value;
var relationId = relation.Id.Value;

// If we've already created this relation, return it (handles circular references)
if (createdRelations.TryGetValue(relationId, out var existingRelation))
{
return existingRelation;
}

// Create the complete relation and add it to the cache immediately
var completeRelation = new CompleteRelation();
completeRelation.Id = relationId;
completeRelation.ChangeSetId = relation.ChangeSetId;
if (relation.Tags != null)
{
completeRelation.Tags = new TagsCollection(relation.Tags);
}
// Add to cache before processing members to handle circular references
createdRelations[relationId] = completeRelation;

if (relation.Members != null)
{
var relationMembers = new List<CompleteRelationMember>();
Expand Down Expand Up @@ -156,7 +172,7 @@ public static CompleteRelation CreateComplete(this Relation relation, IOsmGeoSou
{
continue;
}
var completeMemberRelation = relationMember.CreateComplete(osmGeoSource);
var completeMemberRelation = relationMember.CreateComplete(osmGeoSource, createdRelations);
if (completeMemberRelation != null)
{
member.Member = completeMemberRelation;
Expand Down
22 changes: 22 additions & 0 deletions test/OsmSharp.Test/Stream/OsmSimpleCompleteStreamSourceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Linq;
using System.Reflection;
using NUnit.Framework;
using OsmSharp.Complete;
using OsmSharp.Streams;
using OsmSharp.Streams.Complete;

namespace OsmSharp.Test.Stream;

[TestFixture]
public class OsmSimpleCompleteStreamSourceTests
{
[Test]
public void SimpleComplete()
{
var streamSource = new XmlOsmStreamSource(Assembly.GetExecutingAssembly().GetManifestResourceStream(
"OsmSharp.Test.data.xml.circular-relation.osm"));
var completeSource = new OsmSimpleCompleteStreamSource(streamSource);
var element = completeSource.OfType<CompleteRelation>().ToList();
Assert.That(element.Count, Is.EqualTo(2));
}
}
11 changes: 11 additions & 0 deletions test/OsmSharp.Test/data/xml/circular-relation.osm
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="openstreetmap-cgimap 2.1.0 (4146617 spike-07.openstreetmap.org)" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
<relation id="3875817" visible="true" version="21" changeset="169825447" timestamp="2025-08-01T15:51:58Z" user="Dren ar Frankig" uid="11707888">
<member type="relation" ref="19253398" role="inner"/>
<tag k="access" v="yes"/>
</relation>
<relation id="19253398" visible="true" version="14" changeset="169825447" timestamp="2025-08-01T15:51:58Z" user="Dren ar Frankig" uid="11707888">
<member type="relation" ref="3875817" role="wall"/>
<tag k="name" v="Islamic Park of Israel"/>
</relation>
</osm>