圆角矩形的绘制和曲线均匀化
摘要: 圆角矩形是软件 UI 等视觉设计中的常见表达,一种常见的绘制方法是将矩形的四角替换为与边相切的四分之一圆弧,然而这种绘制方式会在连接处产生视觉上的切折感,这是因为圆弧和直线的连接处只满足 G1G^1G1 连续性。本文探究了如何使用高次埃米尔特插值绘制高阶连续的圆角曲线,以及如何使用常微分方程的数值解法实现曲线的均匀化。
关键词: 圆角矩形;埃米尔特插值;常微分方程数值解
引言
圆角矩形被广泛应用于产品的视觉设计中,例如智能手机的边框、移动应用的图标、家具的边角等等。人们通常将在矩形的四角改为相切的四分之一圆弧来绘制圆角矩形,如图 1a 所示,在和更高阶连续曲线的对比之下,这种方法绘制出的圆角就会在连接处产生切折感,显得不是那么顺滑,原因是这种绘制方式在圆角的连接处只能满足 G1G^1G1 连续,图 1b 直观展示了连接处的曲率突变。这种视觉效果的差别已经被 Apple 公司的视觉设计师注意到,并且成功应用于他们的产品设计中,例如 iOS 7 之后的图标边框抛弃了 圆弧和切线(图 2)。
图1(a):效果对比 | 图1(b):曲率图 |
---|---|
![]() | ![]() |
图2 |
---|
![]() |
根据数值分析的内容,通过埃米尔特插值可以构造任意高阶的多项式,从而可以满足任意高阶的连续性要求,所以我们就可以将其应用于圆角的绘制,从而得到更顺滑的圆角曲线。
问题建模
由于二维曲线上可能存在相同横坐标的点,所以一般情况下不能用形如 y=f(x)y=f(x)y=f(x) 这样的函数表达,我们可以通过引入一个隐变量 ttt 来表达任意的二维曲线:
{Px=x(t)Py=y(t)\begin{equation} \left\{\begin{array}{cc} P_x = x(t) \\ P_y = y(t) \end{array}\right. \end{equation} {Px=x(t)Py=y(t)
隐变量 ttt 可以理解为绘制过程的时间,因此公式实际上也描述了曲线的画法:对指定的时间点 ttt,可以求得要绘制的点 P=(Px,Py)=(x(t),y(t))P = (P_x, P_y) = (x(t), y(t))P=(Px,Py)=(x(t),y(t))。 例如图 1a 中的圆弧和切线组合可以表达为:
P={(0,t)t<0(1−cos(π2t),sin(π2t))0≤t<1(t,1)1≤t\begin{equation} P = \begin{cases} (0, t) & t < 0 \\ (1 - \cos(\frac{\pi}{2} t), \sin(\frac{\pi}{2} t)) & 0 \le t < 1 \\ (t, 1) & 1 \le t \end{cases} \end{equation} P=⎩⎨⎧(0,t)(1−cos(2πt),sin(2πt))(t,1)t<00≤t<11≤t
在数学上,x(t)x(t)x(t) 和 y(t)y(t)y(t) 的 kkk 阶导数连续被称为参数连续性, 使用 CkC^kCk 来表示。然而参数连续性并不能完全表达曲线的连续性,因为相同
的轨迹可能由完全不同的运动过程形成,例如下面的公式和式 2 描述了同样的轨迹,但不满足 C1C^1C1 连续性:
P={(0,t)t<0(1−cos(π2t),sin(π2t))0≤t<1(1,1)1≤t<2(t−1,1)2≤t\begin{equation} P = \begin{cases} (0, t) & t < 0 \\ (1 - \cos(\frac{\pi}{2} t), \sin(\frac{\pi}{2} t)) & 0 \le t < 1 \\ (1, 1) & 1 \le t < 2 \\ (t -1, 1) & 2 \le t \end{cases} \end{equation} P=⎩⎨⎧(0,t)(1−cos(2πt),sin(2πt))(1,1)(t−1,1)t<00≤t<11≤t<22≤t
因此,几何连续性(GkG^kGk)的概念被提出,其含义是位置 P=(x(t),y(t))P=(x(t), y(t))P=(x(t),y(t)) 关于路程 s=∫0tx′2(t)+y′2(t)dts=\int_0^t { \sqrt{x'^2(t) + y'^2(t)}\ \mathrm{d}t }s=∫0tx′2(t)+y′2(t) dt
的参数方程(称为自然参数方程)满足 kkk 阶导数 连续的要求。一般来说,如果一个曲线 P=(x(t),y(t))P=(x(t), y(t))P=(x(t),y(t)) 可以经过一个重参数化过程 P=(x(t(s)),y(t(s)))P=(x(t(s)), y(t(s)))P=(x(t(s)),y(t(s))) 变成 kkk 阶参数连续的,那么它就是 kkk 阶几何连续的。如果 x(t)x(t)x(t) 和 y(t)y(t)y(t) 都是满足 CkC^kCk 的多项式,那么根据经验易知,我们总可以经过一个非线性的时间放缩过程得到其对应的自然参数方程,因而它也是满足 GkG^kGk 的。
不失一般性,下面我们只讨论从 (0,0)(0,0)(0,0) 到 (1,1)(1,1)(1,1) 的圆角绘制问题,并且不妨限定转角的绘制时间为 [0,1][0, 1][0,1]。在这个问题中,x(t)x(t)x(t) 和 y(t)y(t)y(t) 要满足以下约束:
-
起终点位置
x(0)=0,y(0)=0,x(1)=1,y(1)=1\begin{equation} x(0) = 0,\ y(0) = 0, x(1) = 1,\ y(1) = 1 \end{equation} x(0)=0, y(0)=0,x(1)=1, y(1)=1 -
G1G^1G1 连续
圆角的起点和终点都与直线相接:
x′(0)=0,y′(0)=ky,x′(1)=kx,y′(1)=0\begin{equation} x'(0) = 0,\ y'(0) = k_y,\ x'(1) = k_x,\ y'(1) = 0 \end{equation} x′(0)=0, y′(0)=ky, x′(1)=kx, y′(1)=0
式中出现 kyk_yky 和 kxk_xkx 的原因是直线 L=(at,bt)L=(at, bt)L=(at,bt) 乘上一个系数后的结果 L′=(k⋅at,k⋅bt)L'=(k \cdot at, k \cdot bt)L′=(k⋅at,k⋅bt) 形成的图像与此前相同(即对应同样的自然参数方程)。 -
Gn(n>1)G^n\ (n>1)Gn (n>1) 连续
在曲线内部,nnn 阶多项式本身即满足 GnG^nGn 的要求。在端点处,因为直线二阶以上的导数都为 000,所以:
x(n)(0)=y(n)(0)=x(n)(1)=y(n)(1)=0\begin{equation} x^{(n)}(0) = y^{(n)}(0) = x^{(n)}(1) = y^{(n)}(1) = 0 \end{equation} x(n)(0)=y(n)(0)=x(n)(1)=y(n)(1)=0 -
关于角平分线对称
绘制的圆角应该关于角的平分线 x+y=1x+y=1x+y=1 对称:
∀t∈[0,1],∃t′∈[0,1]{x(t)+x(t′)2+y(t)+y(t′)2=1y(t′)−y(t)=x(t′)−x(t)\begin{equation} \forall t \in [0, 1], \exists t' \in [0, 1] \left\{ \begin{aligned} & \frac{x(t) + x(t')}{2} + \frac{y(t) + y(t')}{2} = 1 \\ & y(t') - y(t) = x(t') - x(t) \end{aligned} \right. \end{equation} ∀t∈[0,1],∃t′∈[0,1]⎩⎨⎧2x(t)+x(t′)+2y(t)+y(t′)=1y(t′)−y(t)=x(t′)−x(t)
圆角的绘制
我们可以通过一个更严格的充分条件保证我们设计的函数一定满足约束 4:让绘制过程也关于这条直线对称的, 即 t′=1−tt' = 1 - tt′=1−t,那么我们就可以推出:
y(t)=1−x(1−t)ky=kx\begin{equation} \begin{aligned} y(t) & = 1 - x(1 - t) \\ k_y & = k_x \end{aligned} \end{equation} y(t)ky=1−x(1−t)=kx
现在,我们只需确定 x(t)x(t)x(t) 和 kxk_xkx 即可,这极大简化了设计工作。设计满足约束 1-3 的函数 x(t)x(t)x(t) 本质上是一个插值问题,满足 GnG^nGn
的圆角曲线有 2n+22n+22n+2 个插值条件,因此可以用 2n+12n+12n+1 次埃米尔特插值构造 x(t)x(t)x(t)。
以 n=2n=2n=2 为例,构造均差表 1a,可得插值多项式:
x(t)=t3+(kx−3)t3(t−1)+(6−3kx)t3(t−1)2\begin{equation} \begin{aligned} x(t) = t^3 + (k_x - 3) t^3 (t-1) + (6 - 3k_x) t^3 (t-1)^2 \end{aligned} \end{equation} x(t)=t3+(kx−3)t3(t−1)+(6−3kx)t3(t−1)2
图 3 显示了不同 kxk_xkx 取值曲线的效果,从图上可见,kxk_xkx 值的选取对效果有非常重要的影响,而当 kx=2k_x=2kx=2 时曲线的视觉效果最顺滑。
很难去解释为什么 kx=2k_x=2kx=2 时的曲线效果最好,但观察式 9 可知 kx=2k_x=2kx=2 恰好使得中最高次项系数为 0, 此时插值多项式退化为 2n2n2n 次多项式,这不得不让人怀疑这不是一种巧合。我们有理由猜测,在求更高阶连续的曲线时,同样当 kxk_xkx 值的选取使得最高次项系数为 0 时效果最好。
图 3 |
---|
![]() |
顺着这个猜测会发现一个更有趣的事实:对于任意的高阶连续的曲线 n>1n > 1n>1,使它们最高次项系数为 0 的条件都是
kx=2k_x = 2kx=2!可以这样简单证明这个结论:把 kx=2k_x = 2kx=2 带入表 1a 得到表 1b。当 nnn 由 2 变为 3 会多出两个插值条件,反应到均差表的构造上就是会多出表 1c 中的第 4 行和第 8 行。 在表 1b 中,第 3 行的插值条件往右下和第 6 行的插值条件往右的数字刚好满足"绝对值相等、正负号交替"的性质,则根据均差表的构造规则,在表 1c 中新构造出的一层也满足这个性质,最终右下角的数字一定为两个符号和绝对值相同的数的差,因此一定为 0。
图 4 是 nnn、kxk_xkx 取不同值的效果对比,可明显看出,kx=2k_x=2kx=2 在任何阶次下的效果都是最好的。当可以绘制任意高阶连续的圆角之后,一个很自然的问题是:能否绘制无穷阶连续的圆角?答案是否定的,因为无穷阶连续会使得 x(t)x(t)x(t) 的任意阶导数都为 0,那么根据 x(0)=0x(0)=0x(0)=0,使用泰勒插值可得 x(t)≡0x(t) \equiv 0x(t)≡0,这与 x(1)=1x(1)=1x(1)=1 冲突。从图上也能直观看出,更高阶的曲线则产生更小的圆角,而当无穷阶连续时就会退化为直角。
图4 |
---|
![]() |
曲线均匀化
上一节给出的方法已经能让我们绘制出效果很好的连续圆角曲线了,但其仍有不足之处:所得插值公式在输入均匀的 ttt 时输出的点是不均匀的。这个问题在绘制虚线或者点线等不连续的线时就会显露出来,如图5,点会在拐角处更集中,因此有必要继续探索将曲线均匀化的方法。
图5 |
---|
![]() |
本质上,曲线均匀化就是从上面一节中所得的参数方程求得对应的自然参数方程的过程。自然参数方程在大多
数情况下都很难求,无法得到解析解,只能使用数值方法,在这里也不例外。我们可以通过一个非线性的重参
数化来实现均匀化,即设计一个函数 t(s)t(s)t(s),使得 P=(x(t(s)),y(t(s)))P=(x(t(s)), y(t(s)))P=(x(t(s)),y(t(s))) 满足:
(dPxds)2+(dPyds)2=1\begin{equation} \begin{aligned} \sqrt{ \left(\frac{\mathrm{d}P_x}{\mathrm{d}s}\right)^2 + \left(\frac{\mathrm{d}P_y}{\mathrm{d}s}\right)^2 } = 1 \end{aligned} \end{equation} (dsdPx)2+(dsdPy)2=1
将式 8 代入得:
dPxds2+dPyds2=(x′(t(s))⋅t′(s))2+(x′(1−t(s))⋅t′(s))2=1\begin{equation} \frac{\mathrm{d}P_x}{\mathrm{d}s}^2 + \frac{\mathrm{d}P_y}{\mathrm{d}s}^2 = \left(x'(t(s)) \cdot t'(s) \right)^2 + \left(x'(1 - t(s)) \cdot t'(s) \right)^2 = 1 \end{equation} dsdPx2+dsdPy2=(x′(t(s))⋅t′(s))2+(x′(1−t(s))⋅t′(s))2=1
整理后,可得关于 t(s)t(s)t(s) 的微分方程:
t′(s)=1x′2(t(s))+x′2(1−t(s))\begin{equation} t'(s) = \frac{1}{ \sqrt{x'^2(t(s)) + x'^2(1 - t(s))} } \end{equation} t′(s)=x′2(t(s))+x′2(1−t(s))1
其中开方后的符号对曲线的最终均匀化结果没有影响,故可以取正。
针对本圆角绘制问题,该微分方程的初值条件为 t(0)=0t(0) = 0t(0)=0。绘制均匀化圆角的完整流程如下:
- 使用上一节的方法求出多项式 x(t)x(t)x(t);
- 求出 x(t)x(t)x(t) 的导数 x′(t)x'(t)x′(t),很容易编程实现多项式的求导;
- 给定步长 sss,利用式 12 和初值条件 t(0)=0t(0)=0t(0)=0 求得均匀分布的间隔为 sss 的点对应的 ttt 值;
- 将求得的 ttt 值序列代入 x(t)x(t)x(t) 和式 8,得到最终的点坐标。
图 6b 为在 n=2n=2n=2、kx=2k_x=2kx=2 的圆角曲线上取 s=0.05s=0.05s=0.05 的绘制效果,图 6a 为对应的 ttt 值序列,从图中可以明显看出是非线性的。
图6 |
---|
![]() |
总结
由于研究时间有限,本文只讨论了最常见的 90° 直角的绘制方法,但显然可以在本文的方法上进行一些修补使之进一步推广到任意角度。总的来说,本文基于数值分析课程内容,对圆角矩形的绘制方法进行了深入研究,成功绘制出了高阶连续的均匀圆角曲线,并通过均匀化得到了虚线版本,所得曲线相比较普通的圆弧和切线组合具有更顺滑的视觉效果。附录A展示了不同阶连续的完整矩形及点线版本的效果。
附录
A 完整的圆角矩形图像
B 圆角矩形绘制代码
-
numalgo.py
"""埃米尔特插值实现 """import numpy as np from typing import Callableclass Polynomial:"""多项式函数类"""def __init__(self, a: np.ndarray) -> None:self.a = adef __call__(self, x):return self.a @ np.full_like(self.a, x) ** np.arange(0, len(self.a))def derivate(self) -> "Polynomial":"""求导一次"""return Polynomial(self.a[1:] * np.arange(1, len(self.a)))class Emmert:"""基于均差表的埃米尔特插值函数类"""def __init__(self, x: np.ndarray, y: np.ndarray) -> None:assert x.shape == y.shapeself.x = xself.y = ydef __call__(self, x):x = x - self.xfor i in range(1, len(x)):x[i] *= x[i - 1]x[1:] = x[:-1]x[0] = 1return self.y @ xdef to_polynomial(self) -> Polynomial:"""均差表转多项式"""a = np.zeros_like(self.y)b = np.zeros_like(self.y)b[0] = 1a += self.y[0] * b[0]for i in range(1, len(self.y)):b[1:] = b[:-1]b[0] = 0b[:-1] += -self.x[i - 1] * b[1:]a += self.y[i] * breturn Polynomial(a)def emmert(constraits: dict[float, list[float]]) -> Emmert:"""埃米尔特插值"""px, py = zip(*sorted(constraits.items()))indexes = [len(i) for i in py]indexes = [sum(indexes[:i]) for i in range(len(indexes) + 1)]x = np.empty(indexes[-1], dtype=np.float64)for i in range(0, len(indexes) - 1):x[indexes[i] : indexes[i + 1]] = px[i]y = np.empty_like(x)for i in range(0, len(x) - 1):for j in range(0, len(indexes) - 1):if len(py[j]) > i:y[indexes[j] + i : indexes[j + 1]] = py[j][i]# meandiffstep = i + 1y[step:] = (y[step:] - y[step - 1 : -1]) / (x[step:] - x[:-step])return Emmert(x, y)def euler(deri: Callable[[float, float], float], xs: np.ndarray, y0: float ) -> np.ndarray:"""欧拉法求微分方程数值解"""ans = np.empty_like(xs)ans[0] = y0for i in range(1, len(xs)):ans[i] = ans[i - 1] + (xs[i] - xs[i - 1]) * deri(xs[i - 1], ans[i - 1])return ansdef euler_range(deri: Callable[[float, float], float],x0: float,y0: float,stop: float,step: float, ) -> np.ndarray:"""欧拉法求微分方程数值解,均匀步长当型循环"""ans = []while y0 < stop:ans.append(y0)y0 += step * deri(x0, y0)x0 += stepreturn np.array(ans)
-
a4_roundrect.py
"""绘制完整的圆角矩形"""import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np import sympy as sy from numpy import cos, pi, sinfrom numalgo import emmert, euler_rangempl.rcParams["font.family"] = "Microsoft YaHei"fig, ax = plt.subplots(1, 1, layout="constrained") fig.set_size_inches(8, 10) ax.axis("off") ax.set_xlim([-8, 8]), ax.set_ylim([-11, 11])def mirror_lefttop(arr_x, arr_y):x = np.concatenate((arr_x, -arr_x[::-1], -arr_x, arr_x[::-1]))y = np.concatenate((arr_y, arr_y[::-1], -arr_y, -arr_y[::-1]))return x, y# Gn 插值 for n in range(2, 8):pf = emmert({0: [0, 0] + [0] * (n - 1), 1: [1, 2] + [0] * (n - 1)})p0 = pf.to_polynomial()p1 = p0.derivate()tt = lambda x, y: 1 / np.sqrt(p1(y) ** 2 + p1(1 - y) ** 2)ts = np.concatenate((np.arange(-0.4, 1.3 - n * 1.5 + 0.15, -0.15)[::-1],euler_range(tt, 0, 0, 1, 0.15),np.arange(1.1, n + 0.1, 0.15),))ts0, ts1 = np.sum(ts < 0), np.sum(ts < 1)xs = ts.copy()xs[:ts0] = 0ys = ts.copy()ys[ts1:] = 1for ti in range(ts0, ts1):xs[ti] = p0(ts[ti])ys[ts0:ts1] = 1 - xs[ts1 + 1 : ts0 + 1 : -1]xs, ys = mirror_lefttop(xs - n, ys + n * 1.5 - 1.5)ax.scatter(xs, ys, 5)arr_t = np.linspace(-n * 1.5 + 0.5, n - 0.5, 1000)t0, t1 = np.sum(arr_t < 0), np.sum(arr_t < 1)arr_x, arr_y = arr_t.copy(), arr_t.copy()arr_x[:t0], arr_y[t1:] = 0, 1for ti in range(t0, t1):arr_x[ti] = p0(arr_t[ti])arr_y[t0:t1] = 1 - arr_x[t1 + 1 : t0 + 1 : -1]xs, ys = mirror_lefttop(arr_x - n - 0.5, arr_y + n * 1.5 - 1.25 + 0.5)ax.plot(xs, ys)ax.text(0,n * 1.5 + 0.1,rf"$G^{n}$",horizontalalignment="center",verticalalignment="top",fontsize=16,)# 圆形是无穷阶几何连续的 arr_t = np.arange(0, pi * 2, 0.01) xs = cos(arr_t) ys = sin(arr_t) ax.plot(xs, ys) ax.text(0,0,r"$G^\infty$",horizontalalignment="center",verticalalignment="center",fontsize=16, )# G0 画圆 + 切线 arr_t = np.linspace(-1.25, 1.5, 1000) t0, t1 = np.sum(arr_t < 0), np.sum(arr_t < 1) arr_x, arr_y = arr_t.copy(), arr_t.copy() arr_x[:t0], arr_y[t1:] = 0, 1t = arr_t[t0:t1] x = 1 - cos(t) arr_x[t0:t1] = x arr_y[t0:t1] = 1 - x[::-1]xs, ys = mirror_lefttop(arr_x - 1.5, arr_y + 1.25) ax.plot(xs, ys) ax.text(0,2.1,r"$G^1$",horizontalalignment="center",verticalalignment="top",fontsize=16, )fig.savefig("a4_roundrect.png")
相关文章:

圆角矩形的绘制和曲线均匀化
摘要: 圆角矩形是软件 UI 等视觉设计中的常见表达,一种常见的绘制方法是将矩形的四角替换为与边相切的四分之一圆弧,然而这种绘制方式会在连接处产生视觉上的切折感,这是因为圆弧和直线的连接处只满足 G1G^1G1 连续性。本文探究了…...

【Linux】环境变量,命令行参数,main函数三个参数保姆教学
目录 ☃️1.奇奇怪怪的现象和孤儿进程 ☃️2.环境变量 ☃️3.深刻理解main函数的前两个参数和命令行参数 ☃️1.奇奇怪怪的现象和孤儿进程 首先回顾一下之前我们学过的fork()创建子进程 fork(void)的返回值有两种 注意fork()头…...

美国访问学者生活中有哪些饮食文化特点?
美国的教育毋庸置疑,排在世界数一数二的位置,美食美景更是数不胜数,那么他们有哪些饮食习惯,下面51访学网小编为你们详细介绍这些内容吧。 一、美国饮食文化特点 1、美国的饮食文化体现科学、适度、快捷,以满足人体的…...

RxJava中的Subject
要使用Rxjava首先要导入两个包,其中rxandroid是rxjava在android中的扩展 implementation io.reactivex:rxandroid:1.2.1implementation io.reactivex:rxjava:1.2.0Subject Subject 既可以是一个 Observer 也可以是一个 Observerable,它是连接 Observer 和…...

vue-element-admin在git 上 clone 之后无法install
一. 无法install的原因因为vue-element-admin引入的富文本编辑插件所导致 由于tui-editor变更 名字 导致 依赖查询找不到对应的版本二. 解决的办法先删掉package.json中tui-editor:1.3.3找到 \src\components\MarkdownEditor\index.vue 把所有的import 替换成下面4个import cod…...

Linux线程调度实验
Linux线程调度实验 1.获取线程属性 #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <pthread.h> #include <time.h> #include <stdlib.h> #include <errno.h> #define _GNU_SOURCE#define handle_error…...

洛谷P5735 【深基7.例1】距离函数 C语言/C++
【深基7.例1】距离函数 题目描述 给出平面坐标上不在一条直线上三个点坐标 (x1,y1),(x2,y2),(x3,y3)(x_1,y_1),(x_2,y_2),(x_3,y_3)(x1,y1),(x2,y2),(x3,y3),坐标值是实数,且绝对值不超过 100.00,求围成的三角形周长。保留两位…...

企业什么要建设自有即时通讯软件系统
随着科技的不断发展,各种即时通讯软件也不断发展进步,而这也与企业的发展息息相关,因为每个人,每个企业都有属于自己的机密,属于自己的隐私。 钉钉,企业微信,等公有的即时通讯软件给企业带来便利…...

LocalDNS
目录 文章目录目录本节实战DNS优化1、dns 5s 超时问题解决办法2、NodeLocal DNSCache实验软件关于我最后本节实战 实战名称💘 实战:NodeLocal DNSCache-2022.7.30(测试成功)💘 实战:NodeLocal DNSCache-2023.2.21(测试成功) DNS优…...

线程池种类和拒绝策略
1、newCachedThreadPool():可缓存的线程池,核心线程数量为0,最大线程数量为INT_MAX。线程空闲时间超过60秒被回收。适合处理大量小任务。 2、newFixedThreadPool()。固定线程个数的线程池,线程都是核心线程,没有应急线…...

Python制作9行最简单音乐播放器?不,我不满足
嗨害大家好鸭~我是小熊猫 好久不见啦~这次就来给大家整个大福利 ~ 源码资料电子书:点击此处跳转文末名片获取 最简单的9行代码音乐播放器如下: import time import pygamefile r歌曲路径 pygame.mixer.init() print(正在播放,file) track pygame.mixer.music.lo…...

零基础小白如何学会数据分析?
随着数字经济、大数据时代的发展,数据已然成为当下时代最重要的盈利资源,让企业在做决策和计划方案时更有针对性和依据,能提前预测市场发展方向,做好布局。由此而产生的数据分析岗位也逐渐被更多企业重视,特别是中大型…...

【Linux】vim的使用及常用快捷键(不会使用vim?有这篇文章就够了)
🔥🔥 欢迎来到小林的博客!! 🛰️博客主页:✈️小林爱敲代码 🛰️欢迎关注:👍点赞🙌收藏✍️留言 目录💖vim的基本概念vi…...

刷完这19道leetcode二分查找算法,不信进不了大厂
对于二分题,其实就是设定一个中间值 mid, 然后通过这个值进行一个判断 check(mid), 通过这个函数的返回值,判断将不可能的一半剪切掉; 在刷题的时候需要注意主要是两部分,check 函数的定义以及边界的选择(…...

四、Plugin Request and Sometimes pads
Request and Sometimes pads 到目前为止,我们只处理了总是可用的pad。然而,也有一些pad仅在某些情况下创建,或者仅在应用程序请求pad时创建。第一个有时被称为a;第二个被称为请求pad。pad的可用性(always, sometimes or request)可以在pad的…...

唤醒手腕 Java 后端 Springboot 结合 Redis 数据库学习笔记(更新中)
Redis 基本介绍 Redis Introduction The open source, in-memory data store used by millions of developers as a database, cache, streaming engine, and message broker. 基本概念:redis 是一个开源的、使用 C 语言编写的、支持网络交互的、可基于内存也可持…...

robotiq 2f 140安装在UR3机械臂后面在gazebo仿真中散架、抖动
robotiq 2f 140安装在UR3机械臂后面在gazebo仿真中散架、抖动 搭建环境: ubuntu: 20.04 ros: Nonetic sensor: robotiq_ft300 gripper: robotiq_2f_140_gripper UR: UR3 通过上一篇博客配置好ur3、力传感器和robotiq夹爪的gazebo仿真环境后,夹爪看起来…...

坐标系概念 四元数 欧拉角
1、四个概念:“地理”坐标系、“机体”坐标系、他们之间换算公式、换算公式用的系数。地理坐标系:东、北、天,以下简称地理。在这个坐标系里有重力永远是(0,0,1g),地磁永远是(0,1,x)…...

从0开始写Vue项目-SpringBoot整合Mybatis-plus实现登录、注册功能
1.从0开始写Vue项目-环境和项目搭建_慕言要努力的博客-CSDN博客 2. 从0开始写Vue项目-Vue2集成Element-ui和后台主体框架搭建_慕言要努力的博客-CSDN博客 3. 从0开始写Vue项目-Vue页面主体布局和登录、注册页面_慕言要努力的博客-CSDN博客 一、前言 在之前我们以及搭建好了基…...

K8s中gRpc通信负载均衡失效
上篇文章在做 整合K8sSpringCloudK8sSpringBootgRpc 时,发现K8s中使用gRpc通信,负载均衡功能失效查了下gRpc的最佳实践,找到这里Load balancingSome load balancers dont work effectively with gRPC. L4 (transport) load balancers operate…...

第三届区块链服务网络(BSN)全球合作伙伴大会在杭州成功举办
为持续推动分布式技术和产业创新发展,2023年2月17日,由杭州市人民政府指导,杭州市拱墅区人民政府、国家信息中心主办,中国移动通信集团有限公司、区块链服务网络(BSN)发展联盟承办,中国移动通信…...

人工智能基础部分13-LSTM网络:预测上证指数走势
大家好,我是微学AI,今天给大家介绍一下LSTM网络,主要运用于解决序列问题。 一、LSTM网络简单介绍 LSTM又称为:长短期记忆网络,它是一种特殊的 RNN。LSTM网络主要是为了解决长序列训练过程中的梯度消失和梯度爆炸问题…...

内网穿透/组网/设备上云平台EasyNTS上云网关的安装操作指南
EasyNTS上云网关的主要作用是解决异地视频共享/组网/上云的需求,网页对域名进行添加映射时,添加成功后会生成一个外网访问地址,在浏览器中输入外网访问地址,即可查看内网应用。无需开放端口,EasyNTS上云网关平台会向Ea…...

易点天下基于 StarRocks 全面构建实时离线一体的湖仓方案
作者:易点天下数据平台团队易点天下是一家技术驱动发展的企业国际化智能营销服务公司,致力于为客户提供全球营销推广服务,通过效果营销、品牌塑造、垂直行业解决方案等一体化服务,帮助企业在全球范围内高效地获取用户、提升品牌知…...

Tomcat的类加载机制
不遵循双亲委托 在JVM中并不是一次性地把所有的文件都加载到,而是按需加载,加载机制采用 双亲委托原则,如下图所示: BootStrapClassLoader 引导类加载器ExtClassLoader 扩展类加载器AppClassLoader 应用类加载器CustomClassLoad…...

【shell 编程大全】数组,逻辑判断以及循环
数组,逻辑判断以及循环1. 概述 大家好,我又来了。今天呢我们继续学习shell相关的知识。还是老样子我们先回顾下上一次【脚本交互 以及表达式】学习到的知识 登录shell 关联配置文件什么是子shellumask 修改默认权限read 基础表达式 简单计算表达式expr 计…...

Android13 Bluetooth更新
目录 Android 13 版本说明 LE Audio 代码更新 Android 12代码路径 Android 13代码路径 Android 13 版本说明 里面对蓝牙更新的描述较少,一出提到蓝牙的一...

手工测试混了5年,年底接到了被裁员的消息....
大家都比较看好软件测试行业,只是因为表面上看起来:钱多事少加班少。其实这个都是针对个人运气好的童人才会有此待遇。在不同的阶段做好不同阶段的事情,才有可能离这个目标更近,作为一枚软件测试人员,也许下面才是我们…...

Umi框架
什么是 umi umi 是由 dva 的开发者 云谦 编写的一个新的 React 开发框架。umi 既是一个框架也是一个工具,可以将它简单的理解为一个专注性能的类 next.js 前端框架,并通过约定、自动生成和解析代码等方式来辅助开发,减少开发者的代码量。 u…...

教你学git
前言 git是一种用于多人合作写项目。详细说明如下 文章目录前言什么是版本控制?什么是 Git?它就属于人工版本控制器版本控制工具常见版本控制工具怎么工作的?git 文件生命周期状态区域安装配置-- global检查配置创建仓库工作流与基本操作查看…...