Пример #1
0
        /// <summary>
        /// Project on route and return the next entry index and coordinate.
        /// </summary>
        /// <param name="route"></param>
        /// <param name="coordinates"></param>
        /// <returns></returns>
        private KeyValuePair <int, GeoCoordinate> ProjectOn(Route route, GeoCoordinate coordinates)
        {
            double               distance   = double.MaxValue;
            GeoCoordinate        closest    = null;
            int                  closestIdx = -1;
            List <GeoCoordinate> points     = route.GetPoints();

            for (int idx = 0; idx < points.Count - 1; idx++)
            {
                GeoCoordinateLine line           = new GeoCoordinateLine(points[idx], points[idx + 1], true, true);
                PointF2D          projectedPoint = line.ProjectOn(coordinates);
                GeoCoordinate     projected;
                double            currentDistance;
                if (projectedPoint != null)
                {
                    projected       = new GeoCoordinate(projectedPoint[1], projectedPoint[0]);
                    currentDistance = coordinates.Distance(projected);
                    if (currentDistance < distance)
                    {
                        closest    = projected;
                        closestIdx = idx + 1;
                        distance   = currentDistance;
                    }
                }
                projected       = points[idx];
                currentDistance = coordinates.Distance(projected);
                if (currentDistance < distance)
                {
                    closest    = projected;
                    closestIdx = idx;
                    distance   = currentDistance;
                }
            }
            return(new KeyValuePair <int, GeoCoordinate>(closestIdx, closest));
        }
Пример #2
0
        /// <summary>
        /// Calculates the direction.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static DirectionEnum Calculate(GeoCoordinate from, GeoCoordinate to)
        {
            double offset = 0.01;

            // calculate the angle with the horizontal and vertical axes.
            GeoCoordinate horizonal_from = new GeoCoordinate(from.Latitude, from.Longitude + offset);
            GeoCoordinate vertical_from = new GeoCoordinate(from.Latitude + offset, from.Longitude);

            // create line.
            GeoCoordinateLine line = new GeoCoordinateLine(from, to);
            GeoCoordinateLine vertical_line = new GeoCoordinateLine(from,vertical_from);
            GeoCoordinateLine horizontal_line= new GeoCoordinateLine(from,horizonal_from);

            // calculate angle.
            Degree horizontal_angle = line.Direction.Angle(horizontal_line.Direction);
            Degree vertical_angle = line.Direction.Angle(vertical_line.Direction);

            if (vertical_angle < new Degree(22.5)
                || vertical_angle >= new Degree(360- 22.5))
            { // north
                return DirectionEnum.North;
            }
            else if (vertical_angle >= new Degree(22.5)
                 && vertical_angle < new Degree(90 - 22.5))
            { // north-east.
                return DirectionEnum.NorthEast;
            }
            else if (vertical_angle >= new Degree(90 - 22.5)
                 && vertical_angle < new Degree(90 + 22.5))
            { // east.
                return DirectionEnum.East;
            }
            else if (vertical_angle >= new Degree(90 + 22.5)
                 && vertical_angle < new Degree(180 - 22.5))
            { // south-east.
                return DirectionEnum.SouthEast;
            }
            else if (vertical_angle >= new Degree(180 - 22.5)
                 && vertical_angle < new Degree(180 + 22.5))
            { // south
                return DirectionEnum.South;
            }
            else if (vertical_angle >= new Degree(180 + 22.5)
                 && vertical_angle < new Degree(270 - 22.5))
            { // south-west.
                return DirectionEnum.SouthWest;
            }
            else if (vertical_angle >= new Degree(270 - 22.5)
                 && vertical_angle < new Degree(270 + 22.5))
            { // south-west.
                return DirectionEnum.West;
            }
            else if (vertical_angle >= new Degree(270 + 22.5)
                 && vertical_angle < new Degree(360-22.5))
            { // south-west.
                return DirectionEnum.NorhtWest;
            }
            throw new ArgumentOutOfRangeException();
        }
Пример #3
0
        /// <summary>
        /// Calculates the direction.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static DirectionEnum Calculate(GeoCoordinate from, GeoCoordinate to)
        {
            double offset = 0.01;

            // calculate the angle with the horizontal and vertical axes.
            //GeoCoordinate horizonal_from = new GeoCoordinate(from.Latitude, from.Longitude + offset);
            GeoCoordinate vertical_from = new GeoCoordinate(from.Latitude + offset, from.Longitude);

            // create line.
            GeoCoordinateLine line          = new GeoCoordinateLine(from, to);
            GeoCoordinateLine vertical_line = new GeoCoordinateLine(from, vertical_from);
            //GeoCoordinateLine horizontal_line= new GeoCoordinateLine(from,horizonal_from);

            // calculate angle.
            //Degree horizontal_angle = line.Direction.Angle(horizontal_line.Direction);
            Degree vertical_angle = line.Direction.Angle(vertical_line.Direction);

            if (vertical_angle < new Degree(22.5) ||
                vertical_angle >= new Degree(360 - 22.5))
            { // north
                return(DirectionEnum.North);
            }
            else if (vertical_angle >= new Degree(22.5) &&
                     vertical_angle < new Degree(90 - 22.5))
            { // north-east.
                return(DirectionEnum.NorthEast);
            }
            else if (vertical_angle >= new Degree(90 - 22.5) &&
                     vertical_angle < new Degree(90 + 22.5))
            { // east.
                return(DirectionEnum.East);
            }
            else if (vertical_angle >= new Degree(90 + 22.5) &&
                     vertical_angle < new Degree(180 - 22.5))
            { // south-east.
                return(DirectionEnum.SouthEast);
            }
            else if (vertical_angle >= new Degree(180 - 22.5) &&
                     vertical_angle < new Degree(180 + 22.5))
            { // south
                return(DirectionEnum.South);
            }
            else if (vertical_angle >= new Degree(180 + 22.5) &&
                     vertical_angle < new Degree(270 - 22.5))
            { // south-west.
                return(DirectionEnum.SouthWest);
            }
            else if (vertical_angle >= new Degree(270 - 22.5) &&
                     vertical_angle < new Degree(270 + 22.5))
            { // south-west.
                return(DirectionEnum.West);
            }
            else if (vertical_angle >= new Degree(270 + 22.5) &&
                     vertical_angle < new Degree(360 - 22.5))
            { // south-west.
                return(DirectionEnum.NorhtWest);
            }
            throw new ArgumentOutOfRangeException();
        }
        /// <summary>
        /// Calculates the relative direction.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="along"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static RelativeDirection Calculate(GeoCoordinate from, GeoCoordinate along, GeoCoordinate to)
        {
            RelativeDirection direction = new RelativeDirection();

            double margin = 65;
            double straight_on = 10;
            double turn_back = 5;

            GeoCoordinateLine line_from = new GeoCoordinateLine(from, along);
            GeoCoordinateLine line_to = new GeoCoordinateLine(along, to);

            Degree angle = line_from.Direction.Angle(line_to.Direction);

            if (angle >= new Degree(360 - straight_on)
                || angle < new Degree(straight_on))
            {
                direction.Direction = RelativeDirectionEnum.StraightOn;
            }
            else if (angle >= new Degree(straight_on)
                && angle < new Degree(90 - margin))
            {
                direction.Direction = RelativeDirectionEnum.SlightlyLeft;
            }
            else if (angle >= new Degree(90 - margin)
                && angle < new Degree(90 + margin))
            {
                direction.Direction = RelativeDirectionEnum.Left;
            }
            else if (angle >= new Degree(90 + margin)
                && angle < new Degree(180 - turn_back))
            {
                direction.Direction = RelativeDirectionEnum.SharpLeft;
            }
            else if (angle >= new Degree(180 - turn_back)
                && angle < new Degree(180 + turn_back))
            {
                direction.Direction = RelativeDirectionEnum.TurnBack;
            }
            else if (angle >= new Degree(180 + turn_back)
                && angle < new Degree(270-margin))
            {
                direction.Direction = RelativeDirectionEnum.SharpRight;
            }
            else if (angle >= new Degree(270 - margin)
                && angle < new Degree(270 + margin))
            {
                direction.Direction = RelativeDirectionEnum.Right;
            }
            else if (angle >= new Degree(270 + margin)
                && angle < new Degree(360- straight_on))
            {
                direction.Direction = RelativeDirectionEnum.SlightlyRight;
            }
            //direction.Direction = RelativeDirectionEnum.StraightOn;
            direction.Angle = angle;

            return direction;
        }
