Exemple #1
0
        /// <summary>
        /// Encodes a point along line location.
        /// </summary>
        public static byte[] Encode(PointAlongLineLocation location)
        {
            var data = new byte[17];

            var header = new Header();

            header.Version       = 3;
            header.HasAttributes = true;
            header.ArF0          = false;
            header.IsPoint       = true;
            header.ArF1          = false;
            HeaderConvertor.Encode(data, 0, header);
            CoordinateConverter.Encode(location.First.Coordinate, data, 1);
            FunctionalRoadClassConvertor.Encode(location.First.FuntionalRoadClass.Value, data, 7, 2);
            FormOfWayConvertor.Encode(location.First.FormOfWay.Value, data, 7, 5);
            FunctionalRoadClassConvertor.Encode(location.First.LowestFunctionalRoadClassToNext.Value, data, 8, 0);
            BearingConvertor.Encode(BearingConvertor.EncodeAngleToBearing(location.First.Bearing.Value), data, 8, 3);
            data[9] = DistanceToNextConvertor.Encode(location.First.DistanceToNext);

            CoordinateConverter.EncodeRelative(location.First.Coordinate, location.Last.Coordinate, data, 10);
            FunctionalRoadClassConvertor.Encode(location.Last.FuntionalRoadClass.Value, data, 14, 2);
            FormOfWayConvertor.Encode(location.Last.FormOfWay.Value, data, 14, 5);
            BearingConvertor.Encode(BearingConvertor.EncodeAngleToBearing(location.Last.Bearing.Value), data, 15, 3);

            OrientationConverter.Encode(location.Orientation.Value, data, 7, 0);
            SideOfRoadConverter.Encode(location.SideOfRoad.Value, data, 14, 0);
            if (location.PositiveOffsetPercentage.HasValue)
            { // positive offset percentage is present.
                OffsetConvertor.Encode(location.PositiveOffsetPercentage.Value, data, 16);
            }

            return(data);
        }
