/// <summary> Intersect the <see cref="AxisAlignedBox"/> by a <paramref name="ray"/>. /// Using Amy Williams's "An Efficient and Robust Ray–Box Intersection" Algorithm </summary> /// <param name="ray">The <see cref="Ray"/> to intersect the <see cref="IAxisAlignedBox"/> with</param> /// <returns>Whether and when the <see cref="Ray"/> intersects the <see cref="IAxisAlignedBox"/></returns> public IEnumerable <Position1> IntersectDistances(IRay ray) { Position1 tmin = (Bounds[ray.Sign.X].X - ray.Origin.X) * ray.InvDirection.X; Position1 tmax = (Bounds[1 - ray.Sign.X].X - ray.Origin.X) * ray.InvDirection.X; Position1 tymin = (Bounds[ray.Sign.Y].Y - ray.Origin.Y) * ray.InvDirection.Y; Position1 tymax = (Bounds[1 - ray.Sign.Y].Y - ray.Origin.Y) * ray.InvDirection.Y; if ((tmin > tymax) || (tmax < tymin)) { yield break; } tmin = Position1.Max(tmin, tymin); tmax = Position1.Min(tmax, tymax); Position1 tzmin = (Bounds[ray.Sign.Z].Z - ray.Origin.Z) * ray.InvDirection.Z; Position1 tzmax = (Bounds[1 - ray.Sign.Z].Z - ray.Origin.Z) * ray.InvDirection.Z; if ((tmin > tzmax) || (tmax < tzmin)) { yield break; } yield return(Position1.Max(tmin, tzmin)); yield return(Position1.Min(tmax, tzmax)); }
/// <summary> Clip the <see cref="AxisAlignedBox"/> by a <paramref name="plane"/> </summary> /// <param name="plane">The <see cref="AxisAlignedPlane"/> to clip the <see cref="AxisAlignedBox"/> with</param> /// <returns>A new clipped <see cref="AxisAlignedBox"/> if it's not clipped entirely</returns> public IEnumerable <AxisAlignedBox> Clip(AxisAlignedPlane plane) { Position3 minCorner = MinCorner; Position3 maxCorner = MaxCorner; if (plane.Normal == Normal3.UnitX) { minCorner = new(Position1.Max(MinCorner.X, plane.Position.X), MinCorner.Y, MinCorner.Z); } else if (plane.Normal == -Normal3.UnitX) { maxCorner = new(Position1.Min(MinCorner.X, plane.Position.X), MaxCorner.Y, MaxCorner.Z); } else if (plane.Normal == Normal3.UnitY) { minCorner = new(MinCorner.X, Position1.Max(MinCorner.Y, plane.Position.Y), MinCorner.Z); } else if (plane.Normal == -Normal3.UnitY) { maxCorner = new(MaxCorner.X, Position1.Min(MaxCorner.Y, plane.Position.Y), MaxCorner.Z); } else if (plane.Normal == Normal3.UnitZ) { minCorner = new(MinCorner.X, MinCorner.Y, Position1.Max(MinCorner.Z, plane.Position.Z)); } else if (plane.Normal == -Normal3.UnitZ) { maxCorner = new(MaxCorner.X, MaxCorner.Y, Position1.Min(MaxCorner.Z, plane.Position.Z)); } if (minCorner == MinCorner && maxCorner == MaxCorner) { yield return(this); } else if (minCorner.X < maxCorner.X && minCorner.Y < maxCorner.Y && minCorner.Z < maxCorner.Z) { yield return(new AxisAlignedBox(minCorner, maxCorner)); } }