c#实现的一些几何算法(二)

来源:互联网 发布:淘宝店怎么看订单 编辑:程序博客网 时间:2024/06/04 23:36

续一

//关于线的一些算法

 

   public class GeometricClass

    {

        /* 判断点与线段的关系,用途很广泛 

         本函数是根据下面的公式写的,P是点C到线段AB所在直线的垂足 

 

                 AC dot AB 

         r =     --------- 

                  ||AB||^2 

              (Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay) 

           = ------------------------------- 

                           L^2 

 

         r has the following meaning: 

 

         r=0      P = A 

         r=1      P = B 

         r<0 P is on the backward extension of AB 

         r>1      P is on the forward extension of AB 

         0<r<1 P is interior to AB 

        */

        public static double RelationOfPointAndLine(SpatialPoint p, SpatialLine l)

        {

            SpatialLine tl = new SpatialLine();

            tl.startPoint = l.startPoint;

            tl.endPoint = p;

            return dotmultiply(tl.endPoint, l.endPoint, l.startPoint) / (CalculateFlatDistance(l.startPoint, l.endPoint) * CalculateFlatDistance(l.startPoint, l.endPoint));

        }

 

        // 根据已知两点坐标,求过这两点的直线解析方程: a*x+b*y+c = 0  (a >= 0)  

        public static SpatialLine Makeline(SpatialPoint p1, SpatialPoint p2)

        {

            SpatialLine tl = new SpatialLine();

            int sign = 1;

            tl.a = p2.y - p1.y;

            if (tl.a < 0)

            {

                sign = -1;

                tl.a = sign * tl.a;

            }

            tl.b = sign * (p1.x - p2.x);

            tl.c = sign * (p1.y * p2.x - p1.x * p2.y);

            return tl;

        }

 

        // 根据直线解析方程返回直线的斜率k,水平线返回 0,竖直线返回 1e200 

        public static double SlopeOfLine(SpatialLine l)

        {

            if (Math.Abs(l.a) < INF)

                return 0;

            if (Math.Abs(l.b) < INF)

                return double.MaxValue;

 

            return -(l.a / l.b);

        }

 

        // 返回直线的倾斜角alpha ( 0 - pi) 

        public static double alphaOfLine(SpatialLine l)

        {

            if (Math.Abs(l.a) < INF)

                return 0;

            if (Math.Abs(l.b) < INF)

                return PI / 2;

            double k = SlopeOfLine(l);

            if (k > 0)

                return Math.Atan(k);

            else

                return PI + Math.Atan(k);

        }

 

        // 求点C到线段AB所在直线的垂足 P 

        public static SpatialPoint PerpendicularOnLine(SpatialPoint p, SpatialLine l)

        {

            double r = RelationOfPointAndLine(p, l);

            SpatialPoint tp = new SpatialPoint();

            tp.x = l.startPoint.x + r * (l.endPoint.x - l.startPoint.x);

            tp.y = l.startPoint.y + r * (l.endPoint.y - l.startPoint.y);

            return tp;

        }

 

        // 求点p到线段l所在直线的距离,请注意本函数与上个函数的区别  

        public static double DistanceInPointToLine(SpatialPoint p, SpatialLine l)

        {

            return Math.Abs(multiply(p, l.endPoint, l.startPoint)) / CalculateFlatDistance(l.startPoint, l.endPoint);

        }

 

        // 返回线段l1与l2之间的夹角 单位:弧度 范围(-pi,pi) 

        public static double AngleOfTwoLine(SpatialLine l1, SpatialLine l2)

        {

            SpatialPoint o, s, e;

            o = new SpatialPoint();

            s = new SpatialPoint();

            e = new SpatialPoint();

            o.x = o.y = 0;

            s.x = l1.endPoint.x - l1.startPoint.x;

            s.y = l1.endPoint.y - l1.startPoint.y;

            e.x = l2.endPoint.x - l2.startPoint.x;

            e.y = l2.endPoint.y - l2.startPoint.y;

            return AngleOfThreePoint(o, s, e);

        }

 

        // 如果线段u和v相交(包括相交在端点处)时,返回true 

        //判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。

        //判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 - P1 ) × ( Q2 - P1 ) >= 0。

        public static bool IsIntersect(SpatialLine u, SpatialLine v)

        {

            return ((Math.Max(u.startPoint.x, u.endPoint.x) >= Math.Min(v.startPoint.x, v.endPoint.x)) &&                     //排斥实验 

                    (Math.Max(v.startPoint.x, v.endPoint.x) >= Math.Min(u.startPoint.x, u.endPoint.x)) &&

                    (Math.Max(u.startPoint.y, u.endPoint.y) >= Math.Min(v.startPoint.y, v.endPoint.y)) &&

                    (Math.Max(v.startPoint.y, v.endPoint.y) >= Math.Min(u.startPoint.y, u.endPoint.y)) &&

                    (multiply(v.startPoint, u.endPoint, u.startPoint) * multiply(u.endPoint, v.endPoint, u.startPoint) >= 0) &&         //跨立实验 

                    (multiply(u.startPoint, v.endPoint, v.startPoint) * multiply(v.endPoint, u.endPoint, v.startPoint) >= 0));

        }

 

        //  (线段u和v相交)&&(交点不是双方的端点) 时返回true    

        public static bool IsIntersect_A(SpatialLine u, SpatialLine v)

        {

            return ((IsIntersect(u, v)) &&

                    (!PointIsOnLine(u, v.startPoint)) &&

                    (!PointIsOnLine(u, v.endPoint)) &&

                    (!PointIsOnLine(v, u.endPoint)) &&

                    (!PointIsOnLine(v, u.startPoint)));

        }

 

        // 线段v所在直线与线段u相交时返回true;方法:判断线段u是否跨立线段v  

        public static bool intersect_l(SpatialLine u, SpatialLine v)

        {

            return multiply(u.startPoint, v.endPoint, v.startPoint) * multiply(v.endPoint, u.endPoint, v.startPoint) >= 0;

        }

 

 

        // 如果两条直线 l1(a1*x+b1*y+c1 = 0), l2(a2*x+b2*y+c2 = 0)相交,返回true,且返回交点p  

        public static bool LineIntersect(SpatialLine l1, SpatialLine l2, out SpatialPoint intersectPoint) // 是 L1,L2 

        {

            double d = l1.a * l2.b - l2.a * l1.b;

            intersectPoint = new SpatialPoint();

            if (Math.Abs(d) < EP) // 不相交 

                return false;

            intersectPoint.x = (l2.c * l1.b - l1.c * l2.b) / d;

            intersectPoint.y = (l2.a * l1.c - l1.a * l2.c) / d;

            intersectPoint.h = 0;

            return true;

        }

        // 如果线段l1和l2相交,返回true且交点由(intersectPoint)返回,否则返回false 

        public static bool LineSegmentIntersection(SpatialLine l1, SpatialLine l2, out SpatialPoint intersectPoint)

        {

            SpatialLine ll1, ll2;

            intersectPoint = new SpatialPoint();

            ll1 = Makeline(l1.startPoint, l1.endPoint);

            ll2 = Makeline(l2.startPoint, l2.endPoint);

            if (LineIntersect(ll1, ll2, out intersectPoint))

                return PointIsOnLine(l1, intersectPoint) && PointIsOnLine(l2, intersectPoint);

            else

                return false;

        } 

    }

 

原创粉丝点击