대표적인 시간매개형 프랙탈. mandelbrot set의 색은 각 점에서의 발산 속도에 따른다
수열이 발산하지 않을 복소수 C의 집합으로 정의 된다
tmp = z;
z.r = tmp.r * tmp.r - tmp.i * tmp.i + c.r;
z.i = 2 * tmp.r * tmp.i + c.i;
long map(long x, long in_min, long in_max, long out_min, long out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
void screen_to_world(t_point *point, t_cmplx *cmplx, t_frctl *fr)
{
double rscale;
double iscale;
rscale = (fr->rmax - fr->rmin) / WIN_W;
iscale = (fr->imax - fr->imin) / WIN_H;
cmplx->r = point->x * rscale + fr->rmin;
cmplx->i = point->y * iscale + fr->imin;
}
void screen_to_world(t_point *point, t_cmplx *cmplx, t_frctl *fr)
{
double rscale;
double iscale;
rscale = (fr->rmax - fr->rmin) / WIN_W;
iscale = (fr->imax - fr->imin) / WIN_H;
cmplx->r = (point->x + fr->offx) * rscale + fr->rmin;
cmplx->i = (point->y + fr->offy) * iscale + fr->imin;
}
void screen_to_world(t_point *point, t_cmplx *cmplx, t_frctl *fr)
{
double rscale;
double iscale;
rscale = (fr->rmax - fr->rmin) / WIN_W;
iscale = (fr->imax - fr->imin) / WIN_H;
cmplx->r = (point->x + fr->offx) * rscale * fr->zoom + fr->rmin;
cmplx->i = (point->y + fr->offy) * iscale * fr->zoom + fr->imin;
}
여기서 그냥 끝내면 문제가 생긴다. 확대 축소가 마우스 포지션 중심으로 이뤄지지 않는다. 내가 마우스를 올린 지점에서 확대 되거나 축소 돼야 하는데, screen상의 0,0 즉 왼쪽 위 모서리를 기준으로 확대 축소가 이뤄지게 된다.
이를 해결하는 방법은 다음과 같다.
확대/축소를 하기 전 마우스가 위치한 world 상의 좌표를 구한다.
그 다음 구해둔 world상의 좌표가 확대/축소를 하고 나서 screen상 좌표로 어디에 위치하게 되는지 구한다.(world_to_screen함수 추가 구현)
void world_to_screen(t_cmplx *cmplx, t_point *point, t_frctl *fr)
{
double rscale;
double iscale;
rscale = (fr->rmax - fr->rmin) / WIN_W;
iscale = (fr->imax - fr->imin) / WIN_H;
point->x = (cmplx->r - fr->rmin) / fr->zoom / rscale - fr->offx;
point->y = (cmplx->i - fr->imin) / fr->zoom / iscale - fr->offy;
}