/// <summary> /// Encodes the given location. /// </summary> public static LineLocation Encode(ReferencedLine referencedLocation, Coder coder, EncodingSettings settings) { try { // Step – 1: Check validity of the location and offsets to be encoded. // validate connected and traversal. referencedLocation.ValidateConnected(coder); // validate offsets. referencedLocation.ValidateOffsets(); // validate for binary. referencedLocation.ValidateBinary(); // Step – 2 Adjust start and end node of the location to represent valid map nodes. referencedLocation.AdjustToValidPoints(coder); // keep a list of LR-point. var points = new List <int>(new int[] { 0, referencedLocation.Vertices.Length - 1 }); // Step – 3 Determine coverage of the location by a shortest-path. // Step – 4 Check whether the calculated shortest-path covers the location completely. // Go to step 5 if the location is not covered completely, go to step 7 if the location is covered. // Step – 5 Determine the position of a new intermediate location reference point so that the part of the // location between the start of the shortest-path calculation and the new intermediate is covered // completely by a shortest-path. // Step – 6 Go to step 3 and restart shortest path calculation between the new intermediate location reference // point and the end of the location. if (settings.VerifyShortestPath) { bool isOnShortestPath = false; while (!isOnShortestPath) { // keep on adding intermediates until all paths between intermediates are on shortest paths. isOnShortestPath = true; // loop over all LRP-pairs. for (var i = 0; i < points.Count - 1; i++) { var fromPoint = points[i]; var toPoint = points[i + 1]; var fromEdge = referencedLocation.Edges[fromPoint]; var toEdge = referencedLocation.Edges[toPoint - 1]; var edgeCount = toPoint - fromPoint; // calculate shortest path between their first and last edge. var pathResult = coder.Router.TryCalculateRaw(coder.Profile.Profile, coder.Router.GetDefaultWeightHandler(coder.Profile.Profile), fromEdge, toEdge, coder.Profile.RoutingSettings); if (pathResult.IsError) { try { coder.Profile.RoutingSettings.SetMaxSearch(coder.Profile.Profile.FullName, float.MaxValue); pathResult = coder.Router.TryCalculateRaw(coder.Profile.Profile, coder.Router.GetDefaultWeightHandler(coder.Profile.Profile), fromEdge, toEdge, coder.Profile.RoutingSettings); if (pathResult.IsError) { throw new Exception("No path found between two edges of the line location."); } } catch { throw; } finally { coder.Profile.RoutingSettings.SetMaxSearch(coder.Profile.Profile.FullName, coder.Profile.MaxSearch); } } var path = pathResult.Value; var edges = new List <long>(); while (path.From != null) { edges.Add(path.Edge); path = path.From; } edges.Reverse(); // calculate converage. var splitAt = -1; for (var j = 0; j < edges.Count; j++) { var locationEdgeIdx = j + fromPoint; if (locationEdgeIdx >= referencedLocation.Edges.Length || edges[j] != referencedLocation.Edges[locationEdgeIdx]) { splitAt = j + fromPoint + 1; break; } } // split if needed. if (splitAt != -1) { points.Add(splitAt); points.Sort(); isOnShortestPath = false; break; } } } } // Step – 7 Concatenate the calculated shortest-paths for a complete coverage of the location and form an // ordered list of location reference points (from the start to the end of the location). // Step – 8 Check validity of the location reference path. If the location reference path is invalid then go // to step 9, if the location reference path is valid then go to step 10. // Step – 9 Add a sufficient number of additional intermediate location reference points if the distance // between two location reference points exceeds the maximum distance. Remove the start/end LR-point // if the positive/negative offset value exceeds the length of the corresponding path. referencedLocation.AdjustToValidDistance(coder, points); // Step – 10 Create physical representation of the location reference. var coordinates = referencedLocation.GetCoordinates(coder.Router.Db); var length = coordinates.Length(); // 3: The actual encoding now! // initialize location. var location = new LineLocation(); // build lrp's. var locationReferencePoints = new List <LocationReferencePoint>(); for (var idx = 0; idx < points.Count - 1; idx++) { locationReferencePoints.Add(referencedLocation.BuildLocationReferencePoint(coder, points[idx], points[idx + 1])); } locationReferencePoints.Add(referencedLocation.BuildLocationReferencePointLast( coder, points[points.Count - 2])); // build location. location.First = locationReferencePoints[0]; location.Intermediate = new LocationReferencePoint[locationReferencePoints.Count - 2]; for (var idx = 1; idx < locationReferencePoints.Count - 1; idx++) { location.Intermediate[idx - 1] = locationReferencePoints[idx]; } location.Last = locationReferencePoints[locationReferencePoints.Count - 1]; // set offsets. location.PositiveOffsetPercentage = referencedLocation.PositiveOffsetPercentage; location.NegativeOffsetPercentage = referencedLocation.NegativeOffsetPercentage; return(location); } catch (ReferencedEncodingException) { // rethrow referenced encoding exception. throw; } catch (Exception ex) { // unhandled exception! throw new ReferencedEncodingException(referencedLocation, string.Format("Unhandled exception during ReferencedLineEncoder: {0}", ex.ToString()), ex); } }