Exemplo n.º 1
0
        /// <summary>
        /// Adds an edge.
        /// </summary>
        /// <param name="forward"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="tags"></param>
        private bool AddRoadEdge(TagsCollection tags, bool forward, uint from, uint to)
        {
            float         latitude;
            float         longitude;
            GeoCoordinate fromCoordinate = null;

            if (_dynamicGraph.GetVertex(from, out latitude, out longitude))
            { //
                fromCoordinate = new GeoCoordinate(latitude, longitude);
            }
            GeoCoordinate toCoordinate = null;

            if (_dynamicGraph.GetVertex(to, out latitude, out longitude))
            { //
                toCoordinate = new GeoCoordinate(latitude, longitude);
            }

            if (fromCoordinate != null && toCoordinate != null)
            { // calculate the edge data.
                TEdgeData edgeData = this.CalculateEdgeData(_interpreter.EdgeInterpreter, _tagsIndex, tags, forward, fromCoordinate, toCoordinate);

                _dynamicGraph.AddArc(from, to, edgeData, _edgeComparer);
            }
            return(false);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Rebuilds the vertex index.
 /// </summary>
 public void RebuildVertexIndex()
 {
     _vertexIndex = new QuadTree <GeoCoordinate, uint>();
     for (uint vertex = 0; vertex <= _graph.VertexCount; vertex++)
     {
         float latitude, longitude;
         if (_graph.GetVertex(vertex, out latitude, out longitude))
         {
             _vertexIndex.Add(new GeoCoordinate(latitude, longitude),
                              vertex);
         }
     }
 }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a new osm memory router data source.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="tagsIndex"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public DynamicGraphRouterDataSource(IDynamicGraph <TEdgeData> graph, ITagsIndex tagsIndex)
        {
            if (graph == null)
            {
                throw new ArgumentNullException("graph");
            }
            if (tagsIndex == null)
            {
                throw new ArgumentNullException("tagsIndex");
            }

            _graph       = graph;
            _vertexIndex = new QuadTree <GeoCoordinate, uint>();
            _tagsIndex   = tagsIndex;

            _supportedVehicles = new HashSet <Vehicle>();

            // add the current graph's vertices to the vertex index.
            for (uint newVertexId = 1; newVertexId < graph.VertexCount + 1; newVertexId++)
            {
                // add to the CHRegions.
                float latitude, longitude;
                graph.GetVertex(newVertexId, out latitude, out longitude);
                _vertexIndex.Add(new GeoCoordinate(latitude, longitude), newVertexId);
            }
        }
Exemplo n.º 4
0
        public void TestLiveEdgeDynamicGraphVertex()
        {
            IDynamicGraph <LiveEdge> graph = this.CreateGraph();
            uint vertex = graph.AddVertex(51, 4);

            float latitude, longitude;

            graph.GetVertex(vertex, out latitude, out longitude);

            Assert.AreEqual(51, latitude);
            Assert.AreEqual(4, longitude);

            KeyValuePair <uint, LiveEdge>[] arcs = graph.GetArcs(vertex);
            Assert.AreEqual(0, arcs.Length);
        }
Exemplo n.º 5
0
        public void TestLiveEdgeDynamicGraphVertex10000()
        {
            IDynamicGraph <LiveEdge> graph = this.CreateGraph();
            int count = 10000;

            while (count > 0)
            {
                uint vertex = graph.AddVertex(51, 4);

                float latitude, longitude;
                graph.GetVertex(vertex, out latitude, out longitude);

                Assert.AreEqual(51, latitude);
                Assert.AreEqual(4, longitude);

                KeyValuePair <uint, LiveEdge>[] arcs = graph.GetArcs(vertex);
                Assert.AreEqual(0, arcs.Length);

                count--;
            }

            Assert.AreEqual((uint)10000, graph.VertexCount);
        }
Exemplo n.º 6
0
 /// <summary>
 /// Returns true if a given vertex is in the graph.
 /// </summary>
 /// <param name="id"></param>
 /// <param name="latitude"></param>
 /// <param name="longitude"></param>
 /// <returns></returns>
 public bool GetVertex(uint id, out float latitude, out float longitude)
 {
     return(_graph.GetVertex(id, out latitude, out longitude));
 }
Exemplo n.º 7
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);
                if (edges.Length == 2)
                { // find one of the neighbours that is usefull.
                    vertexToProcess = edges[0].Key;
                    edges           = _graph.GetEdges(vertexToProcess);
                    verticesList.Clear();
                    verticesList.Add(vertexToProcess);
                    while (edges.Length == 2)
                    { // keep looping until there is a vertex that is usefull.
                        vertexToProcess = edges[0].Key;
                        if (verticesList.Contains(vertexToProcess))
                        { // take the other vertex.
                            vertexToProcess = edges[1].Key;
                            if (verticesList.Contains(vertexToProcess))
                            { // an island was detected with only vertices having two neighbours.
                                // TODO: find a way to handle this!
                                edges = new KeyValuePair <uint, LiveEdge> [0];
                                break;
                            }
                        }
                        verticesList.Add(vertexToProcess);
                        edges = _graph.GetEdges(vertexToProcess);
                    }
                }
                if (edges.Length > 0)
                { // ok, the vertex was not already processed.
                    nextPosition++;
                    var oldEdges   = edges.Clone() as KeyValuePair <uint, LiveEdge>[];
                    var ignoreList = new HashSet <uint>();
                    foreach (var oldEdge in oldEdges)
                    {
                        if (ignoreList.Contains(oldEdge.Key))
                        { // ignore this edge: already removed in a previous iteration.
                            break;
                        }

                        // don't re-process edges that already have coordinates.
                        GeoCoordinateSimple[] oldEdgeValueCoordinates;
                        _graph.GetEdgeShape(vertexToProcess, oldEdge.Key, 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.Value.Distance;
                        var current  = oldEdge.Key;
                        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);
                        while (nextEdges.Length == 2)
                        { // ok the current vertex can be removed.
                            var nextEdge = nextEdges[0];
                            if (nextEdge.Key == previous)
                            { // it's the other edge!
                                nextEdge = nextEdges[1];
                            }

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

                            // check for intermediates.
                            GeoCoordinateSimple[] nextEdgeValueCoordinates;
                            _graph.GetEdgeShape(current, nextEdge.Key, 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.Value.Distance;

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

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

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

                            // keep edges that already have intermediates.
                            GeoCoordinateSimple[] edgeToKeepValueCoordinates = null;
                            var edgesToKeep = new List <Tuple <uint, LiveEdge, GeoCoordinateSimple[]> >();
                            foreach (var edgeToKeep in _graph.GetEdges(vertexToProcess))
                            {
                                edgeToKeepValueCoordinates = null;
                                if (edgeToKeep.Key == oldEdge.Key &&
                                    _graph.GetEdgeShape(vertexToProcess, edgeToKeep.Key, out edgeToKeepValueCoordinates))
                                {
                                    edgesToKeep.Add(new Tuple <uint, LiveEdge, GeoCoordinateSimple[]>(
                                                        edgeToKeep.Key, edgeToKeep.Value, edgeToKeepValueCoordinates));
                                }
                            }

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

                            // add new arc.
                            if (oldEdgeValue.Forward)
                            {
                                _graph.AddEdge(vertexToProcess, oldEdge.Key, oldEdgeValue, null);
                            }
                            else
                            {
                                _graph.AddEdge(vertexToProcess, oldEdge.Key, (LiveEdge)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.Value.Forward)
                            {
                                _graph.AddEdge(vertices[0], vertices[vertices.Count - 1], new LiveEdge()
                                {
                                    Forward  = oldEdge.Value.Forward,
                                    Tags     = oldEdge.Value.Tags,
                                    Distance = distance
                                }, coordinates, this);
                            }
                            else
                            {
                                var reverse = new GeoCoordinateSimple[coordinates.Length];
                                coordinates.CopyToReverse(reverse, 0);
                                _graph.AddEdge(vertices[vertices.Count - 1], vertices[0], new LiveEdge()
                                {
                                    Forward  = !oldEdge.Value.Forward,
                                    Tags     = oldEdge.Value.Tags,
                                    Distance = distance
                                }, reverse, this);
                            }
                        }
                    }
                }
                // 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("LiveEdgePreprocessor", TraceEventType.Information,
                                                    "Removing edges... {0}%", progress);
                    latestProgress = progress;
                }
            }

            // compress the graph.
            this.CompressGraph();
        }
