直角多边形添加圆角

来源:互联网 发布:2017年8月进出口数据 编辑:程序博客网 时间:2024/04/28 06:01

        最近工作的时候遇到需要对矩形增加圆角的功能,网上学习了一下添加圆角的方式,先顺利完成了。后来又遇到图档中含有非矩形直角多边形,原来的方式不行了,头疼。仔细研究了一下圆角的添加情况,增加了对圆角中心点的位置判断,顺利解决。希望给有需要的人一些帮助。注:直角多边形定义:任意相交两边互相垂直的封闭平面图形。

        添加圆角做法:先在某边上取与端点(P)距离为圆角半径的一点,以此点(R)为原点,旋转此端点90度(正负与圆角方向有关),可得到此端点处的圆角中心(O)。再以圆角中心为中心,旋转R点,可得圆角上的所有点。

        难点:圆角方向不定,需自行判断。另外一个小点是: 已知一点,以此点为中心,旋转另一点,得到新的点的坐标。

        解决思路:通过三点,判断中间点处的圆角的位置。取多边形相交两边,以起点到终点分别定为点1,点2,点3。分析可知,线12旋转至线13的角度与绕R点旋转P点得到O点时的方向一致,而产生圆角时的角度也与此方向也相关。问题的关键在于如何判断O点的位置。一开始考虑计算线13与线12之间的角度,没直接方案,计算与X轴角度之后再进行加减,顺时针输入四点坐标时是OK的,但逆时针输入四点坐标,发现有一个角出问题,圆角方向有误,Debug发现Atan函数返回的是-pi 到 pi之间的值,因此超过了180度之后,再进行加减就不对了。再观察分析,点O必处于点1,2,3围成的三角形内。故选择暴力破解法,生成两个O点,判断与点3之间的间距,进而确定正确的O点。最终实现了无论顺时针还是逆时针,顺序输入直角多边形各个端点的坐标,即可生成对应的圆角多边形的坐标。

具体C#代码如下:


public struct pointF { public double x; public double y;};


//对直角多边形(大于4边)进行增加圆角功能。直角多边形定义:任意相连两边角度为90度。
        private void AddCircleAngleToRect(pointF[] pointInput,int nCount, double dCircleR, ref double[,] PointArray, ref int iPointNum)
        {
         

 iPointNum = 0;
            for (int i = 0; i < nCount; i++)
            {
                //连续三点坐标判断中间点处的圆角圆心
                //根据判断线 13与线12的角度来判断点2处的圆角圆心的位置


                double dMidRotation = 0.0;
                double dLen12 = TwoPointLen(pointInput[(i + 1) % nCount], pointInput[i]);


                if (dLen12 < dCircleR)
                {
                    MessageBox.Show("错误,圆角半径过大");
                    return false;
                }


                pointF pCircleCenter = new pointF();


                pointF tempPointOnLine12 = new pointF();
                tempPointOnLine12.x = pointInput[(i + 1) % nCount].x * (dLen12 - dCircleR) / dLen12 - pointInput[i].x * (-dCircleR) / dLen12;
                tempPointOnLine12.y = pointInput[(i + 1) % nCount].y * (dLen12 - dCircleR) / dLen12 - pointInput[i].y * (-dCircleR) / dLen12;


                pointF temPoint1 = Rotate(pointInput[(i + 1) % nCount], tempPointOnLine12, 0.5 * Math.PI);
                pointF temPoint2 = Rotate(pointInput[(i + 1) % nCount], tempPointOnLine12, -0.5 * Math.PI);


                double dLen3t1 = TwoPointLen(pointInput[(i + 2) % nCount], temPoint1);
                double dLen3t2 = TwoPointLen(pointInput[(i + 2) % nCount], temPoint2);
                if (dLen3t1 < dLen3t2)
                {
                    pCircleCenter = temPoint1;
                    dMidRotation = 90;
                }
                else
                {
                    pCircleCenter = temPoint2;
                    dMidRotation = -90;
                }

                //画圆角
                for (int n = 0; n * 15 <= 90; n++)
                {
                    pointF pt = Rotate(tempPointOnLine12, pCircleCenter, (n * 15) * (dMidRotation / 90) * Math.PI / 180);


                    PointArray[iPointNum, 0] = pt.x;

                    PointArray[iPointNum, 1] = pt.y;

                    //对应数组的长度

                    iPointNum += 1;
                }


            }
            PointArray[iPointNum, 0] = PointArray[0, 0];
            PointArray[iPointNum, 1] = PointArray[0, 1];
            //iPointNum 做为个数。
            iPointNum += 1;
            return true;


        }

        //返回以pBasciPoint为原点,旋转pFixpoint点 zeta 弧度后得到的点的坐标
        private pointF Rotate(pointF pFixpoint, pointF pBasciPoint, double zeta)
        {
            pointF pFixResult = new pointF();

            pFixResult.x = (pFixpoint.x - pBasciPoint.x) * Math.Cos(zeta) - (pFixpoint.y - pBasciPoint.y) * Math.Sin(zeta) + pBasciPoint.x;
            pFixResult.y = (pFixpoint.x - pBasciPoint.x) * Math.Sin(zeta) + (pFixpoint.y - pBasciPoint.y) * Math.Cos(zeta) + pBasciPoint.y;
            return pFixResult;
        }


        //返回两点间距离
        private double TwoPointLen(pointF pPoint1, pointF pPoint2)
        {
            double dLen = Math.Sqrt((pPoint2.y - pPoint1.y) * (pPoint2.y - pPoint1.y) + (pPoint2.x - pPoint1.x) * (pPoint2.x - pPoint1.x));
            return dLen;
        }


Good luck



0 0