Beispiel #1
0
        /// <summary>
        /// Serializes all edges.
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="graph"></param>
        protected override void SerializeEdges(LimitedStream stream, DynamicGraphRouterDataSource <LiveEdge> graph)
        {
            var typeModel = RuntimeTypeModel.Create();

            typeModel.Add(typeof(SerializableEdge), true);
            typeModel.Add(typeof(GeoCoordinateSimple), true);

            int blockSize = 1000;
            var arcsQueue = new List <SerializableEdge>(blockSize);

            uint vertex = 0;

            while (vertex < graph.VertexCount)
            { // keep looping and serialize all vertices.
                var arcs = graph.GetEdges(vertex);
                if (arcs != null)
                { // serialize the arcs, but serialize them only once.
                    // choose only those arcs that start at a vertex smaller than the target.
                    for (int idx = 0; idx < arcs.Length; idx++)
                    {
                        if (arcs[idx].Key > vertex)
                        {
                            GeoCoordinateSimple[] coordinates;
                            if (!graph.GetEdgeShape(vertex, arcs[idx].Key, out coordinates))
                            {
                                coordinates = null;
                            }
                            arcsQueue.Add(new SerializableEdge()
                            {
                                Distance    = arcs[idx].Value.Distance,
                                FromId      = vertex,
                                ToId        = arcs[idx].Key,
                                Value       = arcs[idx].Value.Value,
                                Coordinates = coordinates
                            });

                            if (arcsQueue.Count == blockSize)
                            { // execute serialization.
                                typeModel.SerializeWithSize(stream, arcsQueue.ToArray());
                                arcsQueue.Clear();
                            }
                        }
                    }

                    // serialize.
                    vertex++;
                }
            }

            if (arcsQueue.Count > 0)
            { // execute serialization.
                typeModel.SerializeWithSize(stream, arcsQueue.ToArray());
                arcsQueue.Clear();
            }
        }
