(彩色版請見 http://novus.pixnet.net/blog/post/26679362 )

Buddhabrot第2版,和前一個版本架構上沒有太大的不同。和我猜的一樣,很多奇奇怪怪的問題在增加取樣之後就解決了,不過圖形也變得單調許多。另一項小小的改良則是計算走捷徑,使得速度大幅提升。

高解析度下載 (1024 x 1024) ~ 沒辦法,photobucket 好像不讓我傳更大的圖


const int ITER_MAX = 1200;
const int PLOT_WIDTH = 625, PLOT_HEIGHT = 625;

// 每個 pixel 取樣倍數
const int SAMPLE_FACTOR = 5;
const int SAMPLE_HOR = PLOT_WIDTH * SAMPLE_FACTOR;
const int SAMPLE_VER = PLOT_HEIGHT * SAMPLE_FACTOR;

const double REAL_MAX = 0.85, REAL_MIN = -1.65;
const double IMAG_MAX = 1.25, IMAG_MIN = -1.25;

const double REAL_STEP = (REAL_MAX - REAL_MIN) / SAMPLE_HOR;
const double IMAG_STEP = (IMAG_MAX - IMAG_MIN) / SAMPLE_VER;

unsigned trace[PLOT_WIDTH * PLOT_HEIGHT];

void PlotData(HDC hdc)
{
    // 把trace上的每個點畫出來
    // 數值越大越亮
    // 請自行發揮
}

// 已知必定不發散的點就直接短路
inline bool IsKnownInside(double cReal, double cImag) 
{
    if (-0.6 < cReal && cReal < -0.5 && -0.4 < cImag && cImag < 0.4) {
        return true;
    } else if (-0.5 < cReal && cReal < 0.2 && -0.5 < cImag && cImag < 0.5) {
        return true;
    } else if (-1.14 < cReal && cReal < -0.86 && -0.14 < cImag && cImag < 0.14) {
        return true;
    } 
    return false;
}

bool Calc(double cReal, double cImag, bool updateTrace)
{
    double zReal = cReal, zImag = cImag;

    for (int i = 0; i < ITER_MAX; i++) {
        double zRealSqr = zReal * zReal;
        double zImagSqr = zImag * zImag;

        if (zRealSqr + zImagSqr > 4) return false;

        if (updateTrace && i > 3) {
            int plotX = (zReal - REAL_MIN) / (REAL_STEP * SAMPLE_FACTOR);
            int plotY = (zImag - IMAG_MIN) / (IMAG_STEP * SAMPLE_FACTOR);

            if (0 <= plotX && plotX < PLOT_WIDTH &&
                0 <= plotY && plotY < PLOT_HEIGHT) {
                ++trace[plotX + plotY * PLOT_WIDTH];
            }
        }

        zImag = 2 * zReal * zImag + cImag;
        zReal = zRealSqr - zImagSqr + cReal;
    }
    return true;
}

void DrawBuddha(HDC hdc)
{
    double cReal = REAL_MIN, cImag = IMAG_MIN;
    memset(trace, 0, sizeof(trace));

    for (int j = 0; j < SAMPLE_VER; ++j) {
        for (int i = 0; i < SAMPLE_HOR; ++i) {
            if (!IsKnownInside(cReal, cImag)) {
                if (!Calc(cReal, cImag, false)) {
                    Calc(cReal, cImag, true);
                }
            }
            cReal += REAL_STEP;
        }
        cImag += IMAG_STEP;
        cReal = REAL_MIN;
    }
    PlotData(hdc);
}
arrow
arrow
    全站熱搜

    novus 發表在 痞客邦 留言(1) 人氣()