예제 #1
0
        /// <summary>
        /// Sets directions.
        /// </summary>
        /// <param name="dirs">Directions.</param>
        /// <param name="stops">Stop datas as direction keeper (for update).</param>
        private static void _SetDirections(IList <Direction[]> dirs, IEnumerable <StopData> stops)
        {
            Debug.Assert(stops != null);
            Debug.Assert(dirs != null);

            // sort stops respecting sequence
            var sortedStops = new List <StopData>(stops);

            SolveHelper.SortBySequence(sortedStops);

            int nDir = 0;

            // starts from fisrt, 0 element do not have directions
            for (int index = 1; index < sortedStops.Count; ++index)
            {
                StopData stop = sortedStops[index];
                if (stop.StopType != StopType.Lunch)
                {
                    if (nDir >= dirs.Count)
                    {
                        throw new RouteException(Properties.Messages.Error_InvalidDirectionsNumber); // exception
                    }
                    Direction[] stopDirs = dirs[nDir];

                    // set path
                    if (_IsDirGeometryValid(stopDirs))
                    {
                        // build path from compact geometry
                        stop.Path = _BuildPath(stopDirs);
                    }
                    else
                    {
                        // NOTE: in some cases compact geometry is not set, for example when
                        // route contains one order which point is the same as start and end
                        // locations points

                        // set geometry of associated object
                        var gc = stop.AssociatedObject as IGeocodable;
                        if (gc != null && gc.IsGeocoded)
                        {
                            stop.Path = new Polyline(new Point[] { (Point)gc.GeoLocation });
                        }
                        else
                        {
                            throw new RouteException(Properties.Messages.Error_BuildStopPathFailed); // exception
                        }
                    }

                    // set directions
                    stop.Directions = stopDirs;
                    ++nDir;
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Method do merge of every Lunch directions with Next stop directions.
        /// Not maneuver, Break Arrive and Break Depart directions are passed.
        /// </summary>
        /// <param name="dirs">Directions.</param>
        /// <param name="stops">Stops.</param>
        /// <returns>Merged directions.</returns>
        private static IList <Direction[]> _MergeBreaksDirections(
            IList <DirectionEx[]> dirs, IEnumerable <StopData> stops)
        {
            Debug.Assert(dirs != null);
            Debug.Assert(stops != null);

            // Sort stops respecting sequence.
            var sortedStops = new List <StopData>(stops);

            SolveHelper.SortBySequence(sortedStops);

            int stopIndex       = 0;
            var lunchDirections = new List <DirectionEx>();

            // Flag is needed for cases when breaks goes one by one.
            bool isLunchFoundBefore = false;

            // Flag means that route started from Lunch (route with Virtual Depot).
            bool lunchAtStart = true;

            if (sortedStops[0].StopType != StopType.Lunch)
            {
                lunchAtStart = false;
            }

            // Start from first element since zero element doesn't have directions.
            for (int index = 1; index < sortedStops.Count; ++index)
            {
                if (stopIndex >= dirs.Count)
                {
                    throw new RouteException(
                              Properties.Messages.Error_InvalidDirectionsNumber);
                }

                DirectionEx[] stopDirections = dirs[stopIndex];

                // Find all Lunch Stops.
                if (sortedStops[index].StopType == StopType.Lunch)
                {
                    if (isLunchFoundBefore)
                    {   // This lunch goes after another one: merge lunch directions.
                        lunchDirections.AddRange(
                            _FilterManeuverDirections(stopDirections,
                                                      StopManeuverType.Stop, StopManeuverType.Depart));

                        // Remove current lunch directions (if it is), to stay with merged ones.
                        if (_IsBreakDirection(dirs[stopIndex]))
                        {
                            dirs.RemoveAt(stopIndex);
                        }
                    }
                    else
                    {
                        if (lunchAtStart)
                        {
                            // First lunch is first on route at all: get only Maneuver directions.
                            lunchDirections = _FilterManeuverDirections(stopDirections,
                                                                        StopManeuverType.Stop, StopManeuverType.Depart);
                        }
                        else
                        {
                            // First lunch in stops queue: get only Maneuver and Depart directions.
                            lunchDirections = _FilterManeuverDirections(stopDirections,
                                                                        StopManeuverType.Stop);
                        }

                        // Remove current lunch directions, to stay with merged ones.
                        dirs.RemoveAt(stopIndex);
                    }

                    // Set flag to consider case when breaks goes one by one.
                    isLunchFoundBefore = true;
                }
                // Remove Depart of last Break and merge all found Lunch directions
                // with stop directions.
                else
                {
                    lunchAtStart = false;

                    if (isLunchFoundBefore)
                    {
                        // Final lunch direction: merge lunch and stops directions.
                        var stopsWithoutDepart = _FilterManeuverDirections(stopDirections,
                                                                           StopManeuverType.Depart);
                        lunchDirections.AddRange(stopsWithoutDepart);

                        dirs[stopIndex] = lunchDirections.ToArray();
                        lunchDirections.Clear();
                        isLunchFoundBefore = false;
                    }

                    ++stopIndex;
                }
            }

            return(_ConvertToDirectionsWithoutType(dirs));
        }
예제 #3
0
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////
        ///////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Builds stop features.
        /// </summary>
        /// <param name="stops">Stops.</param>
        /// <returns>Created route stops recordset for stops.</returns>
        private RouteStopsRecordSet _BuildStopFeatures(IList <StopData> stops)
        {
            Debug.Assert(stops != null);

            // Sort stops respecting sequence.
            var sortedStops = new List <StopData>(stops);

            SolveHelper.SortBySequence(sortedStops);

            Debug.Assert(_context != null);

            SolveHelper.ConsiderArrivalDelayInStops(
                _context.SolverSettings.ArriveDepartDelay, sortedStops);

            // Format impedance attribute name.
            string impedanceAttrName = null;

            if (!string.IsNullOrEmpty(_context.NetworkDescription.ImpedanceAttributeName))
            {
                impedanceAttrName = string.Format(IMPEDANCE_ATTR_FORMAT,
                                                  _context.NetworkDescription.ImpedanceAttributeName);
            }

            var features = new List <GPFeature>();

            for (int index = 0; index < sortedStops.Count; ++index)
            {
                var feature = new GPFeature();

                // Attributes.
                feature.Attributes = new AttrDictionary();

                StopData sd = sortedStops[index];

                Guid objectId = Guid.Empty;
                if (sd.AssociatedObject != null)
                {
                    objectId = sd.AssociatedObject.Id;
                }

                feature.Attributes.Add(NAAttribute.NAME, objectId.ToString());
                feature.Attributes.Add(NAAttribute.ROUTE_NAME, sd.RouteId.ToString());

                // Effective time window.
                DateTime?twStart = null;
                DateTime?twEnd   = null;
                _GetEffectiveTW(sd, out twStart, out twEnd); // NOTE: ignore result
                feature.Attributes.Add(NAAttribute.TW_START, _FormatStopTime(twStart));
                feature.Attributes.Add(NAAttribute.TW_END, _FormatStopTime(twEnd));

                // Service time.
                if (impedanceAttrName != null)
                {
                    feature.Attributes.Add(impedanceAttrName, sd.TimeAtStop);
                }

                var geometry = new GeometryHolder();
                geometry.Value = sd.Geometry;

                if (sd.StopType == StopType.Lunch)
                {
                    var actualStop = SolveHelper.GetActualLunchStop(sortedStops, index);
                    geometry.Value = actualStop.Geometry;
                }

                // Set curb approach.
                var curbApproach = CurbApproachConverter.ToNACurbApproach(
                    _context.SolverSettings.GetOrderCurbApproach());
                if (sd.StopType == StopType.Location)
                {
                    curbApproach = CurbApproachConverter.ToNACurbApproach(
                        _context.SolverSettings.GetDepotCurbApproach());
                }

                feature.Attributes.Add(NAAttribute.CURB_APPROACH, (int)curbApproach);
                feature.Geometry = geometry;

                features.Add(feature);
            }

            var rs = new RouteStopsRecordSet();

            rs.Features = features.ToArray();

            // TODO: will be changed later when support custom AddLocations tool
            rs.DoNotLocateOnRestrictedElements = _context.SolverSettings.ExcludeRestrictedStreets;

            return(rs);
        }