/// <summary> /// Completes the collection, fetching optional missing elements /// </summary> /// <param name="source">The source to search for missing elements from</param> /// <param name="relation_nodes">Find missing nodes from relations?</param> /// <param name="relation_ways">Find missing ways from relations?</param> /// <param name="relation_relations">Find missing relations from relations?</param> public OsmGeoCollection Complete(IDataSourceReadOnly source, bool relation_nodes = false, bool relation_ways = false, bool relation_relations = false) { var missing_node_ids = new List <long>(); var missing_way_ids = new List <long>(); // search relations for missing relations if (relation_relations) { var missing_relation_ids = new List <long>(); do { foreach (var relation in Relations) { foreach (var member in relation.Value.Members) { if (member.MemberType.Value == OsmGeoType.Relation) { if (!Relations.ContainsKey(member.MemberId.Value)) { missing_relation_ids.Add(member.MemberId.Value); } } } } var found_relations = source.GetRelations(missing_relation_ids); foreach (var found_relation in found_relations) { if (!Relations.ContainsKey(found_relation.Id.Value)) { Relations.Add(found_relation.Id.Value, found_relation); } } } while (missing_relation_ids.Count > 0); } // search relations for missing ways and nodes if (relation_ways || relation_nodes) { foreach (var relation in Relations) { foreach (var member in relation.Value.Members) { if (member.MemberType.Value == OsmGeoType.Node) { if (relation_nodes) { if (!Nodes.ContainsKey(member.MemberId.Value)) { missing_node_ids.Add(member.MemberId.Value); } } } else if (member.MemberType.Value == OsmGeoType.Way) { if (relation_ways) { if (!Ways.ContainsKey(member.MemberId.Value)) { missing_way_ids.Add(member.MemberId.Value); } } } else if (member.MemberType.Value == OsmGeoType.Relation) { if (relation_relations) { if (!Relations.ContainsKey(member.MemberId.Value)) { throw new NotImplementedException(); } } } } } } // fetch missing ways var found_ways = source.GetWays(missing_way_ids); foreach (var found_way in found_ways) { Ways.Add(found_way.Id.Value, found_way); } // search ways for missing nodes foreach (var way in Ways) { foreach (var node_id in way.Value.Nodes) { if (!Nodes.ContainsKey(node_id)) { missing_node_ids.Add(node_id); } } } // fetch missing nodes var found_nodes = source.GetNodes(missing_node_ids); foreach (var found_node in found_nodes) { Nodes.Add(found_node.Id.Value, found_node); } return(this); }