Example #1
0
        /// <summary>
        /// Indicates whether or not the given shape is contained entirely within this cylinder (no part of the <paramref name="other"/>
        /// shape may be outside this one).
        /// </summary>
        /// <param name="other">The shape to check.</param>
        /// <returns>True if the other shape is completely within this cylinder, false if any part of it
        /// is outside the cylinder.</returns>
        public bool Contains(Cuboid other)
        {
            float halfHeight  = Height / 2f;
            float errorMargin = MathUtils.FlopsErrorMargin;

            return(Contains(other.GetCorner(Cuboid.CuboidCorner.FrontTopLeft)) &&
                   Contains(other.GetCorner(Cuboid.CuboidCorner.FrontTopRight)) &&
                   Contains(other.GetCorner(Cuboid.CuboidCorner.BackTopLeft)) &&
                   Contains(other.GetCorner(Cuboid.CuboidCorner.BackTopRight)) &&
                   other.FrontBottomLeft.Y + other.Height <= Center.Y + halfHeight + errorMargin &&
                   other.FrontBottomLeft.Y + errorMargin >= Center.Y - halfHeight);
        }
Example #2
0
        /// <summary>
        /// Indicates whether the <paramref name="cuboid"/> intersects (crosses) this plane at any point.
        /// </summary>
        /// <param name="cuboid">The cuboid to test.</param>
        /// <returns>True if the cuboid intersects this plane (or touches it), false if not.</returns>
        public bool Intersects(Cuboid cuboid)
        {
            PointPlaneRelationship firstPointLocation = LocationOf(cuboid.GetCorner((Cuboid.CuboidCorner) 0));

            for (int i = 1; i < Cuboid.NUM_CORNERS; ++i)
            {
                if (LocationOf(cuboid.GetCorner((Cuboid.CuboidCorner)i)) != firstPointLocation)
                {
                    return(true);
                }
            }
            return(false);
        }
Example #3
0
        /// <summary>
        /// Indicates the shortest distance from the edge of the given shape to the edge of this sphere.
        /// </summary>
        /// <param name="other">The shape to check.</param>
        /// <returns>The shortest distance connecting the outer-edges of both shapes.
        /// If the shapes intersect, <c>0f</c> will be returned.</returns>
        public float DistanceFrom(Cuboid other)
        {
            if (Intersects(other))
            {
                return(0f);
            }

            float distanceX = Math.Max(Math.Abs(
                                           Center.X - (float)MathUtils.Clamp(Center.X, other.FrontBottomLeft.X, other.FrontBottomLeft.X + other.Width)) - Radius, 0f);
            float distanceY = Math.Max(Math.Abs(
                                           Center.Y - (float)MathUtils.Clamp(Center.Y, other.FrontBottomLeft.Y, other.FrontBottomLeft.Y + other.Height)) - Radius, 0f);
            float distanceZ = Math.Max(Math.Abs(
                                           Center.Z - (float)MathUtils.Clamp(Center.Z, other.FrontBottomLeft.Z, other.FrontBottomLeft.Z + other.Depth)) - Radius, 0f);

            return((float)Math.Sqrt(distanceX * distanceX + distanceY * distanceY + distanceZ * distanceZ));
        }
Example #4
0
        /// <summary>
        /// Indicates whether or not the given shape is contained entirely within this sphere (no part of the <paramref name="other"/>
        /// shape may be outside this one).
        /// </summary>
        /// <param name="other">The shape to check.</param>
        /// <returns>True if the other shape is completely within this sphere, false if any part of it
        /// is outside the sphere.</returns>
        public bool Contains(Cuboid other)
        {
            float errorMarginSq = MathUtils.FlopsErrorMargin;

            errorMarginSq *= errorMarginSq;
            float radiusSq = Radius * Radius;

            for (int i = 0; i < Cuboid.NUM_CORNERS; ++i)
            {
                if (Vector3.DistanceSquared(Center, other.GetCorner((Cuboid.CuboidCorner)i)) > radiusSq + errorMarginSq)
                {
                    return(false);
                }
            }
            return(true);
        }
Example #5
0
        /// <summary>
        /// Gets the shortest distance from this plane to the <paramref name="cuboid"/>'s outer edge.
        /// </summary>
        /// <param name="cuboid">The cuboid to get the distance to.</param>
        /// <returns>The distance of the shortest path from the cuboid's edge (not its centre) to this plane, or
        /// <c>0f</c> if there is an intersection.</returns>
        public float DistanceFrom(Cuboid cuboid)
        {
            if (Intersects(cuboid))
            {
                return(0f);
            }

            float min = Single.MaxValue;

            for (int i = 0; i < Cuboid.NUM_CORNERS; ++i)
            {
                min = Math.Min(min, DistanceFrom(cuboid.GetCorner((Cuboid.CuboidCorner)i)));
            }

            return(min);
        }
Example #6
0
        /// <summary>
        /// Indicates whether or not the given shape is contained entirely within this cone (no part of the <paramref name="other"/>
        /// shape may be outside this one).
        /// </summary>
        /// <param name="other">The shape to check.</param>
        /// <returns>True if the other shape is completely within this cone, false if any part of it
        /// is outside the cone.</returns>
        public bool Contains(Cuboid other)
        {
            float errorMargin = MathUtils.FlopsErrorMargin;

            if (other.FrontBottomLeft.Y + errorMargin < TopCenter.Y - Height ||
                other.FrontBottomLeft.Y + other.Height > TopCenter.Y + errorMargin)
            {
                return(false);
            }

            if (BottomRadius > TopRadius)
            {
                return(Contains(other.GetCorner(Cuboid.CuboidCorner.FrontTopLeft)) &&
                       Contains(other.GetCorner(Cuboid.CuboidCorner.BackTopRight)));
            }
            else
            {
                return(Contains(other.GetCorner(Cuboid.CuboidCorner.FrontBottomLeft)) &&
                       Contains(other.GetCorner(Cuboid.CuboidCorner.BackBottomRight)));
            }
        }
