【问题标题】:C# XNA: Looking for a function like MathHelper.ClampC# XNA:寻找像 MathHelper.Clamp 这样的函数
【发布时间】:2010-02-03 19:34:38
【问题描述】:

我有一个函数,该函数将采用一系列值,需要将其标准化为范围 [-1, 1]。 MathHelper.Clamp() 只接受超出范围的值并将它们设置为超出的范围。 XNA 或 C# 有什么可以满足我的需求吗? (我正在查看文档,但找不到。)

这是获取鼠标的移动。这些值是一个刻度和下一个刻度之间鼠标坐标的差异。我不确定它的最大值是多少。

此函数将一次取一个值 - 因此没有迭代所有值来缩放它们或查看最小值和最大值是多少。

这是我目前拥有的:

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

【问题讨论】:

  • 当您说“值范围”时,您的意思是例如您有一个点,并且您想将其移动到原点 (0, 0) 的 1 个单位内,以便比率X 和 Y 之间是否保留?如果距离为 1,或者 X 或 Y 的最大值为 1(X 和 Y 的 45 度方向上的距离 1 约为 0.7。)

标签: c# math xna


【解决方案1】:

将公式 2*(x-min)/(max-min) + -1 应用于每个值应该会为您标准化。

(x-min)/(max-min) 给你一个介于 0 和 1 之间的值

乘以 2 得到一个介于 0 和 2 之间的值

减去 1 得到一个介于 -1 和 1 之间的值

【讨论】:

    【解决方案2】:

    如果我正确理解了这个问题,这并不是很难做到,但您需要先了解输入值的可能范围,然后才能确定归一化的输出值。

    例如,如果您的输入值范围是 -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)运动。您需要找出鼠标的操作范围是多少,从中可以得出什么值,这将为您提供最小值和最大值。

    【讨论】:

    • 实际上我的解释似乎有点不清楚,但无论如何这都是有帮助的。
    【解决方案3】:

    我可以通过两种方式解释您的问题。

    在这两种情况下,我都将输入解释为一个值数组,它们将一起缩放。

    在我的第一个解释中,您想计算 N 空间中从“origo”到“向量”的距离(N 是值的数量),然后缩放向量以使距离正好为 1。

    这意味着值 (1, 1) 将缩小到大约 (0.707, 0.707),与 (0, 0) 的距离约为 1。

    在这种情况下,方法如下:

    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)
    

    在第二种解释中,您希望最大值与 0 相差 1,而其余的刻度则适合。

    在这种情况下,只需找到最大值,然后除以它(确保先使其为正。)

    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)
    

    【讨论】:

      【解决方案4】:

      我不相信 XNA 有一个函数可以为你进行标准化。这是一个相当简单的操作...

      1. 遍历所有值并找到最低和最高值 - 这可以让您找到可能值的范围:范围 = 最高值 - 最低值
      2. 再次循环遍历这些值并将每个值设置为 (minValue + value) / range * 2 - 1 以将值从 -1 映射到 1。

      这不是我的想法,所以请彻底测试:) 但这是基本想法。

      【讨论】:

        【解决方案5】:

        我相信这种扩展方法会满足您的要求。

        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;
                }
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2011-11-22
          • 1970-01-01
          • 1970-01-01
          • 2012-10-22
          • 2023-01-13
          • 1970-01-01
          • 2021-12-30
          • 2012-03-15
          • 1970-01-01
          相关资源
          最近更新 更多