コード例 #1
0
        /// <summary>
        /// Starts pre-processing all nodes.
        /// </summary>
        public void Start()
        {
            // build the empty coordinate list.
            var emptyCoordinateList = new GeoCoordinateSimple[0];
            var verticesList        = new HashSet <uint>();

            // initialize status variables.
            uint nextToProcess = 0;
            uint nextPosition  = 0;

            // search edge until a real node.
            double latestProgress = 0;

            while (nextToProcess < _graph.VertexCount)
            { // keep looping until all vertices have been processed.
                // select a new vertext to select.
                var vertexToProcess = nextToProcess;
                var edges           = _graph.GetEdges(vertexToProcess).ToList();
                if (edges.Count == 2)
                { // find one of the neighbours that is usefull.
                    vertexToProcess = edges[0].Neighbour;
                    edges           = _graph.GetEdges(vertexToProcess).ToList();
                    verticesList.Clear();
                    verticesList.Add(vertexToProcess);
                    while (edges.Count == 2)
                    { // keep looping until there is a vertex that is usefull.
                        vertexToProcess = edges[0].Neighbour;
                        if (verticesList.Contains(vertexToProcess))
                        { // take the other vertex.
                            vertexToProcess = edges[1].Neighbour;
                            if (verticesList.Contains(vertexToProcess))
                            { // an island was detected with only vertices having two neighbours.
                                // TODO: find a way to handle this!
                                edges = new List <Edge <Edge> >(0);
                                break;
                            }
                        }
                        verticesList.Add(vertexToProcess);
                        edges = _graph.GetEdges(vertexToProcess).ToList();
                    }
                }
                if (edges.Count > 0)
                { // ok, the vertex was not already processed.
                    nextPosition++;
                    var oldEdges   = new List <Edge <Edge> >(edges);
                    var ignoreList = new HashSet <uint>();
                    foreach (var oldEdge in oldEdges)
                    {
                        if (ignoreList.Contains(oldEdge.Neighbour))
                        { // ignore this edge: already removed in a previous iteration.
                            break;
                        }

                        // don't re-process edges that already have coordinates.
                        ICoordinateCollection oldEdgeValueCoordinates;
                        _graph.GetEdgeShape(vertexToProcess, oldEdge.Neighbour, out oldEdgeValueCoordinates);
                        if (oldEdgeValueCoordinates != null)
                        { // this edge has already been processed.
                            break;
                        }

                        // STEP1: Build list of vertices that are only for form.

                        // set current/previous.
                        var distance = oldEdge.EdgeData.Distance;
                        var current  = oldEdge.Neighbour;
                        var previous = vertexToProcess;

                        // build list of vertices.
                        var vertices = new List <uint>();
                        vertices.Add(previous);
                        vertices.Add(current);

                        // get next edges list.
                        var nextEdges = _graph.GetEdges(current).ToList();
                        while (nextEdges.Count == 2)
                        { // ok the current vertex can be removed.
                            var nextEdge = nextEdges[0];
                            if (nextEdge.Neighbour == previous)
                            { // it's the other edge!
                                nextEdge = nextEdges[1];
                            }

                            // compare edges.
                            if (nextEdge.EdgeData.Forward != oldEdge.EdgeData.Forward ||
                                nextEdge.EdgeData.Tags != oldEdge.EdgeData.Tags)
                            { // oeps, edges are different!
                                break;
                            }

                            // check for intermediates.
                            ICoordinateCollection nextEdgeValueCoordinates;
                            _graph.GetEdgeShape(current, nextEdge.Neighbour, out nextEdgeValueCoordinates);
                            if (nextEdgeValueCoordinates != null)
                            { // oeps, there are intermediates already, this can occur when two osm-ways are drawn on top of eachother.
                                break;
                            }

                            // add distance.
                            distance = distance + nextEdge.EdgeData.Distance;

                            // set current/previous.
                            previous = current;
                            current  = nextEdge.Neighbour;
                            vertices.Add(current);

                            // get next edges.
                            nextEdges = _graph.GetEdges(current).ToList();
                        }

                        // check if the edge contains intermediate points.
                        if (vertices.Count == 2)
                        { // no intermediate points: add the empty coordinate list.
                            var oldEdgeValue = oldEdge.EdgeData;

                            // keep edges that already have intermediates.
                            ICoordinateCollection edgeToKeepValueCoordinates = null;
                            var edgesToKeep = new List <Tuple <uint, Edge, ICoordinateCollection> >();
                            foreach (var edgeToKeep in _graph.GetEdges(vertexToProcess).ToList())
                            {
                                edgeToKeepValueCoordinates = null;
                                if (edgeToKeep.Neighbour == oldEdge.Neighbour &&
                                    _graph.GetEdgeShape(vertexToProcess, edgeToKeep.Neighbour, out edgeToKeepValueCoordinates))
                                {
                                    edgesToKeep.Add(new Tuple <uint, Edge, ICoordinateCollection>(
                                                        edgeToKeep.Neighbour, edgeToKeep.EdgeData, edgeToKeepValueCoordinates));
                                }
                            }

                            // delete olds arcs.
                            _graph.RemoveEdge(vertexToProcess, oldEdge.Neighbour);

                            // add new arc.
                            if (oldEdgeValue.Forward)
                            {
                                _graph.AddEdge(vertexToProcess, oldEdge.Neighbour, oldEdgeValue, null);
                            }
                            else
                            {
                                _graph.AddEdge(vertexToProcess, oldEdge.Neighbour, (Edge)oldEdgeValue.Reverse(), null);
                            }

                            // add edges to keep.
                            foreach (var edgeToKeep in edgesToKeep)
                            {
                                _graph.AddEdge(vertexToProcess, edgeToKeep.Item1, edgeToKeep.Item2, edgeToKeep.Item3);
                            }
                        }
                        else
                        { // intermediate points: build array.
                            // STEP2: Build array of coordinates.
                            var   coordinates = new GeoCoordinateSimple[vertices.Count - 2];
                            float latitude, longitude;
                            for (int idx = 1; idx < vertices.Count - 1; idx++)
                            {
                                _graph.GetVertex(vertices[idx], out latitude, out longitude);
                                coordinates[idx - 1] = new GeoCoordinateSimple()
                                {
                                    Latitude  = latitude,
                                    Longitude = longitude
                                };
                            }

                            // STEP3: Remove all unneeded edges.
                            _graph.RemoveEdge(vertices[0], vertices[1]); // remove first edge.
                            for (int idx = 1; idx < vertices.Count - 1; idx++)
                            {                                            // delete all intermidiate arcs.
                                _graph.RemoveEdges(vertices[idx]);
                            }
                            _graph.RemoveEdge(vertices[vertices.Count - 1], vertices[vertices.Count - 2]); // remove last edge.
                            if (vertices[0] == vertices[vertices.Count - 1])
                            {                                                                              // also remove outgoing edge.
                                ignoreList.Add(vertices[vertices.Count - 2]);                              // make sure this arc is ignored in next iteration.
                            }

                            // STEP4: Add new edge.
                            if (oldEdge.EdgeData.Forward)
                            {
                                _graph.AddEdge(vertices[0], vertices[vertices.Count - 1], new Edge()
                                {
                                    Forward  = oldEdge.EdgeData.Forward,
                                    Tags     = oldEdge.EdgeData.Tags,
                                    Distance = distance
                                }, new CoordinateArrayCollection <GeoCoordinateSimple>(coordinates));
                            }
                            else
                            {
                                var reverse = new GeoCoordinateSimple[coordinates.Length];
                                coordinates.CopyToReverse(reverse, 0);
                                _graph.AddEdge(vertices[vertices.Count - 1], vertices[0], new Edge()
                                {
                                    Forward  = !oldEdge.EdgeData.Forward,
                                    Tags     = oldEdge.EdgeData.Tags,
                                    Distance = distance
                                }, new CoordinateArrayCollection <GeoCoordinateSimple>(reverse));
                            }
                        }
                    }
                }
                // move to the next position.
                nextToProcess++;

                // report progress.
                float progress = (float)System.Math.Round((((double)nextToProcess / (double)_graph.VertexCount) * 100));
                if (progress != latestProgress)
                {
                    OsmSharp.Logging.Log.TraceEvent("Preprocessor", TraceEventType.Information,
                                                    "Removing edges... {0}%", progress);
                    latestProgress = progress;
                }
            }

            // compress the graph.
            this.CompressGraph();
        }