【MIT6.837】A0: IFS

A0:IFS(迭代函數系統)

任務概述

6.837的第一個作業,實現IFS算法。目的是熟悉C++的語法特性,並且熟悉使用兩個和圖像生成和線性代數相關的簡單庫。通過生成一些奇妙的分形物體來體會圖形學的樂趣。

IFS 是一種構造分形的方法,得到的分形通常是自相似(self-similar)的。IFS最經典的例子是繪製一種蕨類植物(Barnsley’s fern),如下圖所示,可以看到,每一個子葉片與整個葉片的形狀相同。

IFS由一個仿射變換(affine transformations)集合所定義,通常定義的仿射變換包括旋轉(rotation)、縮放(scale)、平移(translations)、斜切(skew)等等線性變換方法。這些變換不着了自相似的物體形狀。IFS可以定義在多個維度上,在這個作業中,我們只需實現二維的變換。

實現細節

本實驗已經提供了matrix.h、vectors.h、image.h、image.cpp、matrix.cpp5個文件
而我們要實現的文件是ifs.h、ifs.cpp、main.cpp
因此本實驗的關鍵是實現ifs類、ifs的輸入和ifs的渲染算法

ifs類的創建

#include "matrix.h"
#include "image.h"
#include "vectors.h"
class IFS {
private:
	//仿射變換的個數
	int n;
	//仿射變換矩陣數組
	Matrix* matrix;
	//每一個仿射變換的選取概率數組
	float* prob;
public:
	//構造函數,使用仿射變換個數初始化
	IFS():n(0),matrix(nullptr),prob(nullptr){}
	//析構函數
	~IFS() {
		delete[] matrix;
		delete[] prob;
	}
	//讀取IFS輸入
	void input(const char* file);
	//繪製IFS圖片
	void render(Image& image, int num_points, int num_iters);
};

IFS輸入的實現

void IFS::input(const char* file) {
	FILE* input = fopen(file, "r");
	assert(input != nullptr);//斷言幫助調式解決邏輯bug
	//從一個流中執行格式化輸入,fscanf遇到空格和換行時結束,注意空格時也結束
	fscanf(input, "%d", &n);//讀取變換的數量
	matrix = new Matrix[n];
	prob = new float[n];
	for (int i=0;i<n;i++)
	{
		fscanf(input, "%f", &prob[i]);//讀取變換的概率
		matrix[i].Read3x3(input);//讀取變換的3x3浮點矩陣
	}
	fclose(input);//關閉輸入流
}

IFS算法的實現

void IFS::render(Image& image, int num_points, int num_iters) {
	int width = image.Width();
	int height = image.Height();
	for (int i=0;i<num_points;++i){

		Vec2f v = Vec2f(rand() * 1.0f / RAND_MAX, rand() * 1.0f / RAND_MAX);
		for (int j = 0; j < num_iters; ++j) {
			int k = 0;
			float sum = 0;
			float t = rand() * 1.0f / RAND_MAX;
			for (;k<n;++k){
				sum += prob[k];
				if (sum > t) break;
			}
			matrix[k].Transform(v);
		}
		if (v.x() >= 0 && v.x() <= 1 && v.y() >= 0 && v.y() <= 1) {
			image.SetPixel(v.x() * width, v.y() * height, Vec3f(0.0, 0.0, 0.0));
		}
	}
}

這裏我不是很懂這個算法的思想,主要是參考了別人的代碼完成

實驗結果

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

參考資料

源代碼

Github下載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章