根据点串绘制圆滑贝塞尔曲线

- (UIBezierPath*)pathForPoints:(NSArray*)allPoints {

    UIBezierPath *path = [UIBezierPath bezierPath];

    CGFloatmLineSmoothness =0.18;

    CGFloatprePreviousPointX;

    CGFloatprePreviousPointY;

    CGFloatpreviousPointX;

    CGFloatpreviousPointY;

    CGFloatcurrentPointX;

    CGFloatcurrentPointY;

    CGFloatnextPointX;

    CGFloatnextPointY;

    for(inti =0; i < allPoints.count; i++) {

        CGPointcurrentPoint = [allPoints[i]CGPointValue];

        currentPointX = currentPoint.x;

        currentPointY = currentPoint.y;

        if(i >0) {

            CGPointprePoint = [allPoints[i-1]CGPointValue];

            previousPointX = prePoint.x;

            previousPointY = prePoint.y;

        }else{

            previousPointX = currentPointX;

            previousPointY = currentPointY;

        }

        if(i >1) {

            CGPointprePrePoint = [allPoints[i-2]CGPointValue];

            prePreviousPointX = prePrePoint.x;

            prePreviousPointY = prePrePoint.y;

        }

        if(i < allPoints.count-1) {

            CGPointnextPoint = [allPoints[i+1]CGPointValue];

            nextPointX = nextPoint.x;

            nextPointY = nextPoint.y;

        }else{

            nextPointX = currentPointX;

            nextPointY = currentPointY;

        }

        if(i ==0) {

            [pathmoveToPoint:currentPoint];

        }else{

            CGFloatfirstDiffX = (currentPointX - prePreviousPointX);

            CGFloatfirstDiffY = (currentPointY - prePreviousPointY);

            CGFloatsecondDiffX = (nextPointX - previousPointX);

            CGFloatsecondDiffY = (nextPointY - previousPointY);

            CGFloatfirstControlPointX = previousPointX + (mLineSmoothness * firstDiffX);

            CGFloatfirstControlPointY = previousPointY + (mLineSmoothness * firstDiffY);

            CGFloatsecondControlPointX = currentPointX - (mLineSmoothness * secondDiffX);

            CGFloatsecondControlPointY = currentPointY - (mLineSmoothness * secondDiffY);

            [pathaddCurveToPoint:CGPointMake(currentPointX, currentPointY)controlPoint1:CGPointMake(firstControlPointX, firstControlPointY)controlPoint2:CGPointMake(secondControlPointX, secondControlPointY)];//三次曲线

        }

        // 更新

        prePreviousPointX = previousPointX;

        prePreviousPointY = previousPointY;

        previousPointX = currentPointX;

        previousPointY = currentPointY;

        currentPointX = nextPointX;

        currentPointY = nextPointY;

    }

    returnpath;

}



- (UIBezierPath*)pathForPoints:(NSArray*)allPoints {

    UIBezierPath *path = [UIBezierPath bezierPath];

    //下面的方法效果更好,但是只支持4个点及以上情况

    if(allPoints.count<4) {

        [pathmoveToPoint:[allPoints[0]CGPointValue]];

        CGPointPrePonit;

        for(inti =0; i < allPoints.count; i++) {

            CGPointpoint = [allPoints[i]CGPointValue];

            point =CGPointMake(point.x, point.y);

            if(i ==0) {

                PrePonit = point;

            }else{

                CGPointNowPoint = [allPoints[i]CGPointValue];

                [pathaddCurveToPoint:NowPointcontrolPoint1:CGPointMake((PrePonit.x+NowPoint.x)/2, PrePonit.y)controlPoint2:CGPointMake((PrePonit.x+NowPoint.x)/2, NowPoint.y)];//三次曲线

                PrePonit = NowPoint;

            }

        }

    }else{

        NSIntegergranularity =10;

        [pathmoveToPoint:[allPoints[0]CGPointValue]];

        [pathaddLineToPoint:[allPoints[1]CGPointValue]];

        for(intindex =3; index < allPoints.count; index++) {

            CGPointp0 = [allPoints[index -3]CGPointValue];

            CGPointp1 = [allPoints[index -2]CGPointValue];

            CGPointp2 = [allPoints[index -1]CGPointValue];

            CGPointp3 = [allPoints[index]CGPointValue];

            for(inti =1; i < granularity; i++) {

                floatt = (float)i * (1.0/ granularity);

                floattt = t * t;

                floatttt = tt * t;

                CGPointpi;

                pi.x=0.5* (2* p1.x+(p2.x- p0.x) * t +(2* p0.x-5* p1.x+4*p2.x- p3.x) * tt + (3* p1.x- p0.x-3*p2.x+ p3.x) *ttt );

                pi.y=0.5* (2* p1.y+(p2.y- p0.y) * t +(2* p0.y-5* p1.y+4*p2.y- p3.y) * tt + (3* p1.y- p0.y-3*p2.y+ p3.y) *ttt );

                [pathaddLineToPoint:pi];

            }

            [pathaddLineToPoint:p2];

        }

        [pathaddLineToPoint:[allPoints[allPoints.count-1]CGPointValue]];

    }

    returnpath;

}



在这里采用的是Catmull-Rom插值技术实现的,其实就是一个比较特殊的贝塞尔曲线,如果想用这个方式进行插值,那么在这个曲线上最少要有4个点存在,因为这种方式只能在中间的两个点进行插值,例如有4个点分别是p0、p1、p2、p3依次在这个贝塞尔曲线上,那么我们积可以将值插到p1、p2之间,在上面的代码中可以看到变量t,t的范围是[0,1],当t=0到t=1变化,那么曲线就会从p1(t=0)到p2(t=1)运动,计算出来的点的切向量和这个点的周围两个起点和终点的切向量是平行的,那么如果想要使曲线更加的平滑,那么就要取到更多的点p0、p1、p2、p3、p4,这样就可以有两组分别是p0、p1、p2、p3和p1、p2、p3、p4,就能够在p1、p2和p2、p3之间进行插值,以此类推,使曲线更加的平滑

你可能感兴趣的:(根据点串绘制圆滑贝塞尔曲线)