Exemplo n.º 8
0
        /// <summary>
        /// Returns a topologically sorted version of the given graph.
        /// </summary>
        /// <param name="graph"></param>
        /// <returns></returns>
        public static IDynamicGraph <CHEdgeData> SortGraph(IDynamicGraph <CHEdgeData> graph)
        {
            // also add all downward edges.
            graph.AddDownwardEdges();

            // sort the topologically ordered vertices into bins representing a certain height range.
            List <uint>[] heightBins = new List <uint> [1000];
            foreach (var vertexDepth in new CHDepthFirstEnumerator(graph))
            { // enumerates all vertixes depth-first.
                int binIdx = (int)(vertexDepth.Depth / HeightBinSize);
                if (heightBins.Length < binIdx)
                { // resize bin array if needed.
                    Array.Resize(ref heightBins, System.Math.Max(heightBins.Length + 1000, binIdx + 1));
                }

                // add to the current bin.
                List <uint> bin = heightBins[binIdx];
                if (bin == null)
                { // create new bin.
                    bin = new List <uint>();
                    heightBins[binIdx] = bin;
                }
                bin.Add(vertexDepth.VertexId);
            }

            // temp test.
            MemoryDynamicGraph <CHEdgeData> sortedGraph   = new MemoryDynamicGraph <CHEdgeData>();
            Dictionary <uint, uint>         currentBinIds = new Dictionary <uint, uint>();
            uint newVertexId;

            for (int idx = 0; idx < heightBins.Length; idx++)
            {
                List <uint> bin = heightBins[idx];
                if (bin != null)
                { // translate ids.
                    // fill current bin ids and add vertices to the new graph.
                    foreach (uint binVertexId in bin)
                    {
                        float latitude, longitude;
                        graph.GetVertex(binVertexId, out latitude, out longitude);
                        newVertexId = sortedGraph.AddVertex(latitude, longitude);

                        currentBinIds.Add(binVertexId, newVertexId); // add to the current bin index.
                    }
                }
            }

            // rebuild the CH graph based on the new ordering and build the CHRegions.
            newVertexId = 0;
            for (int idx = 0; idx < heightBins.Length; idx++)
            {
                List <uint> bin = heightBins[idx];
                if (bin != null)
                { // translate ids.
                  // fill current bin ids and add vertices to the new graph.
                  //foreach (uint binVertexId in bin)
                  //{
                  //    float latitude, longitude;
                  //    graph.GetVertex(binVertexId, out latitude, out longitude);
                  //    newVertexId = sortedGraph.AddVertex(latitude, longitude);

                    //    currentBinIds.Add(binVertexId, newVertexId); // add to the current bin index.
                    //}
                    foreach (uint binVertexId in bin)
                    {
                        currentBinIds.TryGetValue(binVertexId, out newVertexId);

                        // get the higher arcs and convert their ids.
                        KeyValuePair <uint, CHEdgeData>[] arcs = graph.GetArcsHigher(binVertexId);
                        foreach (KeyValuePair <uint, CHEdgeData> arc in arcs)
                        {
                            // get target vertex.
                            uint nextVertexArcId = CHEdgeDataDataSourceSerializer.SearchVertex(arc.Key, currentBinIds, heightBins);
                            // convert edge.
                            CHEdgeData newEdge = new CHEdgeData();
                            newEdge.Direction = arc.Value.Direction;
                            if (arc.Value.HasContractedVertex)
                            { // contracted info.
                                newEdge.ContractedVertexId = CHEdgeDataDataSourceSerializer.SearchVertex(arc.Value.ContractedVertexId, currentBinIds, heightBins);
                            }
                            else
                            { // no contracted info.
                                newEdge.ContractedVertexId = 0;
                            }
                            newEdge.Tags   = arc.Value.Tags;
                            newEdge.Weight = arc.Value.Weight;
                            sortedGraph.AddArc(newVertexId, nextVertexArcId, newEdge, null);
                        }
                    }
                }
            }
            return(sortedGraph);
        }
