예제 #1
0
        private static (ushort profile, uint meta) AddProfileAndMeta(RouterDb routerDb, VehicleCache vehicleCache, AttributeCollection attributes)
        {
            // add the edge if the attributes are of use to the vehicles defined.
            var wayAttributes    = attributes;
            var profileWhiteList = new Whitelist();

            if (!vehicleCache.AddToWhiteList(wayAttributes, profileWhiteList))
            {
                return(ushort.MaxValue, uint.MaxValue);
            }

            // way has some use.
            // build profile and meta-data.
            var profileTags = new AttributeCollection();
            var metaTags    = new AttributeCollection();

            foreach (var tag in wayAttributes)
            {
                if (profileWhiteList.Contains(tag.Key))
                {
                    profileTags.AddOrReplace(tag);
                }
                else if (vehicleCache.Vehicles.IsOnProfileWhiteList(tag.Key))
                {
                    metaTags.AddOrReplace(tag);
                }
                else if (vehicleCache.Vehicles.IsOnMetaWhiteList(tag.Key))
                {
                    metaTags.AddOrReplace(tag);
                }
            }

            if (!vehicleCache.AnyCanTraverse(profileTags))
            {
                // way has no use of any profile.
                return(ushort.MaxValue, uint.MaxValue);
            }

            // get profile and meta-data id's.
            var profileCount = routerDb.EdgeProfiles.Count;
            var profile      = routerDb.EdgeProfiles.Add(profileTags);

            if (profileCount != routerDb.EdgeProfiles.Count)
            {
                var stringBuilder = new StringBuilder();
                foreach (var att in profileTags)
                {
                    stringBuilder.Append(att.Key);
                    stringBuilder.Append('=');
                    stringBuilder.Append(att.Value);
                    stringBuilder.Append(' ');
                }

                Logger.Log(nameof(TileParser), Logging.TraceEventType.Information,
                           "Normalized: # profiles {0}: {1}", routerDb.EdgeProfiles.Count,
                           stringBuilder.ToInvariantString());
            }

            if (profile > Data.Edges.EdgeDataSerializer.MAX_PROFILE_COUNT)
            {
                throw new Exception(
                          "Maximum supported profiles exceeded, make sure only routing tags are included in the profiles.");
            }

            var meta = routerDb.EdgeMeta.Add(metaTags);

            return((ushort)profile, meta);
        }