Пример #5
0
        /// <summary>
        /// Calculates the relative direction.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="along"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static RelativeDirection Calculate(GeoCoordinate from, GeoCoordinate along, GeoCoordinate to)
        {
            RelativeDirection direction = new RelativeDirection();

            double margin      = 65;
            double straight_on = 10;
            double turn_back   = 5;

            GeoCoordinateLine line_from = new GeoCoordinateLine(from, along);
            GeoCoordinateLine line_to   = new GeoCoordinateLine(along, to);

            Degree angle = line_from.Direction.Angle(line_to.Direction);

            if (angle >= new Degree(360 - straight_on) ||
                angle < new Degree(straight_on))
            {
                direction.Direction = RelativeDirectionEnum.StraightOn;
            }
            else if (angle >= new Degree(straight_on) &&
                     angle < new Degree(90 - margin))
            {
                direction.Direction = RelativeDirectionEnum.SlightlyLeft;
            }
            else if (angle >= new Degree(90 - margin) &&
                     angle < new Degree(90 + margin))
            {
                direction.Direction = RelativeDirectionEnum.Left;
            }
            else if (angle >= new Degree(90 + margin) &&
                     angle < new Degree(180 - turn_back))
            {
                direction.Direction = RelativeDirectionEnum.SharpLeft;
            }
            else if (angle >= new Degree(180 - turn_back) &&
                     angle < new Degree(180 + turn_back))
            {
                direction.Direction = RelativeDirectionEnum.TurnBack;
            }
            else if (angle >= new Degree(180 + turn_back) &&
                     angle < new Degree(270 - margin))
            {
                direction.Direction = RelativeDirectionEnum.SharpRight;
            }
            else if (angle >= new Degree(270 - margin) &&
                     angle < new Degree(270 + margin))
            {
                direction.Direction = RelativeDirectionEnum.Right;
            }
            else if (angle >= new Degree(270 + margin) &&
                     angle < new Degree(360 - straight_on))
            {
                direction.Direction = RelativeDirectionEnum.SlightlyRight;
            }
            //direction.Direction = RelativeDirectionEnum.StraightOn;
            direction.Angle = angle;

            return(direction);
        }
        /// <summary>
        /// Calculates the relative direction.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="along"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static RelativeDirection Calculate(GeoCoordinate from, GeoCoordinate along, GeoCoordinate to)
        {
            var direction = new RelativeDirection();

            var margin      = 65.0;
            var straight_on = 10.0;
            var turn_back   = 5.0;

            var lineFrom = new GeoCoordinateLine(from, along);
            var lineTo   = new GeoCoordinateLine(along, to);

            var angle = lineFrom.Direction.Angle(lineTo.Direction);

            if (angle >= new Degree(360 - straight_on) ||
                angle < new Degree(straight_on))
            {
                direction.Direction = RelativeDirectionEnum.StraightOn;
            }
            else if (angle >= new Degree(straight_on) &&
                     angle < new Degree(90 - margin))
            {
                direction.Direction = RelativeDirectionEnum.SlightlyLeft;
            }
            else if (angle >= new Degree(90 - margin) &&
                     angle < new Degree(90 + margin))
            {
                direction.Direction = RelativeDirectionEnum.Left;
            }
            else if (angle >= new Degree(90 + margin) &&
                     angle < new Degree(180 - turn_back))
            {
                direction.Direction = RelativeDirectionEnum.SharpLeft;
            }
            else if (angle >= new Degree(180 - turn_back) &&
                     angle < new Degree(180 + turn_back))
            {
                direction.Direction = RelativeDirectionEnum.TurnBack;
            }
            else if (angle >= new Degree(180 + turn_back) &&
                     angle < new Degree(270 - margin))
            {
                direction.Direction = RelativeDirectionEnum.SharpRight;
            }
            else if (angle >= new Degree(270 - margin) &&
                     angle < new Degree(270 + margin))
            {
                direction.Direction = RelativeDirectionEnum.Right;
            }
            else if (angle >= new Degree(270 + margin) &&
                     angle < new Degree(360 - straight_on))
            {
                direction.Direction = RelativeDirectionEnum.SlightlyRight;
            }
            direction.Angle = angle;

            return(direction);
        }
        /// <summary>
        /// Calculates the relative direction.
        /// </summary>
        /// <param name="from"></param>
        /// <param name="along"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public static RelativeDirection Calculate(GeoCoordinate from, GeoCoordinate along, GeoCoordinate to)
        {
            var direction = new RelativeDirection();

            var margin = 65.0;
            var straight_on = 10.0;
            var turn_back = 5.0;

            var lineFrom = new GeoCoordinateLine(from, along);
            var lineTo = new GeoCoordinateLine(along, to);

            var angle = lineFrom.Direction.Angle(lineTo.Direction);

            if (angle >= new Degree(360 - straight_on)
                || angle < new Degree(straight_on))
            {
                direction.Direction = RelativeDirectionEnum.StraightOn;
            }
            else if (angle >= new Degree(straight_on)
                && angle < new Degree(90 - margin))
            {
                direction.Direction = RelativeDirectionEnum.SlightlyLeft;
            }
            else if (angle >= new Degree(90 - margin)
                && angle < new Degree(90 + margin))
            {
                direction.Direction = RelativeDirectionEnum.Left;
            }
            else if (angle >= new Degree(90 + margin)
                && angle < new Degree(180 - turn_back))
            {
                direction.Direction = RelativeDirectionEnum.SharpLeft;
            }
            else if (angle >= new Degree(180 - turn_back)
                && angle < new Degree(180 + turn_back))
            {
                direction.Direction = RelativeDirectionEnum.TurnBack;
            }
            else if (angle >= new Degree(180 + turn_back)
                && angle < new Degree(270-margin))
            {
                direction.Direction = RelativeDirectionEnum.SharpRight;
            }
            else if (angle >= new Degree(270 - margin)
                && angle < new Degree(270 + margin))
            {
                direction.Direction = RelativeDirectionEnum.Right;
            }
            else if (angle >= new Degree(270 + margin)
                && angle < new Degree(360- straight_on))
            {
                direction.Direction = RelativeDirectionEnum.SlightlyRight;
            }
            direction.Angle = angle;

            return direction;
        }
Пример #8
0
        public static bool ProjectOn(this Route route, GeoCoordinate coordinates, out GeoCoordinate projectedCoordinates, out int entryIndex, out Meter distanceFromStart, out Second timeFromStart)
        {
            double num1 = double.MaxValue;

            distanceFromStart = (Meter)0.0;
            timeFromStart     = (Second)0.0;
            double num2 = 0.0;

            projectedCoordinates = (GeoCoordinate)null;
            entryIndex           = -1;
            List <GeoCoordinate> points = route.GetPoints();

            for (int index = 0; index < points.Count - 1; ++index)
            {
                PointF2D pointF2D = new GeoCoordinateLine(points[index], points[index + 1], true, true).ProjectOn((PointF2D)coordinates);
                if (pointF2D != (PointF2D)null)
                {
                    GeoCoordinate point = new GeoCoordinate(pointF2D[1], pointF2D[0]);
                    double        num3  = coordinates.Distance(point);
                    if (num3 < num1)
                    {
                        projectedCoordinates = point;
                        entryIndex           = index;
                        num1 = num3;
                        double num4 = point.DistanceReal(points[index]).Value;
                        distanceFromStart = (Meter)(num2 + num4);
                    }
                }
                GeoCoordinate point1 = points[index];
                double        num5   = coordinates.Distance(point1);
                if (num5 < num1)
                {
                    projectedCoordinates = point1;
                    entryIndex           = index;
                    num1 = num5;
                    distanceFromStart = (Meter)num2;
                }
                num2 += points[index].DistanceReal(points[index + 1]).Value;
            }
            GeoCoordinate point2 = points[points.Count - 1];

            if (coordinates.Distance(point2) < num1)
            {
                projectedCoordinates = point2;
                entryIndex           = points.Count - 1;
                distanceFromStart    = (Meter)num2;
            }
            return(true);
        }
Пример #9
0
        public static RelativeDirection Calculate(GeoCoordinate from, GeoCoordinate along, GeoCoordinate to)
        {
            RelativeDirection relativeDirection = new RelativeDirection();
            double            num1   = 65.0;
            double            num2   = 10.0;
            double            num3   = 5.0;
            Radian            radian = new GeoCoordinateLine(from, along).Direction.Angle(new GeoCoordinateLine(along, to).Direction);

            if ((Degree)radian >= new Degree(360.0 - num2) || (Degree)radian < new Degree(num2))
            {
                relativeDirection.Direction = RelativeDirectionEnum.StraightOn;
            }
            else if ((Degree)radian >= new Degree(num2) && (Degree)radian < new Degree(90.0 - num1))
            {
                relativeDirection.Direction = RelativeDirectionEnum.SlightlyLeft;
            }
            else if ((Degree)radian >= new Degree(90.0 - num1) && (Degree)radian < new Degree(90.0 + num1))
            {
                relativeDirection.Direction = RelativeDirectionEnum.Left;
            }
            else if ((Degree)radian >= new Degree(90.0 + num1) && (Degree)radian < new Degree(180.0 - num3))
            {
                relativeDirection.Direction = RelativeDirectionEnum.SharpLeft;
            }
            else if ((Degree)radian >= new Degree(180.0 - num3) && (Degree)radian < new Degree(180.0 + num3))
            {
                relativeDirection.Direction = RelativeDirectionEnum.TurnBack;
            }
            else if ((Degree)radian >= new Degree(180.0 + num3) && (Degree)radian < new Degree(270.0 - num1))
            {
                relativeDirection.Direction = RelativeDirectionEnum.SharpRight;
            }
            else if ((Degree)radian >= new Degree(270.0 - num1) && (Degree)radian < new Degree(270.0 + num1))
            {
                relativeDirection.Direction = RelativeDirectionEnum.Right;
            }
            else if ((Degree)radian >= new Degree(270.0 + num1) && (Degree)radian < new Degree(360.0 - num2))
            {
                relativeDirection.Direction = RelativeDirectionEnum.SlightlyRight;
            }
            relativeDirection.Angle = (Degree)radian;
            return(relativeDirection);
        }