Exemple #2
0
        /// <summary>
        /// Decodes the given data into a location reference.
        /// </summary>
        public static PointAlongLineLocation Decode(byte[] data)
        {
            var pointAlongLine = new PointAlongLineLocation();

            // decode first location reference point.
            var first = new LocationReferencePoint();

            first.Coordinate         = CoordinateConverter.Decode(data, 1);
            first.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, 7, 2);
            first.FormOfWay          = FormOfWayConvertor.Decode(data, 7, 5);
            first.LowestFunctionalRoadClassToNext = FunctionalRoadClassConvertor.Decode(data, 8, 0);
            first.Bearing        = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, 8, 3));
            first.DistanceToNext = DistanceToNextConvertor.Decode(data[9]);

            // decode second location reference point.
            var last = new LocationReferencePoint();

            last.Coordinate         = CoordinateConverter.DecodeRelative(first.Coordinate, data, 10);
            last.FuntionalRoadClass = FunctionalRoadClassConvertor.Decode(data, 14, 2);
            last.FormOfWay          = FormOfWayConvertor.Decode(data, 14, 5);
            last.Bearing            = BearingConvertor.DecodeAngleFromBearing(BearingConvertor.Decode(data, 15, 3));

            pointAlongLine.First       = first;
            pointAlongLine.Orientation = OrientationConverter.Decode(data, 7, 0);
            pointAlongLine.SideOfRoad  = SideOfRoadConverter.Decode(data, 14, 0);
            pointAlongLine.PositiveOffsetPercentage = OffsetConvertor.Decode(data, 16);
            pointAlongLine.Last = last;

            return(pointAlongLine);
        }
        public void EncodeBase64Test()
        {
            double delta = 0.0001;

            // create a location.
            var location = new PointAlongLineLocation();

            location.First            = new LocationReferencePoint();
            location.First.Coordinate = new Coordinate()
            {
                Latitude  = 49.60597,
                Longitude = 6.12829
            };
            location.First.FuntionalRoadClass = FunctionalRoadClass.Frc2;
            location.First.FormOfWay          = FormOfWay.MultipleCarriageWay;
            location.First.LowestFunctionalRoadClassToNext = FunctionalRoadClass.Frc2;
            location.First.Bearing        = 17;
            location.First.DistanceToNext = (int)(58.6 * 2) + 1;

            location.Last            = new LocationReferencePoint();
            location.Last.Coordinate = new Coordinate()
            {
                Latitude  = 49.60521,
                Longitude = 6.12779
            };
            location.Last.FuntionalRoadClass = FunctionalRoadClass.Frc2;
            location.Last.FormOfWay          = FormOfWay.MultipleCarriageWay;
            location.Last.Bearing            = 3;
            location.Last.DistanceToNext     = 0;

            location.Orientation = Orientation.NoOrientation;
            location.SideOfRoad  = SideOfRoad.Left;
            location.PositiveOffsetPercentage = 30.19f;

            // encode.
            var encoder    = new PointAlongLineEncoder();
            var stringData = encoder.Encode(location);

            // decode again (decoding was tested above).
            var decoder         = new PointAlongLineDecoder();
            var decodedLocation = decoder.Decode(stringData);

            Assert.IsNotNull(decodedLocation);
            Assert.IsInstanceOf <PointAlongLineLocation>(decodedLocation);
            var pointAlongLineLocation = (decodedLocation as PointAlongLineLocation);

            // check first reference.
            Assert.IsNotNull(pointAlongLineLocation.First);
            Assert.AreEqual(location.First.Coordinate.Longitude, pointAlongLineLocation.First.Coordinate.Longitude, delta); // 6.12829°
            Assert.AreEqual(location.First.Coordinate.Latitude, pointAlongLineLocation.First.Coordinate.Latitude, delta);   // 49.60597°
            Assert.AreEqual(location.First.FuntionalRoadClass, pointAlongLineLocation.First.FuntionalRoadClass);
            Assert.AreEqual(location.First.FormOfWay, pointAlongLineLocation.First.FormOfWay);
            Assert.AreEqual(location.First.LowestFunctionalRoadClassToNext, pointAlongLineLocation.First.LowestFunctionalRoadClassToNext);
            Assert.AreEqual(location.First.Bearing.Value, pointAlongLineLocation.First.Bearing.Value, 11.25); // binary encode loses accuracy for bearing.
            Assert.AreEqual(location.First.DistanceToNext, pointAlongLineLocation.First.DistanceToNext);

            // check second reference.
            Assert.IsNotNull(pointAlongLineLocation.Last);
            Assert.AreEqual(location.Last.Coordinate.Longitude, pointAlongLineLocation.Last.Coordinate.Longitude, delta); // 6.12779°
            Assert.AreEqual(location.Last.Coordinate.Latitude, pointAlongLineLocation.Last.Coordinate.Latitude, delta);   // 49.60521°
            Assert.AreEqual(location.Last.FuntionalRoadClass, pointAlongLineLocation.Last.FuntionalRoadClass);
            Assert.AreEqual(location.Last.FormOfWay, pointAlongLineLocation.Last.FormOfWay);
            Assert.AreEqual(location.Last.Bearing.Value, pointAlongLineLocation.Last.Bearing.Value, 11.25); // binary encode loses accuracy for bearing.
            Assert.AreEqual(location.Last.DistanceToNext, pointAlongLineLocation.Last.DistanceToNext);

            // check other properties.
            Assert.AreEqual(location.Orientation, pointAlongLineLocation.Orientation);
            Assert.AreEqual(location.SideOfRoad, pointAlongLineLocation.SideOfRoad);
            Assert.AreEqual(location.PositiveOffsetPercentage.Value, pointAlongLineLocation.PositiveOffsetPercentage.Value, 0.5f); // binary encode loses accuracy.

            // compare again with reference encoded string.
            var referenceStringData      = "KwRbnyNGfhJBAv/P/7WSAEw=";
            var referenceDecodedLocation = decoder.Decode(referenceStringData);

            var referenceBinary = System.Convert.FromBase64String(referenceStringData);
            var encodedBinary   = System.Convert.FromBase64String(stringData);

            // check first reference.
            Assert.IsNotNull(pointAlongLineLocation.First);
            Assert.AreEqual(referenceDecodedLocation.First.Coordinate.Longitude, pointAlongLineLocation.First.Coordinate.Longitude, delta); // 6.12829°
            Assert.AreEqual(referenceDecodedLocation.First.Coordinate.Latitude, pointAlongLineLocation.First.Coordinate.Latitude, delta);   // 49.60597°
            Assert.AreEqual(referenceDecodedLocation.First.FuntionalRoadClass, pointAlongLineLocation.First.FuntionalRoadClass);
            Assert.AreEqual(referenceDecodedLocation.First.FormOfWay, pointAlongLineLocation.First.FormOfWay);
            Assert.AreEqual(referenceDecodedLocation.First.LowestFunctionalRoadClassToNext, pointAlongLineLocation.First.LowestFunctionalRoadClassToNext);
            Assert.AreEqual(referenceDecodedLocation.First.Bearing.Value, pointAlongLineLocation.First.Bearing.Value, 11.25); // binary encode loses accuracy for bearing.

            // check second reference.
            Assert.IsNotNull(pointAlongLineLocation.Last);
            Assert.AreEqual(referenceDecodedLocation.Last.Coordinate.Longitude, pointAlongLineLocation.Last.Coordinate.Longitude, delta); // 6.12779°
            Assert.AreEqual(referenceDecodedLocation.Last.Coordinate.Latitude, pointAlongLineLocation.Last.Coordinate.Latitude, delta);   // 49.60521°
            Assert.AreEqual(referenceDecodedLocation.Last.FuntionalRoadClass, pointAlongLineLocation.Last.FuntionalRoadClass);
            Assert.AreEqual(referenceDecodedLocation.Last.FormOfWay, pointAlongLineLocation.Last.FormOfWay);
            Assert.AreEqual(referenceDecodedLocation.Last.Bearing.Value, pointAlongLineLocation.Last.Bearing.Value, 11.25); // binary encode loses accuracy for bearing.

            // check other properties.
            Assert.AreEqual(referenceDecodedLocation.Orientation, pointAlongLineLocation.Orientation);
            Assert.AreEqual(referenceDecodedLocation.SideOfRoad, pointAlongLineLocation.SideOfRoad);
            Assert.AreEqual(referenceDecodedLocation.PositiveOffsetPercentage.Value, pointAlongLineLocation.PositiveOffsetPercentage.Value, 0.5f); // binary encode loses accuracy.
        }
