/// <summary> /// Add shortcut if the current edge is one. /// </summary> private bool AddShorcut(RoutingEdge edge) { // when both are just regular vertices, this could be a shortcut. var edgeProfile = _routerDb.EdgeProfiles.Get(edge.Data.Profile); var shortcutName = string.Empty; if (edgeProfile.IsShortcut(out shortcutName)) { // ok profile is a shortcut, get the actual path, expand and build route. ShortcutsDb shortcutsDb; if (_routerDb.TryGetShortcuts(shortcutName, out shortcutsDb)) { var shortcutProfile = shortcutsDb.Profile; IAttributeCollection shortcutMeta; var shortcut = shortcutsDb.Get(edge.From, edge.To, out shortcutMeta); if (shortcut != null && shortcut.Length >= 2) { var route = CompleteRouteBuilder.Build(_routerDb, shortcutProfile, _routerDb.CreateRouterPointForVertex(shortcut[0], shortcutProfile, _profile), _routerDb.CreateRouterPointForVertex(shortcut[shortcut.Length - 1], shortcutProfile, _profile), new List <uint>(shortcut)); if (shortcutMeta == null) { shortcutMeta = new AttributeCollection(); } shortcutMeta.AddOrReplace(ShortcutExtensions.SHORTCUT_KEY, shortcutName); this.AppendRoute(route, shortcutMeta); return(true); } } } return(false); }
public static void SetSideStreets(this RouteSegment segment, RouterDb routerDb, uint vertex, uint previousEdge, uint nextVertex) { List <RouteSegmentBranch> routeSegmentBranchList = new List <RouteSegmentBranch>(); RoutingNetwork.EdgeEnumerator edgeEnumerator = routerDb.Network.GetEdgeEnumerator(vertex); while (edgeEnumerator.MoveNext()) { if ((int)edgeEnumerator.Id != (int)previousEdge && (int)edgeEnumerator.To != (int)nextVertex) { RoutingEdge current = edgeEnumerator.Current; RouterDb db = routerDb; EdgeData data = current.Data; int profile = (int)data.Profile; data = current.Data; int metaId = (int)data.MetaId; TagsCollectionBase profileAndMeta = db.GetProfileAndMeta((uint)profile, (uint)metaId); ICoordinate firstPoint = routerDb.Network.GetFirstPoint(current, edgeEnumerator.From); routeSegmentBranchList.Add(new RouteSegmentBranch() { Latitude = firstPoint.Latitude, Longitude = firstPoint.Longitude, Tags = profileAndMeta.ConvertFrom() }); } } if (routeSegmentBranchList.Count <= 0) { return; } segment.SideStreets = routeSegmentBranchList.ToArray(); }
public static Path PathTo(this RouterPoint point, RouterDb db, Func <ushort, Factor> getFactor, RouterPoint target) { if ((int)point.EdgeId != (int)target.EdgeId) { throw new ArgumentException("Target point must be part of the same edge."); } if ((int)point.Offset == (int)target.Offset) { return(new Path(point.VertexId(db))); } bool flag = (int)point.Offset < (int)target.Offset; RoutingEdge edge = db.Network.GetEdge(point.EdgeId); Factor factor = getFactor(edge.Data.Profile); if ((double)factor.Value <= 0.0) { return((Path)null); } if ((int)factor.Direction != 0 && (!flag || (int)factor.Direction != 1) && (flag || (int)factor.Direction != 2)) { return((Path)null); } float weight = (float)System.Math.Abs((int)point.Offset - (int)target.Offset) / (float)ushort.MaxValue * edge.Data.Distance * factor.Value; return(new Path(target.VertexId(db), weight, new Path(point.VertexId(db)))); }
/// <summary> /// Creates a router point for the given edge. /// </summary> public static RouterPoint CreateRouterPointForEdge(this RouterDb routerDb, RoutingEdge edge, bool edgeIsForward, bool atStart) { Coordinate location; if (atStart) { if (!edgeIsForward) { location = routerDb.Network.GetVertex(edge.To); return(new RouterPoint(location.Latitude, location.Longitude, edge.Id, ushort.MaxValue)); } location = routerDb.Network.GetVertex(edge.From); return(new RouterPoint(location.Latitude, location.Longitude, edge.Id, 0)); } else { if (!edgeIsForward) { location = routerDb.Network.GetVertex(edge.From); return(new RouterPoint(location.Latitude, location.Longitude, edge.Id, 0)); } location = routerDb.Network.GetVertex(edge.To); return(new RouterPoint(location.Latitude, location.Longitude, edge.Id, ushort.MaxValue)); } }
private static bool EdgesAreEqual(RoutingEdge edge1, RoutingEdge edge2) { if (edge1.From != edge2.From) { return(false); } if (edge1.To != edge2.To) { return(false); } if (edge1.Data.Profile != edge2.Data.Profile) { return(false); } if (edge1.Data.MetaId != edge2.Data.MetaId) { return(false); } var shape1 = edge1.Shape; var shape2 = edge2.Shape; if (shape1 == null || shape1.Count == 0) { if (shape2 != null && shape2.Count > 0) { return(false); } } if (shape2 == null || shape2.Count == 0) { if (shape1 != null && shape1.Count > 0) { return(false); } } if (shape1 != null && shape2 != null) { if (shape1.Count != shape2.Count) { return(false); } for (var i = 0; i < shape1.Count; i++) { if (Coordinate.DistanceEstimateInMeter( shape1[i], shape2[i]) > 0) { return(false); } } } return(true); }
public static string ToGeoJson(this RoutingEdge edge, RouterDb db) { var edgeShape = db.Network.GetShape(edge); var writer = new StringWriter(); var jsonWriter = new IO.Json.JsonWriter(writer); jsonWriter.WriteOpen(); jsonWriter.WriteProperty("type", "FeatureCollection", true, false); jsonWriter.WritePropertyName("features", false); jsonWriter.WriteArrayOpen(); jsonWriter.WriteOpen(); jsonWriter.WriteProperty("type", "Feature", true, false); jsonWriter.WriteProperty("name", "ShapeMeta", true, false); jsonWriter.WritePropertyName("geometry", false); jsonWriter.WriteOpen(); jsonWriter.WriteProperty("type", "LineString", true, false); jsonWriter.WritePropertyName("coordinates", false); jsonWriter.WriteArrayOpen(); for (var shape = 0; shape < edgeShape.Count; shape++) { jsonWriter.WriteArrayOpen(); jsonWriter.WriteArrayValue(edgeShape[shape].Longitude.ToInvariantString()); jsonWriter.WriteArrayValue(edgeShape[shape].Latitude.ToInvariantString()); if (edgeShape[shape].Elevation.HasValue) { jsonWriter.WriteArrayValue(edgeShape[shape].Elevation.Value.ToInvariantString()); } jsonWriter.WriteArrayClose(); } jsonWriter.WriteArrayClose(); jsonWriter.WriteClose(); jsonWriter.WritePropertyName("properties"); jsonWriter.WriteOpen(); jsonWriter.WriteProperty("id", edge.Id.ToString(), false, false); jsonWriter.WriteProperty("profile", edge.Data.Profile.ToString(), false, false); jsonWriter.WriteProperty("meta", edge.Data.MetaId.ToString(), false, false); jsonWriter.WriteProperty("from", edge.From.ToString(), false, false); jsonWriter.WriteProperty("to", edge.To.ToString(), false, false); jsonWriter.WriteClose(); jsonWriter.WriteClose(); WriteVertex(db, jsonWriter, edge.From); WriteVertex(db, jsonWriter, edge.To); jsonWriter.WriteArrayClose(); jsonWriter.WriteClose(); return(writer.ToString()); }
/// <summary> /// Validates if the location is connected. /// </summary> /// <returns></returns> public static void ValidateConnected(this ReferencedLine line, Coder coder) { var profile = coder.Profile; var edges = line.Edges; var vertices = line.Vertices; // 1: Is the path connected? // 2: Is the path traversable? for (int edgeIdx = 0; edgeIdx < edges.Length; edgeIdx++) { var from = vertices[edgeIdx]; var to = vertices[edgeIdx + 1]; // find edge. var found = false; RoutingEdge foundEdge = null; foreach (var edge in coder.Router.Db.Network.GetEdges(from)) { if (edge.To == to && edge.IdDirected() == edges[edgeIdx]) { // edge was found, is valid. found = true; foundEdge = edge; break; } } if (!found) { // edge is not found, path not connected. throw new ArgumentOutOfRangeException(string.Format("Edge {0} cannot be found between vertex {1} and {2}. The given path is not connected.", edges[edgeIdx].ToInvariantString(), from, to)); } // check whether the edge can traversed. var factor = profile.Profile.Factor(coder.Router.Db.EdgeProfiles.Get(foundEdge.Data.Profile)); if (factor.Value == 0) { // oeps, cannot be traversed. throw new ArgumentOutOfRangeException(string.Format("Edge at index {0} cannot be traversed by vehicle {1}.", edgeIdx, profile.Profile.Name)); } // check whether the edge can be traversed in the correct direction. var canMoveForward = (factor.Direction == 0) || (factor.Direction == 1 && !foundEdge.DataInverted) || (factor.Direction == 2 && foundEdge.DataInverted); if (!canMoveForward) { // path cannot be traversed in this direction. throw new ArgumentOutOfRangeException(string.Format("Edge at index {0} cannot be traversed by vehicle {1} in the direction given.", edgeIdx, profile.Profile.Name)); } } }
public static uint VertexId(this RouterPoint point, RouterDb db) { RoutingEdge edge = db.Network.GetEdge(point.EdgeId); if ((int)point.Offset == 0) { return(edge.From); } if ((int)point.Offset == (int)ushort.MaxValue) { return(edge.To); } return(4294967294); }
/// <summary> /// Generates an edge path for the given edge. /// </summary> public static EdgePath <T> GetPathForEdge <T>(this RouterDb routerDb, WeightHandler <T> weightHandler, RoutingEdge edge, bool edgeForward, bool asSource) where T : struct { var weight = weightHandler.Calculate(edge.Data.Profile, edge.Data.Distance); if (asSource) { if (edgeForward) { return(new EdgePath <T>(edge.To, weight, edge.IdDirected(), new EdgePath <T>(edge.From))); } return(new EdgePath <T>(edge.From, weight, -edge.IdDirected(), new EdgePath <T>(edge.To))); } else { if (edgeForward) { return(new EdgePath <T>(edge.From, weight, -edge.IdDirected(), new EdgePath <T>(edge.To))); } return(new EdgePath <T>(edge.To, weight, edge.IdDirected(), new EdgePath <T>(edge.From))); } }
/// <summary> /// Adds the shape point between from and to and the target location itself. /// </summary> private void Add(uint from, uint to, uint next) { if (from == Constants.NO_VERTEX && _source.IsVertex()) { // replace from with the vertex. from = _source.VertexId(_routerDb); if (from == to) { // nothing to be done. return; } } if (next == Constants.NO_VERTEX && _target.IsVertex()) { // replace next with the vertex. next = _target.VertexId(_routerDb); //if (to == next) //{ // nothing to be done. // return; //} } // get shapepoints and edge. var shape = new List <Coordinate>(0); RoutingEdge edge = null; Coordinate? targetLocation = null; var distance = 0f; var direction = true; if (from == Constants.NO_VERTEX && to == Constants.NO_VERTEX) { // from is the source and to is the target. if (_source.EdgeId != _target.EdgeId) { // a route inside one edge but source and target do not match. this.ErrorMessage = "Target and source have to be on the same vertex with a route with only virtual vertices."; return; } shape = _source.ShapePointsTo(_routerDb, _target); distance = _source.DistanceTo(_routerDb, _target); edge = _routerDb.Network.GetEdge(_source.EdgeId); targetLocation = _target.Location(); shape.Add(targetLocation.Value); } else if (from == Constants.NO_VERTEX) { // from is the source and to is a regular vertex. edge = _routerDb.Network.GetEdge(_source.EdgeId); var toOnEdge = _routerDb.Network.CreateRouterPointForVertex(to, edge.GetOther(to)); shape = _source.ShapePointsTo(_routerDb, toOnEdge); distance = _source.DistanceTo(_routerDb, toOnEdge); targetLocation = _routerDb.Network.GetVertex(to); shape.Add(targetLocation.Value); } else if (to == Constants.NO_VERTEX) { // from is a regular vertex and to is the target. edge = _routerDb.Network.GetEdge(_target.EdgeId); var fromOnEdge = _routerDb.Network.CreateRouterPointForVertex(from, edge.GetOther(from)); shape = fromOnEdge.ShapePointsTo(_routerDb, _target); distance = fromOnEdge.DistanceTo(_routerDb, _target); targetLocation = _target.Location(); shape.Add(targetLocation.Value); } else { // both are just regular vertices. edge = _routerDb.Network.GetEdgeEnumerator(from).First(x => x.To == to); direction = !edge.DataInverted; if (this.AddShorcut(edge)) { return; } distance = edge.Data.Distance; var shapeEnumerable = edge.Shape; if (shapeEnumerable != null) { if (edge.DataInverted) { shapeEnumerable = shapeEnumerable.Reverse(); } shape.AddRange(shapeEnumerable); } targetLocation = _routerDb.Network.GetVertex(to); shape.Add(targetLocation.Value); } // get edge details. var profile = _routerDb.EdgeProfiles.Get(edge.Data.Profile); var speed = this._profile.Speed(profile); var time = 0f; if (speed.Value != 0) { time = distance / speed.Value; } var meta = _routerDb.EdgeMeta.Get(edge.Data.MetaId); var attributes = new AttributeCollection(meta); attributes.AddOrReplace(profile); attributes.AddOrReplace("profile", _profile.FullName); // add shape and meta. _shape.AddRange(shape); var previousMeta = _shapeMeta[_shapeMeta.Count - 1]; var shapeMeta = new Route.Meta() { Shape = _shape.Count - 1, Attributes = attributes, AttributesDirection = direction }; shapeMeta.Distance = distance + previousMeta.Distance; shapeMeta.Time = time + previousMeta.Time; _shapeMeta.Add(shapeMeta); // add sidestreets. if (to != Constants.NO_VERTEX) { _branches.AddBranches(_routerDb, _shape.Count - 1, to, edge.Id, next); } }
public override void AddWay(Way way) { ICoordinate coordinate; EdgeData data; if (way == null) { return; } if (way.Nodes == null) { return; } if (way.Nodes.Count == 0) { return; } if (!this._firstPass) { if (this.Processors != null) { foreach (ITwoPassProcessor processor in this.Processors) { processor.SecondPass(way); } } if (this._vehicles.AnyCanTraverse(way.Tags)) { if (this._processedWays.Contains(way.Id.Value)) { return; } TagsCollection tagsCollection = new TagsCollection(way.Tags.Count); TagsCollection tagsCollection1 = new TagsCollection(way.Tags.Count); foreach (Tag tag in way.Tags) { if (!this._vehicles.IsRelevantForProfile(tag.Key)) { tagsCollection1.Add(tag); } else { tagsCollection.Add(tag); } } if (this._normalizeTags) { TagsCollection tagsCollection2 = new TagsCollection(tagsCollection.Count); if (!tagsCollection.Normalize(tagsCollection2, tagsCollection1, this._vehicles)) { return; } if (this.Processors != null) { foreach (ITwoPassProcessor twoPassProcessor in this.Processors) { Action <TagsCollectionBase, TagsCollectionBase> onAfterWayTagsNormalize = twoPassProcessor.OnAfterWayTagsNormalize; if (onAfterWayTagsNormalize == null) { continue; } onAfterWayTagsNormalize.Invoke(tagsCollection2, tagsCollection); } } tagsCollection = tagsCollection2; } uint num = this._db.EdgeProfiles.Add(tagsCollection); if (num > 16384) { throw new Exception("Maximum supported profiles exeeded, make sure only routing tags are included in the profiles."); } uint num1 = this._db.EdgeMeta.Add(tagsCollection1); int num2 = 0; Label0: while (num2 < way.Nodes.Count - 1) { List <ICoordinate> list = new List <ICoordinate>(); float single = 0f; if (!this._stageCoordinates.TryGetValue(way.Nodes[num2], out coordinate)) { for (int i = 0; i < way.Nodes.Count; i++) { this._anyStageNodes.Add(way.Nodes[i]); } return; } uint from = this.AddCoreNode(way.Nodes[num2], coordinate.Latitude, coordinate.Longitude); long item = way.Nodes[num2]; ICoordinate coordinate1 = coordinate; num2++; long to = -1; long item1 = 9223372036854775807L; while (this._stageCoordinates.TryGetValue(way.Nodes[num2], out coordinate)) { single = single + (float)GeoCoordinate.DistanceEstimateInMeter(coordinate1, coordinate); if (!this._coreNodes.Contains(way.Nodes[num2])) { list.Add(coordinate); coordinate1 = coordinate; num2++; } else { to = this.AddCoreNode(way.Nodes[num2], coordinate.Latitude, coordinate.Longitude); item1 = way.Nodes[num2]; if (from != to) { RoutingEdge routingEdge = Enumerable.FirstOrDefault <RoutingEdge>(this._db.Network.GetEdgeEnumerator(from), (RoutingEdge x) => x.To == to); if (routingEdge != null || from == to) { data = routingEdge.Data; if (data.Distance == single) { data = routingEdge.Data; if (data.Profile == num) { data = routingEdge.Data; if (data.MetaId == num1) { goto Label0; } } } uint metaId = num1; uint profile = num; float distance = single; if (list.Count == 0 && routingEdge != null && routingEdge.Shape != null) { list = new List <ICoordinate>(routingEdge.Shape); from = routingEdge.From; to = routingEdge.To; data = routingEdge.Data; metaId = data.MetaId; data = routingEdge.Data; profile = data.Profile; data = routingEdge.Data; distance = data.Distance; long num3 = to; data = new EdgeData() { MetaId = num1, Distance = System.Math.Max(single, 0f), Profile = (ushort)num }; this.AddCoreEdge(from, (uint)num3, data, null); } if (list.Count <= 0) { GeoCoordinateSimple vertex = this._db.Network.GetVertex(from); uint num4 = this.AddNewCoreNode(item, vertex.Latitude, vertex.Longitude); data = new EdgeData() { Distance = 0f, MetaId = metaId, Profile = (ushort)profile }; this.AddCoreEdge(from, num4, data, null); GeoCoordinateSimple geoCoordinateSimple = this._db.Network.GetVertex((uint)to); uint num5 = this.AddNewCoreNode(item1, geoCoordinateSimple.Latitude, geoCoordinateSimple.Longitude); long num6 = to; data = new EdgeData() { Distance = 0f, MetaId = metaId, Profile = (ushort)profile }; this.AddCoreEdge(num5, (uint)num6, data, null); data = new EdgeData() { Distance = distance, MetaId = metaId, Profile = (ushort)profile }; this.AddCoreEdge(num4, num5, data, null); goto Label0; } else { uint vertexCount = this._db.Network.VertexCount; this._db.Network.AddVertex(vertexCount, list[0].Latitude, list[0].Longitude); float single1 = (float)GeoCoordinate.DistanceEstimateInMeter(this._db.Network.GetVertex(from), list[0]); distance = distance - single1; data = new EdgeData() { MetaId = metaId, Distance = System.Math.Max(single1, 0f), Profile = (ushort)profile }; this.AddCoreEdge(from, vertexCount, data, null); list.RemoveAt(0); long num7 = to; data = new EdgeData() { MetaId = metaId, Distance = System.Math.Max(distance, 0f), Profile = (ushort)profile }; this.AddCoreEdge(vertexCount, (uint)num7, data, list); goto Label0; } } else { long num8 = to; data = new EdgeData() { MetaId = num1, Distance = single, Profile = (ushort)num }; this.AddCoreEdge(from, (uint)num8, data, list); goto Label0; } } else if (list.Count != 1) { if (list.Count < 2) { goto Label0; } uint vertexCount1 = this._db.Network.VertexCount; this._db.Network.AddVertex(vertexCount1, list[0].Latitude, list[0].Longitude); uint vertexCount2 = this._db.Network.VertexCount; this._db.Network.AddVertex(vertexCount2, list[list.Count() - 1].Latitude, list[list.Count - 1].Longitude); float single2 = (float)GeoCoordinate.DistanceEstimateInMeter(this._db.Network.GetVertex(from), list[0]); float single3 = (float)GeoCoordinate.DistanceEstimateInMeter(this._db.Network.GetVertex((uint)to), list[list.Count - 1]); list.RemoveAt(0); list.RemoveAt(list.Count - 1); data = new EdgeData() { MetaId = num1, Distance = single2, Profile = (ushort)num }; this.AddCoreEdge(from, vertexCount1, data, null); data = new EdgeData() { MetaId = num1, Distance = single - single3 - single2, Profile = (ushort)num }; this.AddCoreEdge(vertexCount1, vertexCount2, data, list); uint num9 = (uint)to; data = new EdgeData() { MetaId = num1, Distance = single3, Profile = (ushort)num }; this.AddCoreEdge(vertexCount2, num9, data, null); goto Label0; } else { uint vertexCount3 = this._db.Network.VertexCount; this._db.Network.AddVertex(vertexCount3, list[0].Latitude, list[0].Longitude); data = new EdgeData() { MetaId = num1, Distance = (float)GeoCoordinate.DistanceEstimateInMeter(this._db.Network.GetVertex(from), list[0]), Profile = (ushort)num }; this.AddCoreEdge(from, vertexCount3, data, null); goto Label0; } } } for (int j = 0; j < way.Nodes.Count; j++) { this._anyStageNodes.Add(way.Nodes[j]); } return; } this._processedWays.Add(way.Id.Value); } } else { if (this.Processors != null) { foreach (ITwoPassProcessor processor1 in this.Processors) { processor1.FirstPass(way); } } GeoCoordinateBox geoCoordinateBox = new GeoCoordinateBox(new GeoCoordinate(this._minLatitude, this._minLongitude), new GeoCoordinate(this._maxLatitude, this._maxLongitude)); double num10 = 1E-05; if (this._stages.Count == 0) { if (this._nodeCount > (long)500000000 || this._minimumStages > 1) { double num11 = System.Math.Max(System.Math.Ceiling((double)(this._nodeCount / (long)500000000)), (double)this._minimumStages); if (num11 >= 4) { num11 = 4; this._stages.Add(new GeoCoordinateBox(new GeoCoordinate(this._minLatitude, this._minLongitude), new GeoCoordinate(geoCoordinateBox.Center.Latitude, geoCoordinateBox.Center.Longitude))); this._stages[0] = this._stages[0].Resize(num10); this._stages.Add(new GeoCoordinateBox(new GeoCoordinate(this._minLatitude, geoCoordinateBox.Center.Longitude), new GeoCoordinate(geoCoordinateBox.Center.Latitude, this._maxLongitude))); this._stages[1] = this._stages[1].Resize(num10); this._stages.Add(new GeoCoordinateBox(new GeoCoordinate(geoCoordinateBox.Center.Latitude, this._minLongitude), new GeoCoordinate(this._maxLatitude, geoCoordinateBox.Center.Longitude))); this._stages[2] = this._stages[2].Resize(num10); this._stages.Add(new GeoCoordinateBox(new GeoCoordinate(geoCoordinateBox.Center.Latitude, geoCoordinateBox.Center.Longitude), new GeoCoordinate(this._maxLatitude, this._maxLongitude))); this._stages[3] = this._stages[3].Resize(num10); } else if (num11 < 2) { num11 = 1; this._stages.Add(geoCoordinateBox); this._stages[0] = this._stages[0].Resize(num10); } else { num11 = 2; this._stages.Add(new GeoCoordinateBox(new GeoCoordinate(this._minLatitude, this._minLongitude), new GeoCoordinate(this._maxLatitude, geoCoordinateBox.Center.Longitude))); this._stages[0] = this._stages[0].Resize(num10); this._stages.Add(new GeoCoordinateBox(new GeoCoordinate(this._minLatitude, geoCoordinateBox.Center.Longitude), new GeoCoordinate(this._maxLatitude, this._maxLongitude))); this._stages[1] = this._stages[1].Resize(num10); } } else { this._stages.Add(geoCoordinateBox); this._stages[0] = this._stages[0].Resize(num10); } } if (this._vehicles.AnyCanTraverse(way.Tags)) { for (int k = 0; k < way.Nodes.Count; k++) { long item2 = way.Nodes[k]; if (this._allRoutingNodes.Contains(item2) || this._allNodesAreCore) { this._coreNodes.Add(item2); } this._allRoutingNodes.Add(item2); } this._coreNodes.Add(way.Nodes[0]); this._coreNodes.Add(way.Nodes[way.Nodes.Count - 1]); return; } } }