コード例 #1
0
 /// <summary>
 /// 点是否在共线的线段上
 /// 1 = P is inside S;
 /// 0 = P is not inside S
 /// </returns>
 /// </summary>
 /// <param name="P">a point P</param>
 /// <param name="S">a collinear segment S</param>
 /// <returns></returns>
 public static int InSegment(RPoint P, RSegment S)
 {
     if (S.P0.X != S.P1.X)
     {    // S is not vertical
         if (S.P0.X <= P.X && P.X <= S.P1.X)
         {
             return(1);
         }
         if (S.P0.X >= P.X && P.X >= S.P1.X)
         {
             return(1);
         }
     }
     else
     {    // S is vertical, so test y coordinate
         if (S.P0.Y <= P.Y && P.Y <= S.P1.Y)
         {
             return(1);
         }
         if (S.P0.Y >= P.Y && P.Y >= S.P1.Y)
         {
             return(1);
         }
     }
     return(0);
 }
コード例 #2
0
        //===================================================================
        // 点到线段距离
        //dist_Point_to_Segment(): get the distance of a point to a segment
        //     Input:  a Point P and a Segment S (in any dimension)
        //     Return: the shortest distance from P to S,返回到线段的最短距离
        public static double dist_Point_to_Segment(RPoint P, RSegment S)
        {
            Vector3d v  = S.P1 - S.P0;
            Vector3d w  = P - S.P0;
            double   c1 = RMath.dot(w, v);

            if (c1 <= 0)
            {
                return(RMath.d(P, S.P0));
            }
            double c2 = RMath.dot(v, v);

            if (c2 <= c1)
            {
                return(RMath.d(P, S.P1));
            }
            double b  = c1 / c2;
            RPoint Pb = S.P0 + b * v;

            return(RMath.d(P, Pb));
        }
コード例 #3
0
        //===================================================================
        //3D空间两线段间的最短距离
        //dist3D_Segment_to_Segment():
        //    Input:  two 3D line segments S1 and S2
        //    Return: the shortest distance between S1 and S2
        public static double Dist3D_Segment_to_Segment(RSegment S1, RSegment S2)
        {
            Vector3d u = S1.P1 - S1.P0;
            Vector3d v = S2.P1 - S2.P0;
            Vector3d w = S1.P0 - S2.P0;
            double   a = RMath.dot(u, u);      // always >= 0
            double   b = RMath.dot(u, v);
            double   c = RMath.dot(v, v);      // always >= 0
            double   d = RMath.dot(u, w);
            double   e = RMath.dot(v, w);
            double   D = a * c - b * b; // always >= 0
            double   sc, sN, sD = D;    // sc = sN / sD, default sD = D >= 0
            double   tc, tN, tD = D;    // tc = tN / tD, default tD = D >= 0

            // compute the line parameters of the two closest points
            if (D < RMath.SMALL_NUM)
            {             // the lines are almost parallel
                sN = 0.0; // force using point P0 on segment S1
                sD = 1.0; // to prevent possible division by 0.0 later
                tN = e;
                tD = c;
            }
            else
            {                // get the closest points on the infinite lines
                sN = (b * e - c * d);
                tN = (a * e - b * d);
                if (sN < 0.0)
                {       // sc < 0 => the s=0 edge is visible
                    sN = 0.0;
                    tN = e;
                    tD = c;
                }
                else if (sN > sD)
                {  // sc > 1 => the s=1 edge is visible
                    sN = sD;
                    tN = e + b;
                    tD = c;
                }
            }

            if (tN < 0.0)
            {           // tc < 0 => the t=0 edge is visible
                tN = 0.0;
                // recompute sc for this edge
                if (-d < 0.0)
                {
                    sN = 0.0;
                }
                else if (-d > a)
                {
                    sN = sD;
                }
                else
                {
                    sN = -d;
                    sD = a;
                }
            }
            else if (tN > tD)
            {      // tc > 1 => the t=1 edge is visible
                tN = tD;
                // recompute sc for this edge
                if ((-d + b) < 0.0)
                {
                    sN = 0;
                }
                else if ((-d + b) > a)
                {
                    sN = sD;
                }
                else
                {
                    sN = (-d + b);
                    sD = a;
                }
            }
            // finally do the division to get sc and tc
            sc = (Math.Abs(sN) < RMath.SMALL_NUM ? 0.0 : sN / sD);
            tc = (Math.Abs(tN) < RMath.SMALL_NUM ? 0.0 : tN / tD);

            // get the difference of the two closest points
            Vector3d dP = w + (sc * u) - (tc * v); // = S1(sc) - S2(tc)

            return(RMath.norm(dP));                // return the closest distance
        }
