Пример #1
0
        /// <summary>
        /// Expands the current fill area with all neighbors of the specified <see cref="Graph"/>
        /// node for which the matching predicate succeeds.</summary>
        /// <param name="node">
        /// The <see cref="Graph"/> node whose neighbors to examine.</param>
        /// <remarks><para>
        /// <b>ExpandArea</b> recursively visits all contiguous nodes for which the matching
        /// predicate succeeds, and adds them to the <see cref="Nodes"/> collection.
        /// </para><para>
        /// <b>ExpandArea</b> never revisits nodes that were already added or rejected. The source
        /// node specified in the <see cref="FindMatching"/> call is never added to the <b>Nodes</b>
        /// collection.</para></remarks>

        private void ExpandArea(T node)
        {
            // get valid neighbors of current node
            IList <T> neighbors = Graph.GetNeighbors(node);

            // recurse into all valid neighbors
            for (int i = 0; i < neighbors.Count; i++)
            {
                T neighbor = neighbors[i];

                // skip visited nodes
                if (_visited.Contains(neighbor))
                {
                    continue;
                }
                _visited.Add(neighbor);

                // add match and visit neighbors
                if (_match(neighbor))
                {
                    _nodes.Add(neighbor);
                    ExpandArea(neighbor);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Expands the current coverage area with all neighbors of the specified <see
        /// cref="Graph"/> node that can be reached by the current <see cref="Agent"/>.</summary>
        /// <param name="node">
        /// The <see cref="Graph"/> node whose neighbors to examine.</param>
        /// <param name="cost">
        /// The total path cost to reach <paramref name="node"/>, measured as the sum of all <see
        /// cref="IGraphAgent{T}.GetStepCost"/> results for each movement step between neighboring
        /// nodes.</param>
        /// <remarks><para>
        /// <b>ExpandArea</b> recursively computes all possible movement paths for the current <see
        /// cref="Agent"/>, adding all valid nodes in any affordable path to the <see cref="Nodes"/>
        /// collection.
        /// </para><para>
        /// <b>ExpandArea</b> never revisits nodes that were already reached by a better path. The
        /// source node specified in the <see cref="FindReachable"/> call is never added to the
        /// <b>Nodes</b> collection.</para></remarks>

        private void ExpandArea(T node, double cost)
        {
            // get valid neighbors of current node
            IList <T> neighbors = Graph.GetNeighbors(node);

            // recurse into all valid neighbors
            for (int i = 0; i < neighbors.Count; i++)
            {
                T      neighbor = neighbors[i];
                double minCost;

                // skip nodes with better path
                _pathCosts.TryGetValue(neighbor, out minCost);
                if (minCost != 0 && minCost <= cost)
                {
                    continue;
                }

                // skip unreachable nodes
                if (!_agent.CanMakeStep(node, neighbor))
                {
                    continue;
                }

                // get cost for next movement step
                double stepCost = _agent.GetStepCost(node, neighbor);
                Debug.Assert(stepCost > 0);

                // skip unaffordable nodes
                if (!_agent.RelaxedRange && cost + stepCost > _maxCost)
                {
                    continue;
                }

                // skip nodes with better path
                if (minCost != 0 && minCost <= cost + stepCost)
                {
                    continue;
                }

                // add newly reached neighbor if possible
                if (minCost == 0 && _agent.CanOccupy(neighbor))
                {
                    _nodes.Add(neighbor);
                }

                // store new minimum path cost
                _pathCosts[neighbor] = cost + stepCost;

                // visit neighbors if still affordable
                if (cost + stepCost < _maxCost)
                {
                    ExpandArea(neighbor, cost + stepCost);
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Adds all valid neighbors as children to the specified parent node.</summary>
        /// <param name="parent">
        /// The <see cref="PathNode{T}"/> whose neighbors to examine.</param>

        private void CreateChildren(PathNode <T> parent)
        {
            T source = parent.Node;

            // compute direct neighbors of parent node
            IList <T> neighbors = Graph.GetNeighbors(source);

            // link all children that can be reached
            for (int i = 0; i < neighbors.Count; i++)
            {
                T neighbor = neighbors[i];

                if (_agent.CanMakeStep(source, neighbor))
                {
                    LinkChild(parent, neighbor);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Expands the current collection of obscuring <see cref="Graph"/> nodes with all neighbors
        /// of the specified node, within maximum world distance from the source node.</summary>
        /// <param name="node">
        /// The <see cref="Graph"/> node whose neighbors to examine.</param>
        /// <remarks><para>
        /// <b>FindObscuringNodes</b> recursively visits all directly connected nodes, and adds them
        /// to an internal collection of obscuring nodes if they are opaque. Nodes which are fully
        /// obscured by other obscuring nodes are removed from the collection.
        /// </para><para>
        /// <b>FindObscuringNodes</b> never revisits nodes that were already examined. All visited
        /// nodes are added to <see cref="NodeArcs"/> for later processing by <see
        /// cref="FindVisibleNodes"/>.</para></remarks>

        private void FindObscuringNodes(T node)
        {
            // get valid neighbors of current node
            IList <T> neighbors = Graph.GetNeighbors(node);

            // recurse into all valid neighbors
            for (int i = 0; i < neighbors.Count; i++)
            {
                T neighbor = neighbors[i];

                // skip source and previously visited nodes
                if (ComparerCache <T> .EqualityComparer.Equals(_source, neighbor) ||
                    _nodeArcs.ContainsKey(neighbor))
                {
                    continue;
                }

                // compute tangential arc and source distance
                NodeArc arc = CreateNodeArc(neighbor);

                // skip nodes beyond maximum distance
                if (_distance > 0 && arc.Distance > _distance)
                {
                    continue;
                }

                // record visited node with tangential arc
                _nodeArcs.Add(neighbor, arc);

                // nothing else to do for transparent nodes
                if (!_isOpaque(neighbor))
                {
                    goto nextNeighbor;
                }

                /*
                 * Try adding current opaque node to list of all obscuring nodes recorded so far.
                 *
                 * If any single recorded node completely obscures the current node, we skip it.
                 * If the current node completely obscures any recorded nodes, we delete those.
                 *
                 * We also clear the VisiblityFraction for all completely obscured nodes (current
                 * or recorded) so we won't waste time testing them again in FindVisibleNodes.
                 */

                foreach (var pair in _obscuringNodes)
                {
                    int result = arc.IsObscured(pair.Value);

                    if (result < 0)
                    {
                        arc._visibleFraction = 0;
                        goto nextNeighbor;
                    }
                    if (result > 0)
                    {
                        pair.Value._visibleFraction = 0;
                        _removeNodes.Add(pair.Key);
                    }
                }

                // remove obscuring nodes that were themselves obscured
                for (int j = 0; j < _removeNodes.Count; j++)
                {
                    _obscuringNodes.Remove(_removeNodes[j]);
                }
                _removeNodes.Clear();

                // add neighbor to obscuring nodes
                _obscuringNodes.Add(neighbor, arc);

nextNeighbor:
                FindObscuringNodes(neighbor);
            }
        }