예제 #2
0
        /// <summary>
        /// Adds a way.
        /// </summary>
        public override void AddWay(Way way)
        {
            if (way == null)
            {
                return;
            }
            if (way.Nodes == null)
            {
                return;
            }
            if (way.Nodes.Length == 0)
            {
                return;
            }
            if (way.Tags == null || way.Tags.Count == 0)
            {
                return;
            }

            if (_firstPass)
            { // just keep.
                if (this.Processors != null)
                {
                    foreach (var processor in this.Processors)
                    {
                        processor.FirstPass(way);
                    }
                }

                if (_vehicleCache.AnyCanTraverse(way.Tags.ToAttributes()))
                { // way has some use, add all of it's nodes to the index.
                    _nodeIndex.AddId(way.Nodes[0]);
                    for (var i = 0; i < way.Nodes.Length; i++)
                    {
                        _nodeIndex.AddId(way.Nodes[i]);
                    }
                    _nodeIndex.AddId(way.Nodes[way.Nodes.Length - 1]);
                }
            }
            else
            {
                if (this.Processors != null)
                {
                    foreach (var processor in this.Processors)
                    {
                        processor.SecondPass(way);
                    }
                }

                var wayAttributes    = way.Tags.ToAttributes();
                var profileWhiteList = new Whitelist();
                if (_vehicleCache.AddToWhiteList(wayAttributes, profileWhiteList))
                { // way has some use.
                    // build profile and meta-data.
                    var profileTags = new AttributeCollection();
                    var metaTags    = new AttributeCollection();
                    foreach (var tag in way.Tags)
                    {
                        if (profileWhiteList.Contains(tag.Key) ||
                            _vehicleCache.Vehicles.IsOnProfileWhiteList(tag.Key))
                        {
                            profileTags.Add(tag);
                        }
                        if (_vehicleCache.Vehicles.IsOnMetaWhiteList(tag.Key))
                        {
                            metaTags.Add(tag);
                        }
                    }

                    // get profile and meta-data id's.
                    var profileCount = _db.EdgeProfiles.Count;
                    var profile      = _db.EdgeProfiles.Add(profileTags);
                    if (profileCount != _db.EdgeProfiles.Count)
                    {
                        var stringBuilder = new StringBuilder();
                        foreach (var att in profileTags)
                        {
                            stringBuilder.Append(att.Key);
                            stringBuilder.Append('=');
                            stringBuilder.Append(att.Value);
                            stringBuilder.Append(' ');
                        }
                        Itinero.Logging.Logger.Log("RouterDbStreamTarget", Logging.TraceEventType.Information,
                                                   "Normalized: # profiles {0}: {1}", _db.EdgeProfiles.Count, stringBuilder.ToInvariantString());
                    }
                    if (profile > Data.Edges.EdgeDataSerializer.MAX_PROFILE_COUNT)
                    {
                        throw new Exception("Maximum supported profiles exeeded, make sure only routing tags are included in the profiles.");
                    }
                    var meta = _db.EdgeMeta.Add(metaTags);

                    // convert way into one or more edges.
                    var node   = 0;
                    var isCore = false;
                    while (node < way.Nodes.Length - 1)
                    {
                        // build edge to add.
                        var        intermediates = new List <Coordinate>();
                        var        distance      = 0.0f;
                        Coordinate coordinate;
                        if (!this.TryGetValue(way.Nodes[node], out coordinate, out isCore))
                        { // an incomplete way, node not in source.
                            return;
                        }
                        var fromVertex = this.AddCoreNode(way.Nodes[node],
                                                          coordinate.Latitude, coordinate.Longitude);
                        var fromNode           = way.Nodes[node];
                        var previousCoordinate = coordinate;
                        node++;

                        var toVertex = uint.MaxValue;
                        var toNode   = long.MaxValue;
                        while (true)
                        {
                            if (!this.TryGetValue(way.Nodes[node], out coordinate, out isCore))
                            { // an incomplete way, node not in source.
                                return;
                            }
                            distance += Coordinate.DistanceEstimateInMeter(
                                previousCoordinate, coordinate);
                            if (isCore)
                            { // node is part of the core.
                                toVertex = this.AddCoreNode(way.Nodes[node],
                                                            coordinate.Latitude, coordinate.Longitude);
                                toNode = way.Nodes[node];
                                break;
                            }
                            intermediates.Add(coordinate);
                            previousCoordinate = coordinate;
                            node++;
                        }

                        // try to add edge.
                        if (fromVertex == toVertex)
                        {     // target and source vertex are identical, this must be a loop.
                            if (intermediates.Count == 1)
                            { // there is just one intermediate, add that one as a vertex.
                                var newCoreVertex = _db.Network.VertexCount;
                                _db.Network.AddVertex(newCoreVertex, intermediates[0].Latitude, intermediates[0].Longitude);
                                this.AddCoreEdge(fromVertex, newCoreVertex, new Data.Network.Edges.EdgeData()
                                {
                                    MetaId   = meta,
                                    Distance = Coordinate.DistanceEstimateInMeter(
                                        _db.Network.GetVertex(fromVertex), intermediates[0]),
                                    Profile = (ushort)profile
                                }, null);
                            }
                            else if (intermediates.Count >= 2)
                            { // there is more than one intermediate, add two new core vertices.
                                var newCoreVertex1 = _db.Network.VertexCount;
                                _db.Network.AddVertex(newCoreVertex1, intermediates[0].Latitude, intermediates[0].Longitude);
                                var newCoreVertex2 = _db.Network.VertexCount;
                                _db.Network.AddVertex(newCoreVertex2, intermediates[intermediates.Count - 1].Latitude,
                                                      intermediates[intermediates.Count - 1].Longitude);
                                var distance1 = Coordinate.DistanceEstimateInMeter(
                                    _db.Network.GetVertex(fromVertex), intermediates[0]);
                                var distance2 = Coordinate.DistanceEstimateInMeter(
                                    _db.Network.GetVertex(toVertex), intermediates[intermediates.Count - 1]);
                                intermediates.RemoveAt(0);
                                intermediates.RemoveAt(intermediates.Count - 1);
                                this.AddCoreEdge(fromVertex, newCoreVertex1, new Data.Network.Edges.EdgeData()
                                {
                                    MetaId   = meta,
                                    Distance = distance1,
                                    Profile  = (ushort)profile
                                }, null);
                                this.AddCoreEdge(newCoreVertex1, newCoreVertex2, new Data.Network.Edges.EdgeData()
                                {
                                    MetaId   = meta,
                                    Distance = distance - distance2 - distance1,
                                    Profile  = (ushort)profile
                                }, intermediates);
                                this.AddCoreEdge(newCoreVertex2, toVertex, new Data.Network.Edges.EdgeData()
                                {
                                    MetaId   = meta,
                                    Distance = distance2,
                                    Profile  = (ushort)profile
                                }, null);
                            }
                            continue;
                        }

                        var edge = _db.Network.GetEdgeEnumerator(fromVertex).FirstOrDefault(x => x.To == toVertex);
                        if (edge == null && fromVertex != toVertex)
                        { // just add edge.
                            this.AddCoreEdge(fromVertex, toVertex, new Data.Network.Edges.EdgeData()
                            {
                                MetaId   = meta,
                                Distance = distance,
                                Profile  = (ushort)profile
                            }, intermediates);
                        }
                        else
                        { // oeps, already an edge there.
                            if (edge.Data.Distance == distance &&
                                edge.Data.Profile == profile &&
                                edge.Data.MetaId == meta)
                            {
                                // do nothing, identical duplicate data.
                            }
                            else
                            { // try and use intermediate points if any.
                              // try and use intermediate points.
                                var splitMeta     = meta;
                                var splitProfile  = profile;
                                var splitDistance = distance;
                                if (intermediates.Count == 0 &&
                                    edge != null &&
                                    edge.Shape != null)
                                { // no intermediates in current edge.
                                  // save old edge data.
                                    intermediates = new List <Coordinate>(edge.Shape);
                                    fromVertex    = edge.From;
                                    toVertex      = edge.To;
                                    splitMeta     = edge.Data.MetaId;
                                    splitProfile  = edge.Data.Profile;
                                    splitDistance = edge.Data.Distance;

                                    // just add edge.
                                    _db.Network.RemoveEdges(fromVertex, toVertex); // make sure to overwrite and not add an extra edge.
                                    this.AddCoreEdge(fromVertex, toVertex, new EdgeData()
                                    {
                                        MetaId   = meta,
                                        Distance = System.Math.Max(distance, 0.0f),
                                        Profile  = (ushort)profile
                                    }, null);
                                }

                                if (intermediates.Count > 0)
                                { // intermediates found, use the first intermediate as the core-node.
                                    var newCoreVertex = _db.Network.VertexCount;
                                    _db.Network.AddVertex(newCoreVertex, intermediates[0].Latitude, intermediates[0].Longitude);

                                    // calculate new distance and update old distance.
                                    var newDistance = Coordinate.DistanceEstimateInMeter(
                                        _db.Network.GetVertex(fromVertex), intermediates[0]);
                                    splitDistance -= newDistance;

                                    // add first part.
                                    this.AddCoreEdge(fromVertex, newCoreVertex, new EdgeData()
                                    {
                                        MetaId   = splitMeta,
                                        Distance = System.Math.Max(newDistance, 0.0f),
                                        Profile  = (ushort)splitProfile
                                    }, null);

                                    // add second part.
                                    intermediates.RemoveAt(0);
                                    this.AddCoreEdge(newCoreVertex, toVertex, new EdgeData()
                                    {
                                        MetaId   = splitMeta,
                                        Distance = System.Math.Max(splitDistance, 0.0f),
                                        Profile  = (ushort)splitProfile
                                    }, intermediates);
                                }
                                else
                                { // no intermediate or shapepoint found in either one. two identical edge overlayed with different profiles.
                                  // add two other vertices with identical positions as the ones given.
                                  // connect them with an edge of length '0'.
                                    var fromLocation  = _db.Network.GetVertex(fromVertex);
                                    var newFromVertex = this.AddNewCoreNode(fromNode, fromLocation.Latitude, fromLocation.Longitude);
                                    this.AddCoreEdge(fromVertex, newFromVertex, new EdgeData()
                                    {
                                        Distance = 0,
                                        MetaId   = splitMeta,
                                        Profile  = (ushort)splitProfile
                                    }, null);
                                    var toLocation  = _db.Network.GetVertex(toVertex);
                                    var newToVertex = this.AddNewCoreNode(toNode, toLocation.Latitude, toLocation.Longitude);
                                    this.AddCoreEdge(newToVertex, toVertex, new EdgeData()
                                    {
                                        Distance = 0,
                                        MetaId   = splitMeta,
                                        Profile  = (ushort)splitProfile
                                    }, null);

                                    this.AddCoreEdge(newFromVertex, newToVertex, new EdgeData()
                                    {
                                        Distance = splitDistance,
                                        MetaId   = splitMeta,
                                        Profile  = (ushort)splitProfile
                                    }, null);
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Adds a way.
        /// </summary>
        public override void AddWay(Way way)
        {
            if (way == null)
            {
                return;
            }
            if (way.Nodes == null)
            {
                return;
            }
            if (way.Nodes.Length == 0)
            {
                return;
            }
            if (way.Tags == null || way.Tags.Count == 0)
            {
                return;
            }

            if (_firstPass)
            { // just keep.
                if (this.Processors != null)
                {
                    foreach (var processor in this.Processors)
                    {
                        processor.FirstPass(way);
                    }
                }

                if (_vehicleCache.AnyCanTraverse(way.Tags.ToAttributes()))
                { // way has some use, add all of it's nodes to the index.
                    _nodeIndex.AddId(way.Nodes[0]);
                    for (var i = 0; i < way.Nodes.Length; i++)
                    {
                        _nodeIndex.AddId(way.Nodes[i]);
                    }
                    _nodeIndex.AddId(way.Nodes[way.Nodes.Length - 1]);
                }
            }
            else
            {
                if (this.Processors != null)
                {
                    foreach (var processor in this.Processors)
                    {
                        processor.SecondPass(way);
                    }
                }

                var wayAttributes    = way.Tags.ToAttributes();
                var profileWhiteList = new Whitelist();
                if (_vehicleCache.AddToWhiteList(wayAttributes, profileWhiteList))
                { // way has some use.
                    // build profile and meta-data.
                    var profileTags = new AttributeCollection();
                    var metaTags    = new AttributeCollection();
                    foreach (var tag in way.Tags)
                    {
                        if (profileWhiteList.Contains(tag.Key))
                        {
                            profileTags.Add(tag);
                        }
                        else if (_vehicleCache.Vehicles.IsOnProfileWhiteList(tag.Key))
                        {
                            profileTags.Add(tag);
                        }
                        else if (_vehicleCache.Vehicles.IsOnMetaWhiteList(tag.Key))
                        {
                            metaTags.Add(tag);
                        }
                    }

                    if (!_vehicleCache.AnyCanTraverse(profileTags))
                    { // way has some use, add all of it's nodes to the index.
                        return;
                    }

                    // get profile and meta-data id's.
                    var profileCount = _db.EdgeProfiles.Count;
                    var profile      = _db.EdgeProfiles.Add(profileTags);
                    if (profileCount != _db.EdgeProfiles.Count)
                    {
                        var stringBuilder = new StringBuilder();
                        foreach (var att in profileTags)
                        {
                            stringBuilder.Append(att.Key);
                            stringBuilder.Append('=');
                            stringBuilder.Append(att.Value);
                            stringBuilder.Append(' ');
                        }
                        Itinero.Logging.Logger.Log("RouterDbStreamTarget", Logging.TraceEventType.Information,
                                                   "New edge profile: # profiles {0}: {1}", _db.EdgeProfiles.Count, stringBuilder.ToInvariantString());
                    }
                    if (profile > Data.Edges.EdgeDataSerializer.MAX_PROFILE_COUNT)
                    {
                        throw new Exception("Maximum supported profiles exeeded, make sure only routing tags are included in the profiles.");
                    }
                    var meta = _db.EdgeMeta.Add(metaTags);

                    // convert way into one or more edges.
                    var node        = 0;
                    var fromNodeIdx = 0;
                    var isCore      = false;
                    while (node < way.Nodes.Length - 1)
                    {
                        fromNodeIdx = node;

                        // build edge to add.
                        var        intermediates = new List <Coordinate>();
                        var        distance      = 0.0f;
                        Coordinate coordinate;
                        if (!this.TryGetValue(way.Nodes[node], out coordinate, out isCore))
                        { // an incomplete way, node not in source.
                            return;
                        }
                        var fromVertex = this.AddCoreNode(way.Nodes[node],
                                                          coordinate.Latitude, coordinate.Longitude);
                        var fromNode           = way.Nodes[node];
                        var previousCoordinate = coordinate;
                        node++;

                        var toVertex = uint.MaxValue;
                        var toNode   = long.MaxValue;
                        while (true)
                        {
                            if (!this.TryGetValue(way.Nodes[node], out coordinate, out isCore))
                            { // an incomplete way, node not in source.
                                return;
                            }
                            distance += Coordinate.DistanceEstimateInMeter(
                                previousCoordinate, coordinate);
                            if (isCore)
                            { // node is part of the core.
                                toVertex = this.AddCoreNode(way.Nodes[node],
                                                            coordinate.Latitude, coordinate.Longitude);
                                toNode = way.Nodes[node];
                                break;
                            }
                            intermediates.Add(coordinate);
                            previousCoordinate = coordinate;
                            node++;
                        }

                        // just add edge.
                        // duplicates are allowed, one-edge loops are allowed, and too long edges are added with max-length.
                        // these data-issues are fixed in another processing step.
                        this.AddCoreEdge(fromVertex, toVertex, new Data.Network.Edges.EdgeData()
                        {
                            MetaId   = meta,
                            Distance = distance,
                            Profile  = (ushort)profile
                        }, intermediates, way.Id.Value, (ushort)(fromNodeIdx));
                    }
                }
            }
        }