Exemple #4
0
        public void DecodeReferencedPointAlongLineLocation()
        {
            double delta = 0.0001;

            // build the location to decode.
            var location = new PointAlongLineLocation();

            location.First            = new LocationReferencePoint();
            location.First.Coordinate = new Coordinate()
            {
                Latitude = 49.60597, Longitude = 6.12829
            };
            location.First.DistanceToNext     = 92;
            location.First.FuntionalRoadClass = FunctionalRoadClass.Frc2;
            location.First.FormOfWay          = FormOfWay.MultipleCarriageWay;
            location.First.LowestFunctionalRoadClassToNext = FunctionalRoadClass.Frc2;
            location.First.Bearing   = 203;
            location.Last            = new LocationReferencePoint();
            location.Last.Coordinate = new Coordinate()
            {
                Latitude = 49.60521, Longitude = 6.12779
            };
            location.Last.DistanceToNext      = 10;
            location.Last.FuntionalRoadClass  = FunctionalRoadClass.Frc2;
            location.Last.FormOfWay           = FormOfWay.MultipleCarriageWay;
            location.Last.Bearing             = 23;
            location.PositiveOffsetPercentage = (float)((28.0 / 92.0) * 100.0);
            location.Orientation = Orientation.FirstToSecond;
            location.SideOfRoad  = SideOfRoad.Left;

            // build a graph to decode onto.
            var tags            = new TagsTableCollectionIndex();
            var graphDataSource = new DynamicGraphRouterDataSource <LiveEdge>(tags);
            var vertex1         = graphDataSource.AddVertex(49.60597f, 6.12829f);
            var 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  = true,
                Tags     = tags.Add(new TagsCollection(Tag.Create("highway", "tertiary")))
            }, null);

            // decode the location
            var graph              = new BasicRouterDataSource <LiveEdge>(graphDataSource);
            var decoder            = new PointAlongLineDecoder();
            var router             = new BasicRouter();
            var mainDecoder        = new ReferencedOsmDecoder(graph, new BinaryDecoder());
            var referencedDecoder  = new ReferencedPointAlongLineDecoder(mainDecoder, decoder);
            var referencedLocation = referencedDecoder.Decode(location);

            // confirm result.
            Assert.IsNotNull(referencedLocation);
            Assert.IsNotNull(referencedLocation.Route);
            Assert.IsNotNull(referencedLocation.Route.Edges);
            Assert.AreEqual(vertex1, referencedLocation.Route.Vertices[0]);
            Assert.AreEqual(vertex2, referencedLocation.Route.Vertices[1]);
            var longitudeReference = (location.Last.Coordinate.Longitude - location.First.Coordinate.Longitude) * (location.PositiveOffsetPercentage.Value / 100.0) + location.First.Coordinate.Longitude;
            var latitudeReference  = (location.Last.Coordinate.Latitude - location.First.Coordinate.Latitude) * (location.PositiveOffsetPercentage.Value / 100.0) + location.First.Coordinate.Latitude;

            Assert.AreEqual(longitudeReference, referencedLocation.Longitude, delta);
            Assert.AreEqual(latitudeReference, referencedLocation.Latitude, delta);
            Assert.AreEqual(Orientation.FirstToSecond, referencedLocation.Orientation);
        }
        /// <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);
            }
        }