public PartialRoute DeepCopy() { PartialRoute _DeepCopy = new PartialRoute(); _DeepCopy.partialRoute = partialRoute; //No deeper copy needed since partial route won't be changed foreach (GeocacheRoutingInformation geocacheRoutingInfo in GeocachesInReach) { _DeepCopy.GeocachesInReach.Add(new GeocacheRoutingInformation(geocacheRoutingInfo)); } return(_DeepCopy); }
private RouteData FillRouteWithGeocachesUntilMaxDistanceIsReached(RouteData CompleteRouteData) { Fileoperations.Routerlog.AddSubSection("Entered filling route with geocaches"); //TODO Make MaxDistance to meters as well /////////////////////////////////////////////////////////////////////////////////////// //TAKE CARE RouteDistance is in m, MaxDistance in km!!! //////////////////////////////////////////////////////////////////////////////// GeocacheRoutingInformation GeocacheToAdd = null; do { //Values GeocacheToAdd = null; Route RouteToInsertIn = null; int IndexOfRouteToInsertIn = -1; #region Filter Geocaches /*Remove all Caches that definitely are not in Range (estimated distance, which is the shortest possible distance, bigger than distance set). * Meanwhile find best rated geocache and the route it is the closest to. * Only allow apercentage of the distance set, as the roads are most definitely not straight. * For the case they are, there is another routine that picks up the caches that are directly on the route. */ Parallel.For(0, CompleteRouteData.partialRoutes.Count, CurrentPartialRouteIndex => { PartialRoute CurrentPartialRoute = CompleteRouteData.partialRoutes[CurrentPartialRouteIndex]; List <GeocacheRoutingInformation> GeocachesToRemove = new List <GeocacheRoutingInformation>(); foreach (GeocacheRoutingInformation CurrentGeocache in CurrentPartialRoute.GeocachesInReach) { if (CurrentGeocache.EstimatedExtraDistance > (CompleteRouteData.Profile.MaxDistance * 1000 - CompleteRouteData.TotalDistance)) { GeocachesToRemove.Add(CurrentGeocache); } else if (CompleteRouteData.GeocachesOnRoute().Contains(CurrentGeocache.geocache)) { GeocachesToRemove.Add(CurrentGeocache); } else if (CurrentGeocache.EstimatedExtraDistance < CompleteRouteData.Profile.MaxDistance * 1000 - CompleteRouteData.TotalDistance) { /* If no cache is set as next geocache to insert * If the cache we stumbled accross has more routingpoints than the old cache */ if (GeocacheToAdd == null || CurrentGeocache.RoutingPoints > GeocacheToAdd.RoutingPoints) { lock (GeocacheToAddLocker) //Since one can't lock GeocacheToAdd directly, since it is not the same object that is locked and unlocked { GeocacheToAdd = CurrentGeocache; } lock (RouteToInsertInLocker) //See above { RouteToInsertIn = CurrentPartialRoute.partialRoute; } IndexOfRouteToInsertIn = CurrentPartialRouteIndex; } } } //Remove all geocaches that can't be reached or are already used foreach (GeocacheRoutingInformation Geocache_Info in GeocachesToRemove) { CurrentPartialRoute.GeocachesInReach.Remove(Geocache_Info); } }); #endregion //Won't be able to fit a geocache in if (CompleteRouteData.TotalTime + CompleteRouteData.Profile.TimePerGeocache * 60 > CompleteRouteData.Profile.MaxTime * 60) { GeocacheToAdd = null; } if (GeocacheToAdd != null) { Result <Tuple <Route, Route> > RoutingResult = GetPartialRoutes(CompleteRouteData, RouteToInsertIn, GeocacheToAdd.ResolvedCoordinates); if (!RoutingResult.IsError) { float NewDistance = CompleteRouteData.TotalDistance - RouteToInsertIn.TotalDistance + RoutingResult.Value.Item1.TotalDistance + RoutingResult.Value.Item2.TotalDistance; float NewTimeWithGeocaches = CompleteRouteData.TotalTime - RouteToInsertIn.TotalTime + RoutingResult.Value.Item1.TotalTime + RoutingResult.Value.Item2.TotalTime + (CompleteRouteData.GeocachesOnRoute().Count + 1) * CompleteRouteData.Profile.TimePerGeocache * 60; float NewRoutePoints = CompleteRouteData.TotalPoints + GeocacheToAdd.geocache.Rating; //calculate in meters if (NewDistance < CompleteRouteData.Profile.MaxDistance * 1000 && NewTimeWithGeocaches < CompleteRouteData.Profile.MaxTime * 60) { Debug.WriteLine("Added " + GeocacheToAdd.geocache); CompleteRouteData = ReplaceRoute(CompleteRouteData, RoutingResult.Value.Item1, RoutingResult.Value.Item2, IndexOfRouteToInsertIn); CompleteRouteData.AddGeocacheOnRoute(GeocacheToAdd.geocache); CompleteRouteData.TotalPoints = NewRoutePoints; //Overwrites the addition automatically made in the lne before, to make sure the DisplayPreliminaryRoute(CompleteRouteData); } else { Debug.WriteLine("Made calculation for nothing. Route was longer in distance or time than allowed"); CompleteRouteData.partialRoutes[IndexOfRouteToInsertIn].GeocachesInReach.Remove(GeocacheToAdd); //As the geocache doesn't help from this route } } else { Debug.WriteLine("Routing was errounous. Island detection score:" + FailedRouteCalculations); CompleteRouteData.partialRoutes[IndexOfRouteToInsertIn].GeocachesInReach.Remove(GeocacheToAdd); //Since trying to route to it results in an error } } } while (FailedRouteCalculations < FailedRouteCalculationsLimit && GeocacheToAdd != null); return(CompleteRouteData); }