예제 #1
0
        /// <summary>
        /// Expands an island starting the given vertex.
        /// </summary>
        private uint Expand(uint vertex, ushort island)
        {
            var min = uint.MaxValue;

            _enumerator.MoveTo(vertex);

            while (_enumerator.MoveNext())
            {
                var neighbour = _enumerator.To;
                if (_vertexFlags.Contains(neighbour))
                {
                    continue;
                }

                float  distance;
                ushort edgeProfile;
                EdgeDataSerializer.Deserialize(_enumerator.Data0, out distance, out edgeProfile);

                if (!_canTraverse.Contains(edgeProfile))
                {
                    continue;
                }

                _islands[neighbour] = island; // set the island.

                if (neighbour < min)
                {
                    min = neighbour;
                }
            }
            return(min);
        }
예제 #2
0
        protected override void DoRun()
        {
            bool?nullable = new bool?();
            Dictionary <ushort, Factor> dictionary = new Dictionary <ushort, Factor>();

            Graph.EdgeEnumerator edgeEnumerator = this._source.GetEdgeEnumerator();
            for (uint vertex = 0; vertex < this._source.VertexCount; ++vertex)
            {
                edgeEnumerator.MoveTo(vertex);
                edgeEnumerator.Reset();
                while (edgeEnumerator.MoveNext())
                {
                    float  distance;
                    ushort profile;
                    EdgeDataSerializer.Deserialize(edgeEnumerator.Data0, out distance, out profile);
                    Factor factor = Factor.NoFactor;
                    if (!dictionary.TryGetValue(profile, out factor))
                    {
                        factor = this._getFactor(profile);
                        dictionary[profile] = factor;
                    }
                    if ((double)factor.Value != 0.0)
                    {
                        bool?direction = new bool?();
                        if ((int)factor.Direction == 1)
                        {
                            direction = new bool?(true);
                            if (edgeEnumerator.DataInverted)
                            {
                                direction = new bool?(false);
                            }
                        }
                        else if ((int)factor.Direction == 2)
                        {
                            direction = new bool?(false);
                            if (edgeEnumerator.DataInverted)
                            {
                                direction = new bool?(true);
                            }
                        }
                        uint data = ContractedEdgeDataSerializer.Serialize(distance * factor.Value, direction);
                        int  num  = (int)this._target.AddEdge(edgeEnumerator.From, edgeEnumerator.To, data, 4294967294U);
                    }
                }
            }
            this.HasSucceeded = true;
        }
예제 #3
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            // while the visit list is not empty.
            _current = null;
            if (_heap.Count > 0)
            { // choose the next vertex.
                _current = _heap.Pop();
                while (_current != null && _visits.ContainsKey(_current.Vertex))
                {     // keep dequeuing.
                    if (_heap.Count == 0)
                    { // nothing more to pop.
                        break;
                    }

                    if (this.Visit != null &&
                        this.Visit(_current))
                    { // edge was found and true was returned, this search should stop.
                        return(false);
                    }

                    _current = _heap.Pop();
                }
            }

            if (_current != null &&
                !_visits.ContainsKey(_current.Vertex))
            { // we visit this one, set visit.
                _visits[_current.Vertex] = _current;
            }
            else
            { // route is not found, there are no vertices left
                // or the search went outside of the max bounds.
                return(false);
            }

            if (this.WasFound != null &&
                this.WasFound(_current.Vertex, _current.Weight))
            { // vertex was found and true was returned, this search should stop.
                return(false);
            }

            // check for restrictions.
            var restriction = Constants.NO_VERTEX;

            if (_getRestriction != null)
            {
                restriction = _getRestriction(_current.Vertex);
            }
            if (restriction != Constants.NO_VERTEX)
            { // this vertex is restricted, step is a success but just move
                // to the next one because this vertex's neighbours are not allowed.
                return(true);
            }

            if (this.Visit != null &&
                this.Visit(_current))
            { // edge was found and true was returned, this search should stop.
                return(false);
            }

            // get neighbours and queue them.
            _edgeEnumerator.MoveTo(_current.Vertex);
            while (_edgeEnumerator.MoveNext())
            {
                var edge      = _edgeEnumerator;
                var neighbour = edge.To;

                if (_current.From != null &&
                    _current.From.Vertex == neighbour)
                { // don't go back
                    continue;
                }

                if (this.Visit == null)
                {
                    if (_visits.ContainsKey(neighbour))
                    { // has already been choosen
                        continue;
                    }
                }

                // get the speed from cache or calculate.
                float  distance;
                ushort edgeProfile;
                EdgeDataSerializer.Deserialize(edge.Data0, out distance, out edgeProfile);
                var factor      = Factor.NoFactor;
                var totalWeight = _weightHandler.Add(_current.Weight, edgeProfile, distance, out factor);

                // check the tags against the interpreter.
                if (factor.Value > 0 && (factor.Direction == 0 ||
                                         (!_backward && (factor.Direction == 1) != edge.DataInverted) ||
                                         (_backward && (factor.Direction == 1) == edge.DataInverted)))
                { // it's ok; the edge can be traversed by the given vehicle.
                    // calculate neighbors weight.
                    var edgeWeight = (distance * factor.Value);

                    if (_weightHandler.IsSmallerThan(totalWeight, _sourceMax))
                    { // update the visit list.
                        _heap.Push(new EdgePath <T>(neighbour, totalWeight, edge.IdDirected(), _current),
                                   _weightHandler.GetMetric(totalWeight));
                    }
                    else
                    { // the maxium was reached.
                        this.MaxReached = true;
                    }
                }
            }
            return(true);
        }
