C#XNA:寻找像MathHelper.Clamp这样的函数

时间:2010-02-03 19:34:38

标签: c# math xna

我有一个函数,它将采用一系列值,需要将其标准化为[-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;
}

5 个答案:

答案 0 :(得分:1)

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

(x-min)/(max-min)给出0到1之间的值

乘以2会得到0到2之间的值

减1会给出介于-1和1之间的值

答案 1 :(得分:1)

如果我正确理解了这个问题,这并不是一件非常困难的事情,但在确定标准化输出值之前,您需要知道输入值的可能范围。

例如,如果您的输入值范围为-500到+500,那么像input / 500.0这样的简单函数就可以了。

我要走出困境并假设你想要放弃这个范围的任何值范围,从-1到1,缩放设置使得最极端的输入值将完全设置为-1和1。

在这种情况下,你想迭代你的所有值(O(n),bleh!...但是你将不得不迭代你的所有值来扩展它们,无论如何,所以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)。这会得到.268。那是你的答案。对你集合中的所有点做这个,你已经完成了。

快速健全性检查显示,如果我们尝试700(我们的集合中的最大值),我们得到((700 + 300)/ 500) - 1 = 1.同样,如果我们尝试-300,我们得到((-300) + 300)/ 500) - 1 = -1。

所以把它放到一个函数中,你很好。

如果您的输入范围不是根据您的输入而变化,而是一个已知的常数,您当然可以避免在开始时对数据进行迭代,这肯定是一件好事。

所以希望这有助于......我不会费心写出实际的功能......我猜这将是相当简单的。但如果有任何问题,或者我误解了这个概念,请告诉我。

编辑:回复您的陈述:

  

这是鼠标移动。值是一个刻度与下一个刻度之间的鼠标坐标的差异。我不确定它的最大值是什么。

据推测,在这个系统上有某种驱动器夹紧...如果正常的鼠标移动,比如说(-5,3),可能是鼠标根本无法记录任意大的值(1000000,1000000)用于运动。您需要了解鼠标的工作范围,以及可以产生的值,这将为您提供最小值和最大值。

答案 2 :(得分:1)

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

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

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

这意味着值(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)

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

我不相信XNA有一个能为你做标准化的功能。虽然这是一个相当简单的操作......

  1. 遍历所有值并找到最低和最高值 - 这可以让您找到可能值的范围:range = highestValue - lowestValue
  2. 再次循环显示值并将每个值设置为(minValue + value)/ range * 2 - 1以将值从-1映射到1。
  3. 这是我的头脑,所以测试thorgoughly :)但这是基本的想法。