/// <summary> /// Loads a vertex and returns true if found. /// </summary> /// <param name="vertexId"></param> /// <param name="latitude"></param> /// <param name="longitude"></param> /// <returns></returns> private bool LoadVertex(uint vertexId, out float latitude, out float longitude) { uint blockId = CHBlock.CalculateId(vertexId, _blockSize); CHBlock block; if (!_blocks.TryGet(blockId, out block)) { // damn block not cached! block = this.DeserializeBlock(blockId); if (block == null) { // oops even now the block is not found! longitude = 0; latitude = 0; return(false); } _blocks.Add(blockId, block); } uint blockIdx = vertexId - blockId; if (block.Vertices != null && blockIdx < block.Vertices.Length) { // block is found and the vertex is there! latitude = block.Vertices[blockIdx].Latitude; longitude = block.Vertices[blockIdx].Longitude; return(true); } // oops even now the block is not found! longitude = 0; latitude = 0; return(false); }
/// <summary> /// Loads all arcs associated with the given vertex. /// </summary> /// <param name="vertexId"></param> /// <returns></returns> private KeyValuePair <uint, CHEdgeData>[] LoadArcs(uint vertexId) { uint blockId = CHBlock.CalculateId(vertexId, _blockSize); CHBlock block; if (!_blocks.TryGet(blockId, out block)) { // damn block not cached! block = this.DeserializeBlock(blockId); if (block == null) { // oops even now the block is not found! return(new KeyValuePair <uint, CHEdgeData> [0]); } _blocks.Add(blockId, block); } uint blockIdx = vertexId - blockId; if (block.Vertices != null && blockIdx < block.Vertices.Length) { // block is found and the vertex is there! KeyValuePair <uint, CHEdgeData>[] arcs = new KeyValuePair <uint, CHEdgeData> [ block.Vertices[blockIdx].ArcCount]; for (int arcIdx = block.Vertices[blockIdx].ArcIndex; arcIdx < block.Vertices[blockIdx].ArcIndex + block.Vertices[blockIdx].ArcCount; arcIdx++) { // loop over all arcs. CHArc chArc = block.Arcs[arcIdx]; CHEdgeData edgeData = new CHEdgeData(); edgeData.Direction = chArc.Direction; edgeData.ContractedVertexId = chArc.ShortcutId; edgeData.Weight = chArc.Weight; edgeData.Tags = chArc.TagsId; arcs[arcIdx - block.Vertices[blockIdx].ArcIndex] = new KeyValuePair <uint, CHEdgeData>( chArc.TargetId, edgeData); } return(arcs); } // oops even now the block is not found! return(new KeyValuePair <uint, CHEdgeData> [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 = this.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][START_OF_TAGS][[SIZE_OF_REGION_INDEX][REGION_INDEX][REGIONS]][[SIZE_OF_BLOCK_INDEX][BLOCK_INDEX][BLOCKS]][TAGS] // STRART_OF_BLOCKS: 4bytes // START_OF_STAGS: 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(12, SeekOrigin.Begin); // move to beginning of [REGION_INDEX] _runtimeTypeModel.Serialize(stream, chRegionIndex); // write region index. int sizeRegionIndex = (int)(stream.Position - 12); // 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] // 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; chArc.TagsId = sortedArc.Value.Tags; 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. MemoryStream blockStream = new MemoryStream(); _runtimeTypeModel.Serialize(blockStream, block); byte[] compressed = GZipStream.CompressBuffer(blockStream.ToArray()); blockStream.Dispose(); memoryStream.Write(compressed, 0, compressed.Length); 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(); // write tags after blocks. int tagsPosition = (int)stream.Position; TagIndexSerializer.SerializeBlocks(stream, graph.TagsIndex, 100); 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] // write 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(tagsPosition), 0, 4); stream.Write(BitConverter.GetBytes(sizeRegionIndex), 0, 4); // write size of region index. stream.Flush(); }