Exemplo n.º 1
0
        /// <summary>
        /// Computes an intersection of the ray and the segment
        /// </summary>
        public static bool RaySegment(Vector2 rayOrigin, Vector2 rayDirection, Vector2 segmentA, Vector2 segmentB,
                                      out IntersectionRaySegment2 intersection)
        {
            Vector2 segmentAToOrigin = rayOrigin - segmentA;
            Vector2 segmentDirection = segmentB - segmentA;
            float   denominator      = VectorE.PerpDot(rayDirection, segmentDirection);
            float   perpDotA         = VectorE.PerpDot(rayDirection, segmentAToOrigin);
            // Normalized direction gives more stable results
            float perpDotB = VectorE.PerpDot(segmentDirection.normalized, segmentAToOrigin);

            if (Mathf.Abs(denominator) < Geometry.Epsilon)
            {
                // Parallel
                if (Mathf.Abs(perpDotA) > Geometry.Epsilon || Mathf.Abs(perpDotB) > Geometry.Epsilon)
                {
                    // Not collinear
                    intersection = IntersectionRaySegment2.None();
                    return(false);
                }
                // Collinear

                bool  segmentIsAPoint    = segmentDirection.sqrMagnitude < Geometry.Epsilon;
                float segmentAProjection = Vector2.Dot(rayDirection, segmentA - rayOrigin);
                if (segmentIsAPoint)
                {
                    if (segmentAProjection > -Geometry.Epsilon)
                    {
                        intersection = IntersectionRaySegment2.Point(segmentA);
                        return(true);
                    }
                    intersection = IntersectionRaySegment2.None();
                    return(false);
                }

                float segmentBProjection = Vector2.Dot(rayDirection, segmentB - rayOrigin);
                if (segmentAProjection > -Geometry.Epsilon)
                {
                    if (segmentBProjection > -Geometry.Epsilon)
                    {
                        if (segmentBProjection > segmentAProjection)
                        {
                            intersection = IntersectionRaySegment2.Segment(segmentA, segmentB);
                        }
                        else
                        {
                            intersection = IntersectionRaySegment2.Segment(segmentB, segmentA);
                        }
                    }
                    else
                    {
                        if (segmentAProjection > Geometry.Epsilon)
                        {
                            intersection = IntersectionRaySegment2.Segment(rayOrigin, segmentA);
                        }
                        else
                        {
                            intersection = IntersectionRaySegment2.Point(rayOrigin);
                        }
                    }
                    return(true);
                }
                if (segmentBProjection > -Geometry.Epsilon)
                {
                    if (segmentBProjection > Geometry.Epsilon)
                    {
                        intersection = IntersectionRaySegment2.Segment(rayOrigin, segmentB);
                    }
                    else
                    {
                        intersection = IntersectionRaySegment2.Point(rayOrigin);
                    }
                    return(true);
                }
                intersection = IntersectionRaySegment2.None();
                return(false);
            }

            // Not parallel
            float rayDistance     = perpDotB / denominator;
            float segmentDistance = perpDotA / denominator;

            if (rayDistance > -Geometry.Epsilon &&
                segmentDistance > -Geometry.Epsilon && segmentDistance < 1 + Geometry.Epsilon)
            {
                intersection = IntersectionRaySegment2.Point(segmentA + segmentDirection * segmentDistance);
                return(true);
            }
            intersection = IntersectionRaySegment2.None();
            return(false);
        }
        /// <summary>
        /// Computes an intersection of the ray and the segment
        /// </summary>
        public static bool RaySegment(Vector2 rayOrigin, Vector2 rayDirection, Vector2 segmentA, Vector2 segmentB,
                                      out IntersectionRaySegment2 intersection)
        {
            float   rayDistance;
            float   segmentDistance;
            Vector2 segmentDirection = segmentB - segmentA;
            var     intersectionType = LineLine(rayOrigin, rayDirection, segmentA, segmentDirection, out rayDistance, out segmentDistance);

            if (intersectionType == IntersectionType.Line)
            {
                bool  segmentIsAPoint         = segmentDirection.sqrMagnitude < Geometry.Epsilon;
                float projectionFromOriginToA = Vector2.Dot(rayDirection, segmentA - rayOrigin);
                if (segmentIsAPoint)
                {
                    if (projectionFromOriginToA > -Geometry.Epsilon)
                    {
                        intersection = IntersectionRaySegment2.Point(segmentA);
                        return(true);
                    }
                    intersection = IntersectionRaySegment2.None();
                    return(false);
                }

                float projectionFromOriginToB = Vector2.Dot(rayDirection, segmentB - rayOrigin);
                if (projectionFromOriginToA > -Geometry.Epsilon)
                {
                    if (projectionFromOriginToB > -Geometry.Epsilon)
                    {
                        if (projectionFromOriginToB > projectionFromOriginToA)
                        {
                            intersection = IntersectionRaySegment2.Segment(segmentA, segmentB);
                        }
                        else
                        {
                            intersection = IntersectionRaySegment2.Segment(segmentB, segmentA);
                        }
                    }
                    else
                    {
                        if (projectionFromOriginToA > Geometry.Epsilon)
                        {
                            intersection = IntersectionRaySegment2.Segment(rayOrigin, segmentA);
                        }
                        else
                        {
                            intersection = IntersectionRaySegment2.Point(rayOrigin);
                        }
                    }
                    return(true);
                }
                if (projectionFromOriginToB > -Geometry.Epsilon)
                {
                    if (projectionFromOriginToB > Geometry.Epsilon)
                    {
                        intersection = IntersectionRaySegment2.Segment(rayOrigin, segmentB);
                    }
                    else
                    {
                        intersection = IntersectionRaySegment2.Point(rayOrigin);
                    }
                    return(true);
                }
                intersection = IntersectionRaySegment2.None();
                return(false);
            }
            if (intersectionType == IntersectionType.Point &&
                rayDistance > -Geometry.Epsilon &&
                segmentDistance > -Geometry.Epsilon && segmentDistance < 1 + Geometry.Epsilon)
            {
                intersection = IntersectionRaySegment2.Point(rayOrigin + rayDirection * rayDistance);
                return(true);
            }

            intersection = IntersectionRaySegment2.None();
            return(false);
        }