예제 #1
0
        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);
        }