这是一个做分形计算的实验.
本身的算法很简单,就是随即取分部整张图的点,然后概率性的选取矩阵做迭代,迭代若干次后就可以获得结果.
实验本身提供了vectors,matrix,image类的实现.我们要做的就是给出Ifs类和最后的main函数.
先是Ifs.h文件中Ifs类的申明:
class Ifs {
private:
struct MatrixType
{
Matrix m;
float f;
MatrixType(const Matrix& tm, float tf )
:m(tm)
,f(tf)
{
}
};
typedef std::vector<MatrixType> Matrices;
Matrices Trans;
public:
Ifs(){}
Ifs(Matrices Trans);
void Read(char *filename);
Image* render(int pnum,int inum,int width,int height);
Matrix cal(float n);
};
用了vector来储存分形矩阵和概率.、
因为image函数它本身的初始化过程中了就用了new,所以我们对render函数的调用用指针.
然后Ifs.c文件:
void Ifs::Read( char *filename)
{
ifstream ifile;
ifile.open(filename);
int n;
float f;
ifile>>n;
float a[16];
while(1)
{
if(ifile.eof()!=0)
break;
ifile>>f>>a[0]>>a[1]>>a[3]>>a[4]>>a[5]>>a[7]>>a[12]>>a[13]>>a[15];
Matrix k;
for(int s=0;s<4;s++){
if (s == 2) continue;
for(int t=0;t<4;t++){
if (t == 2) continue;
k.Set(t,s,a[4*s+t]);
}
}
Trans.push_back(MatrixType(k,f));
}
ifile.close();
}
这是读入文件的函数,用push_back来保存到Ifs类Tran中.注意下矩阵变换3*3到4*4是把第三行和第三列全部补成0.
Matrix Ifs::cal(float n)
{
Matrices::iterator i = Trans.begin();
for (;i != Trans.end();i++)
{
n -= i->f;
if (n<=0)
{
return i->m;
}
}
}
Image* Ifs::render(int pnum,int inum,int width,int height)
{
float randp,kp;
srand(time(0));
float(* pointarray)[2]= new float[width*height][2];
Image* myimage=new Image(width,height);
Vec2f vec;
for(int j=0;j<=pnum-1;j++)
{
int k=rand()%100;
kp=k/100.00;
pointarray[j][0]=k;
k=rand()%100;
kp=k/100.00;
pointarray[j][1]=k;
}
for(int i=0;i<=inum-1;i++)
for(int j=0;j<=pnum-1;j++)
{
vec=Vec2f::Vec2f(pointarray[j][0],pointarray[j][1]);
int k=rand()%100;
randp=k/100.00;
Matrix aTran=cal(randp);
aTran.Transform(vec);
pointarray[j][0]=vec.x();
pointarray[j][1]=vec.y();
if(pointarray[j][0]>=1)
pointarray[j][0]=0.99;
if(pointarray[j][0]<0)
pointarray[j][0]=0;
if(pointarray[j][1]>=1)
pointarray[j][1]=0.99;
if(pointarray[j][1]<0)
pointarray[j][1]=0;
}
for(int j=0;j<=pnum-1;j++)
myimage->SetPixel(pointarray[j][0]*width,pointarray[j][1]*height,Vec3f(0.0f,1.0f,0.0f));
delete []pointarray;
return myimage;
}
cal函数是用来按概率选取哪个矩阵的.
render函数就是读入长宽,点数和迭代次数,然后进行迭代生成一个image类的过程.pointarray数组太大,所以new出来.return前记得把它delete掉.这里的image是new出来的,为了不让它在调用结束就析构掉,我们对image是new的,后面在parse.c中记得把它delete掉.注意矩阵变换后可能越界,所以把越界的点拉回来.
最后是parse.c:
int main(int argc,char *argv[])
{
char *input_file = NULL;
int width = 100;
int height = 100;
int pnum = 100;
int inum = 10;
char *output_file = NULL;
float depth_min = 0;
float depth_max = 1;
char *depth_file = NULL;
// sample command lines:
// raycast -input input.txt -size 100 100 -output output.tga
// raycast -input input.txt -size 100 100 -depth 5.5 8.8 output.tga
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i],"-input")) {
i++; assert (i < argc);
input_file = argv[i];
} else if (!strcmp(argv[i],"-size")) {
i++; assert (i < argc);
width = height=atoi(argv[i]);
} else if (!strcmp(argv[i],"-points")) {
i++; assert (i < argc);
pnum = atoi(argv[i]);
} else if (!strcmp(argv[i],"-iters")) {
i++; assert (i < argc);
inum = atoi(argv[i]);
} else if (!strcmp(argv[i],"-output")) {
i++; assert (i < argc);
output_file = argv[i];
} else if (!strcmp(argv[i],"-depth")) {
i++; assert (i < argc);
depth_min = atof(argv[i]);
i++; assert (i < argc);
depth_max = atof(argv[i]);
i++; assert (i < argc);
depth_file = argv[i];
} else {
printf ("whoops error with command line argument %d: '%s'\n",i,argv[i]);
assert(0);
}
}
Ifs myifs;
myifs.Read(input_file);
Image* myimage=myifs.render(pnum,inum,width,height);
myimage->SaveTGA(output_file);
delete myimage;
}
最后记得把myimage delete掉就可以了.