예제 #1
0
 /// <summary>
 /// Returns the position after the given distance is travelled relative to the current position.
 /// </summary>
 /// <param name="distance"></param>
 /// <returns></returns>
 public GeoCoordinate PositionIn(Meter distance)
 {
     return _route.PositionAfter(_distanceFromStart + distance);
 }
예제 #2
0
        /// <summary>
        /// Updates the tracker with the given location.
        /// </summary>
        /// <param name="location">The measured location.</param>
        public void Track(GeoCoordinate location)
        {
            // project onto the route.
            KeyValuePair<int, GeoCoordinate> projectedResult = this.ProjectOn(_route, location);

            // set the current/route position.
            _currentPosition = location;
            _currentRoutePosition = projectedResult.Value;

            // find the next instruction.
            for (int instructionIdx = 0; instructionIdx < _instructions.Count; instructionIdx++)
            {
                Instruction instruction = _instructions[instructionIdx];
                if (instruction.EntryIdx >= projectedResult.Key)
                { // stop here!
                    _nextInstructionIdx = instructionIdx;
                    break;
                }
            }

            // calculate the distance to the next instruction.
            GeoCoordinate previous = (new GeoCoordinate(_route.Entries[projectedResult.Key].Latitude,
                _route.Entries[projectedResult.Key].Longitude));
            Meter distance = previous.DistanceReal(projectedResult.Value);
            for (int idx = projectedResult.Key; idx < _instructions[_nextInstructionIdx].EntryIdx - 1; idx++)
            {
                GeoCoordinate next = (new GeoCoordinate(_route.Entries[idx + 1].Latitude, _route.Entries[idx + 1].Longitude));
                distance = distance + previous.DistanceReal(next);
                previous = next;
            }
            _distanceNextInstruction = distance;

            // calculate the distance from start.
            previous = (new GeoCoordinate(_route.Entries[0].Latitude, _route.Entries[0].Longitude));
            distance = 0;
            for (int idx = 0; idx < projectedResult.Key - 1; idx++)
            {
                GeoCoordinate next = (new GeoCoordinate(_route.Entries[idx + 1].Latitude, _route.Entries[idx + 1].Longitude));
                distance = distance + previous.DistanceReal(next);
                previous = next;
            }
            distance = distance + previous.DistanceReal(projectedResult.Value);
            _distanceFromStart = distance;
        }
예제 #3
0
        /// <summary>
        /// Offset this coordinate with the given distance in meter along the provided direction.
        /// </summary>
        /// <param name="distance"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public GeoCoordinate OffsetWithDirection(Meter distance, DirectionEnum direction)
        {
            double radius_earth = Constants.RadiusOfEarth;
            Radian ratio = distance.Value / radius_earth;

            Radian oldLat = (Degree)(this.Latitude);
            Radian oldLon = (Degree)(this.Longitude);
            Radian bearing = (Degree)(int)direction;

            Radian newLatitude = System.Math.Asin(
                                     System.Math.Sin(oldLat.Value) *
                                     System.Math.Cos(ratio.Value) +
                                     System.Math.Cos(oldLat.Value) *
                                     System.Math.Sin(ratio.Value) *
                                     System.Math.Cos(bearing.Value));

            Radian newLongitude = oldLon.Value + System.Math.Atan2(
                                      System.Math.Sin(bearing.Value) *
                                      System.Math.Sin(ratio.Value) *
                                      System.Math.Cos(oldLat.Value),
                                      System.Math.Cos(ratio.Value) -
                                      System.Math.Sin(oldLat.Value) *
                                      System.Math.Sin(newLatitude.Value));

            // TODO: make this work in other hemispheres
            var newLat = ((Degree)newLatitude).Value;
            if(newLat > 180)
            {
                newLat = newLat - 360;
            }
            var newLon = ((Degree)newLongitude).Value;
            if (newLon > 180)
            {
                newLon = newLon - 360;
            }
            return new GeoCoordinate(newLat, newLon);
        }
예제 #4
0
        /// <summary>
        /// Offset this coordinate with the given distance in meter in both lat-lon directions.
        /// The difference in distance will be sqrt(2) * meter.
        /// </summary>
        /// <param name="meter"></param>
        /// <returns></returns>
        public GeoCoordinate OffsetWithDistances(Meter meter)
        {
            GeoCoordinate offsetLat = new GeoCoordinate(this.Latitude + 0.1,
                                          this.Longitude);
            GeoCoordinate offsetLon = new GeoCoordinate(this.Latitude,
                                          this.Longitude + 0.1);
            Meter latDistance = offsetLat.DistanceReal(this);
            Meter lonDistance = offsetLon.DistanceReal(this);

            return new GeoCoordinate(this.Latitude + (meter.Value / latDistance.Value) * 0.1,
                this.Longitude + (meter.Value / lonDistance.Value) * 0.1);
        }
