Beispiel #1
0
        /// <summary>
        /// Builds a location referenced point for the last vertex.
        /// </summary>
        /// <returns></returns>
        public LocationReferencePoint BuildLocationReferencePointLast(ReferencedLine referencedLocation, int before)
        {
            FormOfWay           fow;
            FunctionalRoadClass frc;

            var end = referencedLocation.Vertices.Length - 1;

            // get all coordinates along the sequence starting at 'before' and ending at 'end'.
            var coordinates = referencedLocation.GetCoordinates(this.Graph, before, end - before + 1);

            // create location reference point.
            var locationReferencedPoint = new LocationReferencePoint();

            locationReferencedPoint.Coordinate = this.GetVertexLocation(referencedLocation.Vertices[end]);
            var tags = this.GetTags(referencedLocation.Edges[end - 1].Tags);

            if (!this.TryMatching(tags, out frc, out fow))
            {
                throw new ReferencedEncodingException(referencedLocation,
                                                      "Could not find frc and/or fow for the given tags.");
            }
            locationReferencedPoint.FormOfWay          = fow;
            locationReferencedPoint.FuntionalRoadClass = frc;
            locationReferencedPoint.Bearing            = (int)BearingEncoder.EncodeBearing(coordinates, true).Value;

            return(locationReferencedPoint);
        }
Beispiel #2
0
        /// <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));
        }
Beispiel #3
0
        /// <summary>
        /// Builds a location referenced point for the last vertex.
        /// </summary>
        /// <returns></returns>
        public static Model.LocationReferencePoint BuildLocationReferencePointLast(this ReferencedLine referencedLocation, Coder coder, int before)
        {
            Model.FormOfWay           fow;
            Model.FunctionalRoadClass frc;

            var end = referencedLocation.Vertices.Length - 1;

            // get all coordinates along the sequence starting at 'before' and ending at 'end'.
            var coordinates = referencedLocation.GetCoordinates(coder.Router.Db, before, end - before + 1);

            // create location reference point.
            var locationReferencedPoint = new Model.LocationReferencePoint();

            locationReferencedPoint.Coordinate = coder.Router.Db.Network.GetVertex(referencedLocation.Vertices[end]).ToCoordinate();
            var edgeProfile = coder.Router.Db.EdgeProfiles.Get(coder.Router.Db.Network.GetEdge(referencedLocation.Edges[end - 1]).Data.Profile);

            if (!coder.Profile.Extract(edgeProfile, out frc, out fow))
            {
                throw new ReferencedEncodingException(referencedLocation,
                                                      "Could not find frc and/or fow for the given tags.");
            }
            locationReferencedPoint.FormOfWay          = fow;
            locationReferencedPoint.FuntionalRoadClass = frc;
            locationReferencedPoint.Bearing            = (int)BearingEncoder.EncodeBearing(coordinates, true);

            return(locationReferencedPoint);
        }
Beispiel #4
0
        /// <summary>
        /// Converts this line location to a line string.
        /// </summary>
        public static LineString ToLineString(this ReferencedLine line, RouterDb routerDb)
        {
            // build coordinates list.
            var coordinates = new List <Coordinate>();

            for (int idx = 0; idx < line.Edges.Length; idx++)
            {
                var shape = routerDb.Network.GetShape(
                    routerDb.Network.GetEdge(line.Edges[idx]));
                if (idx > 0)
                {
                    coordinates.RemoveAt(coordinates.Count - 1);
                }
                if (line.Edges[idx] > 0)
                {
                    coordinates.AddRange(shape.ToCoordinates());
                }
                else
                {
                    for (var i = shape.Count - 1; i >= 0; i--)
                    {
                        coordinates.Add(shape[i].ToGeoAPICoordinate());
                    }
                }
            }

            return(new LineString(coordinates.ToArray()));
        }
Beispiel #5
0
        /// <summary>
        /// Builds a path from the given referenced line start and the first referenced point and ending at the last.
        /// </summary>
        public static EdgePath <float> BuildPathFromLine(this ReferencedLine referencedLine, RouterDb routerDb, out float postiveOffsetInMeters, out float negativeOffsetInMeters)
        {
            RouterPoint source;
            RouterPoint target;

            return(referencedLine.BuildPathFromLine(routerDb, out source, out postiveOffsetInMeters, out target, out negativeOffsetInMeters));
        }
