public GeoCoordinate OffsetWithDistances(Meter meter) { GeoCoordinate geoCoordinate1 = new GeoCoordinate(this.Latitude + 0.1, this.Longitude); GeoCoordinate geoCoordinate2 = new GeoCoordinate(this.Latitude, this.Longitude + 0.1); Meter meter1 = geoCoordinate1.DistanceReal(this); Meter meter2 = geoCoordinate2.DistanceReal(this); return(new GeoCoordinate(this.Latitude + meter.Value / meter1.Value * 0.1, this.Longitude + meter.Value / meter2.Value * 0.1)); }
/// <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)); }
public void TestGeoCoordinateOffsetEstimate() { GeoCoordinate coord1 = new GeoCoordinate(51, 4.8); Meter distance = 10000; GeoCoordinate coord3 = coord1.OffsetWithDistances(distance); GeoCoordinate coord3_lat = new GeoCoordinate(coord3.Latitude, coord1.Longitude); GeoCoordinate coord3_lon = new GeoCoordinate(coord1.Latitude, coord3.Longitude); Meter distance_lat = coord3_lat.DistanceReal(coord1); Meter distance_lon = coord3_lon.DistanceReal(coord1); Assert.AreEqual(distance.Value, distance_lat.Value, 0.001); Assert.AreEqual(distance.Value, distance_lon.Value, 0.001); }
/// <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); }
/// <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; }
/// <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; }
/// <summary> /// Builds a dummy route (as the crow flies) for segments of a route not found. /// </summary> /// <returns></returns> public virtual Route BuildDummyRoute(Vehicle vehicle, GeoCoordinate coordinate1, GeoCoordinate coordinate2) { var route = new Route(); route.Vehicle = vehicle.UniqueName; var segments = new RouteSegment[2]; segments[0] = new RouteSegment(); segments[0].Distance = 0; segments[0].Time = 0; segments[0].Type = RouteSegmentType.Start; segments[0].Vehicle = vehicle.UniqueName; segments[0].Latitude = (float)coordinate1.Latitude; segments[0].Longitude = (float)coordinate1.Longitude; var distance = coordinate1.DistanceReal(coordinate2).Value; var timeEstimage = distance / (vehicle.MaxSpeed().Value) * 3.6; var tags = new TagsCollection(); tags.Add("route", "not_found"); segments[1] = new RouteSegment(); segments[1].Distance = distance; segments[1].Time = timeEstimage; segments[1].Type = RouteSegmentType.Stop; segments[1].Vehicle = vehicle.UniqueName; segments[1].Latitude = (float)coordinate2.Latitude; segments[1].Longitude = (float)coordinate2.Longitude; segments[1].Tags = RouteTagsExtensions.ConvertFrom(tags); route.Segments = segments; return route; }