/// <summary> /// Gets a positive offset routerpoint. /// </summary> public static RouterPoint GetOffsetRouterPoint(this ReferencedLine referencedLine, RouterDb routerDb, float positiveOffsetPercentage) { var length = referencedLine.Length(routerDb); var lengthOffset = (positiveOffsetPercentage / 100.0f) * length; var totalLength = 0f; for (var e = 0; e < referencedLine.Edges.Length; e++) { var directedEdgeId = referencedLine.Edges[e]; var edge = routerDb.Network.GetEdge(directedEdgeId); var shape = routerDb.Network.GetShape(edge); if (directedEdgeId < 0) { shape.Reverse(); } var shapeLength = shape.Length(); if (lengthOffset < shapeLength + totalLength) { // offset is in this edge. var relativeOffset = (lengthOffset - totalLength) / shapeLength; var offset = (ushort)(ushort.MaxValue * relativeOffset); if (directedEdgeId < 0) { offset = (ushort)(ushort.MaxValue - offset); } var routerPoint = new RouterPoint(0, 0, edge.Id, offset); var location = routerPoint.LocationOnNetwork(routerDb); return(new RouterPoint(location.Latitude, location.Longitude, edge.Id, offset)); } totalLength += shapeLength; } return(routerDb.CreateRouterPointForEdge(referencedLine.Edges[referencedLine.Edges.Length - 1], false)); }
/// <summary> /// Tries to adjust this location backwards to a valid point. /// </summary> /// <returns></returns> public static bool TryAdjustToValidPointBackwards(this ReferencedLine line, Coder coder, uint vertex1, uint vertex2, HashSet <uint> exclude) { var length = line.Length(coder.Router.Db); var positiveOffsetLength = (line.PositiveOffsetPercentage / 100) * length; exclude = new HashSet <uint>(exclude); foreach (var vertex in line.Vertices) { exclude.Add(vertex); } if (!coder.IsVertexValid(line.Vertices[0])) { // from is not valid, try to find a valid point. var pathToValid = coder.FindValidVertexFor(line.Vertices[0], line.Edges[0], line.Vertices[1], exclude, false); // build edges list. if (pathToValid != null) { // path found check if on shortest route. var shortestRoute = coder.FindShortestPath(line.Vertices[1], pathToValid.Vertex, false); while (shortestRoute != null && !shortestRoute.HasVertex(line.Vertices[0])) { // the vertex that should be on this shortest route, isn't anymore. // exclude the current target vertex, exclude.Add(pathToValid.Vertex); // calulate a new path-to-valid. pathToValid = coder.FindValidVertexFor(line.Vertices[0], line.Edges[0], line.Vertices[1], exclude, false); if (pathToValid == null) { // a new path was not found. break; } shortestRoute = coder.FindShortestPath(line.Vertices[1], pathToValid.Vertex, false); } if (pathToValid != null) { // no path found, just leave things as is. var pathToValidAsList = pathToValid.ToList(); var newVertices = new List <uint>(); var newEdges = new List <long>(); for (int idx = 0; idx < pathToValidAsList.Count; idx++) { // loop over edges. newVertices.Add(pathToValidAsList[idx].Vertex); if (idx > 0) { newEdges.Add(-pathToValidAsList[idx].Edge); // need the reverse edges. } } newEdges.Reverse(); newVertices.Reverse(); // create new location. var edgesArray = new long[newEdges.Count + line.Edges.Length]; newEdges.CopyTo(0, edgesArray, 0, newEdges.Count); line.Edges.CopyTo(0, edgesArray, newEdges.Count, line.Edges.Length); var vertexArray = new uint[newVertices.Count - 1 + line.Vertices.Length]; newVertices.CopyTo(0, vertexArray, 0, newVertices.Count - 1); line.Vertices.CopyTo(0, vertexArray, newVertices.Count - 1, line.Vertices.Length); line.Edges = edgesArray; line.Vertices = vertexArray; // adjust offset length. var newLength = (float)line.Length(coder.Router.Db); positiveOffsetLength = positiveOffsetLength + (newLength - length); length = newLength; } else { // no valid path was found. return(false); } } else { // no valid path was found. return(false); } } // update offset percentage. line.PositiveOffsetPercentage = (float)((positiveOffsetLength / length) * 100.0); return(true); }