Exemplo n.º 1
0
        /// <summary>
        /// Adjusts the given location by inserting an intermediate LR-point at the point representing pointIdx.
        /// </summary>
        public void AdjustToValidDistance(ReferencedEncoderBase encoder, List <int> points, int start)
        {
            // get start/end vertex.
            var vertexIdx1 = points[start];
            var vertexIdx2 = points[start + 1];
            var count      = vertexIdx2 - vertexIdx1 + 1;

            // calculate length to begin with.
            var coordinates = this.GetCoordinates(encoder.Graph, vertexIdx1, count);
            var length      = coordinates.Length().Value;

            if (length > 15000)
            { // too long.
                // find the best intermediate point.
                var intermediatePoints = new SortedDictionary <double, int>();
                for (int idx = vertexIdx1 + 1; idx < vertexIdx1 + count - 2; idx++)
                {
                    var score = 0.0;
                    if (encoder.IsVertexValid(this.Vertices[idx]))
                    { // a valid vertex is obviously a better choice!
                        score = score + 4096;
                    }

                    // the length is good when close to 15000 but not over.
                    var lengthBefore = this.GetCoordinates(encoder.Graph, vertexIdx1, idx - vertexIdx1 + 1).Length();
                    if (lengthBefore.Value < 15000)
                    { // not over!
                        score = score + (1024 * (lengthBefore.Value / 15000));
                    }
                    var lengthAfter = this.GetCoordinates(encoder.Graph, idx, count - idx).Length();
                    if (lengthAfter.Value < 15000)
                    { // not over!
                        score = score + (1024 * (lengthAfter.Value / 15000));
                    }

                    // add to sorted dictionary.
                    intermediatePoints[8192 - score] = idx;
                }

                // select the best point and insert it in between.
                var bestPoint = intermediatePoints.First().Value;
                points.Insert(start + 1, bestPoint);

                // test the two distances.
                this.AdjustToValidDistance(encoder, points, start + 1);
                this.AdjustToValidDistance(encoder, points, start);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Validates if the location is connected.
        /// </summary>
        /// <returns></returns>
        public void ValidateConnected(ReferencedEncoderBase mainEncoder)
        {
            var edges    = this.Edges;
            var vertices = this.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];

                bool found = false;
                foreach (var edge in mainEncoder.Graph.GetEdges(from))
                {
                    if (edge.Key == to &&
                        edge.Value.Equals(edges[edgeIdx]))
                    { // edge was found, is valid.
                        found = true;
                        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 tags = mainEncoder.Graph.TagsIndex.Get(edges[edgeIdx].Tags);
                if (!mainEncoder.Vehicle.CanTraverse(tags))
                { // oeps, cannot be traversed.
                    throw new ArgumentOutOfRangeException(string.Format("Edge at index {0} cannot be traversed by vehicle {1}.", edgeIdx, mainEncoder.Vehicle.UniqueName));
                }
                // check whether the edge can be traversed in the correct direction.
                var oneway         = mainEncoder.Vehicle.IsOneWay(tags);
                var canMoveForward = (oneway == null) || (oneway.Value == edges[edgeIdx].Forward);
                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, mainEncoder.Vehicle.UniqueName));
                }
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// Creates a new dynamic graph encoder.
 /// </summary>
 /// <param name="mainEncoder"></param>
 /// <param name="rawEncoder"></param>
 public ReferencedEncoder(ReferencedEncoderBase mainEncoder, OpenLR.Encoding.LocationEncoder <TLocation> rawEncoder)
     : base(rawEncoder)
 {
     _mainEncoder = mainEncoder;
 }
 /// <summary>
 /// Creates a point along line referenced encoder.
 /// </summary>
 /// <param name="mainEncoder"></param>
 /// <param name="rawEncoder"></param>
 public ReferencedPointAlongLineEncoder(ReferencedEncoderBase mainEncoder, OpenLR.Encoding.LocationEncoder <PointAlongLineLocation> rawEncoder)
     : base(mainEncoder, rawEncoder)
 {
 }
Exemplo n.º 5
0
        ///// <summary>
        ///// Adjusts this location to use valid LR-points.
        ///// </summary>
        //private bool TryAdjustToValidPoints(ReferencedEncoderBase encoder, long vertex1, long vertex2,
        //    HashSet<long> excludeBackward, HashSet<long> excludeForward)
        //{
        //    var length = (float)this.Length(encoder).Value;
        //    var positiveOffsetLength = (this.PositiveOffsetPercentage / 100) * length;
        //    var negativeOffsetLength = (this.NegativeOffsetPercentage / 100) * length;
        //    var exclude = new HashSet<long>(excludeForward);
        //    if (!encoder.IsVertexValid(this.Vertices[0]))
        //    { // from is not valid, try to find a valid point.
        //        var pathToValid = encoder.FindValidVertexFor(this.Vertices[0], this.Edges[0], this.Vertices[1],
        //            exclude, false);

        //        // build edges list.
        //        if (pathToValid != null)
        //        { // no path found, just leave things as is.
        //            var shortestRoute = encoder.FindShortestPath(this.Vertices[1], pathToValid.Vertex, false);
        //            while (shortestRoute != null && !shortestRoute.Contains(this.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 = encoder.FindValidVertexFor(this.Vertices[0], this.Edges[0], this.Vertices[1],
        //                    exclude, false);
        //                if (pathToValid == null)
        //                { // a new path was not found.
        //                    break;
        //                }
        //                shortestRoute = encoder.FindShortestPath(this.Vertices[1], pathToValid.Vertex, false);
        //            }
        //            if (pathToValid != null)
        //            { // no path found, just leave things as is.
        //                var newVertices = pathToValid.ToArray().Reverse().ToList();
        //                var newEdges = new List<LiveEdge>();
        //                for (int idx = 0; idx < newVertices.Count - 1; idx++)
        //                { // loop over edges.
        //                    var edge = newVertices[idx].Edge;
        //                    // Next OsmSharp version: use closest.Value.Value.Reverse()?
        //                    var reverseEdge = new LiveEdge();
        //                    reverseEdge.Tags = edge.Tags;
        //                    reverseEdge.Forward = !edge.Forward;
        //                    reverseEdge.Distance = edge.Distance;

        //                    edge = reverseEdge;
        //                    newEdges.Add(edge);
        //                }

        //                // create new location.
        //                var edgesArray = new LiveEdge[newEdges.Count + this.Edges.Length];
        //                newEdges.CopyTo(0, edgesArray, 0, newEdges.Count);
        //                this.Edges.CopyTo(0, edgesArray, newEdges.Count, this.Edges.Length);
        //                var vertexArray = new long[newVertices.Count - 1 + this.Vertices.Length];
        //                newVertices.ConvertAll(x => (long)x.Vertex).CopyTo(0, vertexArray, 0, newVertices.Count - 1);
        //                this.Vertices.CopyTo(0, vertexArray, newVertices.Count - 1, this.Vertices.Length);

        //                this.Edges = edgesArray;
        //                this.Vertices = vertexArray;

        //                // adjust offset length.
        //                var newLength = (float)this.Length(encoder).Value;
        //                positiveOffsetLength = positiveOffsetLength + (newLength - length);
        //                length = newLength;
        //            }
        //        }
        //    }
        //    exclude = new HashSet<long>(excludeBackward);
        //    if (!encoder.IsVertexValid(this.Vertices[this.Vertices.Length - 1]))
        //    { // from is not valid, try to find a valid point.
        //        var vertexCount = this.Vertices.Length;
        //        var pathToValid = encoder.FindValidVertexFor(this.Vertices[vertexCount - 1], this.Edges[
        //            this.Edges.Length - 1].ToReverse(), this.Vertices[vertexCount - 2], exclude, true);

        //        // build edges list.
        //        if (pathToValid != null)
        //        { // no path found, just leave things as is.
        //            var shortestRoute = encoder.FindShortestPath(this.Vertices[vertexCount - 2], pathToValid.Vertex, true);
        //            while (shortestRoute != null && !shortestRoute.Contains(this.Vertices[vertexCount - 1]))
        //            { // 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 = encoder.FindValidVertexFor(this.Vertices[vertexCount - 1], this.Edges[
        //                    this.Edges.Length - 1].ToReverse(), this.Vertices[vertexCount - 2], exclude, true);
        //                if (pathToValid == null)
        //                { // a new path was not found.
        //                    break;
        //                }
        //                shortestRoute = encoder.FindShortestPath(this.Vertices[vertexCount - 2], pathToValid.Vertex, true);
        //            }
        //            if (pathToValid != null)
        //            { // no path found, just leave things as is.
        //                var newVertices = pathToValid.ToArray().ToList();
        //                var newEdges = new List<LiveEdge>();
        //                for (int idx = 1; idx < newVertices.Count; idx++)
        //                { // loop over edges.
        //                    var edge = newVertices[idx].Edge;
        //                    newEdges.Add(edge);
        //                }

        //                // create new location.
        //                var edgesArray = new LiveEdge[newEdges.Count + this.Edges.Length];
        //                this.Edges.CopyTo(0, edgesArray, 0, this.Edges.Length);
        //                newEdges.CopyTo(0, edgesArray, this.Edges.Length, newEdges.Count);
        //                var vertexArray = new long[newVertices.Count - 1 + this.Vertices.Length];
        //                this.Vertices.CopyTo(0, vertexArray, 0, this.Vertices.Length);
        //                newVertices.ConvertAll(x => (long)x.Vertex).CopyTo(1, vertexArray, this.Vertices.Length, newVertices.Count - 1);

        //                this.Edges = edgesArray;
        //                this.Vertices = vertexArray;

        //                // adjust offset length.
        //                var newLength = (float)this.Length(encoder).Value;
        //                negativeOffsetLength = negativeOffsetLength + (newLength - length);
        //                length = newLength;
        //            }
        //        }
        //    }

        //    // update offset percentags.
        //    this.PositiveOffsetPercentage = (float)((positiveOffsetLength / length) * 100.0);
        //    this.NegativeOffsetPercentage = (float)((negativeOffsetLength / length) * 100.0);

        //    // fill shapes.
        //    this.EdgeShapes = new GeoCoordinateSimple[this.Edges.Length][];
        //    for (int i = 0; i < this.Edges.Length; i++)
        //    {
        //        this.EdgeShapes[i] = encoder.Graph.GetEdgeShape(
        //            this.Vertices[i], this.Vertices[i + 1]);
        //    }
        //    return true;
        //}

        /// <summary>
        /// Adjusts this location by inserting intermediate LR-points if needed.
        /// </summary>
        ///
        public void AdjustToValidDistances(ReferencedEncoderBase encoder, List <int> points)
        {
            this.AdjustToValidDistance(encoder, points, 0);
        }
Exemplo n.º 6
0
        private bool TryAdjustToValidPointForwards(ReferencedEncoderBase encoder, long vertex1, long vertex2,
                                                   HashSet <long> exclude)
        {
            var length = (float)this.Length(encoder).Value;
            var negativeOffsetLength = (this.NegativeOffsetPercentage / 100) * length;

            exclude = new HashSet <long>(exclude);
            foreach (var vertex in this.Vertices)
            {
                exclude.Add(vertex);
            }

            if (!encoder.IsVertexValid(this.Vertices[this.Vertices.Length - 1]))
            { // from is not valid, try to find a valid point.
                var vertexCount = this.Vertices.Length;
                var pathToValid = encoder.FindValidVertexFor(this.Vertices[vertexCount - 1], this.Edges[
                                                                 this.Edges.Length - 1].ToReverse(), this.Vertices[vertexCount - 2], exclude, true);

                // build edges list.
                if (pathToValid != null)
                { // no path found, just leave things as is.
                    var shortestRoute = encoder.FindShortestPath(this.Vertices[vertexCount - 2], pathToValid.Vertex, true);
                    while (shortestRoute != null && !shortestRoute.Contains(this.Vertices[vertexCount - 1]))
                    { // 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 = encoder.FindValidVertexFor(this.Vertices[vertexCount - 1], this.Edges[
                                                                     this.Edges.Length - 1].ToReverse(), this.Vertices[vertexCount - 2], exclude, true);
                        if (pathToValid == null)
                        { // a new path was not found.
                            break;
                        }
                        shortestRoute = encoder.FindShortestPath(this.Vertices[vertexCount - 2], pathToValid.Vertex, true);
                    }
                    if (pathToValid != null)
                    { // no path found, just leave things as is.
                        var newVertices = pathToValid.ToArray().ToList();
                        var newEdges    = new List <LiveEdge>();
                        for (int idx = 1; idx < newVertices.Count; idx++)
                        { // loop over edges.
                            var edge = newVertices[idx].Edge;
                            newEdges.Add(edge);
                        }

                        // create new location.
                        var edgesArray = new LiveEdge[newEdges.Count + this.Edges.Length];
                        this.Edges.CopyTo(0, edgesArray, 0, this.Edges.Length);
                        newEdges.CopyTo(0, edgesArray, this.Edges.Length, newEdges.Count);
                        var vertexArray = new long[newVertices.Count - 1 + this.Vertices.Length];
                        this.Vertices.CopyTo(0, vertexArray, 0, this.Vertices.Length);
                        newVertices.ConvertAll(x => (long)x.Vertex).CopyTo(1, vertexArray, this.Vertices.Length, newVertices.Count - 1);

                        this.Edges    = edgesArray;
                        this.Vertices = vertexArray;

                        // adjust offset length.
                        var newLength = (float)this.Length(encoder).Value;
                        negativeOffsetLength = negativeOffsetLength + (newLength - length);
                        length = newLength;
                    }
                    else
                    { // no valid path was found.
                        return(false);
                    }
                }
                else
                { // no valid path was found.
                    return(false);
                }
            }

            // update offset percentage
            this.NegativeOffsetPercentage = (float)((negativeOffsetLength / length) * 100.0);

            return(true);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Adjusts this location to use valid LR-points.
        /// </summary>
        public void AdjustToValidPoints(ReferencedEncoderBase encoder)
        {
            if (this.Vertices.Length <= 1)
            {
                throw new ArgumentException("Cannot adjust a line location with only one vertex.");
            }

            var vertex1Valid = encoder.IsVertexValid(this.Vertices[0]);
            var vertex2Valid = encoder.IsVertexValid(this.Vertices[this.Vertices.Length - 1]);

            if (vertex1Valid && vertex2Valid)
            { // already valid.
                return;
            }
            if (this.Vertices.Length > 2)
            {
                return;
            }                                         // line was already adjusted.

            var vertex1 = this.Vertices[0];
            var vertex2 = this.Vertices[1];

            if (!encoder.IsOnShortestPath(this.Vertices[0], this.Vertices[this.Vertices.Length - 1],
                                          vertex1, vertex2))
            { // impossible to expand edge.
                return;
            }

            // make sure the original sequence is still there on the shortest path.
            ReferencedLine validCopy          = null;
            var            backwardExcludeSet = this.GetVerticesSet();

            while (true)
            {
                // search backward.
                var workingCopy = this.Clone() as ReferencedLine;
                if (!workingCopy.TryAdjustToValidPointBackwards(encoder, vertex1, vertex2, backwardExcludeSet))
                { // no more options exist, impossible to expand edge, just keep the edge itself.
                    return;
                }

                if (!vertex2Valid)
                { // search forward.
                    var forwardExcludeSet = workingCopy.GetVerticesSet();
                    do
                    {
                        var forwardWorkingCopy = workingCopy.Clone() as ReferencedLine;
                        if (!forwardWorkingCopy.TryAdjustToValidPointForwards(encoder, vertex1, vertex2, forwardExcludeSet))
                        { // no more forward options for the current backward.
                            break;
                        }

                        // check valid.
                        if (encoder.IsOnShortestPath(forwardWorkingCopy.Vertices[0], forwardWorkingCopy.Vertices[forwardWorkingCopy.Vertices.Length - 1],
                                                     vertex1, vertex2))
                        { // current location is valid.
                            validCopy = forwardWorkingCopy;
                            break;
                        }

                        // not valid here, exclude current forward.
                        forwardExcludeSet.Add(forwardWorkingCopy.Vertices[forwardWorkingCopy.Vertices.Length - 1]);
                    } while (true);
                }
                else
                { // check valid.
                    if (encoder.IsOnShortestPath(workingCopy.Vertices[0], workingCopy.Vertices[workingCopy.Vertices.Length - 1],
                                                 vertex1, vertex2))
                    { // current location is valid.
                        validCopy = workingCopy;
                        break;
                    }
                }

                if (validCopy != null)
                { // current location is valid.
                    break;
                }

                if (vertex1Valid)
                { // vertex1 was already valid, no reason to continue searching.
                    return;
                }

                // exclude current backward and continue.
                backwardExcludeSet.Add(workingCopy.Vertices[0]);
            }

            // copy from working copy.
            this.Edges    = validCopy.Edges;
            this.Vertices = validCopy.Vertices;
            this.NegativeOffsetPercentage = validCopy.NegativeOffsetPercentage;
            this.PositiveOffsetPercentage = validCopy.PositiveOffsetPercentage;

            // fill shapes.
            this.EdgeShapes = new GeoCoordinateSimple[this.Edges.Length][];
            for (int i = 0; i < this.Edges.Length; i++)
            {
                this.EdgeShapes[i] = encoder.Graph.GetEdgeShape(
                    this.Vertices[i], this.Vertices[i + 1]);
            }
        }
Exemplo n.º 8
0
 /// <summary>
 /// Validates the location for encoding in binary format.
 /// </summary>
 public void ValidateBinary(ReferencedEncoderBase mainEncoder)
 {
 }
Exemplo n.º 9
0
 /// <summary>
 /// Validates the offsets.
 /// </summary>
 public void ValidateOffsets(ReferencedEncoderBase mainEncoder)
 {
 }