Ejemplo n.º 1
0
        /// <summary>
        /// Converts this line location to features.
        /// </summary>
        public static FeatureCollection ToFeatures(this ReferencedPointAlongLine line, RouterDb routerDb)
        {
            var features = line.Route.ToFeatures(routerDb);

            features.Add(new Feature(new Point(new Coordinate(line.Longitude, line.Latitude)),
                                     new AttributesTable()));

            return(features);
        }
        public void EncodedReferencedPointAlongLineLocation()
        {
            // build a graph to encode from.
            var  tags            = new TagsTableCollectionIndex();
            var  graphDataSource = new DynamicGraphRouterDataSource <LiveEdge>(tags);
            uint vertex1         = graphDataSource.AddVertex(49.60597f, 6.12829f);
            uint vertex2         = graphDataSource.AddVertex(49.60521f, 6.12779f);

            graphDataSource.AddEdge(vertex1, vertex2, new LiveEdge()
            {
                Distance = 10,
                Forward  = true,
                Tags     = tags.Add(new TagsCollection(
                                        Tag.Create("BAANSUBSRT", "VBD"),
                                        Tag.Create("WEGBEHSRT", "R"),
                                        Tag.Create("WEGNUMMER", string.Empty),
                                        Tag.Create("RIJRICHTNG", "N")))
            }, null);
            graphDataSource.AddEdge(vertex2, vertex1, new LiveEdge()
            {
                Distance = 10,
                Forward  = false,
                Tags     = tags.Add(new TagsCollection(
                                        Tag.Create("BAANSUBSRT", "VBD"),
                                        Tag.Create("WEGBEHSRT", "R"),
                                        Tag.Create("WEGNUMMER", string.Empty),
                                        Tag.Create("RIJRICHTNG", "N"),
                                        Tag.Create("HECTOLTTR", string.Empty)))
            }, null);

            // create a referenced location and encode it.
            var graph = new BasicRouterDataSource <LiveEdge>(graphDataSource);
            var referencedPointAlongLineLocation = new ReferencedPointAlongLine();

            referencedPointAlongLineLocation.Route          = new ReferencedLine(graph);
            referencedPointAlongLineLocation.Route.Edges    = new LiveEdge[1];
            referencedPointAlongLineLocation.Route.Edges[0] = new LiveEdge()
            {
                Distance = 10,
                Forward  = true,
                Tags     = tags.Add(new TagsCollection(
                                        Tag.Create("BAANSUBSRT", "VBD"),
                                        Tag.Create("WEGBEHSRT", "R"),
                                        Tag.Create("WEGNUMMER", string.Empty),
                                        Tag.Create("RIJRICHTNG", "N"),
                                        Tag.Create("HECTOLTTR", string.Empty)))
            };
            referencedPointAlongLineLocation.Route.EdgeShapes    = new GeoCoordinateSimple[1][];
            referencedPointAlongLineLocation.Route.EdgeShapes[0] = new GeoCoordinateSimple[0];
            referencedPointAlongLineLocation.Route.Vertices      = new long[2];
            referencedPointAlongLineLocation.Route.Vertices[0]   = vertex1;
            referencedPointAlongLineLocation.Route.Vertices[1]   = vertex2;
            referencedPointAlongLineLocation.Latitude            = (49.60597f + 49.60521f) / 2f;
            referencedPointAlongLineLocation.Longitude           = (6.12829f + 6.12779f) / 2f;

            // encode location.
            var encoder           = new PointAlongLineEncoder();
            var mainEncoder       = new ReferencedNWBEncoder(graph, null);
            var referencedEncoder = new ReferencedPointAlongLineEncoder(mainEncoder, encoder);
            var location          = referencedEncoder.EncodeReferenced(referencedPointAlongLineLocation);

            // test result.
            Assert.IsNotNull(location);
            Assert.AreEqual(SideOfRoad.OnOrAbove, location.SideOfRoad);
            Assert.AreEqual(Orientation.NoOrientation, location.Orientation);
            Assert.AreEqual(50, location.PositiveOffsetPercentage.Value, 0.5f);

            Assert.AreEqual(49.60597f, location.First.Coordinate.Latitude);
            Assert.AreEqual(6.12829f, location.First.Coordinate.Longitude);
            Assert.AreEqual(91, location.First.DistanceToNext);
            Assert.AreEqual(FormOfWay.SlipRoad, location.First.FormOfWay);
            Assert.AreEqual(FunctionalRoadClass.Frc0, location.First.FuntionalRoadClass);
            Assert.AreEqual(FunctionalRoadClass.Frc0, location.First.LowestFunctionalRoadClassToNext);

            Assert.AreEqual(49.60521f, location.Last.Coordinate.Latitude);
            Assert.AreEqual(6.12779f, location.Last.Coordinate.Longitude);

            // TODO: encode location with a point on or at the first and last points.
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Builds a point along line location.
        /// </summary>
        public static ReferencedPointAlongLine BuildPointAlongLine(this Coder coder, float latitude, float longitude, out RouterPoint resolvedPoint)
        {
            var routerPoint = coder.Router.TryResolve(coder.Profile.Profile, latitude, longitude);

            if (routerPoint.IsError)
            {
                throw new Exception("Could not build point along line: Could not find an edge close to the given location.");
            }
            resolvedPoint = routerPoint.Value;
            var locationOnNetwork = resolvedPoint.LocationOnNetwork(coder.Router.Db);

            // get edge info.
            var edge = coder.Router.Db.Network.GetEdge(routerPoint.Value.EdgeId);

            // check direction.
            var forward = true;
            var factor  = coder.Profile.Profile.Factor(coder.Router.Db.EdgeProfiles.Get(edge.Data.Profile));

            if (factor.Direction == 2)
            {
                forward = false;
            }

            // build the location with one edge.
            ReferencedPointAlongLine referencedPointAlongLine = null;

            if (forward)
            {
                referencedPointAlongLine = new ReferencedPointAlongLine()
                {
                    Route = new ReferencedLine()
                    {
                        Edges         = new long[] { edge.IdDirected() },
                        Vertices      = new uint[] { edge.From, edge.To },
                        StartLocation = coder.Router.Db.CreateRouterPointForEdgeAndVertex(edge.IdDirected(), edge.From),
                        EndLocation   = coder.Router.Db.CreateRouterPointForEdgeAndVertex(edge.IdDirected(), edge.To)
                    },
                    Latitude    = locationOnNetwork.Latitude,
                    Longitude   = locationOnNetwork.Longitude,
                    Orientation = Orientation.NoOrientation
                };
            }
            else
            {
                referencedPointAlongLine = new ReferencedPointAlongLine()
                {
                    Route = new ReferencedLine()
                    {
                        Edges         = new long[] { -edge.IdDirected() },
                        Vertices      = new uint[] { edge.To, edge.From },
                        StartLocation = coder.Router.Db.CreateRouterPointForEdgeAndVertex(edge.IdDirected(), edge.To),
                        EndLocation   = coder.Router.Db.CreateRouterPointForEdgeAndVertex(edge.IdDirected(), edge.From)
                    },
                    Latitude    = locationOnNetwork.Latitude,
                    Longitude   = locationOnNetwork.Longitude,
                    Orientation = Orientation.NoOrientation
                };
            }

            // expand to valid location.
            referencedPointAlongLine.Route.AdjustToValidPoints(coder);
            referencedPointAlongLine.Route.StartLocation = coder.Router.Db.CreateRouterPointForEdgeAndVertex(
                referencedPointAlongLine.Route.Edges[0], referencedPointAlongLine.Route.Vertices[0]);
            referencedPointAlongLine.Route.EndLocation = coder.Router.Db.CreateRouterPointForEdgeAndVertex(
                referencedPointAlongLine.Route.Edges[referencedPointAlongLine.Route.Edges.Length - 1],
                referencedPointAlongLine.Route.Vertices[referencedPointAlongLine.Route.Vertices.Length - 1]);

            return(referencedPointAlongLine);
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Gets the edge closest to the location in the point along line.
 /// </summary>
 public static long GetLocationEdge(this ReferencedPointAlongLine pointAlongLine, RouterDb routerDb, out float offsetInMeter)
 {
     return(pointAlongLine.Route.ProjectOn(routerDb, pointAlongLine.Latitude, pointAlongLine.Longitude, out offsetInMeter));
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Gets the edge closest to the location in the point along line.
        /// </summary>
        public static long GetLocationEdge(this ReferencedPointAlongLine pointAlongLine, RouterDb routerDb)
        {
            var offsetInMeter = float.MaxValue;

            return(pointAlongLine.GetLocationEdge(routerDb, out offsetInMeter));
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Encodes a point along line location.
 /// </summary>
 /// <param name="pointAlongLineLocation"></param>
 /// <returns></returns>
 public virtual string Encode(ReferencedPointAlongLine pointAlongLineLocation)
 {
     return(this.GetReferencedPointAlongLineEncoder().Encode(pointAlongLineLocation));
 }
        /// <summary>
        /// Decodes the given location.
        /// </summary>
        public static ReferencedPointAlongLine Decode(PointAlongLineLocation location, Coder coder)
        {
            CandidateRoute best             = null;
            CombinedScore  bestCombinedEdge = null;

            // get candidate vertices and edges.
            var candidates           = new List <Itinero.Algorithms.Collections.SortedSet <CandidatePathSegment> >();
            var lrps                 = new List <LocationReferencePoint>();
            var fromBearingReference = location.First.Bearing;
            var toBearingReference   = location.Last.Bearing;

            // loop over all lrps.
            lrps.Add(location.First);
            var firstCandidates = coder.FindCandidatesFor(location.First, true);

            candidates.Add(firstCandidates);
            var lastCandidates = coder.FindCandidatesFor(location.Last, false);

            candidates.Add(lastCandidates);

            // build a list of combined scores.
            var combinedScoresSet = new Itinero.Algorithms.Collections.SortedSet <CombinedScore>(new CombinedScoreComparer());

            foreach (var previousCandidate in candidates[0])
            {
                foreach (var currentCandidate in candidates[1])
                {
                    if (previousCandidate.Location.EdgeId != currentCandidate.Location.EdgeId ||
                        previousCandidate.Location.Offset != currentCandidate.Location.Offset)
                    { // make sure vertices are different.
                        combinedScoresSet.Add(new CombinedScore()
                        {
                            Source = previousCandidate,
                            Target = currentCandidate
                        });
                    }
                }
            }

            // find the best candidate route.
            var combinedScores = new List <CombinedScore>(combinedScoresSet);

            while (combinedScores.Count > 0)
            {
                // get the first pair.
                var combinedScore = combinedScores.First();
                combinedScores.Remove(combinedScore);

                // find a route.
                var candidate = coder.FindCandidateRoute(combinedScore.Source, combinedScore.Target,
                                                         lrps[0].LowestFunctionalRoadClassToNext.Value);

                // bring score of from/to also into the mix.
                candidate.Score = candidate.Score + combinedScore.Score;

                // verify bearing by adding it to the score.
                if (candidate != null && candidate.Route != null)
                { // calculate bearing and compare with reference bearing.
                    // calculate distance and compare with distancetonext.
                    var distance         = candidate.Route.GetCoordinates(coder.Router.Db).Length();
                    var expectedDistance = location.First.DistanceToNext;

                    // default a perfect score, only compare large distances.
                    var deviation = Score.New(Score.DISTANCE_COMPARISON,
                                              "Compares expected location distance with decoded location distance (1=perfect, 0=difference bigger than total distance)", 1, 1);
                    if (expectedDistance > Parameters.DONT_CARE_DISTANCE || distance > Parameters.DONT_CARE_DISTANCE)
                    { // non-perfect score.
                        // don't care about difference smaller than Parameters.DONT_CARE_DISTANCE, the binary encoding only handles segments of about 50m.
                        var distanceDiff = System.Math.Max(System.Math.Abs(distance - expectedDistance) - Parameters.DONT_CARE_DISTANCE, 0);
                        deviation = Score.New(Score.DISTANCE_COMPARISON, "Compares expected location distance with decoded location distance (1=prefect, 0=difference bigger than total distance)",
                                              1 - System.Math.Min(System.Math.Max(distanceDiff / expectedDistance, 0), 1), 1);
                    }

                    // add deviation-score.
                    candidate.Score = candidate.Score * deviation;

                    if ((candidate.Score.Value / candidate.Score.Reference) > coder.Profile.ScoreThreshold)
                    { // ok, candidate is good enough.
                        // check candidate.
                        if (best == null)
                        { // there was no previous candidate.
                            best             = candidate;
                            bestCombinedEdge = combinedScore;
                        }
                        else if (best.Score.Value < candidate.Score.Value)
                        { // the new candidate is better.
                            best             = candidate;
                            bestCombinedEdge = combinedScore;
                        }
                        else if (best.Score.Value > candidate.Score.Value)
                        { // the current candidate is better.
                            break;
                        }
                    }
                }
            }

            // check if a location was found or not.
            if (best == null || best.Route == null)
            { // no location could be found.
                throw new ReferencedDecodingException(location, "No valid location was found.");
            }

            // calculate total score.
            var totalScore = bestCombinedEdge.Score + best.Score;

            // calculate the percentage value.
            var offsetRatio = 0.0f;

            if (location.PositiveOffsetPercentage.HasValue)
            { // there is a percentage set.
                offsetRatio = location.PositiveOffsetPercentage.Value / 100.0f;
            }

            // calculate the actual location and take into account the shape.
            int offsetEdgeIdx;

            Itinero.LocalGeo.Coordinate offsetLocation;
            float offsetLength;
            float offsetEdgeLength;
            float edgeLength;
            var   coordinates = best.Route.GetCoordinates(coder, offsetRatio,
                                                          out offsetEdgeIdx, out offsetLocation, out offsetLength, out offsetEdgeLength, out edgeLength);

            var longitudeReference = offsetLocation.Longitude;
            var latitudeReference  = offsetLocation.Latitude;

            // create the referenced location.
            var pointAlongLineLocation = new ReferencedPointAlongLine();

            pointAlongLineLocation.Score     = totalScore;
            pointAlongLineLocation.Route     = best.Route;
            pointAlongLineLocation.Latitude  = latitudeReference;
            pointAlongLineLocation.Longitude = longitudeReference;
            if (location.Orientation.HasValue)
            {
                pointAlongLineLocation.Orientation = location.Orientation.Value;
            }
            else
            {
                pointAlongLineLocation.Orientation = Orientation.NoOrientation;
            }

            // add the edge meta data.
            pointAlongLineLocation.EdgeMeta = new EdgeMeta()
            {
                Idx    = offsetEdgeIdx,
                Length = edgeLength,
                Offset = offsetEdgeLength
            };

            return(pointAlongLineLocation);
        }
        /// <summary>
        /// Encodes the given location.
        /// </summary>
        public static PointAlongLineLocation Encode(ReferencedPointAlongLine referencedLocation, Coder coder)
        {
            try
            {
                // Step – 1: Check validity of the location and offsets to be encoded.
                // validate connected and traversal.
                referencedLocation.Route.ValidateConnected(coder);
                // validate offsets.
                referencedLocation.Route.ValidateOffsets();
                // validate for binary.
                referencedLocation.Route.ValidateBinary();

                // Step – 2 Adjust start and end node of the location to represent valid map nodes.
                referencedLocation.Route.AdjustToValidPoints(coder);

                // keep a list of LR-point.
                var points = new List <int>(new int[] { 0, referencedLocation.Route.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.
                // 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.

                // WARNING: the OpenLR-spec says that there cannot be intermediate points on an PointAlongLineLocation.
                //              this means that if the route found here is > 15.000m it cannot be encoding.
                //              assumed is that the OpenLR-spec assumes that this will never happen (?)
                // referencedLocation.Route.AdjustToValidDistances(this.MainEncoder, points);

                // Step – 10    Create physical representation of the location reference.
                var coordinates   = referencedLocation.Route.GetCoordinates(coder.Router.Db);
                var lengthInMeter = coordinates.Length();

                var location = new PointAlongLineLocation();
                location.First = referencedLocation.Route.BuildLocationReferencePoint(
                    coder, 0, referencedLocation.Route.Vertices.Length - 1);
                location.Last = referencedLocation.Route.BuildLocationReferencePointLast(
                    coder, 0);

                // calculate orientation and side of road.
                float             projectedLatitude;
                float             projectedLongitude;
                float             projectedDistanceFromFirst;
                int               projectedShapeIndex;
                float             distanceToProjected;
                float             totalLength;
                LinePointPosition position;
                if (!coordinates.ProjectOn(referencedLocation.Latitude, referencedLocation.Longitude, out projectedLatitude, out projectedLongitude,
                                           out projectedDistanceFromFirst, out projectedShapeIndex, out distanceToProjected, out totalLength, out position))
                { // the projection on the edge failed.
                    // try to find the closest point.
                    distanceToProjected = float.MaxValue;
                    totalLength         = 0;
                    for (var i = 0; i < coordinates.Count; i++)
                    {
                        var distance = Itinero.LocalGeo.Coordinate.DistanceEstimateInMeter(coordinates[i].Latitude, coordinates[i].Longitude,
                                                                                           referencedLocation.Latitude, referencedLocation.Longitude);
                        if (i > 0)
                        {
                            totalLength += Itinero.LocalGeo.Coordinate.DistanceEstimateInMeter(coordinates[i - 1].Latitude, coordinates[i - 1].Longitude,
                                                                                               coordinates[i].Latitude, coordinates[i].Longitude);
                        }
                        if (distance < distanceToProjected)
                        {
                            projectedDistanceFromFirst = totalLength;
                            distanceToProjected        = distance;
                            projectedShapeIndex        = i;
                            position           = LinePointPosition.On;
                            projectedLatitude  = coordinates[i].Latitude;
                            projectedLongitude = coordinates[i].Longitude;
                        }
                    }
                }
                if (distanceToProjected > MaxDistanceFromProjected)
                {
                    throw new ReferencedEncodingException(referencedLocation, string.Format("The point in the ReferencedPointAlongLine is too far from the referenced edge: {0}m with a max allowed of {1}m.",
                                                                                            distanceToProjected, MaxDistanceFromProjected));
                }

                location.Orientation = referencedLocation.Orientation;
                switch (position)
                {
                case LinePointPosition.Left:
                    location.SideOfRoad = SideOfRoad.Left;
                    break;

                case LinePointPosition.On:
                    location.SideOfRoad = SideOfRoad.OnOrAbove;
                    break;

                case LinePointPosition.Right:
                    location.SideOfRoad = SideOfRoad.Right;
                    break;
                }

                // calculate offset.
                location.PositiveOffsetPercentage = (float)(projectedDistanceFromFirst / lengthInMeter) * 100.0f;
                if (location.PositiveOffsetPercentage >= 100)
                { // should be in the range of [0-100[.
                    // encoding should always work even if not 100% accurate in this case.
                    location.PositiveOffsetPercentage = 99;
                }

                return(location);
            }
            catch (ReferencedEncodingException)
            { // rethrow referenced encoding exception.
                throw;
            }
            catch (Exception ex)
            { // unhandled exception!
                throw new ReferencedEncodingException(referencedLocation,
                                                      string.Format("Unhandled exception during ReferencedPointAlongLineEncoder: {0}", ex.ToString()), ex);
            }
        }
Ejemplo n.º 9
0
 /// <summary>
 /// Converts the referenced point along the line location to features.
 /// </summary>
 public static float Length(this ReferencedPointAlongLine referencedPointALongLineLocation, RouterDb routerDb)
 {
     return(referencedPointALongLineLocation.Route.Length(routerDb));
 }
        public void EncodeReferencedPointAlongLineLocation()
        {
            // build a graph to encode from.
            var  tags            = new TagsTableCollectionIndex();
            var  graphDataSource = new DynamicGraphRouterDataSource <LiveEdge>(tags);
            uint vertex1         = graphDataSource.AddVertex(49.60597f, 6.12829f);
            uint vertex2         = graphDataSource.AddVertex(49.60521f, 6.12779f);

            graphDataSource.AddEdge(vertex1, vertex2, new LiveEdge()
            {
                Distance = 10,
                Forward  = true,
                Tags     = tags.Add(new TagsCollection(Tag.Create("highway", "tertiary")))
            }, null);
            graphDataSource.AddEdge(vertex2, vertex1, new LiveEdge()
            {
                Distance = 10,
                Forward  = false,
                Tags     = tags.Add(new TagsCollection(Tag.Create("highway", "tertiary")))
            }, null);

            // create a referenced location and encode it.
            var graph = new BasicRouterDataSource <LiveEdge>(graphDataSource);
            var referencedPointAlongLineLocation = new ReferencedPointAlongLine();

            referencedPointAlongLineLocation.Route          = new ReferencedLine(graph);
            referencedPointAlongLineLocation.Route.Edges    = new LiveEdge[1];
            referencedPointAlongLineLocation.Route.Edges[0] = new LiveEdge()
            {
                Distance = 10,
                Forward  = true,
                Tags     = tags.Add(new TagsCollection(Tag.Create("highway", "tertiary")))
            };
            referencedPointAlongLineLocation.Route.EdgeShapes    = new GeoCoordinateSimple[1][];
            referencedPointAlongLineLocation.Route.EdgeShapes[0] = new GeoCoordinateSimple[0];
            referencedPointAlongLineLocation.Route.Vertices      = new long[2];
            referencedPointAlongLineLocation.Route.Vertices[0]   = vertex1;
            referencedPointAlongLineLocation.Route.Vertices[1]   = vertex2;
            referencedPointAlongLineLocation.Latitude            = (49.60597f + 49.60521f) / 2f;
            referencedPointAlongLineLocation.Longitude           = (6.12829f + 6.12779f) / 2f;

            // encode location.
            var encoder           = new PointAlongLineEncoder();
            var router            = new Dykstra();
            var mainEncoder       = new ReferencedOsmEncoder(graph, null);
            var referencedEncoder = new ReferencedPointAlongLineEncoder(mainEncoder, encoder);
            var location          = referencedEncoder.EncodeReferenced(referencedPointAlongLineLocation);

            // test result.
            Assert.IsNotNull(location);
            Assert.AreEqual(SideOfRoad.OnOrAbove, location.SideOfRoad);
            Assert.AreEqual(Orientation.NoOrientation, location.Orientation);
            Assert.AreEqual(50, location.PositiveOffsetPercentage.Value, 0.5f);

            Assert.AreEqual(49.60597f, location.First.Coordinate.Latitude);
            Assert.AreEqual(6.12829f, location.First.Coordinate.Longitude);
            Assert.AreEqual(91, location.First.DistanceToNext);
            Assert.AreEqual(203, location.First.Bearing);
            Assert.AreEqual(FormOfWay.SingleCarriageWay, location.First.FormOfWay);
            Assert.AreEqual(FunctionalRoadClass.Frc3, location.First.FuntionalRoadClass);
            Assert.AreEqual(FunctionalRoadClass.Frc3, location.First.LowestFunctionalRoadClassToNext);

            Assert.AreEqual(49.60521f, location.Last.Coordinate.Latitude);
            Assert.AreEqual(6.12779f, location.Last.Coordinate.Longitude);
            Assert.AreEqual(23, location.Last.Bearing);

            // encode location with a point on the first point.
            referencedPointAlongLineLocation                = new ReferencedPointAlongLine();
            referencedPointAlongLineLocation.Route          = new ReferencedLine(graph);
            referencedPointAlongLineLocation.Route.Edges    = new LiveEdge[1];
            referencedPointAlongLineLocation.Route.Edges[0] = new LiveEdge()
            {
                Distance = 10,
                Forward  = true,
                Tags     = tags.Add(new TagsCollection(Tag.Create("highway", "tertiary")))
            };
            referencedPointAlongLineLocation.Route.EdgeShapes    = new GeoCoordinateSimple[1][];
            referencedPointAlongLineLocation.Route.EdgeShapes[0] = new GeoCoordinateSimple[0];
            referencedPointAlongLineLocation.Route.Vertices      = new long[2];
            referencedPointAlongLineLocation.Route.Vertices[0]   = vertex1;
            referencedPointAlongLineLocation.Route.Vertices[1]   = vertex2;
            referencedPointAlongLineLocation.Latitude            = 49.60597f;
            referencedPointAlongLineLocation.Longitude           = 6.12829f;

            // encode location.
            location = referencedEncoder.EncodeReferenced(referencedPointAlongLineLocation);

            // test result.
            Assert.IsNotNull(location);
            Assert.AreEqual(SideOfRoad.OnOrAbove, location.SideOfRoad);
            Assert.AreEqual(Orientation.NoOrientation, location.Orientation);
            Assert.AreEqual(0, location.PositiveOffsetPercentage);

            Assert.AreEqual(49.60597f, location.First.Coordinate.Latitude);
            Assert.AreEqual(6.12829f, location.First.Coordinate.Longitude);
            Assert.AreEqual(91, location.First.DistanceToNext);
            Assert.AreEqual(FormOfWay.SingleCarriageWay, location.First.FormOfWay);
            Assert.AreEqual(FunctionalRoadClass.Frc3, location.First.FuntionalRoadClass);
            Assert.AreEqual(FunctionalRoadClass.Frc3, location.First.LowestFunctionalRoadClassToNext);

            Assert.AreEqual(49.60521f, location.Last.Coordinate.Latitude);
            Assert.AreEqual(6.12779f, location.Last.Coordinate.Longitude);

            // encode location with a point on the last point.
            referencedPointAlongLineLocation                = new ReferencedPointAlongLine();
            referencedPointAlongLineLocation.Route          = new ReferencedLine(graph);
            referencedPointAlongLineLocation.Route.Edges    = new LiveEdge[1];
            referencedPointAlongLineLocation.Route.Edges[0] = new LiveEdge()
            {
                Distance = 10,
                Forward  = true,
                Tags     = tags.Add(new TagsCollection(Tag.Create("highway", "tertiary")))
            };
            referencedPointAlongLineLocation.Route.EdgeShapes    = new GeoCoordinateSimple[1][];
            referencedPointAlongLineLocation.Route.EdgeShapes[0] = new GeoCoordinateSimple[0];
            referencedPointAlongLineLocation.Route.Vertices      = new long[2];
            referencedPointAlongLineLocation.Route.Vertices[0]   = vertex1;
            referencedPointAlongLineLocation.Route.Vertices[1]   = vertex2;
            referencedPointAlongLineLocation.Latitude            = 49.60521f;
            referencedPointAlongLineLocation.Longitude           = 6.12779f;

            // encode location.
            location = referencedEncoder.EncodeReferenced(referencedPointAlongLineLocation);

            // test result.
            Assert.IsNotNull(location);
            Assert.AreEqual(SideOfRoad.OnOrAbove, location.SideOfRoad);
            Assert.AreEqual(Orientation.NoOrientation, location.Orientation);
            Assert.AreEqual(99, location.PositiveOffsetPercentage.Value);

            Assert.AreEqual(49.60597f, location.First.Coordinate.Latitude);
            Assert.AreEqual(6.12829f, location.First.Coordinate.Longitude);
            Assert.AreEqual(91, location.First.DistanceToNext);
            Assert.AreEqual(FormOfWay.SingleCarriageWay, location.First.FormOfWay);
            Assert.AreEqual(FunctionalRoadClass.Frc3, location.First.FuntionalRoadClass);
            Assert.AreEqual(FunctionalRoadClass.Frc3, location.First.LowestFunctionalRoadClassToNext);

            Assert.AreEqual(49.60521f, location.Last.Coordinate.Latitude);
            Assert.AreEqual(6.12779f, location.Last.Coordinate.Longitude);
        }