コード例 #4
0
 /// <summary>
 /// 点是否在线段上
 /// </summary>
 /// <param name="P">任意的点</param>
 /// <param name="S">任意线段</param>
 /// <returns></returns>
 public static int In2D_Point_Segment(RPoint P, RSegment S)
 {
     return(0);
 }
コード例 #5
0
        // perp product (2D)
        // intersect2D_2Segments(): the intersection of 2 finite 2D segments
        //    Input:  two finite segments S1 and S2
        //    Output: *I0 = intersect point (when it exists)
        //            *I1 = endpoint of intersect segment [I0,I1] (when it exists)
        //    Return: 0=disjoint (no intersect)
        //            1=intersect in unique point I0
        //            2=overlap in segment from I0 to I1
        public int Intersect2D_Segments(RSegment S1, RSegment S2, out RPoint I0, out RPoint I1)
        {
            Vector3d u = S1.P1 - S1.P0;
            Vector3d v = S2.P1 - S2.P0;
            Vector3d w = S1.P0 - S2.P0;
            double   D = RMath.perp(u, v);

            // test if they are parallel (includes either being a point)平行
            if (Math.Abs(D) < RMath.SMALL_NUM)
            {
                // S1 and S2 are parallel
                if (RMath.perp(u, w) != 0 || RMath.perp(v, w) != 0)
                {
                    I0 = null;
                    I1 = null;
                    return(0);                   // they are NOT collinear不共线
                }
                // they are collinear or degenerate两线段共线
                // check if they are degenerate points
                double du = RMath.dot2(u, u);
                double dv = RMath.dot2(v, v);
                if (du == 0 && dv == 0)
                {                       // both segments are points
                    if (S1.P0 != S2.P0) // they are distinct points不同的点
                    {
                        I0 = null;
                        I1 = null;
                        return(0);
                    }
                    I0 = S1.P0;
                    I1 = null;// they are the same point同一点
                    return(1);
                }
                if (du == 0)
                {                                                        // S1 is a single point
                    if (TopologicRelationship.InSegment(S1.P0, S2) == 0) // but is not in S2
                    {
                        I0 = null;
                        I1 = null;
                        return(0);
                    }
                    I0 = S1.P0;

                    I1 = null;
                    return(1);
                }
                if (dv == 0)
                {                                                        // S2 a single point
                    if (TopologicRelationship.InSegment(S2.P0, S1) == 0) // but is not in S1
                    {
                        I0 = null;
                        I1 = null;
                        return(0);
                    }
                    I0 = S2.P0;

                    I1 = null;
                    return(1);
                }
                // they are collinear segments - get overlap (or not)
                double   t0, t1;                 // endpoints of S1 in eqn for S2
                Vector3d w2 = S1.P1 - S2.P0;
                if (v.X != 0)
                {
                    t0 = w.X / v.X;
                    t1 = w2.X / v.X;
                }
                else
                {
                    t0 = w.Y / v.Y;
                    t1 = w2.Y / v.Y;
                }
                if (t0 > t1)
                {                                   // must have t0 smaller than t1
                    double t = t0; t0 = t1; t1 = t; // swap if not
                }
                if (t0 > 1 || t1 < 0)
                {
                    I0 = null;
                    I1 = null;
                    return(0);        // NO overlap
                }
                t0 = t0 < 0 ? 0 : t0; // clip to min 0
                t1 = t1 > 1 ? 1 : t1; // clip to max 1
                if (t0 == t1)
                {                     // intersect is a point
                    I0 = S2.P0 + t0 * v;

                    I1 = null;
                    return(1);
                }

                // they overlap in a valid subsegment
                I0 = S2.P0 + t0 * v;
                I1 = S2.P0 + t1 * v;
                return(2);
            }

            // the segments are skew and may intersect in a point
            // get the intersect parameter for S1
            double sI = RMath.perp(v, w) / D;

            if (sI < 0 || sI > 1)
            {// no intersect with S1
                I0 = null;
                I1 = null;
                return(0);
            }

            // get the intersect parameter for S2
            double tI = RMath.perp(u, w) / D;

            if (tI < 0 || tI > 1)
            {// no intersect with S2
                I0 = null;
                I1 = null;
                return(0);
            }

            I0 = S1.P0 + sI * u;               // compute S1 intersect point
            {
                I1 = null;
                return(1);
            }
        }