bool UpdateFromProvider(CachedDistance distance) { if (ErrorWays.Any(x => x.FromHash == distance.FromGeoHash && x.ToHash == distance.ToGeoHash)) { //logger.Warn("Повторный запрос дистанции с ошибкой расчета. Пропускаем..."); return(false); } //logger.Info("Запрашиваем путь {0}->{1} у сервиса {0}.", distance.FromGeoHash, distance.ToGeoHash, Provider); List <PointOnEarth> points = new List <PointOnEarth>(); double latitude, longitude; CachedDistance.GetLatLon(distance.FromGeoHash, out latitude, out longitude); points.Add(new PointOnEarth(latitude, longitude)); CachedDistance.GetLatLon(distance.ToGeoHash, out latitude, out longitude); points.Add(new PointOnEarth(latitude, longitude)); bool ok = false; if (Provider == DistanceProvider.Osrm) { var result = OsrmMain.GetRoute(points, false, GeometryOverview.Full); ok = result?.Code == "Ok"; if (ok && result.Routes.Any()) { distance.DistanceMeters = result.Routes.First().TotalDistance; distance.TravelTimeSec = result.Routes.First().TotalTimeSeconds; distance.PolylineGeometry = result.Routes.First().RouteGeometry; } } else { var result = SputnikMain.GetRoute(points, false, true); ok = result.Status == 0; if (ok) { distance.DistanceMeters = result.RouteSummary.TotalDistance; distance.TravelTimeSec = result.RouteSummary.TotalTimeSeconds; distance.PolylineGeometry = result.RouteGeometry; } } if (ok) { lock (uow) { AddNewCacheDistance(distance); uow.TrySave(distance); uow.Commit(); } addedCached++; return(true); } ErrorWays.Add(new WayHash(distance.FromGeoHash, distance.ToGeoHash)); totalErrors++; return(false); }
public virtual SputnikRouteResponse CalculateDistanceToBase() { var lastAddress = RouteList.Addresses .Where(x => x.Status == RouteListItemStatus.Completed) .OrderByDescending(x => x.StatusLastUpdate) .FirstOrDefault(); if (lastAddress == null) { DistanceToBase = null; return(null); } var points = new List <PointOnEarth>(); var lastPoint = lastAddress.Order.DeliveryPoint; points.Add(new PointOnEarth(lastPoint.Latitude.Value, lastPoint.Longitude.Value)); //Координаты базы if (lastPoint.District == null) { logger.Warn("Для точки доставки не удалось подобрать часть города. Расчёт расстояния до центра СПб"); points.Add(new PointOnEarth(Constants.CenterOfCityLatitude, Constants.CenterOfCityLongitude)); } else if (lastPoint.District != null && lastPoint.District.GeographicGroup.BaseCoordinatesExist) { var gg = lastPoint.District.GeographicGroup; points.Add(new PointOnEarth((double)gg.BaseLatitude.Value, (double)gg.BaseLongitude.Value)); } else { logger.Error("В подобранной части города не указаны координаты базы"); return(null); } var response = SputnikMain.GetRoute(points, false, true); if (response.Status == 0) { DistanceToBase = (double)response.RouteSummary.TotalDistanceKm; } else { logger.Error("Ошибка при получении расстояния до базы {0}: {1}", response.Status, response.StatusMessage); } return(response); }
private CachedDistance LoadDistanceFromService(long fromHash, long toHash) { CachedDistance cachedValue = null; bool ok = false; if (fromHash == toHash) { cachedValue = new CachedDistance { DistanceMeters = 0, TravelTimeSec = 0, FromGeoHash = fromHash, ToGeoHash = toHash }; AddNewCacheDistance(cachedValue); addedCached++; ok = true; } if (!ok) { List <PointOnEarth> points = new List <PointOnEarth> { CachedDistance.GetPointOnEarth(fromHash), CachedDistance.GetPointOnEarth(toHash) }; if (Provider == DistanceProvider.Osrm) { var result = OsrmMain.GetRoute(points, false, GeometryOverview.False); ok = result?.Code == "Ok"; if (ok && result.Routes.Any()) { cachedValue = new CachedDistance { DistanceMeters = result.Routes.First().TotalDistance, TravelTimeSec = result.Routes.First().TotalTimeSeconds, FromGeoHash = fromHash, ToGeoHash = toHash }; } } else { var result = SputnikMain.GetRoute(points, false, false); ok = result.Status == 0; if (ok) { cachedValue = new CachedDistance { DistanceMeters = result.RouteSummary.TotalDistance, TravelTimeSec = result.RouteSummary.TotalTimeSeconds, FromGeoHash = fromHash, ToGeoHash = toHash }; } } } if (MultiTaskLoad && ok) { lock (UoW) { UoW.TrySave(cachedValue as CachedDistance, false); unsavedItems++; if (unsavedItems >= SaveBy) { FlushCache(); } AddNewCacheDistance(cachedValue); addedCached++; } return(cachedValue); } if (ok) { AddNewCacheDistance(cachedValue); addedCached++; return(cachedValue); } ErrorWays.Add(new WayHash(fromHash, toHash)); totalErrors++; //FIXME Реализовать запрос манхентанского расстояния. return(null); }
protected void OnButtonFindGapClicked(object sender, EventArgs e) { trackOnGapOverlay.Clear(); tracksDistance.RemoveAll(x => x.Id == "MissingTrack"); string message = "Найдены разрывы в треке:"; double replacedDistance = 0; TrackPoint lastPoint = null; foreach (var point in track.TrackPoints) { if (lastPoint == null) { lastPoint = point; continue; } var distance = GMapProviders.EmptyProvider.Projection.GetDistance( new PointLatLng(lastPoint.Latitude, lastPoint.Longitude), new PointLatLng(point.Latitude, point.Longitude)); if (distance > 0.5) { logger.Info("Найден разрыв в треке расстоянием в {0}", distance); message += string.Format("\n* разрыв c {1:t} по {2:t} — {0:N1} км.", distance, lastPoint.TimeStamp, point.TimeStamp ); replacedDistance += distance; var addressesByCompletion = routeList.Addresses .Where(x => x.Status == RouteListItemStatus.Completed) .OrderBy(x => x.StatusLastUpdate) .ToList(); RouteListItem addressBeforeGap = addressesByCompletion.LastOrDefault(x => x.StatusLastUpdate < lastPoint.TimeStamp.AddMinutes(2)); RouteListItem addressAfterGap = addressesByCompletion.FirstOrDefault(x => x.StatusLastUpdate > point.TimeStamp.AddMinutes(-2)); var beforeIndex = addressBeforeGap == null ? -1 : addressesByCompletion.IndexOf(addressBeforeGap); var afterIndex = addressAfterGap == null ? addressesByCompletion.Count : addressesByCompletion.IndexOf(addressAfterGap); var routePoints = new List <PointOnEarth> { new PointOnEarth(lastPoint.Latitude, lastPoint.Longitude) }; if (afterIndex - beforeIndex > 1) { var throughAddress = addressesByCompletion.GetRange(beforeIndex + 1, afterIndex - beforeIndex - 1); logger.Info("В разрыве найдены выполенные адреса порядковый(е) номер(а) {0}", String.Join(", ", throughAddress.Select(x => x.IndexInRoute))); routePoints.AddRange( throughAddress.Where(x => x.Order?.DeliveryPoint?.Latitude != null && x.Order?.DeliveryPoint?.Longitude != null) .Select(x => new PointOnEarth(x.Order.DeliveryPoint.Latitude.Value, x.Order.DeliveryPoint.Longitude.Value))); message += $" c выполненными адресами({beforeIndex + 2}-{afterIndex}) п/п в МЛ " + String.Join(", ", throughAddress.Select(x => x.IndexInRoute)); } routePoints.Add(new PointOnEarth(point.Latitude, point.Longitude)); var missedTrack = SputnikMain.GetRoute(routePoints, false, true); if (missedTrack == null) { MessageDialogHelper.RunErrorDialog("Не удалось получить ответ от сервиса \"Спутник\""); return; } if (missedTrack.Status != 0) { MessageDialogHelper.RunErrorDialog("Cервис \"Спутник\" сообщил об ошибке {0}: {1}", missedTrack.Status, missedTrack.StatusMessageRus); return; } var decodedPoints = Polyline.DecodePolyline(missedTrack.RouteGeometry); var points = decodedPoints.Select(p => new PointLatLng(p.Latitude * 0.1, p.Longitude * 0.1)).ToList(); var route = new GMapRoute(points, "MissedRoute") { Stroke = new Pen(Color.DarkMagenta) { Width = 4, DashStyle = System.Drawing.Drawing2D.DashStyle.Dot } }; trackOnGapOverlay.Routes.Add(route); } lastPoint = point; } if (trackOnGapOverlay.Routes.Count > 0) { var distanceLayout = MakeDistanceLayout(trackOnGapOverlay.Routes.ToArray()); distanceLayout.Id = "MissingTrack"; tracksDistance.Add(distanceLayout); var oldDistance = track.DistanceEdited ? trackRoute.Distance : track.Distance; var missedRouteDistance = trackOnGapOverlay.Routes.Sum(x => x.Distance); var newDistance = oldDistance - replacedDistance + missedRouteDistance; var diffDistance = newDistance - oldDistance; message += $"\n Старая длинна трека:{oldDistance:N1} км." + $"\n Новая длинна трека: {newDistance:N1} км.(+{diffDistance:N1})" + "\n Сохранить изменения длинны трека?"; if (MessageDialogHelper.RunQuestionDialog(message)) { track.Distance = newDistance; track.DistanceEdited = true; UoW.Save(track); UoW.Commit(); UpdateDistanceLabel(); } } else { MessageDialogHelper.RunInfoDialog("Разрывов в треке не найдено."); } }