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