Exemplo n.º 9
0
        /// <summary>
        /// Does the v2 serialization.
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="graph"></param>
        /// <returns></returns>
        protected override void DoSerialize(LimitedStream stream,
                                            DynamicGraphRouterDataSource <CHEdgeData> graph)
        {
            // sort the graph.
            IDynamicGraph <CHEdgeData> sortedGraph = CHEdgeDataDataSourceSerializer.SortGraph(graph);

            // create the regions.
            SortedDictionary <ulong, List <uint> > regions = new SortedDictionary <ulong, List <uint> >();

            for (uint newVertexId = 1; newVertexId < sortedGraph.VertexCount + 1; newVertexId++)
            {
                // add to the CHRegions.
                float latitude, longitude;
                sortedGraph.GetVertex(newVertexId, out latitude, out longitude);
                Tile tile = Tile.CreateAroundLocation(new GeoCoordinate(
                                                          latitude, longitude), RegionZoom);
                List <uint> regionVertices;
                if (!regions.TryGetValue(tile.Id, out regionVertices))
                {
                    regionVertices = new List <uint>();
                    regions.Add(tile.Id, regionVertices);
                }
                regionVertices.Add(newVertexId);
            }

            // serialize the sorted graph.
            // [START_OF_BLOCKS][[SIZE_OF_REGION_INDEX][REGION_INDEX][REGIONS]][[SIZE_OF_BLOCK_INDEX][BLOCK_INDEX][BLOCKS]]
            // STRART_OF_BLOCKS:        4bytes

            // SIZE_OF_REGION_INDEX:    4bytes
            // REGION_INDEX:            see SIZE_OF_REGION_INDEX
            // REGIONS:                 see START_OF_BLOCKS - 4bytes

            // SIZE_OF_BLOCK_INDEX:     4bytes
            // BLOCK_INDEX:             see SIZE_OF_BLOCK_INDEX.
            // BLOCKS:                  from START_OF_BLOCKS + 4bytes + SIZE_OF_BLOCKS_INDEX until END.

            // serialize regions and build their index.
            CHVertexRegionIndex chRegionIndex = new CHVertexRegionIndex();

            chRegionIndex.LocationIndex = new int[regions.Count];
            chRegionIndex.RegionIds     = new ulong[regions.Count];
            var memoryStream = new MemoryStream();
            int regionIdx    = 0;

            foreach (KeyValuePair <ulong, List <uint> > region in regions)
            {
                // serialize.
                CHVertexRegion chRegion = new CHVertexRegion();
                chRegion.Vertices = region.Value.ToArray();
                _runtimeTypeModel.Serialize(memoryStream, chRegion);

                // set index.
                chRegionIndex.LocationIndex[regionIdx] = (int)memoryStream.Position;
                chRegionIndex.RegionIds[regionIdx]     = region.Key;
                regionIdx++;
            }
            stream.Seek(8, SeekOrigin.Begin);                   // move to beginning of [REGION_INDEX]
            _runtimeTypeModel.Serialize(stream, chRegionIndex); // write region index.
            int sizeRegionIndex = (int)(stream.Position - 8);   // now at beginning of [REGIONS]

            memoryStream.Seek(0, SeekOrigin.Begin);
            memoryStream.WriteTo(stream);                               // write regions.
            memoryStream.Dispose();
            int startOfBlocks = (int)stream.Position;                   // now at beginning of [SIZE_OF_BLOCK_INDEX]

            stream.Seek(0, SeekOrigin.Begin);                           // move to beginning
            stream.Write(BitConverter.GetBytes(startOfBlocks), 0, 4);   // write start position of blocks. Now at [SIZE_OF_REGION_INDEX]
            stream.Write(BitConverter.GetBytes(sizeRegionIndex), 0, 4); // write size of blocks index.

            // serialize the blocks and build their index.
            memoryStream = new MemoryStream();
            List <int> blockLocations = new List <int>();
            uint       vertexId       = 1;

            while (vertexId < sortedGraph.VertexCount)
            {
                uint            blockId       = vertexId;
                List <CHArc>    blockArcs     = new List <CHArc>();
                List <CHVertex> blockVertices = new List <CHVertex>();
                while (vertexId < blockId + BlockVertexSize &&
                       vertexId < sortedGraph.VertexCount + 1)
                { // create this block.
                    CHVertex chVertex = new CHVertex();
                    float    latitude, longitude;
                    sortedGraph.GetVertex(vertexId, out latitude, out longitude);
                    chVertex.Latitude  = latitude;
                    chVertex.Longitude = longitude;
                    chVertex.ArcIndex  = (ushort)(blockArcs.Count);
                    foreach (KeyValuePair <uint, CHEdgeData> sortedArc in sortedGraph.GetArcs(vertexId))
                    {
                        CHArc chArc = new CHArc();
                        chArc.TargetId   = sortedArc.Key;
                        chArc.ShortcutId = sortedArc.Value.ContractedVertexId;
                        chArc.Weight     = sortedArc.Value.Weight;
                        chArc.Direction  = sortedArc.Value.Direction;
                        blockArcs.Add(chArc);
                    }
                    chVertex.ArcCount = (ushort)(blockArcs.Count - chVertex.ArcIndex);
                    blockVertices.Add(chVertex);

                    vertexId++; // move to the next vertex.
                }

                // create block.
                CHBlock block = new CHBlock();
                block.Arcs     = blockArcs.ToArray();
                block.Vertices = blockVertices.ToArray(); // TODO: get rid of the list and create an array to begin with.

                // write blocks.
                _runtimeTypeModel.Serialize(memoryStream, block);
                blockLocations.Add((int)memoryStream.Position);
            }
            CHBlockIndex blockIndex = new CHBlockIndex();

            blockIndex.LocationIndex = blockLocations.ToArray();

            stream.Seek(startOfBlocks + 4, SeekOrigin.Begin);                  // move to beginning of [BLOCK_INDEX]
            _runtimeTypeModel.Serialize(stream, blockIndex);                   // write region index.
            int sizeBlockIndex = (int)(stream.Position - (startOfBlocks + 4)); // now at beginning of [BLOCKS]

            memoryStream.Seek(0, SeekOrigin.Begin);
            memoryStream.WriteTo(stream);                              // write blocks.
            memoryStream.Dispose();
            stream.Seek(startOfBlocks, SeekOrigin.Begin);              // move to [SIZE_OF_BLOCK_INDEX]
            stream.Write(BitConverter.GetBytes(sizeBlockIndex), 0, 4); // write start position of blocks. Now at [SIZE_OF_REGION_INDEX]
            stream.Flush();
        }