예제 #5
0
 /// <summary>
 /// Offsets this coordinate in a random direction.
 /// </summary>
 /// <param name="meter"></param>
 /// <returns></returns>
 public GeoCoordinate OffsetRandom(Meter meter)
 {
     return this.OffsetRandom(OsmSharp.Math.Random.StaticRandomGenerator.Get(), meter);
 }
예제 #6
0
        /// <summary>
        /// Offsets this coordinate in a random direction.
        /// </summary>
        /// <param name="randomGenerator"></param>
        /// <param name="meter"></param>
        /// <returns></returns>
        public GeoCoordinate OffsetRandom(IRandomGenerator randomGenerator, Meter meter)
        {
            GeoCoordinate offsetCoordinate = this.OffsetWithDistances(meter.Value /
                                             System.Math.Sqrt(2));
            double offsetLat = offsetCoordinate.Latitude - this.Latitude;
            double offsetLon = offsetCoordinate.Longitude - this.Longitude;

            offsetLat = (1.0 - randomGenerator.Generate(2.0)) * offsetLat;
            offsetLon = (1.0 - randomGenerator.Generate(2.0)) * offsetLon;

            return new GeoCoordinate(this.Latitude + offsetLat, this.Longitude + offsetLon);
        }
예제 #7
0
파일: Route.cs 프로젝트: cmberryau/routing
        /// <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;
        }
예제 #8
0
파일: Route.cs 프로젝트: cmberryau/routing
 /// <summary>
 /// Returns an enumerable of route positions with the given interval between them.
 /// </summary>
 /// <param name="interval"></param>
 /// <returns></returns>
 public IEnumerable<GeoCoordinate> GetRouteEnumerable(Meter interval)
 {
     return new RouteEnumerable(this, interval);
 }
예제 #9
0
파일: Route.cs 프로젝트: cmberryau/routing
        /// <summary>
        /// Calculates the position on the route after the given distance from the starting point.
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public GeoCoordinate PositionAfter(Meter m)
        {
            var distanceMeter = 0.0;
            var points = this.GetPoints();
            for (int idx = 0; idx < points.Count - 1; idx++)
            {
                var currentDistance = points[idx].DistanceReal(points[idx + 1]).Value;
                if (distanceMeter + currentDistance >= m.Value)
                { // the current distance should be in this segment.
                    var segmentDistance = m.Value - distanceMeter;
                    var direction = points[idx + 1] - points[idx];
                    direction = direction * (segmentDistance / currentDistance);
                    var position = points[idx] + direction;
                    return new GeoCoordinate(position[1], position[0]);
                }
				distanceMeter += currentDistance;
            }
            return null;
        }
예제 #10
0
파일: Route.cs 프로젝트: cmberryau/routing
 /// <summary>
 /// Calculates the closest point on the route relative to the given coordinate.
 /// </summary>
 /// <param name="coordinates"></param>
 /// <param name="distanceFromStart"></param>
 /// <returns></returns>
 public bool ProjectOn(GeoCoordinate coordinates, out Meter distanceFromStart)
 {
     int entryIdx;
     GeoCoordinate projectedCoordinates;
     Second timeFromStart;
     return this.ProjectOn(coordinates, out projectedCoordinates, out entryIdx, out distanceFromStart, out timeFromStart);
 }
