//线段与凸多边形相交
        //intersect2D_SegPoly():
        //    Input:  S = 2D segment to intersect with the convex polygon
        //            n = number of 2D points in the polygon
        //            V[] = array of n+1 vertex points with V[n]=V[0]
        //      Note: The polygon MUST be convex and
        //                have vertices oriented counterclockwise (ccw).
        //            This code does not check for and verify these conditions.
        //    Output: *IS = the intersection segment (when it exists)
        //    Return: FALSE = no intersection
        //            TRUE  = a valid intersection segment exists
        int intersect2D_SegPoly(RgSegment S, RgPoint[] V, int n, RgSegment IS)
        {
            if (S.P0 == S.P1)
            {                                                          // the segment S is a single point
                // test for inclusion of S.P0 in the polygon
                IS = S;                                                // same point if inside polygon
                return(RgTopologicRelationship.cn_PnPoly(S.P0, V, n)); // March 2001 Algorithm
            }

            float    tE = 0;           // the maximum entering segment parameter
            float    tL = 1;           // the minimum leaving segment parameter
            float    t, N, D;          // intersect parameter t = N / D
            Vector3d dS = S.P1 - S.P0; // the segment direction vector
            Vector3d e;                // edge vector

            // Vector ne;              // edge outward normal (not explicit in code)

            for (int i = 0; i < n; i++)  // process polygon edge V[i]V[i+1]
            {
                RgPoint ePt = V[i + 1] - V[i];
                e = new Vector3d(ePt.X, ePt.Y, 0);
                RgPoint temp = S.P0 - V[i];
                N = (float)RgMath.perp(e, new Vector3d(temp.X, temp.Y, 0)); // = -dot(ne, S.P0-V[i])
                D = (float)-RgMath.perp(e, dS);                             // = dot(ne, dS)
                if (Math.Abs(D) < RgMath.SMALL_NUM)
                {                                                           // S is nearly parallel to this edge
                    if (N < 0)                                              // P0 is outside this edge, so
                    {
                        return(0);                                          // S is outside the polygon
                    }
                    else                                                    // S cannot cross this edge, so
                    {
                        continue;                                           // ignore this edge
                    }
                }

                t = N / D;
                if (D < 0)
                {                    // segment S is entering across this edge
                    if (t > tE)
                    {                // new max tE
                        tE = t;
                        if (tE > tL) // S enters after leaving polygon
                        {
                            return(0);
                        }
                    }
                }
                else
                {                    // segment S is leaving across this edge
                    if (t < tL)
                    {                // new min tL
                        tL = t;
                        if (tL < tE) // S leaves before entering polygon
                        {
                            return(0);
                        }
                    }
                }
            }

            // tE <= tL implies that there is a valid intersection subsegment
            IS.P0 = S.P0 + tE * dS;   // = P(tE) = point where S enters polygon
            IS.P1 = S.P0 + tL * dS;   // = P(tL) = point where S leaves polygon
            return(1);
        }
        // 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(RgSegment S1, RgSegment S2, out Point3D I0, out Point3D I1)
        {
            Vector3d u = S1.P1 - S1.P0;
            Vector3d v = S2.P1 - S2.P0;
            Vector3d w = S1.P0 - S2.P0;
            double   D = RgMath.perp(u, v);

            // test if they are parallel (includes either being a point)平行
            if (Math.Abs(D) < RgMath.SMALL_NUM)
            {
                // S1 and S2 are parallel
                if (RgMath.perp(u, w) != 0 || RgMath.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 = RgMath.dot2(u, u);
                double dv = RgMath.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 (RgTopologicRelationship.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 (RgTopologicRelationship.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 = RgMath.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 = RgMath.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);
            }
        }