///// <summary>
        ///// Adds an edge.
        ///// </summary>
        ///// <param name="forward"></param>
        ///// <param name="from"></param>
        ///// <param name="to"></param>
        ///// <param name="tags"></param>
        ///// <param name="intermediates"></param>
        //protected override void AddRoadEdge(TagsCollectionBase tags, bool forward, uint from, uint to, List<GeoCoordinateSimple> intermediates)
        //{
        //    float latitude;
        //    float longitude;
        //    GeoCoordinate fromCoordinate = null;
        //    if (this.DynamicGraph.GetVertex(from, out latitude, out longitude))
        //    { //
        //        fromCoordinate = new GeoCoordinate(latitude, longitude);
        //    }
        //    GeoCoordinate toCoordinate = null;
        //    if (this.DynamicGraph.GetVertex(to, out latitude, out longitude))
        //    { //
        //        toCoordinate = new GeoCoordinate(latitude, longitude);
        //    }

        //    if (fromCoordinate != null && toCoordinate != null)
        //    { // calculate the edge data.
        //        var edgeData = this.CalculateEdgeData(this.Interpreter.EdgeInterpreter, this.TagsIndex, tags, forward, fromCoordinate, toCoordinate, intermediates);

        //        ICoordinateCollection intermediatesCollection = null;
        //        if(intermediates != null)
        //        {
        //            intermediatesCollection = new CoordinateArrayCollection<GeoCoordinateSimple>(intermediates.ToArray());
        //        }
        //        this.DynamicGraph.AddEdge(from, to, edgeData, intermediatesCollection, this.EdgeComparer);
        //    }
        //}

        /// <summary>
        /// Calculates edge data.
        /// </summary>
        /// <param name="tagsIndex"></param>
        /// <param name="tags"></param>
        /// <param name="directionForward"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="edgeInterpreter"></param>
        /// <param name="intermediates"></param>
        /// <returns></returns>
        protected override LiveEdge CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsCollectionIndex tagsIndex,
                                                      TagsCollectionBase tags, bool tagsForward, GeoCoordinate from, GeoCoordinate to, List <GeoCoordinateSimple> intermediates)
        {
            if (edgeInterpreter == null)
            {
                throw new ArgumentNullException("edgeInterpreter");
            }
            if (tagsIndex == null)
            {
                throw new ArgumentNullException("tagsIndex");
            }
            if (tags == null)
            {
                throw new ArgumentNullException("tags");
            }
            if (from == null)
            {
                throw new ArgumentNullException("from");
            }
            if (to == null)
            {
                throw new ArgumentNullException("to");
            }

            uint tagsId = tagsIndex.Add(tags);

            return(new LiveEdge()
            {
                Forward = tagsForward,
                Tags = tagsId,
                Distance = (float)from.DistanceEstimate(to).Value
            });
        }
예제 #2
0
        /// <summary>
        /// Calculates edge data.
        /// </summary>
        /// <param name="tagsIndex"></param>
        /// <param name="tags"></param>
        /// <param name="tagsForward"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="edgeInterpreter"></param>
        /// <param name="intermediates"></param>
        /// <returns></returns>
        protected override Edge CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsIndex tagsIndex,
                                                  TagsCollectionBase tags, bool tagsForward, GeoCoordinate from, GeoCoordinate to, List <GeoCoordinateSimple> intermediates)
        {
            if (edgeInterpreter == null)
            {
                throw new ArgumentNullException("edgeInterpreter");
            }
            if (tagsIndex == null)
            {
                throw new ArgumentNullException("tagsIndex");
            }
            if (tags == null)
            {
                throw new ArgumentNullException("tags");
            }
            if (from == null)
            {
                throw new ArgumentNullException("from");
            }
            if (to == null)
            {
                throw new ArgumentNullException("to");
            }

            uint tagsId = tagsIndex.Add(tags);

            var shapeInBox = true;

            if (intermediates != null)
            { // verify shape-in-box.
                var box = new GeoCoordinateBox(from, to);
                for (int idx = 0; idx < intermediates.Count; idx++)
                {
                    if (!box.Contains(intermediates[idx].Longitude, intermediates[idx].Latitude))
                    { // shape not in box.
                        shapeInBox = false;
                        break;
                    }
                }
            }

            return(new Edge()
            {
                Forward = tagsForward,
                Tags = tagsId,
                Distance = (float)from.DistanceEstimate(to).Value,
                ShapeInBox = shapeInBox
            });
        }