Пример #10
0
        /// <summary>
        /// Calculates the closest point on the route.
        /// </summary>
        /// <param name="coordinates"></param>
        /// <returns></returns>
        public GeoCoordinate ProjectOn(GeoCoordinate coordinates)
        {
            double               distance = double.MaxValue;
            GeoCoordinate        closests = null;
            List <GeoCoordinate> points   = this.GetPoints();

            for (int idx = 0; idx < points.Count - 1; idx++)
            {
                GeoCoordinateLine line            = new GeoCoordinateLine(points[idx], points[idx + 1]);
                PointF2D          projectedPoint  = line.ProjectOn(coordinates);
                GeoCoordinate     projected       = new GeoCoordinate(projectedPoint[1], projectedPoint[0]);
                double            currentDistance = coordinates.Distance(projected);
                if (currentDistance < distance)
                {
                    closests = projected;
                    distance = currentDistance;
                }
            }
            return(closests);
        }
Пример #11
0
        public static DirectionEnum Calculate(GeoCoordinate from, GeoCoordinate to)
        {
            double        num    = 0.01;
            GeoCoordinate point2 = new GeoCoordinate(from.Latitude + num, from.Longitude);
            Radian        radian = new GeoCoordinateLine(from, to).Direction.Angle(new GeoCoordinateLine(from, point2).Direction);

            if ((Degree)radian < new Degree(22.5) || (Degree)radian >= new Degree(337.5))
            {
                return(DirectionEnum.North);
            }
            if ((Degree)radian >= new Degree(22.5) && (Degree)radian < new Degree(67.5))
            {
                return(DirectionEnum.NorthEast);
            }
            if ((Degree)radian >= new Degree(67.5) && (Degree)radian < new Degree(112.5))
            {
                return(DirectionEnum.East);
            }
            if ((Degree)radian >= new Degree(112.5) && (Degree)radian < new Degree(157.5))
            {
                return(DirectionEnum.SouthEast);
            }
            if ((Degree)radian >= new Degree(157.5) && (Degree)radian < new Degree(202.5))
            {
                return(DirectionEnum.South);
            }
            if ((Degree)radian >= new Degree(202.5) && (Degree)radian < new Degree(247.5))
            {
                return(DirectionEnum.SouthWest);
            }
            if ((Degree)radian >= new Degree(247.5) && (Degree)radian < new Degree(292.5))
            {
                return(DirectionEnum.West);
            }
            if ((Degree)radian >= new Degree(292.5) && (Degree)radian < new Degree(337.5))
            {
                return(DirectionEnum.NorthWest);
            }
            throw new ArgumentOutOfRangeException();
        }
