Genesis 多邊形閉輪廓填充算法


 通過逐行掃描,計算得出直線與多邊形相交點進行求解

原理圖形如下所示:

相關函數:

     /// <summary>
        /// 求點P到線段L距離
        /// </summary>
        /// <param name="p"></param>
        /// <param name="l"></param>
        /// <param name="return_p"></param>
        /// <param name="is_calc_width"></param>
        /// <returns></returns>
        public double p2l_di(gP p, gL l, gPoint return_p, bool is_calc_width = false)
        {
            double b, s, a_side, b_side, c_side;
            a_side = p2p_di(p.p, l.ps);
            if (a_side < eps) return 0;
            b_side = p2p_di(p.p, l.pe);
            if (b_side < eps) return 0;
            c_side = p2p_di(l.ps, l.pe);
            if (b_side < eps) return a_side;

            //' 鈍角或直角三角形
            if (a_side * a_side >= b_side * b_side + c_side * c_side)
            {
                return_p = l.pe;
                if (is_calc_width)
                    return b_side - p.width * 0.0005 - l.width * 0.0005;
                else
                    return b_side;
            }

            if (b_side * b_side >= a_side * a_side + c_side * c_side)
            {
                return_p = l.ps;
                if (is_calc_width)
                    return a_side - p.width * 0.0005 - l.width * 0.0005;
                else
                    return a_side;
            }

            // 銳角三角形
            return_p = p2l_toP(p.p, l);
            b = (a_side + b_side + c_side) * 0.5;
            s = Math.Sqrt(b * (b - a_side) * (b - b_side) * (b - c_side));
            if (is_calc_width)
                return s * 2 / c_side - p.width * 0.0005 - l.width * 0.0005;
            else
                return s * 2 / c_side;
        }
 /// <summary>
        /// 求點P到線L垂足P
        /// </summary>
        /// <param name="p"></param>
        /// <param name="l"></param>
        /// <returns></returns>
        public gPoint p2l_toP(gPoint p, gL l)
        {
            gPoint tempP;
            if (Math.Abs(l.ps.x - l.pe.x) < eps)//垂直
            {
                tempP.x = (l.ps.x + l.pe.x) * 0.5;
                tempP.y = p.y;
            }
            else if (Math.Abs(l.ps.y - l.pe.y) < eps) //水平
            {
                tempP.x = p.x;
                tempP.y = (l.ps.y + l.pe.y) * 0.5;
            }
            else
            {
                double k = (l.pe.y - l.ps.y) / (l.pe.x - l.ps.x);
                tempP.x = (p.y - l.ps.y + k * l.ps.x + p.x * k) * (k + 1 * k);
                tempP.y = p.y - (tempP.x - p.x) / k;
            }
            return tempP;
        }
  /// <summary>
        /// 求線段與線段交點
        /// </summary>
        /// <param name="l1ps"></param>
        /// <param name="l1pe"></param>
        /// <param name="l2ps"></param>
        /// <param name="l2pe"></param>
        /// <param name="isIntersect"></param>
        /// <returns></returns>
        public gPoint l2l_Intersect(gPoint l1ps, gPoint l1pe, gPoint l2ps, gPoint l2pe, ref bool isIntersect)
        {
            gL L1 = new gL(l1ps, l1pe, 0);
            gL L2 = new gL(l2ps, l2pe, 0);
            gPoint tempP = new gPoint();
            double ABC, ABD, CDA, CDB, T;
            //面積符號相同則兩點在線段同側,不相交 (對點在線段上的情況,本例當作不相交處理)
            ABC = (L1.ps.x - L2.ps.x) * (L1.pe.y - L2.ps.y) - (L1.ps.y - L2.ps.y) * (L1.pe.x - L2.ps.x);
            ABD = (L1.ps.x - L2.pe.x) * (L1.pe.y - L2.pe.y) - (L1.ps.y - L2.pe.y) * (L1.pe.x - L2.pe.x);
            CDA = (L2.ps.x - L1.ps.x) * (L2.pe.y - L1.ps.y) - (L2.ps.y - L1.ps.y) * (L2.pe.x - L1.ps.x);  // 三角形cda 面積的2倍 // 注意: 這里有一個小優化.不需要再用公式計算面積,而是通過已知的三個面積加減得出.
            CDB = CDA + ABC - ABD;  // 三角形cdb 面積的2倍
            isIntersect = (CDA * CDB <= 0) && (ABC * ABD <= 0);
            //計算交點
            T = CDA / (ABD - ABC);
            tempP.x = L1.ps.x + T * (L1.pe.x - L1.ps.x);
            tempP.y = L1.ps.y + T * (L1.pe.y - L1.ps.y);
            return tempP;
        }

 

 Genesis實現后圖示:

相關鏈接:http://www.cnblogs.com/zjutlitao/p/4117223.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM