编程与数学 | 一维空间的中心缩放
0. 问题描述:
最近在研究一个功能,期间演化出一些比较有趣的小知识。我把它们整理成独立的问题,来分享给大家。首先来解释一下,什么叫 一维区域空间的中心缩放:
比如,现在有一个刻度尺,视口区域是 [4,12]
,现在求:
若以 8 为缩放中心,将尺子放大两倍。求前视口的刻度区域。
缩放中心,就是在缩放变换过程中的不动点。我们可以把尺子放大两倍后,将区域对应的缩放中心和 8 对齐。下面可以从图中看出,当前视口区域的在 [6,10]
:
于是,就可以抛出本文研究的目标:
一维空间中的 [a,b] 区域,以 c 点为缩放中心,缩放 s 倍,求区域此的范围。
1. 解决思路
现在先分析一下上面案例中的细节,从数学的角度上理解一下,为什么结果是 [6,10]
[4,12]
以 8 为中心放大两倍。
- 原区域刻度长度: 12 - 4 = 8
- 当刻度尺放大两倍,而视口区域不变。则视口刻度长度将会减半。
- 缩放中心的刻度保持不变。
根据上面三点特征,我们就可以将模型简化为,求解区域前后刻度的问题。如下所示,两个问号分别是多少:
小学毕业了的朋友应该可以很轻松地报出答案:
左侧: 8 - 4/2 = 6 右侧: 8 + 4/2 = 10
我们真的将尺子放大两倍,然后观测效果,对规律进行总结,这是 物理学。而对于 数学 来说,根据已知条件,通过逻辑进行推演,就能得到答案。
2. 缩放执行非中点
如下所示,如果此时将缩放中心设置为 10 ,通过真实的缩放观察可以看出结果是 [7~11]。此时缩放中心左侧空间的占比是 (10-4)/(12-4)
。尺子放大之后,区域总刻度是 4 ,则左侧空间程度 (12-4)/2 * (10-4)/(12-4) = 3
。
于是缩放后左侧刻度 10-3 = 7
,右侧自然也就是 10+(4-3) = 11
3. 一般化的一维空间中心缩放
现在我们可以根据推演的逻辑,将这个规律适用于一般化的场合
一维空间中的 [a,b] 区域,以 c 点为缩放中心,缩放 s 倍,求区域此的范围。
- 原区域刻度长度: b - a
- 当刻度尺放大 s 倍,而视口区域不变。则视口刻度长度将缩小 s 倍。
- 缩放中心的刻度保持不变。
左侧坐标: c - (b-a)/s * [(c-a)/(b-a)]
右侧坐标: c + (b-a)/s * [(b-c)/(b-a)]
4. 演算的编程实现
如下所示,定义一个 Area
类型标识区间左右刻度;scale
方法将用于对 Area 对象以 c 为中心,缩放 s 倍:
void main() {
Area area = Area(4, 12);
double center = 10;
double s = 2;
Area ret = scale(area, center, s);
print(ret);
}
Area scale(Area area, double c, double s) {
double len = area.b - area.a;
double lenL = c - area.a;
double lenR = area.b - c;
return Area(
c - len / s * (lenL / len),
c + len / s * (lenR / len),
);
}
class Area {
final double a;
final double b;
Area(this.a, this.b);
@override
String toString() {
return 'Area[$a ~ $b]';
}
}
5. 从矩阵变换的角度思考
其实刻度尺放大 2 倍,然后区域的刻度范围,等价于坐标尺不变,将区域以缩放中心缩小 2 倍。如下所示,可以构造一个变换矩阵 Matrix4 ,将区域起止刻度视为两个维度,通过 transform3 进行运算:
Area scale(Area area, double c, double s) {
Matrix4 m4 = Matrix4.identity();
Matrix4 scaleM = Matrix4.diagonal3Values(1 / s, 1 / s, 1);
Matrix4 moveM = Matrix4.translationValues(c, c, 0);
Matrix4 backM = Matrix4.translationValues(-c, -c, 0);
m4.multiply(moveM);
m4.multiply(scaleM);
m4.multiply(backM);
Vector3 v3 = m4.transform3(Vector3(area.a, area.b, 0));
return Area(v3.x, v3.y);
}
可能会有人问,这有什么用? 下一篇,将向你展示这个小方法的强大威力。敬请期待 ~
转载自:https://juejin.cn/post/7395389351641743372