Exemplo n.º 1
0
        /// <summary>
        /// Inserts a via way point at the specified position.
        /// </summary>
        /// <param name="p">Location of the via way point</param>
        /// <param name="style">Display style of the via way point</param>
        /// <returns>The newly created via way point</returns>
        private Via InsertVia(Point p, ShapeStyle style)
        {
            // create the way point and set owner
            var via = new Via(layer, p, style)
            {
                Route = this
            };

            // find the index where to insert the via way point and insert it there
            Via.Insert(GetViaIndex(via), via);

            // try to update the snapshot if that is possible
            if (snapshot.Valid(Via.Count + 1))
            {
                snapshot.Indices = snapshot.Indices.Insert(Via.IndexOf(via) + 1, via.PolyIndex);
            }
            else
            {
                snapshot = new RouteSnapshot();
            }

            // force via way point z index update
            UpdateZIndex(ZIndex, false, true);

            // return the newly created via way point
            return(via);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Merges this route with another route.
        /// This is usually triggered if a stop is removed.
        /// </summary>
        /// <param name="other"></param>
        public void MergeWith(Route other)
        {
            // invalidate snapshot, force full calculation
            //
            // TODO: this could be optimized. If both routes have a
            // valid snapshot we could create combined snapshot. The update
            // section would then be:
            //
            // from = Via.Count (<- the count before other via way points have been inserted)
            // to = from + 1;
            snapshot = new RouteSnapshot();

            // transfer other via way points
            Via.AddRange(other.Via);

            // set new owner
            other.Via.ForEach(via => via.Route = this);

            // update the z index of the via way points
            UpdateZIndex(ZIndex, false, true);

            // clear via way points of other route
            other.Via.Clear();

            // try to display sort of a preview and trigger update
            UpdateRoutePolylines(Points.Concat(other.Points), "", RouteLayer.ROUTE);
            UpdateRoute(GetRequestData(), null);
        }
Exemplo n.º 3
0
        /// <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);
        }
Exemplo n.º 4
0
        /// <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);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Concatenates two snapshots.
        /// </summary>
        /// <param name="other">Snapshot to concat.</param>
        /// <returns>Concatenated snapshots.</returns>
        private RouteSnapshot Concat(RouteSnapshot other)
        {
            if (!ValidExceptRouteInfo())
            {
                return(other);
            }

            if (!other.ValidExceptRouteInfo())
            {
                return(this);
            }

            return(new RouteSnapshot(
                       Indices.Concat(other.Indices.Skip(1).Select(i => i + Points.Length)),
                       Points.Concat(other.Points),
                       Info ?? other.Info
                       ));
        }
Exemplo n.º 6
0
        /// <summary>
        /// Gets optimized request data for the specified portion of the route that changed.
        /// </summary>
        /// <param name="changesFrom">Index of the way point marking the begin of the route section that changed.</param>
        /// <param name="changesTo">Index of the way point marking the end of the route section that changed.</param>
        /// <returns>Request data object</returns>
        private RequestData GetRequestData(int changesFrom, int changesTo)
        {
            // be sure the indices are in range
            changesFrom = Math.Max(changesFrom, 0);
            changesTo   = Math.Min(changesTo, Via.Count + 1);

            // create request data object
            var data = new RequestData(changesFrom, changesTo,
                                       CanCalculate ? WayPoints.ToArray() : null, updateHash, snapshot);

            // see if snapshot must be invalidated
            if (!snapshot.Valid(Via.Count + 2) || (updateHash.HasValue && updateHash.Value != data.Hash))
            {
                snapshot = new RouteSnapshot();
            }

            // done
            return(data);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Called when an update ends.
        /// </summary>
        /// <param name="resp"></param>
        /// <param name="bFromTimer"></param>
        private void EndUpdate(RouteSnapshot resp = null, bool bFromTimer = false)
        {
            // decrement update counter. If there are no pending updates ...
            if (Interlocked.Decrement(ref updateRef) != 0)
            {
                return;
            }

            // reset update hash
            updateHash = null;

            // if end update has been triggered by the update timer (no matter in what way)
            // other updates will start soon. In this case do no update snapshot and tooltip.

            if (bFromTimer)
            {
                return;
            }

            snapshot = resp ?? new RouteSnapshot();
            layer.UpdateRouteToolTips();
        }
Exemplo n.º 8
0
        /// <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);
        }