How to know if a line intersects a plane in C#?

后端 未结 7 1439
情话喂你
情话喂你 2020-12-13 18:39

I have two points (a line segment) and a rectangle. I would like to know how to calculate if the line segment intersects the rectangle.

7条回答
  •  Happy的楠姐
    2020-12-13 18:51

    From my "Geometry" class:

    public struct Line
    {
        public static Line Empty;
    
        private PointF p1;
        private PointF p2;
    
        public Line(PointF p1, PointF p2)
        {
            this.p1 = p1;
            this.p2 = p2;
        }
    
        public PointF P1
        {
            get { return p1; }
            set { p1 = value; }
        }
    
        public PointF P2
        {
            get { return p2; }
            set { p2 = value; }
        }
    
        public float X1
        {
            get { return p1.X; }
            set { p1.X = value; }
        }
    
        public float X2
        {
            get { return p2.X; }
            set { p2.X = value; }
        }
    
        public float Y1
        {
            get { return p1.Y; }
            set { p1.Y = value; }
        }
    
        public float Y2
        {
            get { return p2.Y; }
            set { p2.Y = value; }
        }
    }
    
    public struct Polygon: IEnumerable
    {
        private PointF[] points;
    
        public Polygon(PointF[] points)
        {
            this.points = points;
        }
    
        public PointF[] Points
        {
            get { return points; }
            set { points = value; }
        }
    
        public int Length
        {
            get { return points.Length; }
        }
    
        public PointF this[int index]
        {
            get { return points[index]; }
            set { points[index] = value; }
        }
    
        public static implicit operator PointF[](Polygon polygon)
        {
            return polygon.points;
        }
    
        public static implicit operator Polygon(PointF[] points)
        {
            return new Polygon(points);
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return (IEnumerator)points.GetEnumerator();
        }
    
        public IEnumerator GetEnumerator()
        {
            return points.GetEnumerator();
        }
    }
    
    public enum Intersection
    {
        None,
        Tangent,
        Intersection,
        Containment
    }
    
    public static class Geometry
    {
    
        public static Intersection IntersectionOf(Line line, Polygon polygon)
        {
            if (polygon.Length == 0)
            {
                return Intersection.None;
            }
            if (polygon.Length == 1)
            {
                return IntersectionOf(polygon[0], line);
            }
            bool tangent = false;
            for (int index = 0; index < polygon.Length; index++)
            {
                int index2 = (index + 1)%polygon.Length;
                Intersection intersection = IntersectionOf(line, new Line(polygon[index], polygon[index2]));
                if (intersection == Intersection.Intersection)
                {
                    return intersection;
                }
                if (intersection == Intersection.Tangent)
                {
                    tangent = true;
                }
            }
            return tangent ? Intersection.Tangent : IntersectionOf(line.P1, polygon);
        }
    
        public static Intersection IntersectionOf(PointF point, Polygon polygon)
        {
            switch (polygon.Length)
            {
                case 0:
                    return Intersection.None;
                case 1:
                    if (polygon[0].X == point.X && polygon[0].Y == point.Y)
                    {
                        return Intersection.Tangent;
                    }
                    else
                    {
                        return Intersection.None;
                    }
                case 2:
                    return IntersectionOf(point, new Line(polygon[0], polygon[1]));
            }
    
            int counter = 0;
            int i;
            PointF p1;
            int n = polygon.Length;
            p1 = polygon[0];
            if (point == p1)
            {
                return Intersection.Tangent;
            }
    
            for (i = 1; i <= n; i++)
            {
                PointF p2 = polygon[i % n];
                if (point == p2)
                {
                    return Intersection.Tangent;
                }
                if (point.Y > Math.Min(p1.Y, p2.Y))
                {
                    if (point.Y <= Math.Max(p1.Y, p2.Y))
                    {
                        if (point.X <= Math.Max(p1.X, p2.X))
                        {
                            if (p1.Y != p2.Y)
                            {
                                double xinters = (point.Y - p1.Y) * (p2.X - p1.X) / (p2.Y - p1.Y) + p1.X;
                                if (p1.X == p2.X || point.X <= xinters)
                                    counter++;
                            }
                        }
                    }
                }
                p1 = p2;
            }
    
            return (counter % 2 == 1) ? Intersection.Containment : Intersection.None;
        }
    
        public static Intersection IntersectionOf(PointF point, Line line)
        {
            float bottomY = Math.Min(line.Y1, line.Y2);
            float topY = Math.Max(line.Y1, line.Y2);
            bool heightIsRight = point.Y >= bottomY &&
                                 point.Y <= topY;
            //Vertical line, slope is divideByZero error!
            if (line.X1 == line.X2)
            {
                if (point.X == line.X1 && heightIsRight)
                {
                    return Intersection.Tangent;
                }
                else
                {
                    return Intersection.None;
                }
            }
            float slope = (line.X2 - line.X1)/(line.Y2 - line.Y1);
            bool onLine = (line.Y1 - point.Y) == (slope*(line.X1 - point.X));
            if (onLine && heightIsRight)
            {
                return Intersection.Tangent;
            }
            else
            {
                return Intersection.None;
            }
        }
    
    }
    

提交回复
热议问题