// Recursive, safe against circular references, may return duplciate nodes. private static IEnumerable <OsmGeo> ToSimpleWithChildrenCircularSafe( this CompleteRelation complete, HashSet <OsmGeoKey> seenGeoKeys) { if (complete.Members == null) { return(new[] { complete.ToSimple() }); } var children = new List <OsmGeo>(); foreach (var completeMember in complete.Members.Where(m => m != null)) { var key = new OsmGeoKey(completeMember.Member.Type, completeMember.Member.Id); if (seenGeoKeys.Add(key)) // Returns true if element was not already present { switch (completeMember.Member) { case Node node: children.Add(node); break; case CompleteWay way: children.AddRange(way.ToSimpleWithChildren()); break; case CompleteRelation relation: children.AddRange(relation.ToSimpleWithChildrenCircularSafe(seenGeoKeys)); break; default: throw new Exception("Unknown Complete Element Type."); } } } return(children.Append(complete.ToSimple())); }
/// <summary> /// Converts a complete relation into its simple counterpart, /// including the simple versions of all members, and their components, recursively. /// </summary> public static OsmGeo[] ToSimpleWithChildren(this CompleteRelation relation) { var withChildren = relation.ToSimpleWithChildrenCircularSafe(new HashSet <OsmGeoKey>()); return(withChildren.DistinctByGeoKey().ToArray()); }
/// <summary> /// Creates a complete relation. /// </summary> public static CompleteRelation CreateComplete(this Relation relation, IOsmGeoSource osmGeoSource) { 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; completeRelation.ChangeSetId = relation.ChangeSetId; if (relation.Tags != null) { completeRelation.Tags = new TagsCollection(relation.Tags); } if (relation.Members != null) { var relationMembers = new List <CompleteRelationMember>(); for (var i = 0; i < relation.Members.Length; i++) { var memberId = relation.Members[i].Id; var role = relation.Members[i].Role; var member = new CompleteRelationMember(); member.Role = role; switch (relation.Members[i].Type) { case OsmGeoType.Node: var memberNode = osmGeoSource.GetNode(memberId); if (memberNode == null) { continue; } var completeMemberNode = memberNode; if (completeMemberNode != null) { member.Member = completeMemberNode; } else { continue; } break; case OsmGeoType.Way: var memberWay = osmGeoSource.GetWay(memberId); if (memberWay == null) { continue; } var completeMemberWay = memberWay.CreateComplete(osmGeoSource); if (completeMemberWay != null) { member.Member = completeMemberWay; } else { continue; } break; case OsmGeoType.Relation: if (relation.Id == memberId) { continue; } var relationMember = osmGeoSource.GetRelation(memberId); if (relationMember == null) { continue; } var completeMemberRelation = relationMember.CreateComplete(osmGeoSource); if (completeMemberRelation != null) { member.Member = completeMemberRelation; } else { continue; } break; } relationMembers.Add(member); } completeRelation.Members = relationMembers.ToArray(); } completeRelation.TimeStamp = relation.TimeStamp; completeRelation.UserName = relation.UserName; completeRelation.UserId = relation.UserId; completeRelation.Version = relation.Version; completeRelation.Visible = relation.Visible; return(completeRelation); }