/// <summary> /// Determines whether the specified bounding boxes intersect. /// </summary> /// <param name="boundingBox1">A bounding box.</param> /// <param name="boundingBox2">A bounding box.</param> /// <param name="intersection">Output variable for the intersection.</param> /// <returns>True if the <paramref name="boundingBox1"/> and the <paramref name="boundingBox2"/> intersect, otherwise false.</returns> public static bool BoundingBoxWithBoundingBox(BoundingBox boundingBox1, BoundingBox boundingBox2, out BoundingBox intersection) { var L = Math.Max(boundingBox1.Minimum.X, boundingBox2.Minimum.X); var R = Math.Min(boundingBox1.Maximum.X, boundingBox2.Maximum.X); var B = Math.Max(boundingBox1.Minimum.Y, boundingBox2.Minimum.Y); var T = Math.Min(boundingBox1.Maximum.Y, boundingBox2.Maximum.Y); var F = Math.Max(boundingBox1.Minimum.Z, boundingBox2.Minimum.Z); var N = Math.Min(boundingBox1.Maximum.Z, boundingBox2.Maximum.Z); if (R >= L && T >= B && F >= N) { intersection = new BoundingBox { Minimum = new Vector3(L, B, N), Maximum = new Vector3(R, T, F), }; return true; } else { intersection = default(BoundingBox); return false; } }
/// <summary> /// Returns the distance between the specified bounding box and the specified line. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="line">A line.</param> /// <returns>The distance between the <paramref name="boundingBox"/> and the <paramref name="line"/>.</returns> public static Number BoundingBoxToLine(BoundingBox boundingBox, Line line) { var center = (boundingBox.Minimum + boundingBox.Maximum) / 2; var position = Project.PointOnLine(center, line); var normal = Vector3.Normalize(center - position); return Distance.BoundingBoxToPlane(boundingBox, new Plane(normal, position)); }
/// <summary> /// Returns the distance between the specified bounding boxes. /// </summary> /// <param name="boundingBox1">A bounding box.</param> /// <param name="boundingBox2">A bounding box.</param> /// <returns>The distance between the <paramref name="boundingBox1"/> and the <paramref name="boundingBox2"/>.</returns> public static Number BoundingBoxToBoundingBox(BoundingBox boundingBox1, BoundingBox boundingBox2) { var center = (boundingBox1.Minimum + boundingBox1.Maximum) / 2; var closestPoint1 = Vector3.Clamp(center, boundingBox2.Minimum, boundingBox2.Maximum); var closestPoint2 = Vector3.Clamp(closestPoint1, boundingBox1.Minimum, boundingBox1.Maximum); return Distance.PointToPoint(closestPoint1, closestPoint2); }
/// <summary> /// Determines whether the specified bounding boxes intersect. /// </summary> /// <param name="boundingBox1">A bounding box.</param> /// <param name="boundingBox2">A bounding box.</param> /// <returns>True if the <paramref name="boundingBox1"/> and the <paramref name="boundingBox2"/> intersect, otherwise false.</returns> public static bool BoundingBoxWithBoundingBox(BoundingBox boundingBox1, BoundingBox boundingBox2) { var L = Math.Max(boundingBox1.Minimum.X, boundingBox2.Minimum.X); var R = Math.Min(boundingBox1.Maximum.X, boundingBox2.Maximum.X); var B = Math.Max(boundingBox1.Minimum.Y, boundingBox2.Minimum.Y); var T = Math.Min(boundingBox1.Maximum.Y, boundingBox2.Maximum.Y); var F = Math.Max(boundingBox1.Minimum.Z, boundingBox2.Minimum.Z); var N = Math.Min(boundingBox1.Maximum.Z, boundingBox2.Maximum.Z); return R >= L && T >= B && F >= N; }
/// <summary> /// Initializes a new instance of the struct. /// </summary> /// <param name="boundingBox">Bounding box to copy.</param> public BoundingBox(BoundingBox boundingBox) { this.Minimum = boundingBox.Minimum; this.Maximum = boundingBox.Maximum; }
/// <summary> /// Determines whether the current bounding box is equal to the specified bounding box. /// </summary> /// <param name="value">A bounding box.</param> /// <returns>True if the current bounding box is equal to the <paramref name="value"/>, otherwise false.</returns> public bool Equals(BoundingBox value) { return this.Minimum == value.Minimum && this.Maximum == value.Maximum; }
/// <summary> /// Attempts to parse the bounding box from the specified string. /// </summary> /// <param name="value">The string to parse.</param> /// <param name="numberStyle">The number style for each component.</param> /// <param name="formatProvider">The format provider for each component.</param> /// <param name="result">The output variable for the bounding box parsed from the <paramref name="value"/>.</param> /// <returns>True if the <paramref name="value"/> was parsed successfully, otherwise false.</returns> public static bool TryParse(string value, NumberStyles numberStyle, IFormatProvider formatProvider, out BoundingBox result) { if (value == null) { throw new ArgumentNullException("value"); } var numbers = Float.Parse(value, numberStyle, formatProvider); if (numbers.Length == ValueCount) { result.Minimum.X = numbers[0]; result.Minimum.Y = numbers[1]; result.Minimum.Z = numbers[2]; result.Maximum.X = numbers[3]; result.Maximum.Y = numbers[4]; result.Maximum.Z = numbers[5]; return true; } else { result = default(BoundingBox); return false; } }
/// <summary> /// Returns the distance between the specified bounding box and the specified ray. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="ray">A ray.</param> /// <returns>The distance between the <paramref name="boundingBox"/> and the <paramref name="ray"/>.</returns> public static Number BoundingBoxToRay(BoundingBox boundingBox, Ray ray) { var center = (boundingBox.Minimum + boundingBox.Maximum) / 2; var u = Vector3.Dot(center - ray.Position, ray.Direction) / ray.Direction.MagnitudeSquared; if (u < 0) { u = 0; } var closestPoint = ray.Position + u * ray.Direction; if (u > 0 && u < 1) { var normal = Vector3.Normalize(center - closestPoint); return BoundingBoxToPlane(boundingBox, new Plane(normal, closestPoint)); } else { return PointToBoundingBox(closestPoint, boundingBox); } }
/// <summary> /// Determines whether the specified plane intersects with the specified bounding box. /// </summary> /// <param name="plane">A plane.</param> /// <param name="boundingBox">A bounding box.</param> /// <returns>True if the <paramref name="plane"/> and the <paramref name="boundingBox"/> intersect, otherwise false.</returns> public static bool PlaneWithBoundingBox(Plane plane, BoundingBox boundingBox) { var min = new Vector3 { X = plane.A > 0 ? boundingBox.Minimum.X : boundingBox.Maximum.X, Y = plane.B > 0 ? boundingBox.Minimum.Y : boundingBox.Maximum.Y, Z = plane.C > 0 ? boundingBox.Minimum.Z : boundingBox.Maximum.Z, }; if (Distance.PointToPlane(min, plane) > 0) { return false; } var max = new Vector3 { X = plane.A < 0 ? boundingBox.Minimum.X : boundingBox.Maximum.X, Y = plane.B < 0 ? boundingBox.Minimum.Y : boundingBox.Maximum.Y, Z = plane.C < 0 ? boundingBox.Minimum.Z : boundingBox.Maximum.Z, }; if (Distance.PointToPlane(max, plane) < 0) { return false; } return true; }
/// <summary> /// Determines whether the specified bounding box intersects with the specified ray. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="ray">A ray.</param> /// <returns>True if the <paramref name="boundingBox"/> and the <paramref name="ray"/> intersect, otherwise false.</returns> public static bool BoundingBoxWithRay(BoundingBox boundingBox, Ray ray) { var n = Number.MinValue; var f = Number.MaxValue; if (Float.Near(ray.Direction.X, 0)) { if (ray.Position.X < boundingBox.Minimum.X || ray.Position.X > boundingBox.Maximum.X) { return false; } } else { var inv = 1 / ray.Direction.X; var d1 = (boundingBox.Minimum.X - ray.Position.X) * inv; var d2 = (boundingBox.Maximum.X - ray.Position.X) * inv; n = Math.Max(n, Math.Min(d1, d2)); f = Math.Min(f, Math.Max(d1, d2)); if (n > f || f < 0) { return false; } } if (Float.Near(ray.Direction.Y, 0)) { if (ray.Position.Y < boundingBox.Minimum.Y || ray.Position.Y > boundingBox.Maximum.Y) { return false; } } else { var inv = 1 / ray.Direction.Y; var d1 = (boundingBox.Minimum.Y - ray.Position.Y) * inv; var d2 = (boundingBox.Maximum.Y - ray.Position.Y) * inv; n = Math.Max(n, Math.Min(d1, d2)); f = Math.Min(f, Math.Max(d1, d2)); if (n > f || f < 0) { return false; } } if (Float.Near(ray.Direction.Z, 0)) { if (ray.Position.Z < boundingBox.Minimum.Z || ray.Position.Z > boundingBox.Maximum.Z) { return false; } } else { var inv = 1 / ray.Direction.Z; var d1 = (boundingBox.Minimum.Z - ray.Position.Z) * inv; var d2 = (boundingBox.Maximum.Z - ray.Position.Z) * inv; n = Math.Max(n, Math.Min(d1, d2)); f = Math.Min(f, Math.Max(d1, d2)); if (n > f || f < 0) { return false; } } return true; }
/// <summary> /// Determines whether any of the fields of the specified bounding box evaluates to positive infinity. /// </summary> /// <param name="value">A bounding box.</param> /// <returns>True if any of the fields of <paramref name="value"/> evaluates to positive infinity, otherwise false.</returns> public static bool IsPositiveInfinity(BoundingBox value) { return Vector3.IsPositiveInfinity(value.Minimum) || Vector3.IsPositiveInfinity(value.Maximum); }
/// <summary> /// Determines whether any of the fields of the specified bounding box evaluates to a value that is not a number. /// </summary> /// <param name="value">A bounding box.</param> /// <returns>True if any of the fields of <paramref name="value"/> evaluates to a value that is not a number, otherwise false.</returns> public static bool IsNaN(BoundingBox value) { return Vector3.IsNaN(value.Minimum) || Vector3.IsNaN(value.Maximum); }
/// <summary> /// Returns the distance between the specified bounding box and the specified line segment. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="lineSegment">A line segment.</param> /// <returns>The distance between the <paramref name="boundingBox"/> and the <paramref name="lineSegment"/>.</returns> public static Number BoundingBoxToLineSegment(BoundingBox boundingBox, LineSegment lineSegment) { var center = (boundingBox.Minimum + boundingBox.Maximum) / 2; var t = lineSegment.End2 - lineSegment.End1; var u = Vector3.Dot(center - lineSegment.End1, t) / t.MagnitudeSquared; if (u < 0) { u = 0; } if (u > 1) { u = 1; } var closestPoint = lineSegment.End1 + u * t; if (u > 0 && u < 1) { var normal = Vector3.Normalize(center - closestPoint); return BoundingBoxToPlane(boundingBox, new Plane(normal, closestPoint)); } else { return PointToBoundingBox(closestPoint, boundingBox); } }
/// <summary> /// Returns the distance between the specified bounding box and the specified bounding sphere. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="boundingSphere">A bounding sphere.</param> /// <returns>The distance between the <paramref name="boundingBox"/> and the <paramref name="boundingSphere"/>.</returns> public static Number BoundingBoxToBoundingSphere(BoundingBox boundingBox, BoundingSphere boundingSphere) { var closestPoint = Vector3.Clamp(boundingSphere.Position, boundingBox.Minimum, boundingBox.Maximum); return Distance.PointToBoundingSphere(closestPoint, boundingSphere); }
/// <summary> /// Returns the distance between the specified point and the specified bounding box. /// </summary> /// <param name="point">A point.</param> /// <param name="boundingBox">A bounding box.</param> /// <returns>The distance between the <paramref name="point"/> and the <paramref name="boundingBox"/>.</returns> public static Number PointToBoundingBox(Vector3 point, BoundingBox boundingBox) { return Distance.PointToPoint(point, Vector3.Clamp(point, boundingBox.Minimum, boundingBox.Maximum)); }
/// <summary> /// Determines whether the specified bounding box intersects with the specified bounding sphere. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="boundingSphere">A bounding sphere.</param> /// <param name="intersection">Output variable for the intersection.</param> /// <returns>True if the <paramref name="boundingBox"/> and the <paramref name="boundingSphere"/> intersect, otherwise false.</returns> public static bool BoundingBoxWithBoundingSphere(BoundingBox boundingBox, BoundingSphere boundingSphere, out Vector3 intersection) { var closestPoint = Vector3.Clamp(boundingSphere.Position, boundingBox.Minimum, boundingBox.Maximum); if (Distance.PointToPointSquared(closestPoint, boundingSphere.Position) <= boundingSphere.Radius * boundingSphere.Radius) { intersection = closestPoint; return true; } else { intersection = default(Vector3); return false; } }
/// <summary> /// Determines whether the specified bounding box intersects with the specified point. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="point">A point.</param> /// <returns>True if the <paramref name="boundingBox"/> and the <paramref name="point"/> intersect, otherwise false.</returns> public static bool BoundingBoxWithPoint(BoundingBox boundingBox, Vector3 point) { return boundingBox.Minimum.X <= point.X && point.X <= boundingBox.Maximum.X && boundingBox.Minimum.Y <= point.Y && point.Y <= boundingBox.Maximum.Y && boundingBox.Minimum.Z <= point.Z && point.Z <= boundingBox.Maximum.Z; }
/// <summary> /// Returns the smallest bounding box containing both of the specified bounding boxes. /// </summary> /// <param name="value1">A bounding box.</param> /// <param name="value2">A bounding box.</param> /// <returns>The smallest bounding box containing both of the <paramref name="value1"/> and the <paramref name="value2"/>.</returns> public static BoundingBox Merge(BoundingBox value1, BoundingBox value2) { return new BoundingBox { Minimum = Vector3.Min(value1.Minimum, value2.Minimum), Maximum = Vector3.Max(value1.Maximum, value2.Maximum), }; }
/// <summary> /// Determines whether the specified bounding box intersects with the specified ray. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="ray">A ray.</param> /// <param name="intersection">Output variable for the intersection.</param> /// <returns>True if the <paramref name="boundingBox"/> and the <paramref name="ray"/> intersect, otherwise false.</returns> public static bool BoundingBoxWithRay(BoundingBox boundingBox, Ray ray, out LineSegment intersection) { var n = Number.MinValue; var f = Number.MaxValue; if (Float.Near(ray.Direction.X, 0)) { if (ray.Position.X < boundingBox.Minimum.X || ray.Position.X > boundingBox.Maximum.X) { intersection = default(LineSegment); return false; } } else { var inv = 1 / ray.Direction.X; var d1 = (boundingBox.Minimum.X - ray.Position.X) * inv; var d2 = (boundingBox.Maximum.X - ray.Position.X) * inv; n = Math.Max(n, Math.Min(d1, d2)); f = Math.Min(f, Math.Max(d1, d2)); if (n > f || f < 0) { intersection = default(LineSegment); return false; } } if (Float.Near(ray.Direction.Y, 0)) { if (ray.Position.Y < boundingBox.Minimum.Y || ray.Position.Y > boundingBox.Maximum.Y) { intersection = default(LineSegment); return false; } } else { var inv = 1 / ray.Direction.Y; var d1 = (boundingBox.Minimum.Y - ray.Position.Y) * inv; var d2 = (boundingBox.Maximum.Y - ray.Position.Y) * inv; n = Math.Max(n, Math.Min(d1, d2)); f = Math.Min(f, Math.Max(d1, d2)); if (n > f || f < 0) { intersection = default(LineSegment); return false; } } if (Float.Near(ray.Direction.Z, 0)) { if (ray.Position.Z < boundingBox.Minimum.Z || ray.Position.Z > boundingBox.Maximum.Z) { intersection = default(LineSegment); return false; } } else { var inv = 1 / ray.Direction.Z; var d1 = (boundingBox.Minimum.Z - ray.Position.Z) * inv; var d2 = (boundingBox.Maximum.Z - ray.Position.Z) * inv; n = Math.Max(n, Math.Min(d1, d2)); f = Math.Min(f, Math.Max(d1, d2)); if (n > f || f < 0) { intersection = default(LineSegment); return false; } } intersection = new LineSegment { End1 = ray.Position + ray.Direction * n, End2 = ray.Position + ray.Direction * f, }; return true; }
/// <summary> /// Attempts to parse the bounding box from the specified string. /// </summary> /// <param name="value">The string to parse.</param> /// <param name="result">The output variable for the bounding box parsed from the <paramref name="value"/>.</param> /// <returns>True if the <paramref name="value"/> was parsed successfully, otherwise false.</returns> public static bool TryParse(string value, out BoundingBox result) { return TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, null, out result); }
/// <summary> /// Attempts to parse the bounding box from the specified string. /// </summary> /// <param name="value">The string to parse.</param> /// <param name="numberStyle">The number style for each component.</param> /// <param name="result">The output variable for the bounding box parsed from the <paramref name="value"/>.</param> /// <returns>True if the <paramref name="value"/> was parsed successfully, otherwise false.</returns> public static bool TryParse(string value, NumberStyles numberStyle, out BoundingBox result) { return TryParse(value, numberStyle, null, out result); }
/// <summary> /// Attempts to parse the bounding box from the specified string. /// </summary> /// <param name="value">The string to parse.</param> /// <param name="formatProvider">The format provider for each component.</param> /// <param name="result">The output variable for the bounding box parsed from the <paramref name="value"/>.</param> /// <returns>True if the <paramref name="value"/> was parsed successfully, otherwise false.</returns> public static bool TryParse(string value, IFormatProvider formatProvider, out BoundingBox result) { return TryParse(value, NumberStyles.Float | NumberStyles.AllowThousands, formatProvider, out result); }
/// <summary> /// Determines whether the specified bounding box intersects with the specified bounding sphere. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="boundingSphere">A bounding sphere.</param> /// <returns>True if the <paramref name="boundingBox"/> and the <paramref name="boundingSphere"/> intersect, otherwise false.</returns> public static bool BoundingBoxWithBoundingSphere(BoundingBox boundingBox, BoundingSphere boundingSphere) { var closestPoint = Vector3.Clamp(boundingSphere.Position, boundingBox.Minimum, boundingBox.Maximum); return Distance.PointToPointSquared(boundingSphere.Position, closestPoint) <= boundingSphere.Radius * boundingSphere.Radius; }
/// <summary> /// Returns the distance between the specified bounding box and the specified plane. /// </summary> /// <param name="boundingBox">A bounding box.</param> /// <param name="plane">A plane.</param> /// <returns>The distance between the <paramref name="boundingBox"/> and the <paramref name="plane"/>.</returns> public static Number BoundingBoxToPlane(BoundingBox boundingBox, Plane plane) { var min = new Vector3 { X = plane.A > 0 ? boundingBox.Minimum.X : boundingBox.Maximum.X, Y = plane.B > 0 ? boundingBox.Minimum.Y : boundingBox.Maximum.Y, Z = plane.C > 0 ? boundingBox.Minimum.Z : boundingBox.Maximum.Z, }; var minDistance = Distance.PointToPlane(min, plane); if (minDistance >= 0) { return minDistance; } var max = new Vector3 { X = plane.A < 0 ? boundingBox.Minimum.X : boundingBox.Maximum.X, Y = plane.B < 0 ? boundingBox.Minimum.Y : boundingBox.Maximum.Y, Z = plane.C < 0 ? boundingBox.Minimum.Z : boundingBox.Maximum.Z, }; var maxDistance = Distance.PointToPlane(max, plane); if (maxDistance <= 0) { return maxDistance; } return 0; }