예제 #3
0
        /// <summary>
        /// Calculates edge data.
        /// </summary>
        /// <param name="tagsIndex"></param>
        /// <param name="tags"></param>
        /// <param name="directionForward"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="edgeInterpreter"></param>
        /// <param name="intermediates"></param>
        /// <returns></returns>
        protected override LiveEdge CalculateEdgeData(IEdgeInterpreter edgeInterpreter, ITagsCollectionIndex tagsIndex,
                                                      TagsCollectionBase tags, bool directionForward, GeoCoordinate from, GeoCoordinate to, List <GeoCoordinateSimple> intermediates)
        {
            if (edgeInterpreter == null)
            {
                throw new ArgumentNullException("edgeInterpreter");
            }
            if (tagsIndex == null)
            {
                throw new ArgumentNullException("tagsIndex");
            }
            if (tags == null)
            {
                throw new ArgumentNullException("tags");
            }
            if (from == null)
            {
                throw new ArgumentNullException("from");
            }
            if (to == null)
            {
                throw new ArgumentNullException("to");
            }

            uint tagsId = tagsIndex.Add(tags);

            GeoCoordinateSimple[] coordinates = null;
            if (intermediates != null && intermediates.Count > 0)
            { // only instiate if needed.
                coordinates = intermediates.ToArray();
            }

            return(new LiveEdge()
            {
                Forward = directionForward,
                Tags = tagsId,
                Distance = (float)from.DistanceEstimate(to).Value
            });
        }
예제 #4
0
        /// <summary>
        /// Returns the weight between two points on an edge with the given tags for the vehicle.
        /// </summary>
        /// <param name="tags"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public virtual float Weight(TagsCollectionBase tags, GeoCoordinate from, GeoCoordinate to)
        {
            var distance = from.DistanceEstimate(to).Value;

            return((float)(distance / (this.ProbableSpeed(tags).Value) * 3.6));
        }
