/// <summary> /// Aggregates a route by remove information useless to the generation of routing instructions. /// </summary> /// <param name="route"></param> /// <returns></returns> public AggregatedPoint Aggregate(Route route) { // create the enumerator. var enumerator = new AggregatedPointEnumerator(route); AggregatedRoutePoint previous = null; AggregatedRoutePoint current = null; AggregatedRoutePoint next = null; AggregatedPoint previousPoint = null; AggregatedArc previousArc = null; AggregatedPoint p = null; // loop over all aggregated points. while (enumerator.MoveNext()) { // get the next point. next = enumerator.Current; // process this.Process(route, previous, current, next, ref p, ref previousArc, ref previousPoint); // make the next, current and the current previous. previous = current; current = next; next = null; } // process once more, the current current has not been processed. this.Process(route, previous, current, next, ref p, ref previousArc, ref previousPoint); return(p); }
/// <summary> /// Returns true if the point between the two arcs represents a significant step in the route. /// </summary> /// <param name="previous_arc"></param> /// <param name="next_arc"></param> /// <param name="vehicle"></param> /// <returns></returns> private bool IsSignificant(Vehicle vehicle, AggregatedArc previous_arc, AggregatedArc next_arc) { if (previous_arc.Next.Points != null && previous_arc.Next.Points.Count > 0) { // the point has at least one important point. return(true); } if (previous_arc.Next.ArcsNotTaken != null && previous_arc.Next.ArcsNotTaken.Count > 0) { // the point has at least one arc not taken. return(true); } // create tag interpreters for arcs to try and work out if the arcs are different for the given vehicle. TagsCollection previousTagsDic = new SimpleTagsCollection(); foreach (Tag pair in previous_arc.Tags) { previousTagsDic.Add(pair.Key, pair.Value); } var nextTagsDic = new SimpleTagsCollection(); foreach (Tag pair in next_arc.Tags) { nextTagsDic.Add(pair.Key, pair.Value); } if (!vehicle.IsEqualFor(previousTagsDic, nextTagsDic)) { // the previous and the next edge do not represent a change for the given vehicle. //RoadTagsInterpreterBase previous_interpreter = new RoadTagsInterpreterBase(previous_tags_dic); //RoadTagsInterpreterBase next_interpreter = new RoadTagsInterpreterBase(next_tags_dic); //if (!previous_interpreter.IsEqualForVehicle(vehicle, next_interpreter)) //{ return(true); } return(false); }
public override void Succes() { // get the last arc and the last point. AggregatedArc latest_arc = (this.FinalMessages[this.FinalMessages.Count - 2] as MicroPlannerMessageArc).Arc; AggregatedPoint latest_point = (this.FinalMessages[this.FinalMessages.Count - 1] as MicroPlannerMessagePoint).Point; // count the number of streets in the same turning direction as the turn // that was found. int count = 0; if (MicroPlannerHelper.IsLeft(latest_point.Angle.Direction, this.Planner.Interpreter)) { count = MicroPlannerHelper.GetLeft(this.FinalMessages, this.Planner.Interpreter); } else if (MicroPlannerHelper.IsRight(latest_point.Angle.Direction, this.Planner.Interpreter)) { count = MicroPlannerHelper.GetRight(this.FinalMessages, this.Planner.Interpreter); } // construct the box indicating the location of the resulting find by this machine. GeoCoordinate point1 = latest_point.Location; GeoCoordinateBox box = new GeoCoordinateBox( new GeoCoordinate(point1.Latitude - 0.001f, point1.Longitude - 0.001f), new GeoCoordinate(point1.Latitude + 0.001f, point1.Longitude + 0.001f)); //string next_street = latest_point.Next.Name; // let the scentence planner generate the correct information. this.Planner.SentencePlanner.GenerateRoundabout(box, count - 1, latest_point.Next.Tags); }
/// <summary> /// Calculcates the metrics. /// </summary> /// <param name="vehicle"></param> /// <param name="p"></param> /// <returns></returns> public override Dictionary <string, double> Calculate(Vehicle vehicle, AggregatedPoint p) { Dictionary <string, double> result = new Dictionary <string, double>(); result.Add(DISTANCE_KEY, 0); result.Add(TIME_KEY, 0); Aggregated next = p; while (next != null) { if (next is AggregatedPoint) { AggregatedPoint point = (next as AggregatedPoint); this.CalculatePointMetrics(vehicle, result, point); } if (next is AggregatedArc) { AggregatedArc arc = (next as AggregatedArc); this.CalculateArcMetrics(vehicle, result, arc); } next = next.GetNext(); } return(result); }
/// <summary> /// Returns true if the point between the two arcs represents a significant step in the route. /// </summary> /// <param name="previous_arc"></param> /// <param name="next_arc"></param> /// <param name="vehicle"></param> /// <returns></returns> protected virtual bool IsSignificant(Vehicle vehicle, AggregatedArc previous_arc, AggregatedArc next_arc) { if (previous_arc.Next.Points != null && previous_arc.Next.Points.Count > 0) { // the point has at least one important point. return(true); } if (previous_arc.Next.ArcsNotTaken != null && previous_arc.Next.ArcsNotTaken.Count > 0) { // the point has at least one arc not taken. return(true); } // create tag interpreters for arcs to try and work out if the arcs are different for the given vehicle. var previousTagsDic = new TagsCollection(); if (previous_arc.Tags != null) { foreach (Tag pair in previous_arc.Tags) { previousTagsDic.Add(pair.Key, pair.Value); } } var nextTagsDic = new TagsCollection(); if (next_arc.Tags != null) { foreach (Tag pair in next_arc.Tags) { nextTagsDic.Add(pair.Key, pair.Value); } } if (!vehicle.IsEqualFor(previousTagsDic, nextTagsDic)) { // the previous and the next edge do not represent a change for the given vehicle. return(true); } return(false); }
/// <summary> /// Returns true if the point between the two arcs represents a significant step in the route. /// </summary> /// <param name="previousArc"></param> /// <param name="nextArc"></param> /// <returns></returns> protected virtual bool IsSignificant(AggregatedArc previousArc, AggregatedArc nextArc) { if (previousArc.Next.Points != null && previousArc.Next.Points.Count > 0) { // the point has at least one important point. return(true); } if (previousArc.Next.ArcsNotTaken != null && previousArc.Next.ArcsNotTaken.Count > 0) { // the point has at least one arc not taken. return(true); } // a vehicle change is also always significant. if (previousArc.Vehicle != nextArc.Vehicle) { // there is a vehicle change. return(true); } // create tag interpreters for arcs to try and work out if the arcs are different for the given vehicle. var previousTagsDic = new TagsCollection(); if (previousArc.Tags != null) { foreach (var pair in previousArc.Tags) { previousTagsDic.Add(pair.Key, pair.Value); } } var nextTagsDic = new TagsCollection(); if (nextArc.Tags != null) { foreach (var pair in nextArc.Tags) { nextTagsDic.Add(pair.Key, pair.Value); } } if (!string.IsNullOrWhiteSpace(previousArc.Vehicle)) { // there is a vehicle set on the previous arc. var vehicle = Vehicle.GetByUniqueName(previousArc.Vehicle); if (!vehicle.IsEqualFor(previousTagsDic, nextTagsDic)) { // the previous and the next edge do not represent a change for the given vehicle. return(true); } } return(false); }
public override void Succes() { // get the last arc and the last point. AggregatedArc latestArc = (this.FinalMessages[this.FinalMessages.Count - 2] as MicroPlannerMessageArc).Arc; AggregatedPoint latestPoint = (this.FinalMessages[this.FinalMessages.Count - 1] as MicroPlannerMessagePoint).Point; AggregatedArc secondLatestArc = (this.FinalMessages[this.FinalMessages.Count - 4] as MicroPlannerMessageArc).Arc; AggregatedPoint secondLatestPoint = (this.FinalMessages[this.FinalMessages.Count - 3] as MicroPlannerMessagePoint).Point; // count the number of streets in the same turning direction as the turn // that was found. int count = 0; if (MicroPlannerHelper.IsLeft(latestPoint.Angle.Direction, this.Planner.Interpreter)) { count = MicroPlannerHelper.GetLeft(this.FinalMessages, this.Planner.Interpreter); } else if (MicroPlannerHelper.IsRight(latestPoint.Angle.Direction, this.Planner.Interpreter)) { count = MicroPlannerHelper.GetRight(this.FinalMessages, this.Planner.Interpreter); } // construct the box indicating the location of the resulting find by this machine. GeoCoordinate point1 = latestPoint.Location; GeoCoordinateBox box = new GeoCoordinateBox( new GeoCoordinate(point1.Latitude - 0.001f, point1.Longitude - 0.001f), new GeoCoordinate(point1.Latitude + 0.001f, point1.Longitude + 0.001f)); // get all the names/direction/counts. TagsCollectionBase nextName = latestPoint.Next.Tags; TagsCollectionBase betweenName = latestArc.Tags; TagsCollectionBase beforeName = secondLatestArc.Tags; int firstCount = count; RelativeDirection firstTurn = secondLatestPoint.Angle; RelativeDirection secondTurn = latestPoint.Angle; // let the scentence planner generate the correct information. this.Planner.SentencePlanner.GenerateImmidiateTurn(latestPoint.EntryIdx, box, beforeName, firstTurn, firstCount, secondTurn, betweenName, nextName, latestPoint.Points); }
/// <summary> /// Processes a part of the route. /// </summary> private void Process(Route route, AggregatedRoutePoint previous, AggregatedRoutePoint current, AggregatedRoutePoint next, ref AggregatedPoint p, ref AggregatedArc previousArc, ref AggregatedPoint previousPoint) { // process the current point. if (current != null) { if (previous == null) { // point is always significant, it is the starting point! // create point. p = new AggregatedPoint(); p.Angle = null; p.ArcsNotTaken = null; p.Location = new GeoCoordinate(current.Segment.Latitude, current.Segment.Longitude); p.Points = new List <PointPoi>(); p.SegmentIdx = current.SegmentIndex; if (current.Segment.Points != null) { foreach (var routePoint in current.Segment.Points) { var poi = new PointPoi(); poi.Name = routePoint.Name; poi.Tags = routePoint.Tags.ConvertTo(); poi.Location = new GeoCoordinate(routePoint.Latitude, routePoint.Longitude); poi.Angle = null; // there is no previous point; no angle is specified. p.Points.Add(poi); } } previousPoint = p; } else { // test if point is significant. var nextArc = this.CreateArcAndPoint(route, previous, current, next); // test if the next point is significant. if (previousArc == null) { // this arc is always significant; it is the first arc. previousPoint.Next = nextArc; previousArc = nextArc; } else { // there is a previous arc; a test can be done if the current point is significant. if (this.IsSignificant(previousArc, nextArc)) { // the arc is significant; append it to the previous arc. previousArc.Next.Next = nextArc; previousArc = nextArc; previousPoint = nextArc.Next; } else { // if the arc is not significant compared to the previous one, the previous one can extend until the next point. // THIS IS THE AGGREGATION STEP! // add distance. var distanceToNext = previousArc.Next.Location.DistanceReal(nextArc.Next.Location); previousArc.Distance = previousArc.Distance + distanceToNext; // set point. previousArc.Next = nextArc.Next; } } } } }
/// <summary> /// Generates an arc and it's next point from the current aggregated point. /// </summary> /// <param name="route"></param> /// <param name="previous"></param> /// <param name="current"></param> /// <param name="next"></param> /// <returns></returns> internal AggregatedArc CreateArcAndPoint(Route route, AggregatedRoutePoint previous, AggregatedRoutePoint current, AggregatedRoutePoint next) { // create the arc. var a = new AggregatedArc(); a.Name = current.Segment.Name; a.Names = current.Segment.Names.ConvertTo(); a.Tags = current.Segment.Tags.ConvertToTagsCollection(); a.Vehicle = string.IsNullOrWhiteSpace(route.Vehicle) ? current.Segment.Vehicle : route.Vehicle; if (previous != null) { var previousCoordinate = new GeoCoordinate(previous.Segment.Latitude, previous.Segment.Longitude); var currentCoordinate = new GeoCoordinate(current.Segment.Latitude, current.Segment.Longitude); var distance = previousCoordinate.DistanceReal(currentCoordinate); a.Distance = distance; } // create the point. var p = new AggregatedPoint(); p.Location = new GeoCoordinate(current.Segment.Latitude, current.Segment.Longitude); p.Points = new List <PointPoi>(); p.SegmentIdx = current.SegmentIndex; if (previous != null && next != null && next.Segment != null) { var previousCoordinate = new GeoCoordinate(previous.Segment.Latitude, previous.Segment.Longitude); var nextCoordinate = new GeoCoordinate(next.Segment.Latitude, next.Segment.Longitude); p.Angle = RelativeDirectionCalculator.Calculate(previousCoordinate, p.Location, nextCoordinate); } if (current.Segment.SideStreets != null && current.Segment.SideStreets.Length > 0) { p.ArcsNotTaken = new List <KeyValuePair <RelativeDirection, AggregatedArc> >(); foreach (var sideStreet in current.Segment.SideStreets) { var side = new AggregatedArc(); side.Name = sideStreet.Name; side.Names = sideStreet.Names.ConvertTo(); side.Tags = sideStreet.Tags.ConvertToTagsCollection(); RelativeDirection sideDirection = null; if (previous != null) { var previousCoordinate = new GeoCoordinate(previous.Segment.Latitude, previous.Segment.Longitude); var nextCoordinate = new GeoCoordinate(sideStreet.Latitude, sideStreet.Longitude); sideDirection = RelativeDirectionCalculator.Calculate(previousCoordinate, p.Location, nextCoordinate); } p.ArcsNotTaken.Add(new KeyValuePair <RelativeDirection, AggregatedArc>(sideDirection, side)); } } if (current.Segment.Points != null) { foreach (var routePoint in current.Segment.Points) { var poi = new PointPoi(); poi.Name = routePoint.Name; poi.Tags = routePoint.Tags.ConvertTo(); poi.Location = new GeoCoordinate(routePoint.Latitude, routePoint.Longitude); var previousCoordinate = new GeoCoordinate(previous.Segment.Latitude, previous.Segment.Longitude); var currentCoordinate = new GeoCoordinate(current.Segment.Latitude, current.Segment.Longitude); poi.Angle = RelativeDirectionCalculator.Calculate(previousCoordinate, currentCoordinate, poi.Location); p.Points.Add(poi); } } // link the arc to the point. a.Next = p; return(a); }
/// <summary> /// Generates an arc and it's next point from the current aggregated point. /// </summary> /// <param name="previous"></param> /// <param name="current"></param> /// <param name="next"></param> /// <returns></returns> internal AggregatedArc CreateArcAndPoint(AggregatedRoutePoint previous, AggregatedRoutePoint current, AggregatedRoutePoint next) { // create the arc. AggregatedArc a = new AggregatedArc(); a.Name = current.Entry.WayFromName; a.Names = current.Entry.WayFromNames.ConvertTo(); a.Tags = current.Entry.Tags.ConvertToTagsCollection(); if (previous != null) { GeoCoordinate previous_coordinate = new GeoCoordinate(previous.Entry.Latitude, previous.Entry.Longitude); GeoCoordinate current_coordinate = new GeoCoordinate(current.Entry.Latitude, current.Entry.Longitude); Meter distance = previous_coordinate.DistanceReal(current_coordinate); a.Distance = distance; } // create the point. AggregatedPoint p = new AggregatedPoint(); p.Location = new GeoCoordinate(current.Entry.Latitude, current.Entry.Longitude); p.Points = new List <PointPoi>(); if (previous != null && next != null && next.Entry != null) { GeoCoordinate previous_coordinate = new GeoCoordinate(previous.Entry.Latitude, previous.Entry.Longitude); GeoCoordinate next_coordinate = new GeoCoordinate(next.Entry.Latitude, next.Entry.Longitude); p.Angle = RelativeDirectionCalculator.Calculate(previous_coordinate, p.Location, next_coordinate); } if (current.Entry.SideStreets != null && current.Entry.SideStreets.Length > 0) { p.ArcsNotTaken = new List <KeyValuePair <RelativeDirection, AggregatedArc> >(); foreach (RoutePointEntrySideStreet side_street in current.Entry.SideStreets) { AggregatedArc side = new AggregatedArc(); side.Name = side_street.WayName; side.Names = side_street.WayNames.ConvertTo(); side.Tags = side_street.Tags.ConvertToTagsCollection(); RelativeDirection side_direction = null; if (previous != null) { GeoCoordinate previous_coordinate = new GeoCoordinate(previous.Entry.Latitude, previous.Entry.Longitude); GeoCoordinate next_coordinate = new GeoCoordinate(side_street.Latitude, side_street.Longitude); side_direction = RelativeDirectionCalculator.Calculate(previous_coordinate, p.Location, next_coordinate); } p.ArcsNotTaken.Add(new KeyValuePair <RelativeDirection, AggregatedArc>(side_direction, side)); } } if (current.Entry.Points != null) { foreach (RoutePoint route_point in current.Entry.Points) { PointPoi poi = new PointPoi(); poi.Name = route_point.Name; poi.Tags = route_point.Tags.ConvertTo(); poi.Location = new GeoCoordinate(route_point.Latitude, route_point.Longitude); GeoCoordinate previous_coordinate = new GeoCoordinate(previous.Entry.Latitude, previous.Entry.Longitude); GeoCoordinate current_coordinate = new GeoCoordinate(current.Entry.Latitude, current.Entry.Longitude); poi.Angle = RelativeDirectionCalculator.Calculate(previous_coordinate, current_coordinate, poi.Location); p.Points.Add(poi); } } // link the arc to the point. a.Next = p; return(a); }
/// <summary> /// Calculate metrics for a given arc. /// </summary> /// <param name="vehicle"></param> /// <param name="result"></param> /// <param name="arc"></param> private void CalculateArcMetrics(Vehicle vehicle, Dictionary <string, double> result, AggregatedArc arc) { // update the distance. result[DISTANCE_KEY] = result[DISTANCE_KEY] + arc.Distance.Value; // update the time. KilometerPerHour speed = vehicle.ProbableSpeed(arc.Tags); Second time = arc.Distance / speed; // FOR NOW USE A METRIC OF 75% MAX SPEED. // TODO: improve this for a more realistic estimated based on the type of road. result[TIME_KEY] = result[TIME_KEY] + time.Value; }