Ming Apps

Objective-c Tutorial: Spline – Line Smoothing Techniques

Posted on: 2011/04/09

Xcode logo

當我在做FYP之時,

第一個遇上的問題就是這個!

為甚麼我畫線(Line Drawing)的時候,

條線一D都唔smooth!

objective-c tutorial: not smooth line demo

找尋良久,

終於讓我發現了一個很有趣的原因。

原來大部份電子產品,

都是利用了fixed sampling rate的設計,

意思即是每隔一千分之一秒(depends on你hardware, 可以係60分之一秒),

才會讀取user的input之類。

所以ipad的設計拿取touch point的數值之後,

點與點(point to point)之間的距離變得這樣大,

看來就不像曲線了。

所以要靠計數的方法!

Calculation 計返中間曲線的點!

Ming Apps Objective-c tutorial demo: line smoothed by spline

原來呢一招係Microsoft小畫家(mspaint)亦都需要用到呢~

招式正統名稱為: Spline Interpolation

比較常見的是Hermite spline or Cubic Hermite spline兩種。

筆者數學能力尚淺,

所以筆者還是找來了一個我在FYP中使用的方式,

主要是從cocos2d forum找來的c program code,

(不是objective-c! 因為我的program code改了還是貼上原文的code吧~)

void genCubicInterpolation(CGPoint *points, unsigned num, unsigned segments, CGPoint *vertices)
{
    int count = 0;
    float dt = 1.f / (float) segments;

    if (num < 2) return;

    // We need two extra points
    CGPoint d0, dN;

    d0 = ccpAdd(points[0], ccpNormalize(ccpSub(points[1], points[0])));
    dN = ccpAdd(points[num-1], ccpNormalize(ccpSub(points[num-1], points[num-2])));

    for (int i=0; i<(num-1); i++) {
        vertices[count] = points[i];
        count++;

        CGPoint y0, y1, y2, y3;

        if (i==0) {
            y0 = d0;
        } else {
            y0 = points[i-1];
        }
        y1 = points[i];
        y2 = points[i+1];
        if (i==(num-2)) {
            y3 = dN;
        } else {
            y3 = points[i+2];
        }

        for (float mu=dt; mu < 1.f; mu += dt) {
            CGPoint a0, a1, a2, a3, p;
            double mu2 = mu * mu;

            // Two variants, the second is smoother

            // First
            a0.x = y3.x - y2.x - y0.x + y1.x;
            a0.y = y3.y - y2.y - y0.y + y1.y;

            a1.x = y0.x - y1.x - a0.x;
            a1.y = y0.y - y1.y - a0.y;

            a2.x = y2.x - y0.x;
            a2.y = y2.y - y0.y;

            a3.x = y1.x;
            a3.y = y1.y;

            // Second, the same as Catmull/Rom
            /*
            a0.x = -0.5f * y0.x + 1.5f * y1.x -  1.5f * y2.x + 0.5f * y3.x;
            a0.y = -0.5f * y0.y + 1.5f * y1.y -  1.5f * y2.y + 0.5f * y3.y;

            a1.x = y0.x - 2.5f * y1.x + 2.f * y2.x - 0.5f * y3.x;
            a1.y = y0.y - 2.5f * y1.y + 2.f * y2.y - 0.5f * y3.y;

            a2.x = -0.5f * y0.x + 0.5f * y2.x;
            a2.y = -0.5f * y0.y + 0.5f * y2.y;

            a3.x = y1.x;
            a3.y = y1.y;
             */

            // The point
            p.x = (a0.x * mu * mu2) + (a1.x * mu2) + (a2.x * mu) + a3.x;
            p.y = (a0.y * mu * mu2) + (a1.y * mu2) + (a2.y * mu) + a3.y;

            vertices[count] = p;
            count++;
        }
    }

    vertices[count] = points[num-1];
}

大家嘗試自己將它變做自己的sourcecode吧!

注:  The vertices array must have a length of ((num-1)*segments)+1!!!

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s

%d 位部落客按了讚: