コード例 #1
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);
            }
        }
コード例 #2
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);
        }
コード例 #3
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);
        }
コード例 #4
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);
        }
コード例 #5
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);
        }
コード例 #6
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);
        }
コード例 #7
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);
        }
コード例 #8
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));
 }
コード例 #9
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)));
        }
コード例 #10
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);
            }
        }
コード例 #11
0
        public void TestReferencedLineGetCoordinates1()
        {
            var routerDb = new RouterDb();

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

            var line = new ReferencedLine()
            {
                Edges         = new long[] { 1 },
                Vertices      = new uint[] { 0, 1 },
                StartLocation = new RouterPoint(0, 0, 0, 0),
                EndLocation   = new RouterPoint(1, 1, 0, ushort.MaxValue)
            };

            var shape = line.GetCoordinates(routerDb);

            Assert.IsNotNull(shape);
            Assert.AreEqual(2, shape.Count);
            var vertex0 = routerDb.Network.GetVertex(0);

            Assert.AreEqual(vertex0.Latitude, shape[0].Latitude);
            Assert.AreEqual(vertex0.Longitude, shape[0].Longitude);
            var vertex1 = routerDb.Network.GetVertex(1);

            Assert.AreEqual(vertex1.Latitude, shape[1].Latitude);
            Assert.AreEqual(vertex1.Longitude, shape[1].Longitude);

            line = new ReferencedLine()
            {
                Edges         = new long[] { 1 },
                Vertices      = new uint[] { Itinero.Constants.NO_VERTEX, 1 },
                StartLocation = new RouterPoint(0, 0, 0, (ushort)(ushort.MaxValue * 0.25)),
                EndLocation   = new RouterPoint(1, 1, 0, ushort.MaxValue)
            };

            shape = line.GetCoordinates(routerDb);
            Assert.IsNotNull(shape);
            Assert.AreEqual(2, shape.Count);
            var resolvedLocation = line.StartLocation.LocationOnNetwork(routerDb);

            Assert.AreEqual(resolvedLocation.Latitude, shape[0].Latitude);
            Assert.AreEqual(resolvedLocation.Longitude, shape[0].Longitude);
            Assert.AreEqual(vertex1.Latitude, shape[1].Latitude);
            Assert.AreEqual(vertex1.Longitude, shape[1].Longitude);

            line = new ReferencedLine()
            {
                Edges         = new long[] { 1 },
                Vertices      = new uint[] { Itinero.Constants.NO_VERTEX, 1 },
                StartLocation = new RouterPoint(0, 0, 0, 0),
                EndLocation   = new RouterPoint(1, 1, 0, (ushort)(ushort.MaxValue * 0.75))
            };

            shape = line.GetCoordinates(routerDb);
            Assert.IsNotNull(shape);
            Assert.AreEqual(2, shape.Count);
            Assert.AreEqual(vertex0.Latitude, shape[0].Latitude);
            Assert.AreEqual(vertex0.Longitude, shape[0].Longitude);
            resolvedLocation = line.EndLocation.LocationOnNetwork(routerDb);
            Assert.AreEqual(resolvedLocation.Latitude, shape[1].Latitude);
            Assert.AreEqual(resolvedLocation.Longitude, shape[1].Longitude);

            line = new ReferencedLine()
            {
                Edges         = new long[] { 1 },
                Vertices      = new uint[] { Itinero.Constants.NO_VERTEX, 1 },
                StartLocation = new RouterPoint(0, 0, 0, (ushort)(ushort.MaxValue * 0.25)),
                EndLocation   = new RouterPoint(1, 1, 0, (ushort)(ushort.MaxValue * 0.75))
            };

            shape = line.GetCoordinates(routerDb);
            Assert.IsNotNull(shape);
            Assert.AreEqual(2, shape.Count);
            resolvedLocation = line.StartLocation.LocationOnNetwork(routerDb);
            Assert.AreEqual(resolvedLocation.Latitude, shape[0].Latitude);
            Assert.AreEqual(resolvedLocation.Longitude, shape[0].Longitude);
            resolvedLocation = line.EndLocation.LocationOnNetwork(routerDb);
            Assert.AreEqual(resolvedLocation.Latitude, shape[1].Latitude);
            Assert.AreEqual(resolvedLocation.Longitude, shape[1].Longitude);
        }