コード例 #1
0
        /// <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);
            }
        }