Beispiel #6
0
        /// <summary>
        /// Projects the given coordinates on the referenced line and returns the edge.
        /// </summary>
        public static long ProjectOn(this ReferencedLine line, RouterDb routerDb, float latitude, float longitude, out float offsetInMeter)
        {
            long edge         = Itinero.Constants.NO_EDGE;
            var  bestDistance = float.MaxValue;

            offsetInMeter = float.MaxValue;

            for (var j = 0; j < line.Edges.Length; j++)
            {
                var shape = routerDb.Network.GetShape(routerDb.Network.GetEdge(line.Edges[j]));
                if (line.Edges[j] < 0)
                {
                    shape.Reverse();
                }

                float             projectedLatitude;
                float             projectedLongitude;
                int               projectedShapeIndex;
                float             distanceToProjected;
                float             totalLength;
                float             projectedOffsetInMeter;
                LinePointPosition position;
                if (!shape.ProjectOn(latitude, longitude, out projectedLatitude, out projectedLongitude,
                                     out projectedOffsetInMeter, out projectedShapeIndex, out distanceToProjected, out totalLength, out position))
                {
                    // try to find the closest point.
                    distanceToProjected = float.MaxValue;
                    totalLength         = 0;
                    for (var i = 0; i < shape.Count; i++)
                    {
                        var distance = Itinero.LocalGeo.Coordinate.DistanceEstimateInMeter(shape[i].Latitude, shape[i].Longitude,
                                                                                           latitude, longitude);
                        if (i > 0)
                        {
                            totalLength += Itinero.LocalGeo.Coordinate.DistanceEstimateInMeter(shape[i - 1].Latitude, shape[i - 1].Longitude,
                                                                                               shape[i].Latitude, shape[i].Longitude);
                        }
                        if (distance < distanceToProjected)
                        {
                            projectedOffsetInMeter = totalLength;
                            distanceToProjected    = distance;
                            projectedShapeIndex    = i;
                            position           = LinePointPosition.On;
                            projectedLatitude  = shape[i].Latitude;
                            projectedLongitude = shape[i].Longitude;
                        }
                    }
                }

                if (distanceToProjected < bestDistance)
                {
                    edge          = line.Edges[j];
                    offsetInMeter = projectedOffsetInMeter;
                    bestDistance  = distanceToProjected;
                }
            }
            return(edge);
        }
Beispiel #7
0
        public void EncodeReferencedLineLocationNotShortestPath()
        {
            var e = 0.00001f;

            // setup a routing network to test against.
            var routerDb = new RouterDb();

            routerDb.LoadTestNetwork(
                System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(
                    "OpenLR.Test.test_data.networks.network3.geojson"));
            routerDb.Sort();
            routerDb.AddSupportedVehicle(Itinero.Osm.Vehicles.Vehicle.Car);

            // setup test location and data to verify this.
            var vertex2  = routerDb.Network.GetVertex(2);
            var vertex3  = routerDb.Network.GetVertex(3);
            var vertex4  = routerDb.Network.GetVertex(4);
            var vertex5  = routerDb.Network.GetVertex(5);
            var vertex6  = routerDb.Network.GetVertex(6);
            var vertex7  = routerDb.Network.GetVertex(7);
            var location = new ReferencedLine()
            {
                Edges                    = new long[] { 1, 3, 4, 5, 2 },
                Vertices                 = new uint[] { 7, 4, 3, 2, 5, 6 },
                StartLocation            = routerDb.CreateRouterPointForVertex(7, routerDb.GetSupportedProfile("car")),
                EndLocation              = routerDb.CreateRouterPointForVertex(6, routerDb.GetSupportedProfile("car")),
                NegativeOffsetPercentage = 0,
                PositiveOffsetPercentage = 0
            };
            var json = location.ToFeatures(routerDb).ToGeoJson();

            var length = Itinero.LocalGeo.Coordinate.DistanceEstimateInMeter(
                new List <Itinero.LocalGeo.Coordinate>(new Itinero.LocalGeo.Coordinate[]
            {
                vertex7,
                vertex4,
                vertex3,
                vertex2,
                vertex5,
                vertex6
            }));

            // encode and verify result.
            var encoded = ReferencedLineCodec.Encode(location, new Coder(routerDb, new OsmCoderProfile()));

            Assert.IsNotNull(encoded.First);
            Assert.AreEqual(vertex7.Latitude, encoded.First.Coordinate.Latitude, e);
            Assert.AreEqual(vertex7.Longitude, encoded.First.Coordinate.Longitude, e);
            Assert.IsTrue(encoded.Intermediate != null && encoded.Intermediate.Length == 1);
            Assert.AreEqual(vertex6.Latitude, encoded.Last.Coordinate.Latitude, e);
            Assert.AreEqual(vertex6.Longitude, encoded.Last.Coordinate.Longitude, e);
            Assert.AreEqual(0, encoded.NegativeOffsetPercentage);
            Assert.AreEqual(0, encoded.PositiveOffsetPercentage);
            Assert.AreEqual(FunctionalRoadClass.Frc4, encoded.First.FuntionalRoadClass);
            Assert.AreEqual(FunctionalRoadClass.Frc4, encoded.First.LowestFunctionalRoadClassToNext);
            Assert.AreEqual(length, encoded.First.DistanceToNext + encoded.Intermediate[0].DistanceToNext, 1);
        }
