C # XNA: Ищем такую ​​функцию, как MathHelper.Clamp - PullRequest
3 голосов
/ 03 февраля 2010

У меня есть функция, которая будет принимать диапазон значений, которые должны быть нормализованы до диапазона [-1, 1]. MathHelper.Clamp() просто принимает значения, которые находятся за пределами диапазона, и устанавливает их в зависимости от того, какой предел он превышает. Есть ли в XNA или C # что-то, что я ищу? (Я просматриваю документацию, но не могу ее найти.)

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

Эта функция будет принимать значения по одному за раз - поэтому нет итерации по всем значениям для масштабирования их всех или просмотра значений min и max.

Это то, что у меня сейчас есть:

// max - min cannot == 0
private float normalizeToRange(float value, float min, float max) {
      return (2.0f * (value - min) / (max - min)) -1.0f;
}

Ответы [ 5 ]

1 голос
/ 03 февраля 2010

Я могу интерпретировать ваш вопрос двумя способами.

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

В моей первой интерпретации вы хотели бы рассчитать расстояние от "origo" до "вектора" в N-пространстве (N - это число значений), а затем масштабировать вектор так, чтобы расстояние было ровно 1.

Это означает, что значения (1, 1) будут уменьшены примерно до (0,707, 0,707), что составляет расстояние приблизительно от 1 (0, 0).

В этом случае способ сделать это выглядит следующим образом:

dist = sqrt(vector[0]^2 + vector[1]^2 + ... + vector[N-1]^2)
vector[x] = vector[x] / dist, for x=0..N-1

Пример вектора со значениями (2, 1, 3) даст:

dist = sqrt(2^2 + 1^2 + 3^2) = sqrt(24) ~ 4.9
vector[0] = vector[0] / 4.9 ~ 0.41
vector[1] = vector[1] / 4.9 ~ 0.2
vector[2] = vector[2] / 4.9 ~ 0.61
vector = (0.41, 0.2, 0.61)

Во второй интерпретации вы хотите, чтобы максимальное значение было точно равно 1 от 0, а остальная шкала соответствовала.

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

maxValue = abs(max(vector[0], vector[1], ..., vector[N-1]))
vector[x] = vector[x] / maxValue, for x=0..N-1

Тот же вектор, что и выше, даст:

maxValue = abs(max(2, 1, 3)) = abs(3) = 3
vector[0] = vector[0] / 3 ~ 0.67
vector[1] = vector[1] / 3 ~ 0.33
vector[2] = vector[2] / 3 ~ 1
vector = (0.67, 0.33, 1)
1 голос
/ 03 февраля 2010

Если я правильно понимаю вопрос, это не сложно сделать, но вам нужно знать возможный диапазон ваших входных значений, прежде чем вы сможете определить нормализованные выходные значения.

Например, если ваши входные значения могут находиться в диапазоне от -500 до +500, то простая функция, такая как input / 500.0, справится с задачей.

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

В этом случае вы хотите перебрать все ваши значения (O (n), блин! ... но вам придется перебирать все ваши значения, чтобы масштабировать их, несмотря ни на что, поэтому O (n ) не избежать), и найдите как самые низкие, так и самые высокие значения. Определите разницу между этими двумя значениями, разделите ее на выходной диапазон и используйте ее в качестве коэффициента масштабирования. Для каждого числа, которое вы хотите масштабировать, добавьте значение, обратное минимальному входному значению, масштабируйте по коэффициенту масштабирования и затем вычтите смещение выходного диапазона.

Это звучит как много тарабарщины, поэтому позвольте мне привести пример. Например, после итерации вы обнаружите, что минимальное входное значение равно -300, а максимальное входное значение равно 700. Разница между этими двумя значениями (abs (max-min)) составляет 1000. Поскольку ваш выходной диапазон имеет размер 2 (-1 1) разделите ваш коэффициент масштабирования на 2 ... это даст вам ваш конечный коэффициент масштабирования 1000/2 = 500.

Затем вы берете первую точку в ваших входных данных ... мы скажем, что это 334. Вы вычитаете из нее минимальное значение, получая 334 + 300 = 634. Вы делите это число на свой коэффициент масштабирования, так что вы получите 634/500 = 1,268. Возьмите это число и вычтите 1 (иначе мы будем масштабироваться до (от 0 до 2) вместо (от -1 до 1). Это дает 0,268. Это ваш ответ. Сделайте это для всех точек в вашем наборе, и все готово.

Быстрая проверка работоспособности показывает, что если мы попробуем 700 (максимальное значение в нашем наборе), то получим ((700 + 300) / 500) - 1 = 1. Аналогично, если мы попробуем -300, мы получим ((-300 + 300) / 500) - 1 = -1.

Так что включите это в функцию, и все хорошо.

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

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

Редактировать: Отвечая на ваше заявление:

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

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

1 голос
/ 03 февраля 2010

Применение формулы 2 * (х-мин) / (макс-мин) + -1 к каждому значению должно нормализовать ее для вас.

(х-мин) / (макс-мин) дает значение от 0 до 1

умножение на 2 дает значение от 0 до 2

вычитание 1 дает значение от -1 до 1

0 голосов
/ 03 февраля 2010

Я не верю, что в XNA есть функция, которая сделает эту нормализацию за вас. Хотя это довольно простая операция ...

  1. Переберите все значения и найдите самое низкое и самое высокое значение - это позволит вам найти диапазон возможных значений: range = самое высокое значение - самое низкое значение
  2. Повторно просматривайте значения и установите для каждого значения (minValue + value) / range * 2 - 1, чтобы отобразить значения от -1 до 1.

Это не в моей голове, так что проверяйте тщательно :) Но это основная идея.

0 голосов
/ 03 февраля 2010

Я считаю, что этот метод расширения сделает то, что вы просите.

public static class Extension
{
    public static IEnumerable<double> Normalize(this IEnumerable<double> source)
    {
        var min = source.Min();
        var max = source.Max();
        var range = max - min;
        foreach (var d in source)
        {
            yield return ((d - min) / range) * 2 - 1;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...