【iOS】使用一組點畫出平滑的曲線

今天在項目中需要人臉上的點來勾勒出人臉的輪廓,我的想法是將要畫的點存入一個數(shù)組,使用了UIBezierPath來連接每一個點。但是這樣畫出來的圖是折線,顯得過于生硬。查了若干資料,后來終于在stackoverflow上找到了一個很好的解決辦法。

這個做法的原理其實是在每兩個點之間加入一些點,來使得兩個點可以平滑的過度。這其實就是Centripetal Catmull–Rom spline的思想。

于是便照葫蘆畫瓢,寫出了我的代碼

#define POINT(_INDEX_) [(NSValue *)[points objectAtIndex:_INDEX_] CGPointValue]
- (void)smoothedPathWithPoints:(NSArray *) pointsArray andGranularity:(NSInteger)granularity {
    
    NSMutableArray *points = [pointsArray mutableCopy];
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetAllowsAntialiasing(context, YES);
    CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
    CGContextSetLineWidth(context, 0.6);
    
    UIBezierPath *smoothedPath = [UIBezierPath bezierPath];
    
    // Add control points to make the math make sense
    [points insertObject:[points objectAtIndex:0] atIndex:0];
    [points addObject:[points lastObject]];
    [smoothedPath moveToPoint:POINT(0)];
    
    for (NSUInteger index = 1; index < points.count - 2; index++) {
        CGPoint p0 = POINT(index - 1);
        CGPoint p1 = POINT(index);
        CGPoint p2 = POINT(index + 1);
        CGPoint p3 = POINT(index + 2);
        
        // now add n points starting at p1 + dx/dy up until p2 using Catmull-Rom splines
        for (int i = 1; i < granularity; i++) {
            
            float t = (float) i * (1.0f / (float) granularity);
            float tt = t * t;
            float ttt = tt * t;
            
            CGPoint pi; // intermediate point
            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);
            [smoothedPath addLineToPoint:pi];
        }
        
        // Now add p2
        [smoothedPath addLineToPoint:p2];
    }
    
    // finish by adding the last point
    [smoothedPath addLineToPoint:POINT(points.count - 1)];
    
    CGContextAddPath(context, smoothedPath.CGPath);
    CGContextDrawPath(context, kCGPathStroke);
    
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 在iOS開發(fā)過程中,我們會經(jīng)常遇到畫線的功能,比如線性圖。 目前iOS畫線有兩大類方法 (我所知道的)。1、基于C...
    平原河流閱讀 6,799評論 14 20
  • 前言 本文只要描述了iOS中的Core Animation(核心動畫:隱式動畫、顯示動畫)、貝塞爾曲線、UIVie...
    GitHubPorter閱讀 3,736評論 7 11
  • 如果有個異性經(jīng)常找你聊天,然后對你說“我只想和你更多地交流思想”。十有八九你會覺得他或者她對自己有意思,人之常情嘛...
    MitoNatsume閱讀 177評論 0 0
  • 夏至金烏復回首, 絲絳梅雨何時休。 月夜把盞傷四序, 仰看七曜夢九州。
    LinkinPark_9100閱讀 254評論 0 0
  • 我們本是一個獨立的個體,如果不是因為相愛,就不會也不必在一起。 我很欣賞楊瀾,她是一位相當優(yōu)雅的女性。 這本書是她...
    微光222閱讀 741評論 8 3

友情鏈接更多精彩內(nèi)容