Beispiel #8
0
        /// <summary>
        /// Converts the referenced line location to features.
        /// </summary>
        public static List <Coordinate> GetCoordinates(this ReferencedLine referencedLine, RouterDb routerDb, int start, int count)
        {
            var coordinates = new List <Coordinate>();

            if (count <= 0)
            {
                return(coordinates);
            }

            for (var i = start; i < start + count - 1; i++)
            {
                List <Coordinate> shape = null;
                if (i == 0 && referencedLine.Vertices[0] == Itinero.Constants.NO_VERTEX)
                {     // shape from startlocation -> vertex1.
                    if (referencedLine.Edges.Length == 1)
                    { // only 1 edge, shape from startLocation -> endLocation.
                        shape = referencedLine.StartLocation.ShapePointsTo(routerDb, referencedLine.EndLocation);
                        shape.Insert(0, referencedLine.StartLocation.LocationOnNetwork(routerDb));
                        shape.Add(referencedLine.EndLocation.LocationOnNetwork(routerDb));
                    }
                    else
                    { // just get shape to first vertex.
                        shape = referencedLine.StartLocation.ShapePointsTo(routerDb, referencedLine.Vertices[1]);
                        shape.Insert(0, referencedLine.StartLocation.LocationOnNetwork(routerDb));
                        shape.Add(routerDb.Network.GetVertex(referencedLine.Vertices[1]));
                    }
                }
                else if (i == referencedLine.Edges.Length - 1 && referencedLine.Vertices[referencedLine.Vertices.Length - 1] == Itinero.Constants.NO_VERTEX)
                { // shape from second last vertex -> endlocation.
                    shape = referencedLine.EndLocation.ShapePointsTo(routerDb, referencedLine.Vertices[referencedLine.Vertices.Length - 2]);
                    shape.Reverse();
                    shape.Insert(0, routerDb.Network.GetVertex(referencedLine.Vertices[referencedLine.Vertices.Length - 2]));
                    shape.Add(referencedLine.EndLocation.LocationOnNetwork(routerDb));
                }
                else
                { // regular 2 vertices and edge.
                    shape = routerDb.Network.GetShape(routerDb.Network.GetEdge(referencedLine.Edges[i]));
                    if (referencedLine.Edges[i] < 0)
                    {
                        shape.Reverse();
                    }
                }
                if (shape != null)
                {
                    if (coordinates.Count > 0)
                    {
                        coordinates.RemoveAt(coordinates.Count - 1);
                    }
                    for (var j = 0; j < shape.Count; j++)
                    {
                        coordinates.Add(shape[j]);
                    }
                }
            }
            return(coordinates);
        }
Beispiel #9
0
        /// <summary>
        /// Builds a path from the given referenced line start and the first referenced point and ending at the last.
        /// </summary>
        public static EdgePath <float> BuildPathFromLine(this ReferencedLine referencedLine, RouterDb routerDb, out RouterPoint source, out float postiveOffsetInMeters,
                                                         out RouterPoint target, out float negativeOffsetInMeters)
        {
            source = referencedLine.GetPositiveOffsetRouterPoint(routerDb);
            target = referencedLine.GetNegativeOffsetRouterPoint(routerDb);
            negativeOffsetInMeters = 0;
            postiveOffsetInMeters  = 0;

            var started = false;
            var path    = new EdgePath <float>();

            for (var e = 0; e < referencedLine.Edges.Length; e++)
            {
                var directedEdgeId = referencedLine.Edges[e];
                var edge           = routerDb.Network.GetEdge(directedEdgeId);

                var to = edge.To;
                if (directedEdgeId < 0)
                {
                    to = edge.From;
                }

                if (!started)
                {
                    if (edge.Id != source.EdgeId)
                    {
                        continue;
                    }
                    negativeOffsetInMeters = (source.Offset / (float)ushort.MaxValue) * edge.Data.Distance;
                    if (directedEdgeId < 0)
                    {
                        negativeOffsetInMeters = edge.Data.Distance - negativeOffsetInMeters;
                    }
                    path    = new EdgePath <float>(to, edge.Data.Distance - negativeOffsetInMeters, directedEdgeId, path);
                    started = true;
                    continue;
                }

                if (edge.Id == target.EdgeId)
                {
                    postiveOffsetInMeters = (target.Offset / (float)ushort.MaxValue) * edge.Data.Distance;
                    if (directedEdgeId > 0)
                    {
                        postiveOffsetInMeters = edge.Data.Distance - postiveOffsetInMeters;
                    }
                    path = new EdgePath <float>(Constants.NO_VERTEX, path.Weight + edge.Data.Distance - postiveOffsetInMeters, directedEdgeId, path);
                    break;
                }
                else
                {
                    path = new EdgePath <float>(to, path.Weight + edge.Data.Distance, directedEdgeId, path);
                }
            }

            return(path);
        }
