OpenGL de プログラミング - OpenCV::2分木
現在地 >> メニュー >> サンプルコード::OpenCV >> OpenCV::2分木

問題


再帰処理を用いて、2分木を描画せよ

答え


#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θ

となる。