internal static SimpleChangeSet ConvertToSimple(Osm.Xml.v0_6.delete delete) { // create change set record. SimpleChangeSet change_set = new SimpleChangeSet(); // create change record. SimpleChange change = new SimpleChange(); change.Type = SimpleChangeType.Delete; change.OsmGeo = new List<SimpleOsmGeo>(); // add all relations to the list. if (delete.relation != null) { foreach (Osm.Xml.v0_6.relation osm_geo in delete.relation) { change.OsmGeo.Add(XmlSimpleConverter.ConvertToSimple(osm_geo)); } } // add all ways to the list. if (delete.way != null) { foreach (Osm.Xml.v0_6.way osm_geo in delete.way) { change.OsmGeo.Add(XmlSimpleConverter.ConvertToSimple(osm_geo)); } } // add all nodes to the list. if (delete.node != null) { foreach (Osm.Xml.v0_6.node osm_geo in delete.node) { change.OsmGeo.Add(XmlSimpleConverter.ConvertToSimple(osm_geo)); } } // add change to changeset change_set.Changes = new List<SimpleChange>(); change_set.Changes.Add(change); return change_set; }
/// <summary> /// Filters the geo objects in the changeset and omits the ones not inside the bb. /// </summary> /// <param name="simpleChangeSet"></param> /// <returns></returns> private KeyValuePair<SimpleChangeSet, GeoCoordinateBox> FilterChanges(SimpleChangeSet simpleChangeSet) { List<GeoCoordinate> changes_coordinates = new List<GeoCoordinate>(); SimpleChangeSet filtered_changeset = new SimpleChangeSet(); filtered_changeset.Changes = new List<SimpleChange>(); // keep a list of tested relation to prevent circular references from hanging this process. _tested_relations = new List<long>(); // keep all the objects that could not be checked and check them later. List<KeyValuePair<SimpleOsmGeo, SimpleChange>> objects_not_checked = new List<KeyValuePair<SimpleOsmGeo, SimpleChange>>(); // loop over all objects inside this box and if they are nodes they can be checked. HashSet<long> nodes_inside = new HashSet<long>(); // keep track of all the nodes inside for quick checks later! foreach (SimpleChange change in simpleChangeSet.Changes) { // keep the changed nodes that are ok for the filter. List<SimpleOsmGeo> nodes_changed = new List<SimpleOsmGeo>(); // loop over all objects in this set and keep the nodes. foreach (SimpleOsmGeo geo in change.OsmGeo) { if (geo is SimpleNode) { SimpleNode node = geo as SimpleNode; GeoCoordinate coord = new GeoCoordinate(node.Latitude.Value, node.Longitude.Value); if (_box.IsInsideAny(new OsmSharp.Tools.Math.PointF2D[] { coord })) { nodes_changed.Add(node); nodes_inside.Add(node.Id.Value); changes_coordinates.Add(coord); } } else { objects_not_checked.Add(new KeyValuePair<SimpleOsmGeo,SimpleChange>(geo as SimpleOsmGeo,change)); } } // are there changes in the nodes? if (nodes_changed.Count > 0) { SimpleChange nodes_change = new SimpleChange(); nodes_change.OsmGeo = nodes_changed; nodes_change.Type = change.Type; filtered_changeset.Changes.Add(nodes_change); } } // try all ways. HashSet<long> ways_inside = new HashSet<long>(); // keep the ways inside for quick checks later! foreach(KeyValuePair<SimpleOsmGeo,SimpleChange> change_pair in objects_not_checked) { SimpleOsmGeo geo = change_pair.Key; SimpleChange change = change_pair.Value; // keep the changed ways that are ok for the filter. List<SimpleOsmGeo> ways_changed = new List<SimpleOsmGeo>(); // detect if the way is part of the filter! if (geo is SimpleWay && (geo as SimpleWay).Nodes != null) { // try the cached nodes. foreach (long node_id in (geo as SimpleWay).Nodes) { if (nodes_inside.Contains(node_id)) { ways_changed.Add(geo); ways_inside.Add(geo.Id.Value); break; } } // first try to load the complete way. OsmSharp.Osm.Way way = _data_source.GetWay(geo.Id.Value); if (way != null && way.Nodes != null) { foreach (Osm.Node node in way.Nodes) { if (node != null) { // only if the node is found changes_coordinates.Add(node.Coordinate); if (_box.IsInsideAny(new OsmSharp.Tools.Math.PointF2D[] { node.Coordinate })) { changes_coordinates.Add(node.Coordinate); ways_changed.Add(geo); ways_inside.Add(geo.Id.Value); break; } } } } if (change.Type == SimpleChangeType.Delete && way != null && (way.Nodes == null || way.Nodes.Count == 0)) { // alway delete empty ways! ways_changed.Add(geo); ways_inside.Add(geo.Id.Value); } // second try to load the nodes individually. foreach (long node_id in (geo as SimpleWay).Nodes) { OsmSharp.Osm.Node node = _data_source.GetNode(node_id); if (node != null) { // only if the node is found if (_box.IsInsideAny(new OsmSharp.Tools.Math.PointF2D[] { node.Coordinate })) { changes_coordinates.Add(node.Coordinate); ways_changed.Add(geo); ways_inside.Add(geo.Id.Value); break; } } } } // are there changes in the nodes? if (ways_changed.Count > 0) { SimpleChange ways_change = new SimpleChange(); ways_change.OsmGeo = ways_changed; ways_change.Type = change.Type; filtered_changeset.Changes.Add(ways_change); } } // try all relations. foreach(KeyValuePair<SimpleOsmGeo,SimpleChange> change_pair in objects_not_checked) { SimpleOsmGeo geo = change_pair.Key; SimpleChange change = change_pair.Value; // keep the changed ways that are ok for the filter. List<SimpleOsmGeo> relations_changed = new List<SimpleOsmGeo>(); // test all relations. if (geo is SimpleRelation) { if (!_tested_relations.Contains(geo.Id.Value)) { _tested_relations.Add(geo.Id.Value); if (this.IsInsideBoxRelation((geo as SimpleRelation).Members,nodes_inside,ways_inside)) { relations_changed.Add(geo); } } } // are there changes in the nodes? if (relations_changed.Count > 0) { SimpleChange relations_change = new SimpleChange(); relations_change.OsmGeo = relations_changed; relations_change.Type = change.Type; filtered_changeset.Changes.Add(relations_change); } } // create bounding box of the found changes! GeoCoordinateBox box = null; if (changes_coordinates.Count > 0) { box = new GeoCoordinateBox(changes_coordinates); } return new KeyValuePair<SimpleChangeSet, GeoCoordinateBox>(filtered_changeset, box); }