Algorithm for creating rounded corners in a polygon

前端 未结 5 726
醉酒成梦
醉酒成梦 2020-12-02 06:15

I\'m looking for an algorithm that allows me to create rounded corners from a polygon. In Input, I get an array of points that represents the polygon (red line) and in outpu

5条回答
  •  予麋鹿
    予麋鹿 (楼主)
    2020-12-02 06:33

    Here is my realisation of dbc's idea on c#:

    /// 
    /// Round polygon corners
    /// 
    /// Vertices array
    /// Round radius
    /// 
    static public GraphicsPath RoundCorners(PointF[] points, float radius) {
        GraphicsPath retval = new GraphicsPath();
        if (points.Length < 3) {
            throw new ArgumentException();
        }
        rects = new RectangleF[points.Length];
        PointF pt1, pt2;
        //Vectors for polygon sides and normal vectors
        Vector v1, v2, n1 = new Vector(), n2 = new Vector();
        //Rectangle that bounds arc
        SizeF size = new SizeF(2 * radius, 2 * radius);
        //Arc center
        PointF center = new PointF();
    
        for (int i = 0; i < points.Length; i++) {
            pt1 = points[i];//First vertex
            pt2 = points[i == points.Length - 1 ? 0 : i + 1];//Second vertex
            v1 = new Vector(pt2.X, pt2.Y) - new Vector(pt1.X, pt1.Y);//One vector
            pt2 = points[i == 0 ? points.Length - 1 : i - 1];//Third vertex
            v2 = new Vector(pt2.X, pt2.Y) - new Vector(pt1.X, pt1.Y);//Second vector
            //Angle between vectors
            float sweepangle = (float)Vector.AngleBetween(v1, v2);
            //Direction for normal vectors
            if (sweepangle < 0) { 
                n1 = new Vector(v1.Y, -v1.X);
                n2 = new Vector(-v2.Y, v2.X);
            }
            else {
                n1 = new Vector(-v1.Y, v1.X);
                n2 = new Vector(v2.Y, -v2.X);
            }
    
            n1.Normalize(); n2.Normalize();
            n1 *= radius; n2 *= radius;
            /// Points for lines which intersect in the arc center
            PointF pt = points[i];
            pt1 = new PointF((float)(pt.X + n1.X), (float)(pt.Y + n1.Y));
            pt2 = new PointF((float)(pt.X + n2.X), (float)(pt.Y + n2.Y));
            double m1 = v1.Y / v1.X, m2 = v2.Y / v2.X;
            //Arc center
            if (v1.X == 0) {// first line is parallel OY
                center.X = pt1.X;
                center.Y = (float)(m2 * (pt1.X - pt2.X) + pt2.Y);
            }
            else if (v1.Y == 0) {// first line is parallel OX
                center.X = (float)((pt1.Y - pt2.Y) / m2 + pt2.X);
                center.Y = pt1.Y;
            }
            else if (v2.X == 0) {// second line is parallel OY
                center.X = pt2.X;
                center.Y = (float)(m1 * (pt2.X - pt1.X) + pt1.Y);
            }
            else if (v2.Y == 0) {//second line is parallel OX
                center.X = (float)((pt2.Y - pt1.Y) / m1 + pt1.X);
                center.Y = pt2.Y;
            }
            else {
                center.X = (float)((pt2.Y - pt1.Y + m1 * pt1.X - m2 * pt2.X) / (m1 - m2));
                center.Y = (float)(pt1.Y + m1 * (center.X - pt1.X));
            }
            rects[i] = new RectangleF(center.X - 2, center.Y - 2, 4, 4);
            //Tangent points on polygon sides
            n1.Negate(); n2.Negate();
            pt1 = new PointF((float)(center.X + n1.X), (float)(center.Y + n1.Y));
            pt2 = new PointF((float)(center.X + n2.X), (float)(center.Y + n2.Y));
            //Rectangle that bounds tangent arc
            RectangleF rect = new RectangleF(new PointF(center.X - radius, center.Y - radius), size);
            sweepangle = (float)Vector.AngleBetween(n2, n1);
            retval.AddArc(rect, (float)Vector.AngleBetween(new Vector(1, 0), n2), sweepangle);
        }
        retval.CloseAllFigures();
        return retval;
    }
    

提交回复
热议问题