예제 #11
0
        /// <summary>
        /// Updates the tracker with the given location.
        /// </summary>
        /// <param name="location">The measured location.</param>
        public void Track(GeoCoordinate location)
        {
            // set the current location.
            _currentPosition = location;

            // calculate the total distance.
            var previous = new GeoCoordinate(_route.Segments[0].Latitude, _route.Segments[0].Longitude); ;
            var totalDistance = 0.0;
            for (int idx = 1; idx < _route.Segments.Length; idx++)
            {
                GeoCoordinate next = new GeoCoordinate(_route.Segments[idx].Latitude, _route.Segments[idx].Longitude);
                totalDistance = totalDistance + previous.DistanceReal(next).Value;
                previous = next;
            }
            double totalTime = _route.TotalTime;

            // project onto the route.
            int entryIdx;
            _route.ProjectOn(_currentPosition, out _currentRoutePosition, out entryIdx, out _distanceFromStart, out _timeFromStart);
            _distanceToEnd = totalDistance - _distanceFromStart;
            _timeToEnd = totalTime - _timeFromStart.Value;

            // find the next instruction.
            _nextInstructionIdx = -1;
            for (int instructionIdx = 0; instructionIdx < _instructions.Count; instructionIdx++)
            {
                var instruction = _instructions[instructionIdx];
                if (instruction.LastSegmentIdx > entryIdx)
                { // stop here!
                    _nextInstructionIdx = instructionIdx;
                    break;
                }
            }
            if(_nextInstructionIdx < 0)
            { // no instruction was found after the entryIdx: assume last instruction.
                _nextInstructionIdx = _instructions.Count - 1;
            }

            // calculate the distance to the next instruction.
            previous = _currentRoutePosition;
            var distance = 0.0;
            for (int idx = entryIdx + 1; idx <= _instructions[_nextInstructionIdx].LastSegmentIdx && idx < _route.Segments.Length; idx++)
            {
                var next = (new GeoCoordinate(_route.Segments[idx].Latitude, _route.Segments[idx].Longitude));
                distance = distance + previous.DistanceReal(next).Value;
                previous = next;
            }
            _distanceNextInstruction = distance;
        }
예제 #12
0
        /// <summary>
        /// Tries to parse a distance measure from a given tag-value.
        /// </summary>
        /// <param name="s"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool TryParseLength(string s, out Meter result)
        {
            result = double.MaxValue;

            if (Utilities.IsNullOrWhiteSpace(s))
                return false;

            Regex metresRegex = new Regex("^" + REGEX_DECIMAL + REGEX_UNIT_METERS + "$", RegexOptions.IgnoreCase);
            Match metresMatch = metresRegex.Match(s);
            if (metresMatch.Success)
            {
                result = double.Parse(metresMatch.Groups[1].Value, CultureInfo.InvariantCulture);
                return true;
            }

            Regex feetInchesRegex = new Regex("^(\\d+)\\'(\\d+)\\\"$", RegexOptions.IgnoreCase);
            Match feetInchesMatch = feetInchesRegex.Match(s);
            if (feetInchesMatch.Success)
            {
                int feet = int.Parse(feetInchesMatch.Groups[1].Value, CultureInfo.InvariantCulture);
                int inches = int.Parse(feetInchesMatch.Groups[2].Value, CultureInfo.InvariantCulture);

                result = feet * 0.3048 + inches * 0.0254;
                return true;
            }

            return false;
        }
예제 #13
0
 /// <summary>
 /// Searches for a max width tag and returns the associated value.
 /// 
 /// http://wiki.openstreetmap.org/wiki/Key:maxwidth
 /// </summary>
 /// <param name="tags">The tags to search.</param>
 /// <param name="result"></param>
 /// <returns></returns>
 public static bool TryGetMaxWidth(this TagsCollectionBase tags, out Meter result)
 {
     result = double.MaxValue;
     string tagValue;
     if (tags == null || !tags.TryGetValue("maxwidth", out tagValue) || Utilities.IsNullOrWhiteSpace(tagValue))
         return false;
     return TagExtensions.TryParseLength(tagValue, out result);
 }
예제 #14
0
        /// <summary>
        /// Searches for a max length tag and returns the associated value.
        /// 
        /// http://wiki.openstreetmap.org/wiki/Key:maxlength
        /// </summary>
        /// <param name="tags">The tags to search.</param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool TryGetMaxLength(this IDictionary<string, string> tags, out Meter result)
        {
            result = double.MaxValue;

            string tagValue;
            if (tags == null || !tags.TryGetValue("maxlength", out tagValue) || string.IsNullOrWhiteSpace(tagValue))
                return false;

            return TagExtensions.TryParseLength(tagValue, out result);
        }
예제 #15
0
        /// <summary>
        /// Searches for a max height tag and returns the associated value.
        /// 
        /// http://wiki.openstreetmap.org/wiki/Maxheight
        /// </summary>
        /// <param name="tags">The tags to search.</param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool TryGetMaxHeight(this TagsCollection tags, out Meter result)
        {
            result = double.MaxValue;

            string tagValue;
            if (tags == null || !tags.TryGetValue("maxheight", out tagValue) || string.IsNullOrWhiteSpace(tagValue))
                return false;

            return TagExtensions.TryParseLength(tagValue, out result);
        }