Beispiel #10
0
        /// <summary>
        /// Converts the referenced point along the line location to features.
        /// </summary>
        public static float Length(this ReferencedLine referencedLine, RouterDb routerDb)
        {
            var length = 0.0f;

            for (int idx = 0; idx < referencedLine.Edges.Length; idx++)
            {
                length = length + routerDb.Network.GetShape(
                    routerDb.Network.GetEdge(referencedLine.Edges[idx])).Length();
            }
            return(length);
        }
Beispiel #11
0
        /// <summary>
        /// Builds a point along line location.
        /// </summary>
        /// <returns></returns>
        public static ReferencedPointAlongLine BuildPointAlongLine(this ReferencedEncoderBase encoder, GeoCoordinate location, Meter maxDistance, double boxSize = 0.01)
        {
            if (location == null)
            {
                throw new ArgumentNullException("location");
            }

            // get the closest edge that can be traversed to the given location.
            var closest = encoder.Graph.GetClosestEdge(location, maxDistance, boxSize);

            if (closest == null)
            { // no location could be found.
                throw new BuildLocationFailedException("No network features found near the given location. Make sure the network covers the given location.");
            }
            var oneway = encoder.Vehicle.IsOneWay(encoder.Graph.TagsIndex.Get(closest.Item3.Tags));

            if (oneway.HasValue && oneway.Value != closest.Item3.Forward)
            { // when the edge is not traversible in the direct that it's given in, reverse it.
                var reverseEdge = new LiveEdge();
                reverseEdge.Tags     = closest.Item3.Tags;
                reverseEdge.Forward  = !closest.Item3.Forward;
                reverseEdge.Distance = closest.Item3.Distance;

                closest = new Tuple <long, long, LiveEdge>(closest.Item2, closest.Item1,
                                                           reverseEdge);
            }

            // get locations of edge.
            var startLocation = encoder.GetVertexLocation(closest.Item1).ToGeoCoordinate();
            var endLocation   = encoder.GetVertexLocation(closest.Item2).ToGeoCoordinate();

            // build a proper referenced line.
            var referencedLine = new ReferencedLine(encoder.Graph);

            referencedLine.Vertices = new long[] { closest.Item1, closest.Item2 };
            referencedLine.Edges    = new LiveEdge[] { closest.Item3 };
            referencedLine.PositiveOffsetPercentage = 0;
            referencedLine.NegativeOffsetPercentage = 0;
            referencedLine.EdgeShapes = new GeoCoordinateSimple[][]
            {
                encoder.Graph.GetEdgeShape(
                    referencedLine.Vertices[0], referencedLine.Vertices[1])
            };

            // build the point-along-line location.
            return(new ReferencedPointAlongLine()
            {
                Route = referencedLine,
                Latitude = location.Latitude,
                Longitude = location.Longitude,
                Orientation = Model.Orientation.NoOrientation
            });
        }
Beispiel #12
0
        public void TestReferencedLineGetCoordinates2()
        {
            var routerDb = new RouterDb();

            routerDb.LoadTestNetwork(
                System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(
                    "OpenLR.Test.test_data.networks.network2.geojson"));

            // build a referenced line 0->1->2->5.
            var enumerator = routerDb.Network.GetEdgeEnumerator();

            enumerator.MoveTo(0);
            enumerator.MoveNextUntil(x => x.To == 1);
            var edge01Directed = enumerator.IdDirected();
            var edge01         = enumerator.Id;

            enumerator.MoveTo(1);
            enumerator.MoveNextUntil(x => x.To == 2);
            var edge12Directed = enumerator.IdDirected();
            var edge12         = enumerator.Id;

            enumerator.MoveTo(2);
            enumerator.MoveNextUntil(x => x.To == 5);
            var edge25Directed = enumerator.IdDirected();
            var edge25         = enumerator.Id;

            var vertex0 = routerDb.Network.GetVertex(0);
            var vertex1 = routerDb.Network.GetVertex(1);
            var vertex2 = routerDb.Network.GetVertex(2);
            var vertex5 = routerDb.Network.GetVertex(5);

            var line = new ReferencedLine()
            {
                Edges         = new long[] { edge01Directed, edge12Directed, edge25Directed },
                Vertices      = new uint[] { 0, 1, 2, 5 },
                StartLocation = routerDb.CreateRouterPointForVertex(0, Itinero.Osm.Vehicles.Vehicle.Car.Shortest()),
                EndLocation   = routerDb.CreateRouterPointForVertex(5, Itinero.Osm.Vehicles.Vehicle.Car.Shortest())
            };

            var shape = line.GetCoordinates(routerDb);

            Assert.IsNotNull(shape);
            Assert.AreEqual(4, shape.Count);
            Assert.AreEqual(vertex0.Latitude, shape[0].Latitude);
            Assert.AreEqual(vertex0.Longitude, shape[0].Longitude);
            Assert.AreEqual(vertex1.Latitude, shape[1].Latitude);
            Assert.AreEqual(vertex1.Longitude, shape[1].Longitude);
            Assert.AreEqual(vertex2.Latitude, shape[2].Latitude);
            Assert.AreEqual(vertex2.Longitude, shape[2].Longitude);
            Assert.AreEqual(vertex5.Latitude, shape[3].Latitude);
            Assert.AreEqual(vertex5.Longitude, shape[3].Longitude);
        }