Пример #12
0
        /// <summary>
        /// Searches the data for a point on an edge closest to the given coordinate.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="vehicle"></param>
        /// <param name="coordinate"></param>
        /// <param name="delta"></param>
        /// <param name="matcher"></param>
        /// <param name="pointTags"></param>
        /// <param name="interpreter"></param>
        /// <param name="verticesOnly"></param>
        public SearchClosestResult SearchClosest(IBasicRouterDataSource <TEdgeData> graph, IRoutingInterpreter interpreter, Vehicle vehicle,
                                                 GeoCoordinate coordinate, float delta, IEdgeMatcher matcher, TagsCollection pointTags, bool verticesOnly)
        {
            var closestWithMatch    = new SearchClosestResult(double.MaxValue, 0);
            var closestWithoutMatch = new SearchClosestResult(double.MaxValue, 0);

            double searchBoxSize = delta;
            // create the search box.
            var searchBox = new GeoCoordinateBox(new GeoCoordinate(
                                                     coordinate.Latitude - searchBoxSize, coordinate.Longitude - searchBoxSize),
                                                 new GeoCoordinate(
                                                     coordinate.Latitude + searchBoxSize, coordinate.Longitude + searchBoxSize));

            // get the arcs from the data source.
            KeyValuePair <uint, KeyValuePair <uint, TEdgeData> >[] arcs = graph.GetArcs(searchBox);

            if (!verticesOnly)
            { // find both closest arcs and vertices.
                // loop over all.
                foreach (KeyValuePair <uint, KeyValuePair <uint, TEdgeData> > arc in arcs)
                {
                    TagsCollection arcTags        = graph.TagsIndex.Get(arc.Value.Value.Tags);
                    bool           canBeTraversed = vehicle.CanTraverse(arcTags);
                    if (canBeTraversed)
                    { // the edge can be traversed.
                        // test the two points.
                        float  fromLatitude, fromLongitude;
                        float  toLatitude, toLongitude;
                        double distance;
                        if (graph.GetVertex(arc.Key, out fromLatitude, out fromLongitude) &&
                            graph.GetVertex(arc.Value.Key, out toLatitude, out toLongitude))
                        { // return the vertex.
                            var fromCoordinates = new GeoCoordinate(fromLatitude, fromLongitude);
                            distance = coordinate.Distance(fromCoordinates);

                            if (distance < 0.00001)
                            { // the distance is smaller than the tolerance value.
                                closestWithoutMatch = new SearchClosestResult(
                                    distance, arc.Key);
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                {
                                    closestWithMatch = new SearchClosestResult(
                                        distance, arc.Key);
                                    break;
                                }
                            }

                            if (distance < closestWithoutMatch.Distance)
                            { // the distance is smaller for the without match.
                                closestWithoutMatch = new SearchClosestResult(
                                    distance, arc.Key);
                            }
                            if (distance < closestWithMatch.Distance)
                            { // the distance is smaller for the with match.
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, graph.TagsIndex.Get(arc.Value.Value.Tags)))
                                {
                                    closestWithMatch = new SearchClosestResult(
                                        distance, arc.Key);
                                }
                            }
                            var toCoordinates = new GeoCoordinate(toLatitude, toLongitude);
                            distance = coordinate.Distance(toCoordinates);

                            if (distance < closestWithoutMatch.Distance)
                            { // the distance is smaller for the without match.
                                closestWithoutMatch = new SearchClosestResult(
                                    distance, arc.Value.Key);
                            }
                            if (distance < closestWithMatch.Distance)
                            { // the distance is smaller for the with match.
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                {
                                    closestWithMatch = new SearchClosestResult(
                                        distance, arc.Value.Key);
                                }
                            }

                            // create a line.
                            double distanceTotal = fromCoordinates.Distance(toCoordinates);
                            if (distanceTotal > 0)
                            { // the from/to are not the same location.
                                var line = new GeoCoordinateLine(fromCoordinates, toCoordinates, true, true);
                                distance = line.Distance(coordinate);

                                if (distance < closestWithoutMatch.Distance)
                                { // the distance is smaller.
                                    PointF2D projectedPoint =
                                        line.ProjectOn(coordinate);

                                    // calculate the position.
                                    if (projectedPoint != null)
                                    { // calculate the distance
                                        double distancePoint = fromCoordinates.Distance(projectedPoint);
                                        double position      = distancePoint / distanceTotal;

                                        closestWithoutMatch = new SearchClosestResult(
                                            distance, arc.Key, arc.Value.Key, position);
                                    }
                                }
                                if (distance < closestWithMatch.Distance)
                                {
                                    PointF2D projectedPoint =
                                        line.ProjectOn(coordinate);

                                    // calculate the position.
                                    if (projectedPoint != null)
                                    { // calculate the distance
                                        double distancePoint = fromCoordinates.Distance(projectedPoint);
                                        double position      = distancePoint / distanceTotal;

                                        if (matcher == null ||
                                            (pointTags == null || pointTags.Count == 0) ||
                                            matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                        {
                                            closestWithMatch = new SearchClosestResult(
                                                distance, arc.Key, arc.Value.Key, position);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            { // only find closest vertices.
                // loop over all.
                foreach (KeyValuePair <uint, KeyValuePair <uint, TEdgeData> > arc in arcs)
                {
                    float fromLatitude, fromLongitude;
                    float toLatitude, toLongitude;
                    if (graph.GetVertex(arc.Key, out fromLatitude, out fromLongitude) &&
                        graph.GetVertex(arc.Value.Key, out toLatitude, out toLongitude))
                    {
                        var    vertexCoordinate = new GeoCoordinate(fromLatitude, fromLongitude);
                        double distance         = coordinate.Distance(vertexCoordinate);
                        if (distance < closestWithoutMatch.Distance)
                        { // the distance found is closer.
                            closestWithoutMatch = new SearchClosestResult(
                                distance, arc.Key);
                        }

                        vertexCoordinate = new GeoCoordinate(toLatitude, toLongitude);
                        distance         = coordinate.Distance(vertexCoordinate);
                        if (distance < closestWithoutMatch.Distance)
                        { // the distance found is closer.
                            closestWithoutMatch = new SearchClosestResult(
                                distance, arc.Value.Key);
                        }
                    }
                }
            }

            // return the best result.
            if (closestWithMatch.Distance < double.MaxValue)
            {
                return(closestWithMatch);
            }
            return(closestWithoutMatch);
        }
Пример #13
0
        /// <summary>
        /// Calculates the closest point on the route relative to the given coordinate.
        /// </summary>
        /// <returns></returns>
        public bool ProjectOn(GeoCoordinate coordinates, out GeoCoordinate projectedCoordinates, out int entryIndex, out Meter distanceFromStart, out Second timeFromStart)
        {
            double distance = double.MaxValue;

            distanceFromStart = 0;
            timeFromStart     = 0;
            double currentDistanceFromStart = 0;

            projectedCoordinates = null;
            entryIndex           = -1;

            // loop over all points and try to project onto the line segments.
            GeoCoordinate projected;
            double        currentDistance;
            var           points = this.GetPoints();

            for (int idx = 0; idx < points.Count - 1; idx++)
            {
                var line           = new GeoCoordinateLine(points[idx], points[idx + 1], true, true);
                var projectedPoint = line.ProjectOn(coordinates);
                if (projectedPoint != null)
                { // there was a projected point.
                    projected       = new GeoCoordinate(projectedPoint[1], projectedPoint[0]);
                    currentDistance = coordinates.Distance(projected);
                    if (currentDistance < distance)
                    { // this point is closer.
                        projectedCoordinates = projected;
                        entryIndex           = idx;
                        distance             = currentDistance;

                        // calculate distance/time.
                        double localDistance = projected.DistanceReal(points[idx]).Value;
                        distanceFromStart = currentDistanceFromStart + localDistance;
                        if (this.HasTimes && idx > 0)
                        { // there should be proper timing information.
                            double timeToSegment     = this.Segments[idx].Time;
                            double timeToNextSegment = this.Segments[idx + 1].Time;
                            timeFromStart = timeToSegment + ((timeToNextSegment - timeToSegment) * (localDistance / line.LengthReal.Value));
                        }
                    }
                }

                // check first point.
                projected       = points[idx];
                currentDistance = coordinates.Distance(projected);
                if (currentDistance < distance)
                { // this point is closer.
                    projectedCoordinates = projected;
                    entryIndex           = idx;
                    distance             = currentDistance;
                    distanceFromStart    = currentDistanceFromStart;
                    if (this.HasTimes)
                    { // there should be proper timing information.
                        timeFromStart = this.Segments[idx].Time;
                    }
                }

                // update distance from start.
                currentDistanceFromStart = currentDistanceFromStart + points[idx].DistanceReal(points[idx + 1]).Value;
            }

            // check last point.
            projected       = points[points.Count - 1];
            currentDistance = coordinates.Distance(projected);
            if (currentDistance < distance)
            { // this point is closer.
                projectedCoordinates = projected;
                entryIndex           = points.Count - 1;
                distance             = currentDistance;
                distanceFromStart    = currentDistanceFromStart;
                if (this.HasTimes)
                { // there should be proper timing information.
                    timeFromStart = this.Segments[points.Count - 1].Time;
                }
            }
            return(true);
        }
Пример #14
0
        public static bool ProjectOn(this GeometricGraph graph, GeometricEdge edge, float latitude, float longitude, out float projectedLatitude, out float projectedLongitude, out float projectedDistanceFromFirst, out int projectedShapeIndex, out float distanceToProjected, out float totalLength)
        {
            distanceToProjected        = float.MaxValue;
            projectedDistanceFromFirst = 0.0f;
            projectedLatitude          = float.MaxValue;
            projectedLongitude         = float.MaxValue;
            projectedShapeIndex        = -1;
            ICoordinate coordinate1 = (ICoordinate)graph.GetVertex(edge.From);
            ShapeBase   shape       = edge.Shape;
            IEnumerator <ICoordinate> enumerator = (IEnumerator <ICoordinate>)null;

            if (shape != null)
            {
                enumerator = shape.GetEnumerator();
                enumerator.Reset();
            }
            float num1 = 0.0f;
            int   num2 = -1;

            while (true)
            {
                bool        flag = true;
                ICoordinate coordinate2;
                if (enumerator != null && enumerator.MoveNext())
                {
                    coordinate2 = enumerator.Current;
                }
                else
                {
                    flag        = false;
                    coordinate2 = (ICoordinate)graph.GetVertex(edge.To);
                }
                PointF2D pointF2D = new GeoCoordinateLine(new GeoCoordinate((double)coordinate1.Latitude, (double)coordinate1.Longitude), new GeoCoordinate((double)coordinate2.Latitude, (double)coordinate2.Longitude), true, true).ProjectOn((PointF2D) new GeoCoordinate((double)latitude, (double)longitude));
                if (pointF2D != (PointF2D)null)
                {
                    double num3 = GeoCoordinate.DistanceEstimateInMeter(pointF2D[1], pointF2D[0], (double)latitude, (double)longitude);
                    if (num3 < (double)distanceToProjected)
                    {
                        distanceToProjected        = (float)num3;
                        projectedLatitude          = (float)pointF2D[1];
                        projectedLongitude         = (float)pointF2D[0];
                        projectedDistanceFromFirst = num1 + (float)GeoCoordinate.DistanceEstimateInMeter((double)projectedLatitude, (double)projectedLongitude, (double)coordinate1.Latitude, (double)coordinate1.Longitude);
                        projectedShapeIndex        = num2 + 1;
                    }
                }
                if (flag)
                {
                    num1 += (float)GeoCoordinate.DistanceEstimateInMeter((double)coordinate1.Latitude, (double)coordinate1.Longitude, (double)coordinate2.Latitude, (double)coordinate2.Longitude);
                    ++num2;
                    coordinate1 = coordinate2;
                }
                else
                {
                    break;
                }
            }
            GeoCoordinateSimple vertex = graph.GetVertex(edge.To);

            totalLength = num1 + (float)GeoCoordinate.DistanceEstimateInMeter((double)coordinate1.Latitude, (double)coordinate1.Longitude, (double)vertex.Latitude, (double)vertex.Longitude);
            return((double)distanceToProjected != 3.40282346638529E+38);
        }
Пример #15
0
        /// <summary>
        /// Searches the data for a point on an edge closest to the given coordinate.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="vehicle"></param>
        /// <param name="coordinate"></param>
        /// <param name="delta"></param>
        /// <param name="matcher"></param>
        /// <param name="pointTags"></param>
        /// <param name="interpreter"></param>
        /// <param name="verticesOnly"></param>
        /// <param name="parameters"></param>
        public SearchClosestResult <TEdgeData> SearchClosest(IBasicRouterDataSource <TEdgeData> graph, IRoutingInterpreter interpreter, Vehicle vehicle,
                                                             GeoCoordinate coordinate, float delta, IEdgeMatcher matcher, TagsCollectionBase pointTags, bool verticesOnly, Dictionary <string, object> parameters)
        {
            Meter distanceEpsilon = .1; // 10cm is the tolerance to distinguish points.

            var closestWithMatch    = new SearchClosestResult <TEdgeData>(double.MaxValue, 0);
            var closestWithoutMatch = new SearchClosestResult <TEdgeData>(double.MaxValue, 0);

            double searchBoxSize = delta;
            // create the search box.
            var searchBox = new GeoCoordinateBox(new GeoCoordinate(
                                                     coordinate.Latitude - searchBoxSize, coordinate.Longitude - searchBoxSize),
                                                 new GeoCoordinate(
                                                     coordinate.Latitude + searchBoxSize, coordinate.Longitude + searchBoxSize));

            // get the arcs from the data source.
            var arcs = graph.GetEdges(searchBox);

            if (!verticesOnly)
            { // find both closest arcs and vertices.
                // loop over all.
                while (arcs.MoveNext())
                {
                    if (!graph.TagsIndex.Contains(arcs.EdgeData.Tags))
                    { // skip this edge, no valid tags found.
                        continue;
                    }
                    var arcTags        = graph.TagsIndex.Get(arcs.EdgeData.Tags);
                    var canBeTraversed = vehicle.CanTraverse(arcTags);
                    if (canBeTraversed)
                    { // the edge can be traversed.
                        // test the two points.
                        float  fromLatitude, fromLongitude;
                        float  toLatitude, toLongitude;
                        double distance;
                        if (graph.GetVertex(arcs.Vertex1, out fromLatitude, out fromLongitude) &&
                            graph.GetVertex(arcs.Vertex2, out toLatitude, out toLongitude))
                        { // return the vertex.
                            var fromCoordinates = new GeoCoordinate(fromLatitude, fromLongitude);
                            distance = coordinate.DistanceReal(fromCoordinates).Value;
                            ICoordinateCollection coordinates;
                            ICoordinate[]         coordinatesArray = null;
                            if (!graph.GetEdgeShape(arcs.Vertex1, arcs.Vertex2, out coordinates))
                            {
                                coordinates = null;
                            }
                            if (coordinates != null)
                            {
                                coordinatesArray = coordinates.ToArray();
                            }

                            if (distance < distanceEpsilon.Value)
                            { // the distance is smaller than the tolerance value.
                                closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                    distance, arcs.Vertex1);
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                {
                                    closestWithMatch = new SearchClosestResult <TEdgeData>(
                                        distance, arcs.Vertex1);
                                    break;
                                }
                            }

                            if (distance < closestWithoutMatch.Distance)
                            { // the distance is smaller for the without match.
                                closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                    distance, arcs.Vertex1);
                            }
                            if (distance < closestWithMatch.Distance)
                            { // the distance is smaller for the with match.
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, graph.TagsIndex.Get(arcs.EdgeData.Tags)))
                                {
                                    closestWithMatch = new SearchClosestResult <TEdgeData>(
                                        distance, arcs.Vertex1);
                                }
                            }
                            var toCoordinates = new GeoCoordinate(toLatitude, toLongitude);
                            distance = coordinate.DistanceReal(toCoordinates).Value;

                            if (distance < closestWithoutMatch.Distance)
                            { // the distance is smaller for the without match.
                                closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                    distance, arcs.Vertex2);
                            }
                            if (distance < closestWithMatch.Distance)
                            { // the distance is smaller for the with match.
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                {
                                    closestWithMatch = new SearchClosestResult <TEdgeData>(
                                        distance, arcs.Vertex2);
                                }
                            }

                            // search along the line.
                            var distanceTotal            = 0.0;
                            var previous                 = fromCoordinates;
                            var arcValueValueCoordinates = arcs.Intermediates;
                            if (arcValueValueCoordinates != null)
                            { // calculate distance along all coordinates.
                                var arcValueValueCoordinatesArray = arcValueValueCoordinates.ToArray();
                                for (int idx = 0; idx < arcValueValueCoordinatesArray.Length; idx++)
                                {
                                    var current = new GeoCoordinate(arcValueValueCoordinatesArray[idx].Latitude, arcValueValueCoordinatesArray[idx].Longitude);
                                    distanceTotal = distanceTotal + current.DistanceReal(previous).Value;
                                    previous      = current;
                                }
                            }
                            distanceTotal = distanceTotal + toCoordinates.DistanceReal(previous).Value;
                            if (distanceTotal > 0)
                            { // the from/to are not the same location.
                                // loop over all edges that are represented by this arc (counting intermediate coordinates).
                                previous = fromCoordinates;
                                GeoCoordinateLine line;
                                var distanceToSegment = 0.0;
                                if (arcValueValueCoordinates != null)
                                {
                                    var arcValueValueCoordinatesArray = arcValueValueCoordinates.ToArray();
                                    for (int idx = 0; idx < arcValueValueCoordinatesArray.Length; idx++)
                                    {
                                        var current = new GeoCoordinate(
                                            arcValueValueCoordinatesArray[idx].Latitude, arcValueValueCoordinatesArray[idx].Longitude);
                                        line = new GeoCoordinateLine(previous, current, true, true);

                                        distance = line.DistanceReal(coordinate).Value;

                                        if (distance < closestWithoutMatch.Distance)
                                        { // the distance is smaller.
                                            var projectedPoint = line.ProjectOn(coordinate);

                                            // calculate the position.
                                            if (projectedPoint != null)
                                            { // calculate the distance
                                                var distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment;
                                                var position      = distancePoint / distanceTotal;

                                                closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                                    distance, arcs.Vertex1, arcs.Vertex2, position, arcs.EdgeData, coordinatesArray);
                                            }
                                        }
                                        if (distance < closestWithMatch.Distance)
                                        {
                                            var projectedPoint = line.ProjectOn(coordinate);

                                            // calculate the position.
                                            if (projectedPoint != null)
                                            { // calculate the distance
                                                var distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment;
                                                var position      = distancePoint / distanceTotal;

                                                if (matcher == null ||
                                                    (pointTags == null || pointTags.Count == 0) ||
                                                    matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                                {
                                                    closestWithMatch = new SearchClosestResult <TEdgeData>(
                                                        distance, arcs.Vertex1, arcs.Vertex2, position, arcs.EdgeData, coordinatesArray);
                                                }
                                            }
                                        }

                                        // add current segment distance to distanceToSegment for the next segment.
                                        distanceToSegment = distanceToSegment + line.LengthReal.Value;

                                        // set previous.
                                        previous = current;
                                    }
                                }

                                // check the last segment.
                                line = new GeoCoordinateLine(previous, toCoordinates, true, true);

                                distance = line.DistanceReal(coordinate).Value;

                                if (distance < closestWithoutMatch.Distance)
                                { // the distance is smaller.
                                    var projectedPoint = line.ProjectOn(coordinate);

                                    // calculate the position.
                                    if (projectedPoint != null)
                                    { // calculate the distance
                                        double distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment;
                                        double position      = distancePoint / distanceTotal;

                                        closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                            distance, arcs.Vertex1, arcs.Vertex2, position, arcs.EdgeData, coordinatesArray);
                                    }
                                }
                                if (distance < closestWithMatch.Distance)
                                {
                                    var projectedPoint = line.ProjectOn(coordinate);

                                    // calculate the position.
                                    if (projectedPoint != null)
                                    { // calculate the distance
                                        double distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment;
                                        double position      = distancePoint / distanceTotal;

                                        if (matcher == null ||
                                            (pointTags == null || pointTags.Count == 0) ||
                                            matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                        {
                                            closestWithMatch = new SearchClosestResult <TEdgeData>(
                                                distance, arcs.Vertex1, arcs.Vertex2, position, arcs.EdgeData, coordinatesArray);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            { // only find closest vertices.
                // loop over all.
                while (arcs.MoveNext())
                {
                    float fromLatitude, fromLongitude;
                    float toLatitude, toLongitude;
                    if (graph.GetVertex(arcs.Vertex1, out fromLatitude, out fromLongitude) &&
                        graph.GetVertex(arcs.Vertex2, out toLatitude, out toLongitude))
                    {
                        var    vertexCoordinate = new GeoCoordinate(fromLatitude, fromLongitude);
                        double distance         = coordinate.DistanceReal(vertexCoordinate).Value;
                        if (distance < closestWithoutMatch.Distance)
                        { // the distance found is closer.
                            closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                distance, arcs.Vertex1);
                        }

                        vertexCoordinate = new GeoCoordinate(toLatitude, toLongitude);
                        distance         = coordinate.DistanceReal(vertexCoordinate).Value;
                        if (distance < closestWithoutMatch.Distance)
                        { // the distance found is closer.
                            closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                distance, arcs.Vertex2);
                        }

                        var arcValueValueCoordinates = arcs.Intermediates;
                        if (arcValueValueCoordinates != null)
                        { // search over intermediate points.
                            var arcValueValueCoordinatesArray = arcValueValueCoordinates.ToArray();
                            for (int idx = 0; idx < arcValueValueCoordinatesArray.Length; idx++)
                            {
                                vertexCoordinate = new GeoCoordinate(
                                    arcValueValueCoordinatesArray[idx].Latitude,
                                    arcValueValueCoordinatesArray[idx].Longitude);
                                distance = coordinate.DistanceReal(vertexCoordinate).Value;
                                if (distance < closestWithoutMatch.Distance)
                                { // the distance found is closer.
                                    closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                        distance, arcs.Vertex1, arcs.Vertex2, idx, arcs.EdgeData, arcValueValueCoordinatesArray);
                                }
                            }
                        }
                    }
                }
            }

            // return the best result.
            if (closestWithMatch.Distance < double.MaxValue)
            {
                return(closestWithMatch);
            }
            return(closestWithoutMatch);
        }
Пример #16
0
        public static List <uint> SearchCloserThan(this GeometricGraph graph, float latitude, float longitude, float offset, float maxDistanceMeter, Func <GeometricEdge, bool> isOk)
        {
            HashSet <uint> uintSet1      = new HashSet <uint>();
            GeoCoordinate  geoCoordinate = new GeoCoordinate((double)latitude, (double)longitude);
            HashSet <uint> uintSet2      = graph.Search(latitude, longitude, offset);

            GeometricGraph.EdgeEnumerator edgeEnumerator = graph.GetEdgeEnumerator();
            foreach (uint vertex1 in uintSet2)
            {
                GeoCoordinateSimple vertex2 = graph.GetVertex(vertex1);
                if (GeoCoordinate.DistanceEstimateInMeter((double)latitude, (double)longitude, (double)vertex2.Latitude, (double)vertex2.Longitude) < (double)maxDistanceMeter)
                {
                    edgeEnumerator.MoveTo(vertex1);
                    while (edgeEnumerator.MoveNext())
                    {
                        if (isOk(edgeEnumerator.Current))
                        {
                            uintSet1.Add(edgeEnumerator.Id);
                            break;
                        }
                    }
                }
            }
            GeoCoordinateBox geoCoordinateBox = new GeoCoordinateBox(new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)((double)maxDistanceMeter), DirectionEnum.NorthWest), new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)((double)maxDistanceMeter), DirectionEnum.SouthEast));
            HashSet <uint>   uintSet3         = new HashSet <uint>();

            foreach (uint vertex1 in uintSet2)
            {
                GeoCoordinateSimple vertex2 = graph.GetVertex(vertex1);
                if (edgeEnumerator.MoveTo(vertex1) && edgeEnumerator.HasData)
                {
                    while (edgeEnumerator.MoveNext())
                    {
                        if (!uintSet3.Contains(edgeEnumerator.Id))
                        {
                            uintSet3.Add(edgeEnumerator.Id);
                            bool        flag       = isOk == null;
                            ICoordinate coordinate = (ICoordinate)vertex2;
                            ShapeBase   shapeBase  = edgeEnumerator.Shape;
                            if (shapeBase != null)
                            {
                                if (edgeEnumerator.DataInverted)
                                {
                                    shapeBase = shapeBase.Reverse();
                                }
                                IEnumerator <ICoordinate> enumerator = shapeBase.GetEnumerator();
                                enumerator.Reset();
                                while (enumerator.MoveNext())
                                {
                                    ICoordinate current = enumerator.Current;
                                    if (GeoCoordinate.DistanceEstimateInMeter((double)current.Latitude, (double)current.Longitude, (double)latitude, (double)longitude) < (double)maxDistanceMeter)
                                    {
                                        if (!flag && isOk(edgeEnumerator.Current))
                                        {
                                            flag = true;
                                        }
                                        if (flag)
                                        {
                                            uintSet1.Add(edgeEnumerator.Id);
                                        }
                                    }
                                    if (geoCoordinateBox.IntersectsPotentially((double)coordinate.Longitude, (double)coordinate.Latitude, (double)current.Longitude, (double)current.Latitude))
                                    {
                                        PointF2D pointF2D = new GeoCoordinateLine(new GeoCoordinate((double)coordinate.Latitude, (double)coordinate.Longitude), new GeoCoordinate((double)current.Latitude, (double)current.Longitude), true, true).ProjectOn((PointF2D)geoCoordinate);
                                        if (pointF2D != (PointF2D)null && GeoCoordinate.DistanceEstimateInMeter(pointF2D[1], pointF2D[0], (double)latitude, (double)longitude) < (double)maxDistanceMeter)
                                        {
                                            if (!flag && isOk(edgeEnumerator.Current))
                                            {
                                                flag = true;
                                            }
                                            if (flag)
                                            {
                                                uintSet1.Add(edgeEnumerator.Id);
                                            }
                                        }
                                    }
                                    coordinate = current;
                                }
                            }
                            ICoordinate vertex3 = (ICoordinate)graph.GetVertex(edgeEnumerator.To);
                            if (geoCoordinateBox.IntersectsPotentially((double)coordinate.Longitude, (double)coordinate.Latitude, (double)vertex3.Longitude, (double)vertex3.Latitude))
                            {
                                PointF2D pointF2D = new GeoCoordinateLine(new GeoCoordinate((double)coordinate.Latitude, (double)coordinate.Longitude), new GeoCoordinate((double)vertex3.Latitude, (double)vertex3.Longitude), true, true).ProjectOn((PointF2D)geoCoordinate);
                                if (pointF2D != (PointF2D)null && GeoCoordinate.DistanceEstimateInMeter(pointF2D[1], pointF2D[0], (double)latitude, (double)longitude) < (double)maxDistanceMeter)
                                {
                                    if (!flag && isOk(edgeEnumerator.Current))
                                    {
                                        flag = true;
                                    }
                                    if (flag)
                                    {
                                        uintSet1.Add(edgeEnumerator.Id);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(new List <uint>((IEnumerable <uint>)uintSet1));
        }
Пример #17
0
        public static uint[] SearchClosestEdges(this GeometricGraph graph, float latitude, float longitude, float latitudeOffset, float longitudeOffset, float maxDistanceMeter, Func <GeometricEdge, bool>[] isOks)
        {
            GeoCoordinate  geoCoordinate = new GeoCoordinate((double)latitude, (double)longitude);
            HashSet <uint> uintSet1      = graph.Search(latitude - latitudeOffset, longitude - longitudeOffset, latitude + latitudeOffset, longitude + longitudeOffset);

            uint[]   numArray1 = new uint[isOks.Length];
            double[] numArray2 = new double[isOks.Length];
            for (int index = 0; index < numArray1.Length; ++index)
            {
                numArray1[index] = uint.MaxValue;
                numArray2[index] = (double)maxDistanceMeter;
            }
            GeometricGraph.EdgeEnumerator edgeEnumerator = graph.GetEdgeEnumerator();
            foreach (uint vertex1 in uintSet1)
            {
                GeoCoordinateSimple vertex2 = graph.GetVertex(vertex1);
                double num = GeoCoordinate.DistanceEstimateInMeter((double)latitude, (double)longitude, (double)vertex2.Latitude, (double)vertex2.Longitude);
                for (int index = 0; index < isOks.Length; ++index)
                {
                    if (num < numArray2[index])
                    {
                        edgeEnumerator.MoveTo(vertex1);
                        while (edgeEnumerator.MoveNext())
                        {
                            if (isOks[index](edgeEnumerator.Current))
                            {
                                numArray2[index] = num;
                                numArray1[index] = edgeEnumerator.Id;
                                break;
                            }
                        }
                    }
                }
            }
            GeoCoordinateBox[] boxes = new GeoCoordinateBox[isOks.Length];
            for (int index = 0; index < boxes.Length; ++index)
            {
                boxes[index] = new GeoCoordinateBox(new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)((double)maxDistanceMeter), DirectionEnum.NorthWest), new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)((double)maxDistanceMeter), DirectionEnum.SouthEast));
            }
            HashSet <uint> uintSet2 = new HashSet <uint>();

            foreach (uint vertex1 in uintSet1)
            {
                GeoCoordinateSimple vertex2 = graph.GetVertex(vertex1);
                if (edgeEnumerator.MoveTo(vertex1) && edgeEnumerator.HasData)
                {
                    while (edgeEnumerator.MoveNext())
                    {
                        if (!uintSet2.Contains(edgeEnumerator.Id))
                        {
                            uintSet2.Add(edgeEnumerator.Id);
                            bool[] flagArray = new bool[isOks.Length];
                            for (int index = 0; index < isOks.Length; ++index)
                            {
                                flagArray[index] = isOks[index] == null;
                            }
                            ICoordinate coordinate = (ICoordinate)vertex2;
                            ShapeBase   shapeBase  = edgeEnumerator.Shape;
                            if (shapeBase != null)
                            {
                                if (edgeEnumerator.DataInverted)
                                {
                                    shapeBase = shapeBase.Reverse();
                                }
                                IEnumerator <ICoordinate> enumerator = shapeBase.GetEnumerator();
                                enumerator.Reset();
                                while (enumerator.MoveNext())
                                {
                                    ICoordinate current = enumerator.Current;
                                    double      num1    = GeoCoordinate.DistanceEstimateInMeter((double)current.Latitude, (double)current.Longitude, (double)latitude, (double)longitude);
                                    for (int index = 0; index < numArray1.Length; ++index)
                                    {
                                        if (num1 < numArray2[index])
                                        {
                                            if (!flagArray[index] && isOks[index](edgeEnumerator.Current))
                                            {
                                                flagArray[index] = true;
                                            }
                                            if (flagArray[index])
                                            {
                                                numArray2[index] = num1;
                                                numArray1[index] = edgeEnumerator.Id;
                                                boxes[index]     = new GeoCoordinateBox(new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)numArray2[index], DirectionEnum.NorthWest), new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)numArray2[index], DirectionEnum.SouthEast));
                                            }
                                        }
                                    }
                                    if (boxes.AnyIntersectsPotentially((double)coordinate.Longitude, (double)coordinate.Latitude, (double)current.Longitude, (double)current.Latitude))
                                    {
                                        PointF2D pointF2D = new GeoCoordinateLine(new GeoCoordinate((double)coordinate.Latitude, (double)coordinate.Longitude), new GeoCoordinate((double)current.Latitude, (double)current.Longitude), true, true).ProjectOn((PointF2D)geoCoordinate);
                                        if (pointF2D != (PointF2D)null)
                                        {
                                            double num2 = GeoCoordinate.DistanceEstimateInMeter(pointF2D[1], pointF2D[0], (double)latitude, (double)longitude);
                                            for (int index = 0; index < numArray1.Length; ++index)
                                            {
                                                if (num2 < numArray2[index])
                                                {
                                                    if (!flagArray[index] && isOks[index](edgeEnumerator.Current))
                                                    {
                                                        flagArray[index] = true;
                                                    }
                                                    if (flagArray[index])
                                                    {
                                                        numArray2[index] = num2;
                                                        numArray1[index] = edgeEnumerator.Id;
                                                        boxes[index]     = new GeoCoordinateBox(new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)numArray2[index], DirectionEnum.NorthWest), new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)numArray2[index], DirectionEnum.SouthEast));
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    coordinate = current;
                                }
                            }
                            ICoordinate vertex3 = (ICoordinate)graph.GetVertex(edgeEnumerator.To);
                            if (boxes.AnyIntersectsPotentially((double)coordinate.Longitude, (double)coordinate.Latitude, (double)vertex3.Longitude, (double)vertex3.Latitude))
                            {
                                PointF2D pointF2D = new GeoCoordinateLine(new GeoCoordinate((double)coordinate.Latitude, (double)coordinate.Longitude), new GeoCoordinate((double)vertex3.Latitude, (double)vertex3.Longitude), true, true).ProjectOn((PointF2D)geoCoordinate);
                                if (pointF2D != (PointF2D)null)
                                {
                                    double num = GeoCoordinate.DistanceEstimateInMeter(pointF2D[1], pointF2D[0], (double)latitude, (double)longitude);
                                    for (int index = 0; index < isOks.Length; ++index)
                                    {
                                        if (num < numArray2[index])
                                        {
                                            if (!flagArray[index] && isOks[index](edgeEnumerator.Current))
                                            {
                                                flagArray[index] = true;
                                            }
                                            if (flagArray[index])
                                            {
                                                numArray2[index] = num;
                                                numArray1[index] = edgeEnumerator.Id;
                                                boxes[index]     = new GeoCoordinateBox(new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)numArray2[index], DirectionEnum.NorthWest), new GeoCoordinate((double)latitude, (double)longitude).OffsetWithDirection((Meter)numArray2[index], DirectionEnum.SouthEast));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(numArray1);
        }
Пример #18
0
        /// <summary>
        /// Searches the data for a point on an edge closest to the given coordinate.
        /// </summary>
        /// <param name="graph"></param>
        /// <param name="vehicle"></param>
        /// <param name="coordinate"></param>
        /// <param name="delta"></param>
        /// <param name="matcher"></param>
        /// <param name="pointTags"></param>
        /// <param name="interpreter"></param>
        /// <param name="verticesOnly"></param>
        /// <param name="parameters"></param>
        public SearchClosestResult <TEdgeData> SearchClosest(IRoutingAlgorithmData <TEdgeData> graph, IRoutingInterpreter interpreter, Vehicle vehicle,
                                                             GeoCoordinate coordinate, float delta, IEdgeMatcher matcher, TagsCollectionBase pointTags, bool verticesOnly, Dictionary <string, object> parameters)
        {
            Meter distanceEpsilon = .1; // 10cm is the tolerance to distinguish points.

            var closestWithMatch = new SearchClosestResult <TEdgeData>(double.MaxValue, 0);
            GeoCoordinateBox closestWithMatchBox = null;
            var closestWithoutMatch = new SearchClosestResult <TEdgeData>(double.MaxValue, 0);
            GeoCoordinateBox closestWithoutMatchBox = null;

            double searchBoxSize = delta;
            // create the search box.
            var searchBox = new GeoCoordinateBox(new GeoCoordinate(
                                                     coordinate.Latitude - searchBoxSize, coordinate.Longitude - searchBoxSize),
                                                 new GeoCoordinate(
                                                     coordinate.Latitude + searchBoxSize, coordinate.Longitude + searchBoxSize));

            // get the arcs from the data source.
            var edges = graph.GetEdges(searchBox);

            if (!verticesOnly)
            { // find both closest arcs and vertices.
                // loop over all.
                while (edges.MoveNext())
                {
                    //if (!graph.TagsIndex.Contains(edges.EdgeData.Tags))
                    //{ // skip this edge, no valid tags found.
                    //    continue;
                    //}

                    // test the two points.
                    float  fromLatitude, fromLongitude;
                    float  toLatitude, toLongitude;
                    double distance;
                    if (graph.GetVertex(edges.Vertex1, out fromLatitude, out fromLongitude) &&
                        graph.GetVertex(edges.Vertex2, out toLatitude, out toLongitude))
                    { // return the vertex.
                        var vertex1Coordinate = new GeoCoordinate(fromLatitude, fromLongitude);
                        var vertex2Coordinate = new GeoCoordinate(toLatitude, toLongitude);

                        if (edges.EdgeData.ShapeInBox)
                        { // ok, check if it is needed to even check this edge.
                            var edgeBox        = new GeoCoordinateBox(vertex1Coordinate, vertex2Coordinate);
                            var edgeBoxOverlap = false;
                            if (closestWithoutMatchBox == null ||
                                closestWithoutMatchBox.Overlaps(edgeBox))
                            { // edge box overlap.
                                edgeBoxOverlap = true;
                            }
                            else if (closestWithMatchBox == null ||
                                     closestWithMatchBox.Overlaps(edgeBox))
                            { // edge box overlap.
                                edgeBoxOverlap = true;
                            }
                            if (!edgeBoxOverlap)
                            { // no overlap, impossible this edge is a candidate.
                                continue;
                            }
                        }

                        var arcTags        = graph.TagsIndex.Get(edges.EdgeData.Tags);
                        var canBeTraversed = vehicle.CanTraverse(arcTags);
                        if (canBeTraversed)
                        { // the edge can be traversed.
                            distance = coordinate.DistanceEstimate(vertex1Coordinate).Value;
                            if (distance < distanceEpsilon.Value)
                            { // the distance is smaller than the tolerance value.
                                var diff = coordinate - vertex1Coordinate;
                                closestWithoutMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                              new GeoCoordinate(coordinate - diff));
                                closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                    distance, edges.Vertex1);
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                {
                                    closestWithMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                               new GeoCoordinate(coordinate - diff));
                                    closestWithMatch = new SearchClosestResult <TEdgeData>(
                                        distance, edges.Vertex1);
                                    break;
                                }
                            }

                            if (distance < closestWithoutMatch.Distance)
                            { // the distance is smaller for the without match.
                                var diff = coordinate - vertex1Coordinate;
                                closestWithoutMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                              new GeoCoordinate(coordinate - diff));
                                closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                    distance, edges.Vertex1);
                            }
                            if (distance < closestWithMatch.Distance)
                            { // the distance is smaller for the with match.
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, graph.TagsIndex.Get(edges.EdgeData.Tags)))
                                {
                                    var diff = coordinate - vertex1Coordinate;
                                    closestWithMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                               new GeoCoordinate(coordinate - diff));
                                    closestWithMatch = new SearchClosestResult <TEdgeData>(
                                        distance, edges.Vertex1);
                                }
                            }

                            distance = coordinate.DistanceEstimate(vertex2Coordinate).Value;
                            if (distance < closestWithoutMatch.Distance)
                            { // the distance is smaller for the without match.
                                var diff = coordinate - vertex2Coordinate;
                                closestWithoutMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                              new GeoCoordinate(coordinate - diff));
                                closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                    distance, edges.Vertex2);
                            }
                            if (distance < closestWithMatch.Distance)
                            { // the distance is smaller for the with match.
                                if (matcher == null ||
                                    (pointTags == null || pointTags.Count == 0) ||
                                    matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                {
                                    var diff = coordinate - vertex2Coordinate;
                                    closestWithMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                               new GeoCoordinate(coordinate - diff));
                                    closestWithMatch = new SearchClosestResult <TEdgeData>(
                                        distance, edges.Vertex2);
                                }
                            }
                            // search along the line.
                            var coordinatesArray         = new ICoordinate[0];
                            var distanceTotal            = 0.0;
                            var arcValueValueCoordinates = edges.Intermediates;
                            if (arcValueValueCoordinates != null)
                            { // calculate distance along all coordinates.
                                coordinatesArray = arcValueValueCoordinates.ToArray();
                            }

                            // loop over all edges that are represented by this arc (counting intermediate coordinates).
                            var previous = vertex1Coordinate;
                            GeoCoordinateLine line;
                            var distanceToSegment = 0.0;
                            if (arcValueValueCoordinates != null)
                            {
                                for (int idx = 0; idx < coordinatesArray.Length; idx++)
                                {
                                    var current = new GeoCoordinate(
                                        coordinatesArray[idx].Latitude, coordinatesArray[idx].Longitude);
                                    var edgeBox        = new GeoCoordinateBox(previous, current);
                                    var edgeBoxOverlap = false;
                                    if (closestWithoutMatchBox == null ||
                                        closestWithoutMatchBox.Overlaps(edgeBox))
                                    { // edge box overlap.
                                        edgeBoxOverlap = true;
                                    }
                                    else if (closestWithMatchBox == null ||
                                             closestWithMatchBox.Overlaps(edgeBox))
                                    { // edge box overlap.
                                        edgeBoxOverlap = true;
                                    }
                                    if (edgeBoxOverlap)
                                    { // overlap, possible this edge is a candidate.
                                        line     = new GeoCoordinateLine(previous, current, true, true);
                                        distance = line.DistanceReal(coordinate).Value;

                                        if (distance < closestWithoutMatch.Distance)
                                        { // the distance is smaller.
                                            var projectedPoint = line.ProjectOn(coordinate);

                                            // calculate the position.
                                            if (projectedPoint != null)
                                            {     // calculate the distance.
                                                if (distanceTotal == 0)
                                                { // calculate total distance.
                                                    var pCoordinate = vertex1Coordinate;
                                                    for (int cIdx = 0; cIdx < coordinatesArray.Length; cIdx++)
                                                    {
                                                        var cCoordinate = new GeoCoordinate(coordinatesArray[cIdx].Latitude, coordinatesArray[cIdx].Longitude);
                                                        distanceTotal = distanceTotal + cCoordinate.DistanceReal(pCoordinate).Value;
                                                        pCoordinate   = cCoordinate;
                                                    }
                                                    distanceTotal = distanceTotal + vertex2Coordinate.DistanceReal(pCoordinate).Value;
                                                }

                                                var distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment;
                                                var position      = distancePoint / distanceTotal;

                                                var diff = coordinate - new GeoCoordinate(projectedPoint);
                                                closestWithoutMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                                              new GeoCoordinate(coordinate - diff));
                                                closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                                    distance, edges.Vertex1, edges.Vertex2, position, edges.EdgeData, coordinatesArray);
                                            }
                                        }
                                        if (distance < closestWithMatch.Distance)
                                        {
                                            var projectedPoint = line.ProjectOn(coordinate);

                                            // calculate the position.
                                            if (projectedPoint != null)
                                            {     // calculate the distance
                                                if (distanceTotal == 0)
                                                { // calculate total distance.
                                                    var pCoordinate = vertex1Coordinate;
                                                    for (int cIdx = 0; cIdx < coordinatesArray.Length; cIdx++)
                                                    {
                                                        var cCoordinate = new GeoCoordinate(coordinatesArray[cIdx].Latitude, coordinatesArray[cIdx].Longitude);
                                                        distanceTotal = distanceTotal + cCoordinate.DistanceReal(pCoordinate).Value;
                                                        pCoordinate   = cCoordinate;
                                                    }
                                                    distanceTotal = distanceTotal + vertex2Coordinate.DistanceReal(pCoordinate).Value;
                                                }

                                                var distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment;
                                                var position      = distancePoint / distanceTotal;

                                                if (matcher == null ||
                                                    (pointTags == null || pointTags.Count == 0) ||
                                                    matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                                {
                                                    var diff = coordinate - new GeoCoordinate(projectedPoint);
                                                    closestWithMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                                               new GeoCoordinate(coordinate - diff));
                                                    closestWithMatch = new SearchClosestResult <TEdgeData>(
                                                        distance, edges.Vertex1, edges.Vertex2, position, edges.EdgeData, coordinatesArray);
                                                }
                                            }
                                        }
                                    }

                                    // add current segment distance to distanceToSegment for the next segment.
                                    distanceToSegment = distanceToSegment + previous.DistanceEstimate(current).Value;

                                    // set previous.
                                    previous = current;
                                }
                            }

                            // check the last segment.
                            line = new GeoCoordinateLine(previous, vertex2Coordinate, true, true);

                            distance = line.DistanceReal(coordinate).Value;

                            if (distance < closestWithoutMatch.Distance)
                            { // the distance is smaller.
                                var projectedPoint = line.ProjectOn(coordinate);

                                // calculate the position.
                                if (projectedPoint != null)
                                {     // calculate the distance
                                    if (distanceTotal == 0)
                                    { // calculate total distance.
                                        var pCoordinate = vertex1Coordinate;
                                        for (int cIdx = 0; cIdx < coordinatesArray.Length; cIdx++)
                                        {
                                            var cCoordinate = new GeoCoordinate(coordinatesArray[cIdx].Latitude, coordinatesArray[cIdx].Longitude);
                                            distanceTotal = distanceTotal + cCoordinate.DistanceReal(pCoordinate).Value;
                                            pCoordinate   = cCoordinate;
                                        }
                                        distanceTotal = distanceTotal + vertex2Coordinate.DistanceReal(pCoordinate).Value;
                                    }

                                    double distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment;
                                    double position      = distancePoint / distanceTotal;

                                    var diff = coordinate - new GeoCoordinate(projectedPoint);
                                    closestWithoutMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                                  new GeoCoordinate(coordinate - diff));
                                    closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                        distance, edges.Vertex1, edges.Vertex2, position, edges.EdgeData, coordinatesArray);
                                }
                            }
                            if (distance < closestWithMatch.Distance)
                            {
                                var projectedPoint = line.ProjectOn(coordinate);

                                // calculate the position.
                                if (projectedPoint != null)
                                {     // calculate the distance
                                    if (distanceTotal == 0)
                                    { // calculate total distance.
                                        var pCoordinate = vertex1Coordinate;
                                        for (int cIdx = 0; cIdx < coordinatesArray.Length; cIdx++)
                                        {
                                            var cCoordinate = new GeoCoordinate(coordinatesArray[cIdx].Latitude, coordinatesArray[cIdx].Longitude);
                                            distanceTotal = distanceTotal + cCoordinate.DistanceReal(pCoordinate).Value;
                                            pCoordinate   = cCoordinate;
                                        }
                                        distanceTotal = distanceTotal + vertex2Coordinate.DistanceReal(pCoordinate).Value;
                                    }

                                    double distancePoint = previous.DistanceReal(new GeoCoordinate(projectedPoint)).Value + distanceToSegment;
                                    double position      = distancePoint / distanceTotal;

                                    if (matcher == null ||
                                        (pointTags == null || pointTags.Count == 0) ||
                                        matcher.MatchWithEdge(vehicle, pointTags, arcTags))
                                    {
                                        var diff = coordinate - new GeoCoordinate(projectedPoint);
                                        closestWithMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                                   new GeoCoordinate(coordinate - diff));
                                        closestWithMatch = new SearchClosestResult <TEdgeData>(
                                            distance, edges.Vertex1, edges.Vertex2, position, edges.EdgeData, coordinatesArray);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            { // only find closest vertices.
                // loop over all.
                while (edges.MoveNext())
                {
                    float fromLatitude, fromLongitude;
                    float toLatitude, toLongitude;
                    if (graph.GetVertex(edges.Vertex1, out fromLatitude, out fromLongitude) &&
                        graph.GetVertex(edges.Vertex2, out toLatitude, out toLongitude))
                    {
                        var    vertexCoordinate = new GeoCoordinate(fromLatitude, fromLongitude);
                        double distance         = coordinate.DistanceReal(vertexCoordinate).Value;
                        if (distance < closestWithoutMatch.Distance)
                        { // the distance found is closer.
                            var diff = coordinate - vertexCoordinate;
                            closestWithoutMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                          new GeoCoordinate(coordinate - diff));
                            closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                distance, edges.Vertex1);
                        }

                        vertexCoordinate = new GeoCoordinate(toLatitude, toLongitude);
                        distance         = coordinate.DistanceReal(vertexCoordinate).Value;
                        if (distance < closestWithoutMatch.Distance)
                        { // the distance found is closer.
                            var diff = coordinate - vertexCoordinate;
                            closestWithoutMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                          new GeoCoordinate(coordinate - diff));
                            closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                distance, edges.Vertex2);
                        }

                        var arcValueValueCoordinates = edges.Intermediates;
                        if (arcValueValueCoordinates != null)
                        { // search over intermediate points.
                            var arcValueValueCoordinatesArray = arcValueValueCoordinates.ToArray();
                            for (int idx = 0; idx < arcValueValueCoordinatesArray.Length; idx++)
                            {
                                vertexCoordinate = new GeoCoordinate(
                                    arcValueValueCoordinatesArray[idx].Latitude,
                                    arcValueValueCoordinatesArray[idx].Longitude);
                                distance = coordinate.DistanceReal(vertexCoordinate).Value;
                                if (distance < closestWithoutMatch.Distance)
                                { // the distance found is closer.
                                    var diff = coordinate - vertexCoordinate;
                                    closestWithoutMatchBox = new GeoCoordinateBox(new GeoCoordinate(coordinate + diff),
                                                                                  new GeoCoordinate(coordinate - diff));
                                    closestWithoutMatch = new SearchClosestResult <TEdgeData>(
                                        distance, edges.Vertex1, edges.Vertex2, idx, edges.EdgeData, arcValueValueCoordinatesArray);
                                }
                            }
                        }
                    }
                }
            }

            // return the best result.
            if (closestWithMatch.Distance < double.MaxValue)
            {
                return(closestWithMatch);
            }
            return(closestWithoutMatch);
        }