/// <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);
        }