Beispiel #13
0
        /// <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));
                }
            }
        }
Beispiel #14
0
        /// <summary>
        /// Gets all vertices in one hashset.
        /// </summary>
        /// <returns></returns>
        public static HashSet <uint> GetVerticesSet(this ReferencedLine line)
        {
            var set = new HashSet <uint>();

            if (line.Vertices == null)
            { // empty set is ok.
                return(set);
            }
            for (var i = 0; i < line.Vertices.Length; i++)
            {
                set.Add(line.Vertices[i]);
            }
            return(set);
        }
        /// <summary>
        /// Gets covered edges, once an edge is covered by more then the given tolerance it's returned.
        /// </summary>
        public static IEnumerable <long> GetCoveredEdges(this ReferencedLine line, RouterDb routerDb, float tolerancePercentage = 1f)
        {
            if (line.PositiveOffsetPercentage == 0 &&
                line.NegativeOffsetPercentage == 0)
            {
                foreach (var e in line.Edges)
                {
                    yield return(e);
                }
            }
            else
            {
                var lengths     = new float[line.Edges.Length];
                var totalLength = 0f;
                for (var i = 0; i < line.Edges.Length; i++)
                {
                    lengths[i]   = routerDb.Network.GetEdge(line.Edges[i]).Data.Distance;
                    totalLength += lengths[i];
                }

                var offset = 0f;
                for (var i = 0; i < line.Edges.Length; i++)
                {
                    var endOffset = offset + lengths[i];

                    var startPercentage = (offset / totalLength) * 100;
                    var endPercentage   = (endOffset / totalLength) * 100;

                    var startDiff = startPercentage - line.PositiveOffsetPercentage;
                    if (System.Math.Abs(startDiff) < tolerancePercentage)
                    {
                        startDiff = 0;
                    }
                    var endDiff = (100 - endPercentage) - line.NegativeOffsetPercentage;
                    if (System.Math.Abs(endDiff) < tolerancePercentage)
                    {
                        endDiff = 0;
                    }

                    if (startDiff >= 0 && endDiff >= 0)
                    {
                        yield return(line.Edges[i]);
                    }

                    offset = endOffset;
                }
            }
        }
