/// <inheritdoc/> public virtual IEnumerable <T> GetOverlaps(Ray ray) { #if !POOL_ENUMERABLES Aabb rayAabb = new Aabb(ray.Origin, ray.Origin); rayAabb.Grow(ray.Origin + ray.Direction * ray.Length); var rayDirectionInverse = new Vector3F( 1 / ray.Direction.X, 1 / ray.Direction.Y, 1 / ray.Direction.Z); float epsilon = Numeric.EpsilonF * (1 + Aabb.Extent.Length); foreach (var candidate in GetOverlaps(rayAabb)) { if (GeometryHelper.HaveContact(GetAabbForItem(candidate), ray.Origin, rayDirectionInverse, ray.Length, epsilon)) { yield return(candidate); } } #else // Avoiding garbage: return(GetOverlapsWithRayWork.Create(this, ref ray)); #endif }
/// <inheritdoc/> public IEnumerable <int> GetOverlaps(Ray ray) { Update(false); #if !POOL_ENUMERABLES if (_numberOfItems == 0) { yield break; } var rayDirectionInverse = new Vector3F( 1 / ray.Direction.X, 1 / ray.Direction.Y, 1 / ray.Direction.Z); float epsilon = Numeric.EpsilonF * (1 + Aabb.Extent.Length); // ----- Stackless traversal of tree: // The AABB tree nodes are stored in preorder traversal order. We can visit them in linear // order. The EscapeOffset of each node can be used to skip a subtree. int index = 0; while (index < _nodes.Length) { Node node = _nodes[index]; bool haveContact = GeometryHelper.HaveContact(GetAabb(node), ray.Origin, rayDirectionInverse, ray.Length, epsilon); if (haveContact && node.IsLeaf) { yield return(node.Item); } if (haveContact || node.IsLeaf) { // Given AABB intersects the internal AABB tree node or the node is a leaf. // Continue with next item in preorder traversal order. index++; } else { // Given AABB does not touch the internal AABB tree node. // --> Skip the subtree. index += node.EscapeOffset; } } #else // Avoiding garbage: return(GetOverlapsWithRayWork.Create(this, ref ray)); #endif }
/// <inheritdoc/> public override IEnumerable <T> GetOverlaps(Ray ray) { UpdateInternal(); #if !POOL_ENUMERABLES if (_root == null) { yield break; } var rayDirectionInverse = new Vector3F( 1 / ray.Direction.X, 1 / ray.Direction.Y, 1 / ray.Direction.Z); float epsilon = Numeric.EpsilonF * (1 + Aabb.Extent.Length); var stack = DigitalRune.ResourcePools <Node> .Stacks.Obtain(); stack.Push(_root); while (stack.Count > 0) { var node = stack.Pop(); node.IsActive = true; if (GeometryHelper.HaveContact(node.Aabb, ray.Origin, rayDirectionInverse, ray.Length, epsilon)) { if (node.IsLeaf) { yield return(node.Item); } else { SplitIfNecessary(node); stack.Push(node.RightChild); stack.Push(node.LeftChild); } } } DigitalRune.ResourcePools <Node> .Stacks.Recycle(stack); #else // Avoiding garbage: return(GetOverlapsWithRayWork.Create(this, ref ray)); #endif }