/// <summary> /// Decodes the given line and augments all covered edges with the given attributes. /// </summary> /// <returns>True if the line is decoded properly and edges have been augmented with new data.</returns> public static bool DecodeLine(this Coder coder, string encodedLine, IAttributeCollection attributes, Func <IAttributeCollection, IAttributeCollection> reverse = null) { // check if routerdb is readonly or not. if (coder.Router.Db.EdgeProfiles.IsReadonly) { //throw new ArgumentException("Cannot augment routerdb, EdgeProfiles are readonly."); } if (coder.Router.Db.EdgeMeta.IsReadonly) { //throw new ArgumentException("Cannot augment routerdb, EdgeMeta is readonly."); } var vehicle = coder.Profile.Profile.Parent; var success = false; // decode line. var decoded = coder.Decode(encodedLine); var line = decoded as ReferencedLine; if (line == null) { return(false); } // loop over all covered edges. var coveredEdges = line.GetCoveredEdges(coder.Router.Db); foreach (var directedEdgeId in coveredEdges) { // get the edge id and set forward flag. uint edgeId = (uint)(directedEdgeId - 1); var forward = true; if (directedEdgeId < 0) { edgeId = (uint)((-directedEdgeId) - 1); forward = false; } // reverse if needed and possible. var attributesToApply = attributes; if (!forward && reverse != null) { attributesToApply = reverse(attributes); } // get edge details. var edge = coder.Router.Db.Network.GetEdge(edgeId); var profile = coder.Router.Db.EdgeProfiles.Get(edge.Data.Profile); var meta = coder.Router.Db.EdgeMeta.Get(edge.Data.MetaId); var existingAttributes = new AttributeCollection(meta); existingAttributes.AddOrReplace(profile); // add new attributes existingAttributes.AddOrReplace(attributesToApply); // update edge. var newProfile = new AttributeCollection(); var newMeta = new AttributeCollection(); foreach (var a in existingAttributes) { if (vehicle.ProfileWhiteList.Contains(a.Key)) { newProfile.AddOrReplace(a.Key, a.Value); } else { newMeta.AddOrReplace(a.Key, a.Value); } } // add data to routerdb. var profileId = edge.Data.Profile; if (!newProfile.ContainsSame(profile)) { profileId = (ushort)coder.Router.Db.EdgeProfiles.Add(newProfile); } var metaId = edge.Data.MetaId; if (!newMeta.ContainsSame(meta)) { metaId = coder.Router.Db.EdgeMeta.Add(newMeta); } // update edge in place. coder.Router.Db.Network.UpdateEdgeData(edgeId, new Itinero.Data.Network.Edges.EdgeData() { Distance = edge.Data.Distance, MetaId = metaId, Profile = profileId }); success = true; } return(success); }