Example #7
0
 /// <summary>
 /// Indicates whether any portion of this cylinder and the <paramref name="other"/> shape overlap.
 /// </summary>
 /// <param name="other">The shape to check against this one.</param>
 /// <returns>True if any part of both shapes overlap, false if they are entirely separate.</returns>
 public bool Intersects(Cuboid other)
 {
     return(other.Intersects(this));
 }
Example #8
0
        /// <summary>
        /// Determines the first point on the cuboid that is touched by this ray.
        /// </summary>
        /// <param name="other">The cuboid to test for intersection with this ray.</param>
        /// <returns>A <see cref="Vector3"/> indicating the first point on the cuboid edge touched by this ray,
        /// or <c>null</c> if no intersection occurs.</returns>
        // Based on "Fast Ray-Box Intersection" algorithm by Andrew Woo, "Graphics Gems", Academic Press, 1990
        public unsafe Vector3?IntersectionWith(Cuboid other)
        {
            const int NUM_DIMENSIONS = 3;

            Assure.Equal(NUM_DIMENSIONS, 3);             // If that value is ever changed, this algorithm will need some maintenance

            const byte QUADRANT_MIN     = 0;
            const byte QUADRANT_MAX     = 1;
            const byte QUADRANT_BETWEEN = 2;

            // Step 1: Work out which direction from the start point to test for intersection for all 3 dimensions, and the distance
            byte * quadrants                = stackalloc byte[NUM_DIMENSIONS];
            float *candidatePlanes          = stackalloc float[NUM_DIMENSIONS];
            float *cuboidMinPoints          = stackalloc float[NUM_DIMENSIONS];
            float *cuboidMaxPoints          = stackalloc float[NUM_DIMENSIONS];
            bool   startPointIsInsideCuboid = true;

            cuboidMinPoints[0] = other.FrontBottomLeft.X;
            cuboidMinPoints[1] = other.FrontBottomLeft.Y;
            cuboidMinPoints[2] = other.FrontBottomLeft.Z;
            cuboidMaxPoints[0] = other.FrontBottomLeft.X + other.Width;
            cuboidMaxPoints[1] = other.FrontBottomLeft.Y + other.Height;
            cuboidMaxPoints[2] = other.FrontBottomLeft.Z + other.Depth;

            for (byte i = 0; i < NUM_DIMENSIONS; ++i)
            {
                if (StartPoint[i] < cuboidMinPoints[i])
                {
                    quadrants[i]             = QUADRANT_MIN;
                    candidatePlanes[i]       = cuboidMinPoints[i];
                    startPointIsInsideCuboid = false;
                }
                else if (StartPoint[i] > cuboidMaxPoints[i])
                {
                    quadrants[i]             = QUADRANT_MAX;
                    candidatePlanes[i]       = cuboidMaxPoints[i];
                    startPointIsInsideCuboid = false;
                }
                else
                {
                    quadrants[i] = QUADRANT_BETWEEN;
                }
            }

            if (startPointIsInsideCuboid)
            {
                return(StartPoint);
            }

            // Step 2: Find farthest dimension from cuboid
            float maxDistance          = Single.NegativeInfinity;
            byte  maxDistanceDimension = 0;

            for (byte i = 0; i < NUM_DIMENSIONS; ++i)
            {
                // ReSharper disable once CompareOfFloatsByEqualityOperator Exact check is desired here: Anything other than 0f is usable
                if (quadrants[i] != QUADRANT_BETWEEN && Orientation[i] != 0f)
                {
                    float thisDimensionDist = (candidatePlanes[i] - StartPoint[i]) / Orientation[i];
                    if (thisDimensionDist > maxDistance)
                    {
                        maxDistance          = thisDimensionDist;
                        maxDistanceDimension = i;
                    }
                }
            }

            float errorMargin = MathUtils.FlopsErrorMargin;

            if (maxDistance < 0f || maxDistance - Length > errorMargin)
            {
                return(null);
            }

            // Step 3: Find potential intersection point
            float *intersectionPoint = stackalloc float[NUM_DIMENSIONS];

            for (byte i = 0; i < NUM_DIMENSIONS; ++i)
            {
                if (maxDistanceDimension == i)
                {
                    intersectionPoint[i] = StartPoint[i] + maxDistance * Orientation[i];
                    if (cuboidMinPoints[i] - intersectionPoint[i] > errorMargin || intersectionPoint[i] - cuboidMaxPoints[i] > errorMargin)
                    {
                        return(null);
                    }
                }
                else
                {
                    intersectionPoint[i] = candidatePlanes[i];
                }
            }

            Vector3 result = new Vector3(intersectionPoint[0], intersectionPoint[1], intersectionPoint[2]);

            if (!IsInfiniteLength && Vector3.DistanceSquared(StartPoint, result) > Length * Length + errorMargin * errorMargin)
            {
                return(null);
            }
            else if (!Contains(result))
            {
                return(null);
            }
            else
            {
                return(result);
            }
        }