/// <summary> /// Removes a via way point from the route. /// </summary> /// <param name="wayPoint"></param> public void Remove(WayPoint wayPoint) { // get way point index int idx = WayPoints.ToList().IndexOf(wayPoint); // remove from via list Via.RemoveAt(idx - 1); // try to update snapshot also, if that is possible if (snapshot.Valid(Via.Count + 3)) { snapshot.Indices = snapshot.Indices.RemoveAt(idx); } else { snapshot = new RouteSnapshot(); } // dispose way point - removes the way point from the map wayPoint.Dispose(); // update z indices of via way points UpdateZIndex(ZIndex, false, true); // update route, try a delta update for the portion that changed UpdateRoute(GetRequestData(idx - 1, idx), null); }
/// <summary> /// Creates and initializes a RequestData object. /// </summary> /// <param name="from">Index of the way point marking the begin of the route section that is going to change.</param> /// <param name="to">Index of the way point marking the end of the route section that is going to change.</param> /// <param name="wayPoints">The route way points</param> /// <param name="updateHash">The hash of previous update operations</param> /// <param name="snapshot">The snapshot of the current route</param> public RequestData(int from, int to, WayPoint[] wayPoints, ulong?updateHash, RouteSnapshot snapshot) { // unique, consecutive id of the data object Id = NextId++; // make update hash out of the way point indices Hash = ((ulong)from << 32) | (ulong)to; // initialize snapshots objects Left = new RouteSnapshot(); Right = new RouteSnapshot(); if (wayPoints == null) { return; } // if there are way points ... OriginalWayPoints = wayPoints; // get and store the full list of way points and its labels RequestWaypoints = Waypoints = wayPoints.Select(s => s.Waypoint).ToArray(); Labels = wayPoints.Select(s => s is Stop ? ((Stop)s).Label : "").ToArray(); // if the specified snapshot is valid and the hash matches the hash of previous // updates then we only need to update a portion of the route. // // If the hashes don't match we have multiple pending updates that each update a // different section of the route. In this case we use this data object to force // a full update. if (!snapshot.Valid(wayPoints.Length + 2) || (updateHash.HasValue && updateHash.Value != Hash)) { return; } // get the way points of the route portion to be updated RequestWaypoints = Waypoints.Take(to + 1).Skip(@from).ToArray(); // beginning and end must be a stop - remove any via type set RequestWaypoints.First().viaType = null; RequestWaypoints.Last().viaType = null; // get the parts of the route that remain stable Right = snapshot.Right(to); Left = snapshot.Left(@from); }
/// <summary> /// Handles the route calculation results. /// </summary> /// <param name="result">Route calculation results.</param> public void RouteCalculated(IAsyncResult result) { layer.Map.Dispatcher.Invoke((Action)(() => { // get request data and initialize a snapshot var req = (RequestData)result.AsyncState; var routeSnapshot = new RouteSnapshot(); try { // skip this response if there are newer responses // that have already been processed. if (req.Id < latestIdCalculated) { return; } // store request id latestIdCalculated = req.Id; // get route result var route = xRoute.EndcalculateRoute(result); // create snapshot out of route result routeSnapshot = RouteSnapshot.FromXRoute( route.wrappedStations.Select(w => w.polyIdx).ToArray(), wkbReader.Read(route.polygon.wkb).Coordinates.Select(p => p.PtvSmartUnitsToWgs84()).ToArray(), route.info ); // merge snapshot with request data. If only a part of the route has // been updated, this step creates the 'full route information' routeSnapshot.MergeWithRequest(req); var toolTip = FormatRouteToolTip(req.Labels.First(), req.Labels.Last(), routeSnapshot.Info); UpdateRoutePolylines(routeSnapshot.Points, toolTip, RouteLayer.ROUTE); // if there are no pending updates also set calculationSucceeded flag // and store the polygon indices of the via way points if (updateRef == 1) { calculationSucceeded = routeSnapshot.Valid(Via.Count + 2); if (calculationSucceeded) { for (int i = 0; i < routeSnapshot.Indices.Length; ++i) { if (i == 0 || i == routeSnapshot.Indices.Length - 1) { if (req.OriginalWayPoints[i] is Stop) { ((Stop)req.OriginalWayPoints[i]).LinkPoint = routeSnapshot.Points[Math.Min(routeSnapshot.Points.Length - 1, routeSnapshot.Indices[i])]; } } else { Via[i - 1].PolyIndex = routeSnapshot.Indices[i]; } } } } } catch (Exception e) { // Response processing failed. If there are no pending updates we create an error polyline here. // We also invalidate the route snapshot and set the exception message as the tool tip. if (updateRef == 1) { Func <WaypointDesc, Point> WaypointToPoint = wp => wp.wrappedCoords[0].point.PtvSmartUnitsToWgs84(); UpdateRoutePolylines(req.Waypoints.Select(WaypointToPoint), e.Message, RouteLayer.ROUTE_ERROR); routeSnapshot = new RouteSnapshot(); } } // another update done EndUpdate(routeSnapshot); }), DispatcherPriority.Send, null); }