예제 #5
0
        /// <summary>
        /// Finds candidate vertices for a location reference point.
        /// </summary>
        /// <param name="lrp"></param>
        /// <param name="maxVertexDistance"></param>
        /// <returns></returns>
        public virtual IEnumerable <CandidateVertex> FindCandidateVerticesFor(LocationReferencePoint lrp, Meter maxVertexDistance)
        {
            // convert to geo coordinate.
            var geoCoordinate = new GeoCoordinate(lrp.Coordinate.Latitude, lrp.Coordinate.Longitude);

            // build candidates list.
            var candidates       = new HashSet <long>();
            var scoredCandidates = new List <CandidateVertex>();

            float latitude, longitude;

            // create a search box.
            var box = new GeoCoordinateBox(geoCoordinate, geoCoordinate);

            box = box.Resize(_candidateSearchBoxSize);

            // get arcs.
            var arcs = this.Graph.GetEdges(box);

            foreach (var arc in arcs)
            {
                long vertex = arc.Item1;
                if (!candidates.Contains(vertex))
                {
                    this.Graph.GetVertex(vertex, out latitude, out longitude);
                    var distance = geoCoordinate.DistanceEstimate(new GeoCoordinate(latitude, longitude));
                    if (distance.Value < maxVertexDistance.Value)
                    {
                        candidates.Add(vertex);
                        scoredCandidates.Add(new CandidateVertex()
                        {
                            Score  = Score.New(Score.VERTEX_DISTANCE, string.Format("The vertex score compare to max distance {0}", _maxVertexDistance), (float)System.Math.Max(0, (1.0 - (distance.Value / _maxVertexDistance.Value))), 1), // calculate scoring compared to the fixed max distance.
                            Vertex = vertex
                        });
                    }
                }
                vertex = arc.Item2;
                if (!candidates.Contains(vertex))
                {
                    this.Graph.GetVertex(vertex, out latitude, out longitude);
                    var distance = geoCoordinate.DistanceEstimate(new GeoCoordinate(latitude, longitude));
                    if (distance.Value < maxVertexDistance.Value)
                    {
                        candidates.Add(vertex);
                        scoredCandidates.Add(new CandidateVertex()
                        {
                            Score  = Score.New(Score.VERTEX_DISTANCE, string.Format("The vertex score compare to max distance {0}", _maxVertexDistance), (float)System.Math.Max(0, (1.0 - (distance.Value / _maxVertexDistance.Value))), 1), // calculate scoring compared to the fixed max distance.
                            Vertex = vertex
                        });
                    }
                }
            }

            if (scoredCandidates.Count == 0)
            { // no candidates, create a virtual candidate.
                var closestEdge = this.Graph.GetClosestEdge(geoCoordinate, maxVertexDistance, 0.1);
                if (closestEdge != null)
                {
                    var coordinates = this.Graph.GetCoordinates(closestEdge);

                    OsmSharp.Math.Primitives.PointF2D          bestProjected;
                    OsmSharp.Math.Primitives.LinePointPosition bestPosition;
                    Meter bestOffset;
                    int   bestIndex;
                    if (coordinates.ProjectOn(geoCoordinate, out bestProjected, out bestPosition, out bestOffset, out bestIndex))
                    { // successfully projected, insert virtual vertex.
                        var distance = geoCoordinate.DistanceEstimate(new GeoCoordinate(bestProjected[1], bestProjected[0]));
                        if (distance.Value < maxVertexDistance.Value)
                        {
                            this.Graph.RemoveEdge(closestEdge.Item1, closestEdge.Item2);
                            this.Graph.RemoveEdge(closestEdge.Item2, closestEdge.Item1);

                            var newVertex = this.Graph.AddVertex((float)bestProjected[1], (float)bestProjected[0]);

                            // build distance before/after.
                            var distanceBefore = bestOffset.Value;
                            var distanceAfter  = closestEdge.Item3.Distance - bestOffset.Value;

                            // build coordinates before/after.
                            var coordinatesBefore = new List <GeoCoordinateSimple>(
                                coordinates.GetRange(1, bestIndex).Select(x => new GeoCoordinateSimple()
                            {
                                Latitude  = (float)x.Latitude,
                                Longitude = (float)x.Longitude
                            }));
                            var coordinatesAfter = new List <GeoCoordinateSimple>(
                                coordinates.GetRange(bestIndex + 1, coordinates.Count - 1 - bestIndex - 1).Select(x => new GeoCoordinateSimple()
                            {
                                Latitude  = (float)x.Latitude,
                                Longitude = (float)x.Longitude
                            }));

                            this.Graph.AddEdge(closestEdge.Item1, newVertex, new LiveEdge()
                            {
                                Distance = (float)distanceBefore,
                                Forward  = closestEdge.Item3.Forward,
                                Tags     = closestEdge.Item3.Tags
                            }, coordinatesBefore.Count > 0 ? coordinatesBefore.ToArray() : null);
                            this.Graph.AddEdge(newVertex, closestEdge.Item2, new LiveEdge()
                            {
                                Distance = (float)distanceAfter,
                                Forward  = closestEdge.Item3.Forward,
                                Tags     = closestEdge.Item3.Tags
                            }, coordinatesAfter.Count > 0 ? coordinatesAfter.ToArray() : null);

                            scoredCandidates.Add(new CandidateVertex()
                            {
                                Score = Score.New(Score.VERTEX_DISTANCE,
                                                  string.Format("The vertex score compare to max distance {0}", _maxVertexDistance),
                                                  (float)System.Math.Max(0, (1.0 - (distance.Value / _maxVertexDistance.Value))), 1), // calculate scoring compared to the fixed max distance.
                                Vertex = newVertex
                            });
                        }
                    }
                }
            }
            return(scoredCandidates);
        }
예제 #6
0
        /// <summary>
        /// Returns the weight between two points on an edge with the given tags for the vehicle.
        /// </summary>
        /// <param name="tags"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public virtual float Weight(TagsCollectionBase tags, GeoCoordinate from, GeoCoordinate to)
        {
            var distance = (float)from.DistanceEstimate(to).Value;

            return(this.Weight(tags, distance));
        }
예제 #7
0
        /// <summary>
        /// Returns the weight between two points on an edge with the given tags for the given vehicle.
        /// </summary>
        /// <param name="tags"></param>
        /// <param name="vehicle"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public double Weight(IDictionary<string, string> tags, VehicleEnum vehicle, GeoCoordinate from, GeoCoordinate to)
        {
            double distance = from.DistanceEstimate(to).Value;

            return distance / (this.MaxSpeed(vehicle, tags).Value) * 3.6;
        }
예제 #8
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);
        }
예제 #9
0
        /// <summary>
        ///     Returns the weight between two points on an edge with the given tags for the vehicle.
        /// </summary>
        /// <param name="tags"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        public virtual double Weight(TagsCollection tags, GeoCoordinate from, GeoCoordinate to)
        {
            var distance = from.DistanceEstimate(to).Value;

            return(distance / (MaxSpeed(tags).Value) * 3.6);
        }