Плавное масштабирование с помощью мыши в наборе Мандельброта (C)

Последние несколько дней я работал над программой набора C Mandelbrot, и мне удалось заставить ее работать нормально, однако моя конечная цель - иметь возможность плавно увеличивать набор с помощью мыши, а это то, что я не сделал. еще не смог сделать, поэтому мне может понадобиться немного помощи!

Вот часть моего кода (ну, полная функция Мандельброта):

//removed to free space

Вот изображение вывода: (Извините, оно не очень красивое, цвета не были моим приоритетом, но я обязательно поработаю над ними, как только разберусь с увеличением!)

Мандельброт

Что я хочу уметь делать:

  • левый щелчок -> центр изображения становится mouse_x и mouse_y. Затем он начинает увеличиваться, пока удерживается левый щелчок.
  • щелкните правой кнопкой мыши -> [...] он начинает уменьшаться, пока удерживается правый щелчок
  • переместить мышь -> если в настоящее время увеличивается / уменьшается, центр изображения перемещается в координаты мыши вместе с ним. В противном случае ничего не происходит.

(уже есть функция, которая получает положение мыши и нажатую кнопку)

Спасибо большое за вашу помощь !


person Dukev    schedule 22.01.2017    source источник


Ответы (1)


Видимая область представляет собой прямоугольник, определяемый (Re.min, Im.min) и (Re.max, Im.max). Когда вы нажимаете на определенную точку, вы можете сопоставить положение мыши с точкой (mouseRe, mouseIm), используя то же сопоставление, которое вы используете при рендеринге:

double mouseRe = (double)mouse_x / (WIN_L / (e->Re.max - e->Re.min)) + e->Re.min;
double mouseIm = (double)mouse_y / (WIN_H / (e->Im.max - e->Im.min)) + e->Im.min;

Чтобы увеличить масштаб, представьте, что вы рисуете линию от (mouseRe, mouseIm) центральной точки масштабирования до каждого из углов видимой области, образуя кривую букву X. В зависимости от масштаба найдите 4 новые точки на определенной части расстояния вдоль этих линий, эти точки даст вам ваш новый прямоугольник. Например, если вы увеличиваете масштаб в 3 раза, найдите точку на 1/3 пути от центральной точки до углов. Это создаст новый прямоугольник со сторонами, равными 1/3 размера оригинала, и площадью, равной 1/9 размера.

Для этого вы можете определить простую функцию интерполяции:

double interpolate(double start, double end, double interpolation)
{
    return start + ((end - start) * interpolation);
}

Затем используйте функцию, чтобы найти новые точки:

void applyZoom(t_fractal* e, double mouseRe, double mouseIm, double zoomFactor)
{
     double interpolation = 1.0 / zoomFactor;
     e->Re.min = interpolate(mouseRe, e->Re.min, interpolation);
     e->Im.min = interpolate(mouseIm, e->Im.min, interpolation);
     e->Re.max = interpolate(mouseRe, e->Re.max, interpolation);
     e->Im.max = interpolate(mouseIm, e->Im.max, interpolation);
}

Основываясь на моем описании, вы можете подумать, что вам нужно найти 8 значений (4 точки для 4 сторон X с 2 измерениями каждая), но на практике есть только 4 уникальных значения, потому что каждая из сторон выровнена по оси.

Для плавного масштабирования вызовите его с коэффициентом масштабирования чуть более 1,0, например. 1.01. Чтобы уменьшить масштаб, передайте инверсию, например. 1,0/1,01.

В качестве альтернативы, если вы хотите, чтобы центр вида перемещался в определенную позицию при щелчке мышью, рассчитайте mouseRe и mouseIm, как указано выше, а затем сместите углы прямоугольника вида на разницу между этими значениями и центром прямоугольника вида. . Вы можете сохранить эти значения во время первого нажатия кнопки мыши и использовать их для увеличения, пока она удерживается.

person samgak    schedule 23.01.2017
comment
Большое спасибо, что нашли время написать такой отличный ответ. ! Работает отлично. - person Dukev; 23.01.2017
comment
Пожалуйста. Кстати, я думаю, вам следует отменить свое редактирование, это будет более полезно для всех, кто читает вопрос, чтобы увидеть ваш код. Не беспокойтесь о том, что он займет слишком много места. - person samgak; 23.01.2017