Algorithm for creating rounded corners in a polygon

前端 未结 5 727
醉酒成梦
醉酒成梦 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:21

    Objective-C adaptation of nempoBu4 answer:

    typedef enum {
        path_move_to,
        path_line_to
    } Path_command;
    
    
    
    
    
    static inline CGFloat sqr (CGFloat a)
    {
        return a * a;
    }
    
    
    
    
    
    static inline CGFloat positive_angle (CGFloat angle)
    {
        return angle < 0 ? angle + 2 * (CGFloat) M_PI : angle;
    }
    
    
    
    
    
    static void add_corner (UIBezierPath* path, CGPoint p1, CGPoint p, CGPoint p2, CGFloat radius, Path_command first_add)
    {
        // 2
        CGFloat angle = positive_angle (atan2f (p.y - p1.y, p.x - p1.x) - atan2f (p.y - p2.y, p.x - p2.x));
    
        // 3
        CGFloat segment = radius / fabsf (tanf (angle / 2));
        CGFloat p_c1 = segment;
        CGFloat p_c2 = segment;
    
        // 4
        CGFloat p_p1 = sqrtf (sqr (p.x - p1.x) + sqr (p.y - p1.y));
        CGFloat p_p2 = sqrtf (sqr (p.x - p2.x) + sqr (p.y - p2.y));
        CGFloat min = MIN(p_p1, p_p2);
        if (segment > min) {
            segment = min;
            radius = segment * fabsf (tanf (angle / 2));
        }
    
        // 5
        CGFloat p_o = sqrtf (sqr (radius) + sqr (segment));
    
        // 6
        CGPoint c1;
        c1.x = (CGFloat) (p.x - (p.x - p1.x) * p_c1 / p_p1);
        c1.y = (CGFloat) (p.y - (p.y - p1.y) * p_c1 / p_p1);
    
        //  7
        CGPoint c2;
        c2.x = (CGFloat) (p.x - (p.x - p2.x) * p_c2 / p_p2);
        c2.y = (CGFloat) (p.y - (p.y - p2.y) * p_c2 / p_p2);
    
        // 8
        CGFloat dx = p.x * 2 - c1.x - c2.x;
        CGFloat dy = p.y * 2 - c1.y - c2.y;
    
        CGFloat p_c = sqrtf (sqr (dx) + sqr (dy));
    
        CGPoint o;
        o.x = p.x - dx * p_o / p_c;
        o.y = p.y - dy * p_o / p_c;
    
        // 9
        CGFloat start_angle = positive_angle (atan2f ((c1.y - o.y), (c1.x - o.x)));
        CGFloat end_angle = positive_angle (atan2f ((c2.y - o.y), (c2.x - o.x)));
    
    
        if (first_add == path_move_to) {
            [path moveToPoint: c1];
        }
        else {
            [path addLineToPoint: c1];
        }
        [path addArcWithCenter: o radius: radius startAngle: start_angle endAngle: end_angle clockwise: angle < M_PI];
    }
    
    
    
    
    
    UIBezierPath* path_with_rounded_corners (NSArray* points, CGFloat corner_radius)
    {
        UIBezierPath* path = [UIBezierPath bezierPath];
        NSUInteger count = points.count;
        for (NSUInteger i = 0; i < count; ++i) {
            CGPoint prev = points[i > 0 ? i - 1 : count - 1].CGPointValue;
            CGPoint p = points[i].CGPointValue;
            CGPoint next = points[i + 1 < count ? i + 1 : 0].CGPointValue;
            add_corner (path, prev, p, next, corner_radius, i == 0 ? path_move_to : path_line_to);
        }
        [path closePath];
        return path;
    }
    

提交回复
热议问题