答え
#include <iostream>
#include <cmath>
#include <cv.h>
#include <highgui.h>
using namespace std;
/**************[プロトタイプ宣言]************************/
void DRAW_FRACTAL(IplImage *imgA);
void DRAW_FRACTAL_BIN_TREE(IplImage *imgA,CvPoint p1,CvPoint p2,double angle,int dim);
/************* [メイン関数] *************/
int main( int argc, char **argv)
{
static CvSize window_size={300,300};
IplImage *imgA = cvCreateImage(window_size,IPL_DEPTH_8U,3);
cvSet (imgA, cvScalarAll (255), 0);
imgA->origin = 1; //左下原点にする
DRAW_FRACTAL(imgA);
cvNamedWindow("window",CV_WINDOW_AUTOSIZE);
cvShowImage("window",imgA);
cvWaitKey(0); // 0秒待つ => ずっと入力待ち
cvReleaseImage(& imgA);
cvDestroyWindow("window");
return 0;
}
/**************[ここから、各種関数]****************/
#define PI_OVER_180 0.0174532925
void DRAW_FRACTAL(IplImage *imgA)
{
CvPoint p1=cvPoint(150,20),p2=cvPoint(150,150);//スタート地点
const double angle = 30 * PI_OVER_180;
const int dim = 4; //階層の深さ
DRAW_FRACTAL_BIN_TREE(imgA,p1,p2,angle,dim); //ここから再帰
}
void DRAW_FRACTAL_BIN_TREE(IplImage *imgA,CvPoint p1,CvPoint p2,double angle,int dim)
{
cvLine(imgA,p1,p2,CV_RGB(0,200,0));
if(dim == 0)
{
return;
}
CvPoint2D64f Sin_Cos = cvPoint2D64f(sin(angle),cos(angle));
CvPoint2D64f DX_DY = cvPoint2D64f(0.5* double(p2.x - p1.x),0.5* double(p2.y - p1.y)); //ベクトル取得
/*** 回転行列でまわす ***/
CvPoint p3=cvPoint(int(p2.x + DX_DY.x * Sin_Cos.y - DX_DY.y * Sin_Cos.x), int(p2.y + DX_DY.x * Sin_Cos.x + DX_DY.y * Sin_Cos.y));
CvPoint p4=cvPoint(int(p2.x + DX_DY.x * Sin_Cos.y + DX_DY.y * Sin_Cos.x), int(p2.y - DX_DY.x * Sin_Cos.x + DX_DY.y * Sin_Cos.y));
DRAW_FRACTAL_BIN_TREE(imgA,p2,p3,angle,dim-1);
DRAW_FRACTAL_BIN_TREE(imgA,p2,p4,angle,dim-1);
}
メモ
左下原点。
ある地点(x,y)からθだけ回転させる行列は
[cosθ - sinθ]
[sinθ cosθ]
である。
回転後の座標を(X,Y)とすると
[cosθ - sinθ][x]
[sinθ cosθ][y]
より
X = x*cosθ- y*sinθ
Y = x*sinθ+ y*cosθ
となる。