Beispiel #1
0
        /// <summary>
        /// Executes the actual algorithm.
        /// </summary>
        protected override void DoRun()
        {
            // calculate maxOffset in degrees.
            var offsettedLocation = (new Coordinate(_latitude, _longitude)).OffsetWithDistances(_maxOffsetInMeter);
            var latitudeOffset    = System.Math.Abs(_latitude - offsettedLocation.Latitude);
            var longitudeOffset   = System.Math.Abs(_longitude - offsettedLocation.Longitude);

            // get the closest edge.
            uint[] edgeIds = null;
            if (_isBetter == null)
            { // do not evaluate both, just isOk.
                edgeIds    = new uint[2];
                edgeIds[0] = _graph.SearchClosestEdge(_latitude, _longitude,
                                                      latitudeOffset, longitudeOffset, _maxDistance, _isAcceptable);
            }
            else
            { // evaluate both.
                edgeIds = _graph.SearchClosestEdges(_latitude, _longitude,
                                                    latitudeOffset, longitudeOffset, _maxDistance, new Func <GeometricEdge, bool>[] { _isAcceptable, (potentialEdge) =>
                                                                                                                                      { // at least also make sure the edge is acceptable.
                                                                                                                                          if (_isAcceptable(potentialEdge))
                                                                                                                                          {
                                                                                                                                              return(_isBetter(potentialEdge));
                                                                                                                                          }
                                                                                                                                          return(false);
                                                                                                                                      } });
            }

            if (edgeIds[0] == Constants.NO_EDGE)
            { // oeps, no edge was found, too far from road network.
                this.ErrorMessage = string.Format("Could not resolve point at [{0}, {1}]. Probably too far from closest road or outside of the loaded network.",
                                                  _latitude.ToInvariantString(), _longitude.ToInvariantString());
                return;
            }

            // project onto the edge.
            var   edge = _graph.GetEdge(edgeIds[0]);
            var   edgeId = edgeIds[0];
            float projectedLatitude, projectedLongitude, projectedDistanceFromFirst, totalLength, distanceToProjected;
            int   projectedShapeIndex;

            if (!_graph.ProjectOn(edge, _latitude, _longitude,
                                  out projectedLatitude, out projectedLongitude, out projectedDistanceFromFirst,
                                  out projectedShapeIndex, out distanceToProjected, out totalLength))
            { // oeps, could not project onto edge.
                var points   = _graph.GetShape(edge);
                var previous = points[0];

                var bestProjectedDistanceFromFirst = 0.0f;
                projectedDistanceFromFirst = 0;
                var bestDistanceToProjected = Coordinate.DistanceEstimateInMeter(previous,
                                                                                 new Coordinate(_latitude, _longitude));
                projectedLatitude  = previous.Latitude;
                projectedLongitude = previous.Longitude;
                for (var i = 1; i < points.Count; i++)
                {
                    var current = points[i];
                    projectedDistanceFromFirst += Coordinate.DistanceEstimateInMeter(current, previous);
                    distanceToProjected         = Coordinate.DistanceEstimateInMeter(current,
                                                                                     new Coordinate(_latitude, _longitude));
                    if (distanceToProjected < bestDistanceToProjected)
                    {
                        bestDistanceToProjected        = distanceToProjected;
                        bestProjectedDistanceFromFirst = projectedDistanceFromFirst;
                        projectedLatitude  = current.Latitude;
                        projectedLongitude = current.Longitude;
                    }
                    previous = current;
                }

                // set best distance.
                projectedDistanceFromFirst = bestProjectedDistanceFromFirst;
            }

            if (_isBetter != null)
            { // there was a request to search for better edges.
                if (edgeIds[0] != edgeIds[1] &&
                    edgeIds[1] != Constants.NO_EDGE)
                { // edges are not equal, check if the better edge is acceptable.
                    // project onto the better edge.
                    var   edge1 = _graph.GetEdge(edgeIds[1]);
                    float projectedLatitude1, projectedLongitude1, projectedDistanceFromFirst1, totalLength1,
                          distanceToProjected1;
                    int projectedShapeIndex1;
                    if (!_graph.ProjectOn(edge1, _latitude, _longitude,
                                          out projectedLatitude1, out projectedLongitude1, out projectedDistanceFromFirst1,
                                          out projectedShapeIndex1, out distanceToProjected1, out totalLength1))
                    { // oeps, could not project onto edge.
                        var points   = _graph.GetShape(edge1);
                        var previous = points[0];

                        var bestProjectedDistanceFromFirst = 0.0f;
                        projectedDistanceFromFirst1 = 0;
                        var bestDistanceToProjected = Coordinate.DistanceEstimateInMeter(previous,
                                                                                         new Coordinate(_latitude, _longitude));
                        projectedLatitude1  = previous.Latitude;
                        projectedLongitude1 = previous.Longitude;
                        for (var i = 1; i < points.Count; i++)
                        {
                            var current = points[i];
                            projectedDistanceFromFirst1 += Coordinate.DistanceEstimateInMeter(current, previous);
                            distanceToProjected1         = Coordinate.DistanceEstimateInMeter(current,
                                                                                              new Coordinate(_latitude, _longitude));
                            if (distanceToProjected1 < bestDistanceToProjected)
                            {
                                bestDistanceToProjected        = distanceToProjected1;
                                bestProjectedDistanceFromFirst = projectedDistanceFromFirst1;
                                projectedLatitude1             = current.Latitude;
                                projectedLongitude1            = current.Longitude;
                            }
                            previous = current;
                        }

                        // set best distance.
                        projectedDistanceFromFirst1 = bestProjectedDistanceFromFirst;
                    }

                    if (distanceToProjected1 <= BetterEdgeThreshold ||
                        distanceToProjected1 <= distanceToProjected * BetterEdgeFactor)
                    { // ok, take the better edge.
                        totalLength                = totalLength1;
                        edgeId                     = edgeIds[1];
                        projectedLatitude          = projectedLatitude1;
                        projectedLongitude         = projectedLongitude1;
                        projectedDistanceFromFirst = projectedDistanceFromFirst1;
                    }
                }
            }

            var offset = (ushort)((projectedDistanceFromFirst / totalLength) * ushort.MaxValue);

            _result = new RouterPoint(_latitude, _longitude, edgeId, offset);

            this.HasSucceeded = true;
        }