zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    class(类)和构造函数(原型对象)
    es6中export和export default的区别
    vue混入 (mixin)的使用
    ES6(Module模块化)
    vue-cli3构建和发布 实现分环境打包步骤(给不同的环境配置相对应的打包命令)
    Vue中使用Echarts 脱坑
    Nginx配置详解
    VUE面包屑组件
    更改 pip 默认下载源(pip 配置文件)
    常见免费API接口
  • 原文地址:https://www.cnblogs.com/pcbren/p/9131069.html
Copyright © 2011-2022 走看看