예제 #1
0
        /// <summary>
        /// Search in the BVH tree using a flexible "locator" object, which should return the
        /// "distance" of a BVH Node object.  Returns a list of results in increasing distance
        /// up to a relative bound and absolute maximum.
        /// </summary>
        /// <param name="distance_max">The maximum distance to look for.</param>
        /// <param name="relative_bound">Stop returning more items after 'relative_bound' times
        /// the first item's distance.</param>
        /// <param name="locator">A delegate, like Locate() but passed also the current 'distance_max'.</param>
        /// <returns>A list of instances of the concrete BVHNodeBase subclass.</returns>
        public List <BVHNodeBase> LocateList(float distance_max, float relative_bound, DistanceToNodeEx locator)
        {
            var output_list = new List <BVHNodeBase>();

            if (!(root is BVHNode))
            {
                if (root != null)
                {
                    float distance = locator(root, distance_max);
                    if (distance < distance_max)
                    {
                        output_list.Add(root);
                    }
                }
                return(output_list);
            }
            var         heapq      = new HeapQ <LocNext>();
            BVHNodeBase base_node  = root;
            float       distance_1 = 0;

            while (distance_1 < distance_max)
            {
                if (base_node is BVHNode)
                {
                    var node = (BVHNode)base_node;

                    float d_left = locator(node.left, distance_max);
                    if (d_left < distance_max)
                    {
                        if (!(node.left is BVHNode))
                        {
                            distance_max = Mathf.Min(distance_max, d_left * relative_bound);
                        }
                        heapq.Push(new LocNext(d_left, node.left));
                    }

                    float d_right = locator(node.right, distance_max);
                    if (d_right < distance_max)
                    {
                        if (!(node.right is BVHNode))
                        {
                            distance_max = Mathf.Min(distance_max, d_right * relative_bound);
                        }
                        heapq.Push(new LocNext(d_right, node.right));
                    }
                }
                else
                {
                    output_list.Add(base_node);
                }
                if (heapq.Empty)
                {
                    break;
                }
                LocNext next = heapq.Pop();
                distance_1 = next.distance;
                base_node  = next.node;
            }
            return(output_list);
        }
예제 #2
0
        /// <summary>
        /// Search in the BVH tree using a flexible "locator" delegate, which should return the
        /// "distance" of a BVH Node object.
        /// </summary>
        /// <param name="distance">The maximum distance to look for.</param>
        /// <param name="locator">A delegate.  A typical implementation has got two cases: if
        /// given an instance of a concrete class that the caller knows about, it should return
        /// the distance to that; otherwise, it should return the distance to the bounding box.
        /// The present algorithm assumes that when a bounding box grows, the distance returned
        /// by "locator" decreases or stays constant.</param>
        /// <returns>A instance of the concrete BVHNodeBase subclass.</returns>
        public BVHNodeBase Locate(float distance_max, DistanceToNode locator)
        {
            if (!(root is BVHNode))
            {
                if (root != null)
                {
                    float distance = locator(root, distance_max);
                    if (distance < distance_max)
                    {
                        return(root);
                    }
                }
                return(null);
            }
            var         heapq     = new HeapQ <LocNext>();
            BVHNodeBase base_node = root;

            while (true)
            {
                if (base_node is BVHNode)
                {
                    var node = (BVHNode)base_node;

                    float d_left = locator(node.left, distance_max);
                    if (d_left < distance_max)
                    {
                        if (!(node.left is BVHNode))
                        {
                            distance_max = d_left;
                        }
                        heapq.Push(new LocNext(d_left, node.left));
                    }

                    float d_right = locator(node.right, distance_max);
                    if (d_right < distance_max)
                    {
                        if (!(node.right is BVHNode))
                        {
                            distance_max = d_right;
                        }
                        heapq.Push(new LocNext(d_right, node.right));
                    }
                }
                else
                {
                    return(base_node);
                }
                if (heapq.Empty)
                {
                    break;
                }
                LocNext next = heapq.Pop();
                base_node = next.node;
            }
            return(null);
        }