Генерация равномерно распределенного случайного шума - PullRequest
0 голосов
/ 13 сентября 2010

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

Учитывая два целых числа X и Y и начальное значение, я делаю следующее:

  • Используйте MurmurHash2 для генерации случайного числа (-1,1).Это равномерно распределено.
  • Интерполяция точек между целочисленными значениями с кубической интерполяцией.Значения теперь попадают в диапазон (-2,25, 2,25), поскольку интерполяция может экстраполировать более высокие точки (на 1,5 в каждом измерении) между аналогичными значениями, и распределение больше не является равномерным.
  • Создайте эти интерполированные точки, суммируяони вместе, вдвое уменьшая амплитуды (см .: Perling noise ) По мере того, как количество сумм приближается к бесконечности, предел диапазона теперь приближается в два раза к предыдущим значениям, или (-4,5, 4,5), и теперь еще меньшеРавномерное.

Это, очевидно, не работает, когда я хочу диапазон от (-1, 1), поэтому я делю все окончательные значения на 4,5.На самом деле, я делю их по пути (на 1,5 после интерполяции каждого измерения, затем на 2 после суммирования шума.)

После деления у меня остается теоретический диапазон (-1, 1),Тем не менее, подавляющее большинство значений (-0,2,0,2).Это плохо работает при создании моих карт, так как мне нужно определить процент заполненной карты.Я также не могу использовать гистограммы, чтобы определить, какой порог использовать, так как я генерирую квадраты по требованию, а не всю карту.

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

Мой дистрибутив выглядит так:

Normal distribution

Мне нужно этовыглядеть так:

Uniform distribution

(Оба изображения из Википедии.)

Любые решения приветствуются, но яписать на C #, поэтому фрагменты кода будут чрезвычайно полезны.

Ответы [ 3 ]

2 голосов
/ 13 сентября 2010

Объедините полученную выборку с CDF для гауссианы, который равен 0,5 * erf (x) + 1 (erf = функция ошибки).

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

1 голос
/ 29 марта 2013

Это ответ на ваш последний комментарий, а не на ваш вопрос. Я не обязательно думаю, что вы можете масштабировать ваш получившийся дистрибутив обратно в единый дистрибутив, и я не уверен, что вы захотите, если сможете. Но если ваша цель состоит в том, чтобы получить, скажем, все значения ниже 50% как траву, может быть проще и с меньшей вероятностью измерить (или оценить) медиану вашего выхода и назвать это 50%.

Результат тот же, и вам не нужно иметь дело со сложными (и поэтому подверженными ошибкам) ​​функциями масштабирования.

0 голосов
/ 13 сентября 2010

Это простая проблема масштабирования.И все простые задачи масштабирования являются просто проявлениями прямой линии в декартовой геометрии:

У вас есть линия:

       |   /
     1 + -/,
       | / ,
____,__|/__,____
 -4.5 /|   4.5
    ,/ |
    /- + -1
   /   |

на этой линии, когда x = 4.5, y = 1 и когдах = -4,5, у = -1.Теперь я уверен, что как только вы поймете это, вы узнаете решение.y=mx + c.Поскольку прямая симметрична как на положительной, так и на отрицательной сторонах, можно предположить, что она пересекается в нуле, поэтому c=0.Теперь, чтобы найти наклон:

m = dy/dx
m = (1 - -1)/(4.5 - -4.5)
m = 2/9

, поэтому:

y = 2/9 x + 0
y = 2x / 9

Итак, теперь вы можете подключить это. Что такое y, когда x = 3?:

y = 2*3 / 9
y = 6/9
y = 2/3

и что такое y, когда x = 4?:

y = 2*4 / 9
y = 8/9

дополнительные примечания:

Предположим, что линия пересекает-Нет, что я делаю, потому что мой опытный глаз говорит мне, что это правильно.Но если бы я делал это для экзамена по математике в средней школе, я бы, вероятно, потерял кредиты (даже если мой ответ правильный).Для правильного формульного решения *1025*, чтобы найти c, сначала нужно найти m, а затем подставить x и y значения известной координаты:

y = 2/9 x + c

учитывая, что (4.5,1) и (-4,5, -1) являются известными координатами, замените x и y на 4.5 и 1:

1 = 2*4.5/9 + c
1 = 9/9 + c
1 = 1 + c
c = 1 - 1
c = 0

Все это может быть зафиксировано в функции масштабирования:

// example code in javascript:
function makeScaler (x1, y1, x2, y2) {
    var m = (x2-x1)/(y2-y1);
    var c = y1 - m*x1;

    // return a scaling function:
    return function (x) {
        return m*x + c;
    }
}

var f = makeScaler(-4.5,-1,4.5,1);
alert(f(4)); // what y is when x is 4

// or if you prefer:
var g = makeScaler(-4.5,0,4.5,1); // scale from 0 to 1
alert(g(4));
...