Beispiel #2
0
        /// <summary>
        /// Does the v1 serialization.
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="graph"></param>
        /// <returns></returns>
        protected override void DoSerialize(LimitedStream stream,
                                            DynamicGraphRouterDataSource <LiveEdge> graph)
        {
            // create an index per tile.
            var dataPerTile = new Dictionary <Tile, UnserializedTileData>();

            for (uint vertex = 1; vertex < graph.VertexCount + 1; vertex++)
            { // loop over all vertices and serialize all into the correct tile.
                float latitude, longitude;
                if (graph.GetVertex(vertex, out latitude, out longitude))
                { // the vertex was found.
                    // build the correct tile.
                    var tile = Tile.CreateAroundLocation(new GeoCoordinate(latitude, longitude), Zoom);
                    UnserializedTileData serializableGraphTile;
                    if (!dataPerTile.TryGetValue(tile, out serializableGraphTile))
                    { // create the new tile.
                        serializableGraphTile             = new UnserializedTileData();
                        serializableGraphTile.Ids         = new List <uint>();
                        serializableGraphTile.Latitude    = new List <ushort>();
                        serializableGraphTile.Longitude   = new List <ushort>();
                        serializableGraphTile.StringTable = new Dictionary <string, int>();
                        serializableGraphTile.Arcs        = new List <SerializableGraphArcs>();

                        dataPerTile.Add(tile, serializableGraphTile);
                    }

                    // create short latitude/longitude.
                    serializableGraphTile.Ids.Add(vertex);
                    serializableGraphTile.Latitude.Add((ushort)(((tile.TopLeft.Latitude - latitude)
                                                                 / tile.Box.DeltaLat) * ushort.MaxValue));
                    serializableGraphTile.Longitude.Add((ushort)(((longitude - tile.TopLeft.Longitude)
                                                                  / tile.Box.DeltaLon) * ushort.MaxValue));

                    // get the arcs.
                    var arcs = graph.GetEdges(vertex);

                    // serialize the arcs.
                    if (arcs != null && arcs.Length > 0)
                    {
                        var serializableGraphArcs = new SerializableGraphArcs();
                        serializableGraphArcs.DestinationId = new uint[arcs.Length];
                        serializableGraphArcs.Forward       = new bool[arcs.Length];
                        serializableGraphArcs.TileX         = new int[arcs.Length];
                        serializableGraphArcs.TileY         = new int[arcs.Length];
                        serializableGraphArcs.Tags          = new SerializableTags[arcs.Length];
                        serializableGraphArcs.Intermediates = new SerializableCoordinates[arcs.Length];
                        serializableGraphArcs.Distances     = new float[arcs.Length];

                        for (int idx = 0; idx < arcs.Length; idx++)
                        {
                            var arc = arcs[idx];
                            // get destination tile.
                            if (graph.GetVertex(arc.Key, out latitude, out longitude))
                            { // the destionation was found.
                                GeoCoordinateSimple[] arcValueCoordinates;
                                if (!graph.GetEdgeShape(vertex, arc.Key, out arcValueCoordinates))
                                {
                                    arcValueCoordinates = null;
                                }
                                var destinationTile = Tile.CreateAroundLocation(new GeoCoordinate(latitude, longitude), Zoom);
                                serializableGraphArcs.DestinationId[idx] = arc.Key;
                                serializableGraphArcs.TileX[idx]         = destinationTile.X;
                                serializableGraphArcs.TileY[idx]         = destinationTile.Y;
                                serializableGraphArcs.Forward[idx]       = arc.Value.Forward;
                                serializableGraphArcs.Intermediates[idx] = new SerializableCoordinates()
                                {
                                    Coordinates = SerializableCoordinate.FromSimpleArray(arcValueCoordinates)
                                };
                                serializableGraphArcs.Distances[idx] = arc.Value.Distance;

                                // get the tags.
                                var tagsCollection = graph.TagsIndex.Get(arc.Value.Tags);
                                if (tagsCollection != null)
                                {
                                    serializableGraphArcs.Tags[idx]        = new SerializableTags();
                                    serializableGraphArcs.Tags[idx].Keys   = new int[tagsCollection.Count];
                                    serializableGraphArcs.Tags[idx].Values = new int[tagsCollection.Count];
                                    int tagsIndex = 0;
                                    foreach (var tag in tagsCollection)
                                    {
                                        int key;
                                        if (!serializableGraphTile.StringTable.TryGetValue(
                                                tag.Key, out key))
                                        { // string not yet in string table.
                                            key = serializableGraphTile.StringTable.Count;
                                            serializableGraphTile.StringTable.Add(tag.Key,
                                                                                  key);
                                        }
                                        int value;
                                        if (!serializableGraphTile.StringTable.TryGetValue(
                                                tag.Value, out value))
                                        { // string not yet in string table.
                                            value = serializableGraphTile.StringTable.Count;
                                            serializableGraphTile.StringTable.Add(tag.Value,
                                                                                  value);
                                        }
                                        serializableGraphArcs.Tags[idx].Keys[tagsIndex]   = key;
                                        serializableGraphArcs.Tags[idx].Values[tagsIndex] = value;
                                        tagsIndex++;
                                    }
                                }
                            }
                        }

                        serializableGraphTile.Arcs.Add(serializableGraphArcs);
                    }
                }
            }

            // LAYOUT OF V2: {HEADER}{compressionflag(1byte)}{#tiles(4byte)}{tilesMetaEnd(8byte)}{tiles-meta-data-xxxxxxx}{tiles-data}
            // {HEADER} : already written before this method.
            // {#tiles(4byte)} : the number of tiles in this file (calculate the offset of the {tiles-data}
            //                   section using (TileMetaSize * dataPerTile.Count + 4 + 8)
            // {tilesMetaEnd(8byte)} : the end of the meta tiles.
            // {tiles-meta-data-xxxxxxx} : the serialized tile metadata.
            // {tiles-data} : the actual tile data.

            // calculate the space needed for the tile offset.
            const long tileMetaOffset = 1 + 4 + 8;
            long       tileOffset     = TileMetaSize * dataPerTile.Count +
                                        tileMetaOffset; // all tile metadata + a tile count + tags offset.

            // build the tile metadata while writing the tile data.
            stream.Seek(tileOffset, SeekOrigin.Begin);
            var metas = new SerializableGraphTileMetas();

            metas.Length = new int[dataPerTile.Count];
            metas.Offset = new long[dataPerTile.Count];
            metas.TileX  = new int[dataPerTile.Count];
            metas.TileY  = new int[dataPerTile.Count];
            int metasIndex = 0;

            foreach (var unserializedTileData in dataPerTile)
            {
                // create the tile meta.
                metas.TileX[metasIndex]  = unserializedTileData.Key.X;
                metas.TileY[metasIndex]  = unserializedTileData.Key.Y;
                metas.Offset[metasIndex] = stream.Position;

                // create the tile.
                var serializableGraphTile = new SerializableGraphTile();
                serializableGraphTile.Arcs        = unserializedTileData.Value.Arcs.ToArray();
                serializableGraphTile.Ids         = unserializedTileData.Value.Ids.ToArray();
                serializableGraphTile.Latitude    = unserializedTileData.Value.Latitude.ToArray();
                serializableGraphTile.Longitude   = unserializedTileData.Value.Longitude.ToArray();
                serializableGraphTile.StringTable = new string[unserializedTileData.Value.StringTable.Count];
                foreach (var stringEntry in unserializedTileData.Value.StringTable)
                {
                    serializableGraphTile.StringTable[stringEntry.Value] =
                        stringEntry.Key;
                }

                // serialize the tile.
                if (!_compress)
                { // compresses the file.
                    _runtimeTypeModel.Serialize(stream, serializableGraphTile);
                }
                else
                { // first compress the data, then write.
                    var uncompressed = new MemoryStream();
                    _runtimeTypeModel.Serialize(uncompressed, serializableGraphTile);
                    var uncompressedBuffer = uncompressed.ToArray();

                    byte[] compressed = GZipStream.CompressBuffer(uncompressedBuffer);
                    stream.Write(compressed, 0, compressed.Length);
                }

                // calculate the length of the data that was just serialized.
                metas.Length[metasIndex] = (int)(stream.Position - metas.Offset[metasIndex]);

                metasIndex++;
            }

            // serialize all tile meta data.
            stream.Seek(tileMetaOffset, SeekOrigin.Begin);
            _runtimeTypeModel.Serialize(stream, metas);
            long tileMetaEnd = stream.Position; // save the meta and.

            // save all the offsets.
            stream.Seek(0, SeekOrigin.Begin);
            byte[] compressionFlag = new[] { (byte)(_compress ? 1 : 0) };
            stream.Write(compressionFlag, 0, 1);
            byte[] tileCountBytes = BitConverter.GetBytes(metas.TileX.Length);
            stream.Write(tileCountBytes, 0, tileCountBytes.Length);     // 4 bytes
            byte[] tileMetaEndBytes = BitConverter.GetBytes(tileMetaEnd);
            stream.Write(tileMetaEndBytes, 0, tileMetaEndBytes.Length); // 8 bytes

            stream.Flush();
        }