Java Мандельброт вопросы визуализации по масштабированию и раскраске - PullRequest
0 голосов
/ 19 ноября 2018

Я пытаюсь запрограммировать визуализацию для набора Мандельброта в Java, и есть несколько вещей, с которыми я борюсь, чтобы запрограммировать.Я понимаю, что вопросы по этой теме задавались много, и есть много документации онлайн, но многие вещи кажутся очень сложными, и я относительно новичок в программировании.

Первый выпуск

Первая проблема, которую я имею, связана с увеличением фрактала.Моя цель состоит в том, чтобы сделать «бесконечное» масштабирование фрактала (конечно, не бесконечным, насколько это позволяет обычный компьютер в отношении времени и точности вычисления).Подход, который я сейчас использую, заключается в следующем:

  • Нарисуйте множество, используя некоторое количество итераций в диапазоне (-2, 2) на действительной оси и (2, 2)на мнимой оси.
  • Измените эти диапазоны, чтобы увеличить масштаб.
  • Перерисовать эту часть набора с количеством итераций.

Это второй шаг, с которым я борюсь.Это мой текущий код:

for (int Py = beginY; Py < endY; Py++) {
        for (int Px = beginX; Px < endX; Px++) {
            double x0 = map(Px, 0, height,-2, 2);
            double y0 = map(Py, 0, width, -2, 2);

Px и Py - это координаты пикселей на изображении.Изображение 1000x1000.Функция карты принимает число, в данном случае Px или Py, с диапазоном (0, 1000) и равномерно делит его на диапазон (-2, 2), поэтому возвращает соответствующее значение в этом диапазоне.

Я думаю, что для увеличения мне придется каким-то образом изменить значения -2 и 2 в таймере, но что бы я ни пытался, это не сработало.Через некоторое время зум всегда замедляется, иначе он приведет к увеличению части набора, которая находится в наборе, а не границ.Я пытался умножить их на некоторый масштабный коэффициент каждый тик таймера, но это не дает результата, который я искал.

Теперь у меня есть два вопроса по этому вопросу.

  1. Является ли это правильным подходом для визуализации набора и увеличения (рисование, изменение диапазона, перерисовка)?
  2. Если это так, как мне правильно увеличить интересующую область, которая будет продолжать увеличиваться правильно даже после нескольких минут бега?

Второй выпуск

Конечно, когда вы визуализируете что-то, вам нужно получить что-то реальное.В этом случае я хочу раскрасить набор так, как вы видите здесь: (https://upload.wikimedia.org/wikipedia/commons/f/fc/Mandel_zoom_08_satellite_antenna.jpg).

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

Color[] colors = new Color[maxIterations + 2];
    for (int i = 0; i < colors.length; i++) {
        colors[i] = new Color((int)map(i, 0, maxIterations + 2, 0, 255), 
        (int)map(i, 0, maxIterations + 2, 0, 255), 
        (int)map(i, 0, maxIterations + 2, 0, 255));
    }

Затем я просто заполнил количество итераций в массиве и назначил этот цвет пикселю. У меня есть два вопроса по этому поводу:

  1. Будет ли это работать, когда мы увеличиваем фрактал описанным ранее способом?
  2. Как я могу добавить свою собственную цветовую схему в это, как на картинке? Я прочитал некоторые вещинасчет "линейной интерполяции", но я не совсем понимаю, что это такое и как это может мне помочь.

1 Ответ

0 голосов
/ 19 ноября 2018

Похоже, вы хорошо начали.

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

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

Простой способ сделать это - позволить пользователю нарисовать прямоугольник над изображением и использовать функцию map для преобразования пиксельных координат нарисованного прямоугольника в новые действительные и мнимые координаты вашей области увеличения.

Вы также можете комбинировать оба подхода: найдя где-то интересное, вручную выбирая область масштабирования, вы можете установить ее как «конечный пункт назначения» и постепенно и плавно увеличивать код, чтобы создать хороший фильм.

Тем не менее, он будет постепенно становиться все медленнее, поскольку вы начнете использовать все более точные координаты, пока не достигнете пределов точности с помощью double, и это не станет пиксельным беспорядком. Оттуда, если вы хотите увеличить масштаб, вам придется взглянуть на арифметику произвольной точности с BigDecimal - и она будет становиться все медленнее и медленнее.

По второму вопросу: начинать с вычисления значения numIterations / maxIterations (то есть между 0 и 1) для каждого пикселя - правильная идея (я думаю, что это в основном то, что вы делаете).

Оттуда есть все виды способов преобразовать это значение в цвет, пришло время проявить творческий подход!

Простой способ - иметь массив из нескольких очень разных цветов. Например. если бы у вас было белое (0,0), красное (0,25), зеленое (0,5), синее (0,75), черное (1,0), то, если рассчитанное вами число было точно одним из перечисленных, вы бы использовали соответствующий цвет. Если это где-то между, вы смешиваете цвета, например за 0,3 вы бы взяли:

((0.5-0.3)*red + (0.3-0.25)*green) / (0.5 - 0.25)
= 0.8*red + 0.2*green

Взяв средневзвешенное значение двух цветов, я оставлю это упражнение;) (подсказка: возьмите отдельные средние значения r, g и b. Может также подойти игра со значениями альфа).

Еще один вариант, если вы хотите получить больше математики, - это взять уравнение для спирали и использовать его для вычисления точки на плоскости в цветовом пространстве HSB (вы может поддерживать яркость на некотором фиксированном значении, скажем, 1). Фактически, любая кривая в 2D или 3D, которую вы знаете, как написать уравнение одной реальной переменной, может быть использована для плавного изменения цвета, если вы интерпретируете координаты как точки в некотором цветовом пространстве.

Надеюсь, этого будет достаточно, чтобы вы продолжали! Дайте мне знать, если неясно.

...