Exemplo n.º 1
0
        /// <summary>
        /// Determines whether the current <see cref="NodeArc"/> completely obscures the specified
        /// instance, or vice versa.</summary>
        /// <param name="arc">
        /// The <see cref="NodeArc"/> to examine.</param>
        /// <returns><para>
        /// An <see cref="Int32"/> value indicating the relative obscuration of this instance and
        /// <paramref name="arc"/>, as follows:
        /// </para><list type="table"><listheader>
        /// <term>Return Value</term><description>Condition</description>
        /// </listheader><item>
        /// <term>Less than zero</term><description>
        /// <paramref name="arc"/> completely obscures this instance.</description>
        /// </item><item>
        /// <term>Zero</term><description>
        /// Neither instance completely obscures the other.</description>
        /// </item><item>
        /// <term>Greater than zero</term><description>
        /// This instance completely obscures <paramref name="arc"/>.</description>
        /// </item></list></returns>
        /// <remarks>
        /// <b>IsObscured</b> takes the <see cref="Distance"/> of both instances into account to
        /// determine which instance obscures the other, if any.</remarks>

        public int IsObscured(NodeArc arc)
        {
            // start of specified arc relative to current arc
            double relativeStart = arc.Start - Start;

            if (relativeStart <= -Math.PI)
            {
                relativeStart += 2 * Math.PI;
            }
            else if (relativeStart > Math.PI)
            {
                relativeStart -= 2 * Math.PI;
            }

            Debug.Assert(relativeStart > -Math.PI && relativeStart <= Math.PI);
            double relativeSweep = relativeStart + arc.Sweep;

            // specified arc completely obscures current arc
            if (relativeStart <= 0 && relativeSweep >= Sweep && arc.Distance <= Distance)
            {
                return(-1);
            }

            // current arc completely obscures specified arc
            if (relativeStart >= 0 && relativeSweep <= Sweep && arc.Distance > Distance)
            {
                return(+1);
            }

            return(0);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Expands the current visibility area with all visible <see cref="Graph"/> nodes, within
        /// maximum world distance from the source node.</summary>
        /// <remarks><para>
        /// <b>FindVisibleNodes</b> iterates over all <see cref="NodeArcs"/> found by <see
        /// cref="FindObscuringNodes"/>, and adjusts their <see cref="NodeArc.VisibleFraction"/>
        /// according to the collection of obscuring nodes also created by that method.
        /// </para><para>
        /// Any node whose <see cref="NodeArc"/> remains unobscured by at least the current <see
        /// cref="Threshold"/> is added to the <see cref="Nodes"/> collection.</para></remarks>

        private void FindVisibleNodes()
        {
            // iterate over all visited nodes that may be visible
            foreach (var pair in _nodeArcs)
            {
                NodeArc arc = pair.Value;

                if (arc._visibleFraction == 0)
                {
                    continue;
                }
                double start = arc.Start, sweep = arc.Sweep;

                // compare visited node to all obscuring nodes (except itself)
                foreach (var obscuringPair in _obscuringNodes)
                {
                    if (ComparerCache <T> .EqualityComparer.Equals(pair.Key, obscuringPair.Key))
                    {
                        continue;
                    }

                    // ignore obscuring nodes at a greater source distance
                    NodeArc obscuringAngle = obscuringPair.Value;
                    if (obscuringAngle.Distance > arc.Distance)
                    {
                        continue;
                    }

                    // obscure visibility arc of visited node
                    obscuringAngle.Obscure(ref start, ref sweep);
                    arc._visibleFraction = sweep / arc.Sweep;

                    // check if arc is sufficiently obscured
                    if (arc._visibleFraction < _threshold)
                    {
                        goto nextVisited;
                    }
                }

                // add visible node to search results
                _nodes.Add(pair.Key);

nextVisited:
                continue;
            }
        }
Exemplo n.º 3
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);
            }
        }