将值限制在范围内(有点)

Posted

技术标签:

【中文标题】将值限制在范围内(有点)【英文标题】:Clamping a value to a range (sort of) 【发布时间】:2012-06-30 04:34:59 【问题描述】:

我有一个滑块,它返回从 0.0f 到 1.0f 的值。

我想使用这个值并将其钳制为 MIN 和 MAX,但不完全钳制。

假设最小值为 0.2f,最大值为 0.3f。当滑块为 0 时,我想要 0.2f。当滑块在 0.5f 时,我想要 0.25f,依此类推。

只是让滑块的效果没那么强。

给定 MIN MAX 和 sliderVal,我怎样才能钳制 sliderVal?

谢谢

【问题讨论】:

这称为“线性插值”。 【参考方案1】:
slider_range = slider_max - slider_min;
range = range_max - range_min;

value = (double)(slider_pos - slider_min) / slider_range * range + range_min;

【讨论】:

@OliCharlesworth:糟糕——我想我已经解决了这个问题。谢谢。 这实际上是线性插值吗?【参考方案2】:

假设您希望滑块在0.2f0.3f 之间线性变化,那么从区间[0.0 1.0][0.2 0.3] 的转换是微不足道的:

newVal = 0.2f + (sliderVal)*0.1f;

根据您的描述,从数学角度来看,您希望输出与输入成线性关系。因此,输入和输出值之间的传递函数必须是以下形式:

y = mx + b

x 值视为输入(滑块值),将y 值视为输出(新的所需值)。因此,您有两点:(0.0, 0.2)(1.0, 0.3) 将这些点代入上述等式:

0.2 = (0.0)m + b
0.3 = (1.0)m + b

您现在有一个线性方程组,求解起来很简单:

0.2 = (0.0)m + b --> b = 0.2
0.3 = (1.0)m + b --> 0.3 = m + 0.2 --> m = 0.1

因此,传递函数为:

y = 0.1 * x + 0.2

Q.E.D.

我们可以概括上述过程。不要使用点(0.0, 0.2)(1.0, 0.3),而是使用点(minSlider, maxSlider)(minValue, maxValue)

minValue = (minSlider)m + b
maxValue = (maxSlider)m + b

消除变量b

minValue = (minSlider)m + b
-maxValue = -(maxSlider)m - b

--> minValue-maxValue = (minSlider-maxSlider)m
m = (minValue-maxValue)/(minSlider-maxSlider)

消除变量m

minValue*maxSlider = (minSlider*maxSlider)m + b*maxSlider
-maxValue*minSlider = -(minSlider*maxSlider)m - b*minSlider

--> minValue*maxSlider - maxValue*minSlider = b(maxSlider-minSlider)
b = (minValue*maxSlider - maxValue*minSlider)/(maxSlider-minSlider)

您可以验证这些等式为您提供的 mb 的值是否完全相同。如果我们假设最小滑块值将始终为0.0

m = (minValue-maxValue)/(minSlider-maxSlider)
b = (minValue*maxSlider - maxValue*minSlider)/(maxSlider-minSlider)

--> m = (maxValue-minValue)/(maxSlider)
    b = minValue

在 C++ 中:

const double maxSlider = 1.0;
const double minValue = 0.2;
const double maxValue = 0.3;
double value = (maxValue-minValue)/(maxSlider)*getSliderPosition() + minValue;

【讨论】:

很多数字很好,但您不像其他答案那样显示通用形式 @Mooing Duck:我们的想法是让 OP 知道如何 得出答案,而不仅仅是给出公式让 OP 不假思索地使用它。 :-)【参考方案3】:

基本上你有

0.0f -> MIN
1.0f -> MAX

你想要

clampedVal = sliderVal * ( MAX - MIN ) + MIN

【讨论】:

【参考方案4】:

std::lerp 这样做。它接受三个浮点数,并在第一个和第二个之间插入第三个参数。

转自cppreference:

#include <iostream>
#include <cmath>
 
int main()

    float a=10.0f, b=20.0f;
 
    std::cout << "a=" << a << ", " << "b=" << b << '\n'
              << "mid point=" << std::lerp(a,b,0.5f) << '\n'
              << std::boolalpha << (a == std::lerp(a,b,0.0f)) << ' '
              << std::boolalpha << (b == std::lerp(a,b,1.0f)) << '\n';

输出:

a=10, b=20
mid point=15
true true

【讨论】:

以上是关于将值限制在范围内(有点)的主要内容,如果未能解决你的问题,请参考以下文章

Redis限制在规定时间范围内登陆错误次数限制

如何将数字限制在指定范围内? (Python)

将值映射到色标

城市范围内的限制标记android谷歌地图

如何将神经网络的输出限制在特定范围内?

Godot将 Camera 的视野范围限制在 TileMap 内