Beispiel #16
0
        /// <summary>
        /// Adjusts this location by inserting intermediate LR-points if needed.
        /// </summary>
        ///
        public static void AdjustToValidDistance(this ReferencedLine line, Coder coder, List <int> points, int start = 0)
        {
            // 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 = line.GetCoordinates(coder.Router.Db, vertexIdx1, count);
            var length      = coordinates.Length();

            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 (coder.IsVertexValid(line.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 = line.GetCoordinates(coder.Router.Db, vertexIdx1, idx - vertexIdx1 + 1).Length();
                    if (lengthBefore < 15000)
                    { // not over!
                        score = score + (1024 * (lengthBefore / 15000));
                    }
                    var lengthAfter = line.GetCoordinates(coder.Router.Db, idx, count - idx).Length();
                    if (lengthAfter < 15000)
                    { // not over!
                        score = score + (1024 * (lengthAfter / 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.
                line.AdjustToValidDistance(coder, points, start + 1);
                line.AdjustToValidDistance(coder, points, start);
            }
        }
Beispiel #17
0
        /// <summary>
        /// Builds a location referenced point for the vertex at the given start-index.
        /// </summary>
        /// <returns></returns>
        public LocationReferencePoint BuildLocationReferencePoint(ReferencedLine referencedLocation, int start, int end)
        {
            FormOfWay           fow;
            FunctionalRoadClass frc;

            // get all coordinates along the sequence starting at 'start' and ending at 'end'.
            var coordinates = referencedLocation.GetCoordinates(this.Graph, start, end - start + 1);

            // create location reference point.
            var locationReferencePoint = new LocationReferencePoint();

            locationReferencePoint.Coordinate = this.GetVertexLocation(referencedLocation.Vertices[start]);
            var tags = this.GetTags(referencedLocation.Edges[start].Tags);

            if (!this.TryMatching(tags, out frc, out fow))
            {
                throw new ReferencedEncodingException(referencedLocation,
                                                      "Could not find frc and/or fow for the given tags.");
            }
            locationReferencePoint.FormOfWay          = fow;
            locationReferencePoint.FuntionalRoadClass = frc;
            locationReferencePoint.Bearing            = (int)BearingEncoder.EncodeBearing(coordinates).Value;
            locationReferencePoint.DistanceToNext     = (int)coordinates.Length().Value;
            FunctionalRoadClass?lowest = null;

            for (var edge = start; edge < end; edge++)
            {
                tags = this.GetTags(referencedLocation.Edges[edge].Tags);
                if (!this.TryMatching(tags, out frc, out fow))
                {
                    throw new ReferencedEncodingException(referencedLocation,
                                                          "Could not find frc and/or fow for the given tags.");
                }

                if (!lowest.HasValue ||
                    frc < lowest)
                {
                    lowest = frc;
                }
            }
            locationReferencePoint.LowestFunctionalRoadClassToNext = lowest;

            return(locationReferencePoint);
        }
Beispiel #18
0
        /// <summary>
        /// Builds a location referenced point for the vertex at the given start-index.
        /// </summary>
        /// <returns></returns>
        public static Model.LocationReferencePoint BuildLocationReferencePoint(this ReferencedLine referencedLocation, Coder coder, int start, int end)
        {
            Model.FormOfWay           fow;
            Model.FunctionalRoadClass frc;

            // get all coordinates along the sequence starting at 'start' and ending at 'end'.
            var coordinates = referencedLocation.GetCoordinates(coder.Router.Db, start, end - start + 1);

            // create location reference point.
            var locationReferencePoint = new Model.LocationReferencePoint();

            locationReferencePoint.Coordinate = coder.Router.Db.Network.GetVertex(referencedLocation.Vertices[start]).ToCoordinate();
            var edgeProfile = coder.Router.Db.EdgeProfiles.Get(coder.Router.Db.Network.GetEdge(referencedLocation.Edges[start]).Data.Profile);

            if (!coder.Profile.Extract(edgeProfile, out frc, out fow))
            {
                throw new ReferencedEncodingException(referencedLocation,
                                                      "Could not find frc and/or fow for the given tags.");
            }
            locationReferencePoint.FormOfWay          = fow;
            locationReferencePoint.FuntionalRoadClass = frc;
            locationReferencePoint.Bearing            = (int)BearingEncoder.EncodeBearing(coordinates);
            locationReferencePoint.DistanceToNext     = (int)coordinates.Length();
            Model.FunctionalRoadClass?lowest = null;
            for (var edge = start; edge < end; edge++)
            {
                edgeProfile = coder.Router.Db.EdgeProfiles.Get(coder.Router.Db.Network.GetEdge(referencedLocation.Edges[edge]).Data.Profile);
                if (!coder.Profile.Extract(edgeProfile, out frc, out fow))
                {
                    throw new ReferencedEncodingException(referencedLocation,
                                                          "Could not find frc and/or fow for the given tags.");
                }

                if (!lowest.HasValue ||
                    frc > lowest)
                {
                    lowest = frc;
                }
            }
            locationReferencePoint.LowestFunctionalRoadClassToNext = lowest;

            return(locationReferencePoint);
        }
Beispiel #19
0
        public void EncodeReferencedLineLocation()
        {
            var e = 0.00001f;

            // setup a routing network to test against.
            var routerDb = new RouterDb();

            routerDb.LoadTestNetwork(
                System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(
                    "OpenLR.Test.test_data.networks.network3.geojson"));
            routerDb.Sort();
            routerDb.AddSupportedVehicle(Itinero.Osm.Vehicles.Vehicle.Car);

            // setup test location and data to verify this.
            var start    = routerDb.Network.GetVertex(7);
            var end      = routerDb.Network.GetVertex(6);
            var location = new ReferencedLine()
            {
                Edges                    = new long[] { 1, -6, 2 },
                Vertices                 = new uint[] { 7, 4, 5, 6 },
                StartLocation            = routerDb.CreateRouterPointForVertex(7, routerDb.GetSupportedProfile("car")),
                EndLocation              = routerDb.CreateRouterPointForVertex(6, routerDb.GetSupportedProfile("car")),
                NegativeOffsetPercentage = 0,
                PositiveOffsetPercentage = 0
            };

            // encode and verify result.
            var encoded = ReferencedLineCodec.Encode(location, new Coder(routerDb, new OsmCoderProfile()));

            Assert.IsNotNull(encoded.First);
            Assert.AreEqual(start.Latitude, encoded.First.Coordinate.Latitude, e);
            Assert.AreEqual(start.Longitude, encoded.First.Coordinate.Longitude, e);
            Assert.IsTrue(encoded.Intermediate == null || encoded.Intermediate.Length == 0);
            Assert.AreEqual(end.Latitude, encoded.Last.Coordinate.Latitude, e);
            Assert.AreEqual(end.Longitude, encoded.Last.Coordinate.Longitude, e);
            Assert.AreEqual(0, encoded.NegativeOffsetPercentage);
            Assert.AreEqual(0, encoded.PositiveOffsetPercentage);
            Assert.AreEqual(FunctionalRoadClass.Frc4, encoded.First.FuntionalRoadClass);
            Assert.AreEqual(FunctionalRoadClass.Frc4, encoded.First.LowestFunctionalRoadClassToNext);
            Assert.AreEqual(Itinero.LocalGeo.Coordinate.DistanceEstimateInMeter(start, end),
                            encoded.First.DistanceToNext, 1);
        }
Beispiel #20
0
 /// <summary>
 /// Encodes a line location.
 /// </summary>
 /// <param name="lineLocation"></param>
 /// <returns></returns>
 public virtual string Encode(ReferencedLine lineLocation)
 {
     return(this.GetReferencedLineEncoder().Encode(lineLocation));
 }
Beispiel #21
0
        /// <summary>
        /// Converts the referenced line location to a list of sorted coordinates.
        /// </summary>
        /// <returns></returns>
        public static List <Coordinate> GetCoordinates(this ReferencedLine route, Coder coder, float offsetRatio,
                                                       out int offsetEdgeIdx, out Coordinate offsetLocation, out float offsetLength, out float offsetEdgeLength, out float edgeLength)
        {
            if (route == null)
            {
                throw new ArgumentNullException("route");
            }
            if (route.Edges == null || route.Edges.Length == 0)
            {
                throw new ArgumentOutOfRangeException("route", "Route has no edges.");
            }
            if (route.Vertices == null || route.Vertices.Length == 0)
            {
                throw new ArgumentOutOfRangeException("route", "Route has no vertices.");
            }
            if (route.Vertices.Length != route.Edges.Length + 1)
            {
                throw new ArgumentOutOfRangeException("route", "Route is invalid: there should be n vertices and n-1 edges.");
            }

            // calculate the total length first.
            var totalLength = route.GetCoordinates(coder.Router.Db).Length();

            // calculate the lenght at the offst.
            offsetLength     = (float)(totalLength * offsetRatio);
            offsetEdgeLength = -1;
            offsetEdgeIdx    = -1;
            edgeLength       = -1;

            // loop over all coordinates and collect offsetLocation and offsetEdgeIdx.
            float currentOffsetLength = 0;
            float currentEdgeLength   = 0;
            var   coordinates         = new List <Coordinate>();

            for (var i = 0; i < route.Edges.Length; i++)
            {
                List <Coordinate> shape = null;
                currentEdgeLength = 0;
                if (i == 0 && route.Vertices[0] == Itinero.Constants.NO_VERTEX)
                {     // shape from startlocation -> vertex1.
                    if (route.Edges.Length == 1)
                    { // only 1 edge, shape from startLocation -> endLocation.
                        shape = route.StartLocation.ShapePointsTo(coder.Router.Db, route.EndLocation);
                        shape.Insert(0, route.StartLocation.LocationOnNetwork(coder.Router.Db));
                        shape.Add(route.EndLocation.LocationOnNetwork(coder.Router.Db));
                    }
                    else
                    { // just get shape to first vertex.
                        shape = route.StartLocation.ShapePointsTo(coder.Router.Db, route.Vertices[1]);
                        shape.Insert(0, route.StartLocation.LocationOnNetwork(coder.Router.Db));
                        shape.Add(coder.Router.Db.Network.GetVertex(route.Vertices[1]));
                    }
                }
                else if (i == route.Edges.Length - 1 && route.Vertices[route.Vertices.Length - 1] == Itinero.Constants.NO_VERTEX)
                { // shape from second last vertex -> endlocation.
                    shape = route.EndLocation.ShapePointsTo(coder.Router.Db, route.Vertices[route.Vertices.Length - 2]);
                    shape.Reverse();
                    shape.Insert(0, coder.Router.Db.Network.GetVertex(route.Vertices[route.Vertices.Length - 2]));
                    shape.Add(route.EndLocation.LocationOnNetwork(coder.Router.Db));
                }
                else
                { // regular 2 vertices and edge.
                    shape = coder.Router.Db.Network.GetShape(coder.Router.Db.Network.GetEdge(route.Edges[i]));
                    if (route.Edges[i] < 0)
                    {
                        shape.Reverse();
                    }
                }
                if (shape != null)
                {
                    currentEdgeLength = currentEdgeLength + shape.Length();
                    if (coordinates.Count > 0)
                    {
                        coordinates.RemoveAt(coordinates.Count - 1);
                    }
                    for (var j = 0; j < shape.Count; j++)
                    {
                        coordinates.Add(shape[j]);
                    }
                }

                // add current edge length to current offset.
                if ((currentOffsetLength + currentEdgeLength) >= offsetLength &&
                    edgeLength < 0)
                { // it's this edge that has the valuable info.
                    offsetEdgeIdx    = i;
                    offsetEdgeLength = offsetLength - currentOffsetLength;
                    edgeLength       = currentEdgeLength;
                }
                currentOffsetLength = currentOffsetLength + currentEdgeLength;
            }

            // choose the last edge.
            if (edgeLength < 0)
            { // it's this edge that has the valuable info.
                offsetEdgeIdx    = route.Edges.Length - 1;
                offsetEdgeLength = offsetLength - currentOffsetLength;
                edgeLength       = currentEdgeLength;
            }

            // calculate actual offset position.
            offsetLocation = coordinates.GetPositionLocation(offsetRatio);
            return(coordinates);
        }
Beispiel #22
0
        /// <summary>
        /// Gets the negative offset location.
        /// </summary>
        public static Coordinate GetNegativeOffsetLocation(this ReferencedLine referencedLine, RouterDb routerDb)
        {
            var coordinates = referencedLine.GetCoordinates(routerDb);

            return(coordinates.GetPositionLocation(1f - (referencedLine.NegativeOffsetPercentage / 100.0f)));
        }
Beispiel #23
0
 /// <summary>
 /// Encodes a referenced line location into an unreferenced location.
 /// </summary>
 /// <param name="lineLocation"></param>
 /// <returns></returns>
 public virtual LineLocation EncodeReferenced(ReferencedLine lineLocation)
 {
     return(this.GetReferencedLineEncoder().EncodeReferenced(lineLocation));
 }
Beispiel #24
0
 /// <summary>
 /// Converts the referenced line location to features.
 /// </summary>
 public static List <Coordinate> GetCoordinates(this ReferencedLine referencedLine, RouterDb routerDb)
 {
     return(referencedLine.GetCoordinates(routerDb, 0, referencedLine.Vertices.Length));
 }
Beispiel #25
0
 /// <summary>
 /// Gets the negative offset routerpoint.
 /// </summary>
 public static RouterPoint GetNegativeOffsetRouterPoint(this ReferencedLine referencedLine, RouterDb routerDb)
 {
     return(referencedLine.GetOffsetRouterPoint(routerDb, 100 - referencedLine.NegativeOffsetPercentage));
 }
Beispiel #26
0
 /// <summary>
 /// Validates the offsets.
 /// </summary>
 public static void ValidateOffsets(this ReferencedLine line)
 {
 }
Beispiel #27
0
 /// <summary>
 /// Validates the location for encoding in binary format.
 /// </summary>
 public static void ValidateBinary(this ReferencedLine line)
 {
 }
Beispiel #28
0
        /// <summary>
        /// Projects the given coordinates on the referenced line and returns the edge.
        /// </summary>
        public static long ProjectOn(this ReferencedLine line, RouterDb routerDb, float latitude, float longitude)
        {
            var offsetInMeter = float.MaxValue;

            return(line.ProjectOn(routerDb, latitude, longitude, out offsetInMeter));
        }
Beispiel #29
0
        /// <summary>
        /// Adjusts this location to use valid LR-points.
        /// </summary>
        public static void AdjustToValidPoints(this ReferencedLine line, Coder coder)
        {
            if (line.Vertices.Length <= 1)
            {
                throw new ArgumentException("Cannot adjust a line location with only one vertex.");
            }

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

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

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

            if (!coder.IsOnShortestPath(line.Vertices[0], line.Vertices[line.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 = line.GetVerticesSet();

            while (true)
            {
                // search backward.
                var workingCopy = line.Clone() as ReferencedLine;
                if (!workingCopy.TryAdjustToValidPointBackwards(coder, 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(coder, vertex1, vertex2, forwardExcludeSet))
                        { // no more forward options for the current backward.
                            break;
                        }

                        // check valid.
                        if (coder.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 (coder.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.
            line.Edges    = validCopy.Edges;
            line.Vertices = validCopy.Vertices;
            line.NegativeOffsetPercentage = validCopy.NegativeOffsetPercentage;
            line.PositiveOffsetPercentage = validCopy.PositiveOffsetPercentage;
        }
Beispiel #30
0
        /// <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);
        }