예제 #4
0
 /// <summary>
 /// Moves to the given vertex.
 /// </summary>
 /// <returns></returns>
 public bool MoveTo(uint vertex)
 {
     return(_enumerator.MoveTo(vertex));
 }
예제 #5
0
        /// <summary>
        /// Executes one step in the search.
        /// </summary>
        public bool Step()
        {
            // while the visit list is not empty.
            var cPointer = uint.MaxValue;

            while (cPointer == uint.MaxValue)
            { // choose the next edge.
                if (_pointerHeap.Count == 0)
                {
                    return(false);
                }
                cPointer = _pointerHeap.Pop();
            }

            // get details.
            uint cEdge, cPreviousPointer;
            T    cWeight;

            _weightHandler.GetPathTree(_pathTree, cPointer, out cEdge, out cWeight, out cPreviousPointer);
            if (_visits.Contains(cEdge))
            {
                return(true);
            }
            _visits.Add(cEdge);
            var cDirectedEdge = new DirectedEdgeId()
            {
                Raw = cEdge
            };

            // signal was found.
            if (this.WasFound != null)
            {
                this.WasFound(cPointer, cDirectedEdge, cWeight);
            }

            // move to the current edge's target vertex.
            _edgeEnumerator.MoveToEdge(cDirectedEdge.EdgeId);
            var cOriginalEdge = new OriginalEdge(_edgeEnumerator.From, _edgeEnumerator.To);

            if (!cDirectedEdge.Forward)
            {
                cOriginalEdge = cOriginalEdge.Reverse();
            }
            var cEdgeWeightAndDirection = _weightHandler.GetEdgeWeight(_edgeEnumerator);

            // calculate total weight.
            var totalWeight = _weightHandler.Add(cEdgeWeightAndDirection.Weight, cWeight);

            if (!_weightHandler.IsSmallerThan(totalWeight, _sourceMax))
            { // weight is too big.
                this.MaxReached = true;
                return(true);
            }

            // loop over all neighbours.
            _edgeEnumerator.MoveTo(cOriginalEdge.Vertex2);
            var turn = new Turn(cOriginalEdge, Constants.NO_VERTEX);

            _restrictions.Update(turn.Vertex2);
            while (_edgeEnumerator.MoveNext())
            {
                turn.Vertex3 = _edgeEnumerator.To;
                if (turn.IsUTurn ||
                    turn.IsRestrictedBy(_restrictions))
                { // turn is restricted.
                    continue;
                }

                var nDirectedEdgeId = _edgeEnumerator.DirectedEdgeId();
                if (_visits.Contains(nDirectedEdgeId.Raw))
                { // has already been choosen.
                    continue;
                }

                // get the speed from cache or calculate.
                var nWeightAndDirection = _weightHandler.GetEdgeWeight(_edgeEnumerator);
                var nWeightMetric       = _weightHandler.GetMetric(nWeightAndDirection.Weight);
                if (nWeightMetric <= 0)
                { // edge is not valid for profile.
                    continue;
                }
                if (!_backward && !nWeightAndDirection.Direction.F)
                { // cannot do forward search on edge.
                    continue;
                }
                if (_backward && !nWeightAndDirection.Direction.B)
                { // cannot do backward on edge.
                    continue;
                }

                // update the visit list.
                _pointerHeap.Push(_weightHandler.AddPathTree(_pathTree, nDirectedEdgeId.Raw, totalWeight, cPointer), _weightHandler.GetMetric(totalWeight));
            }
            return(true);
        }