嘎嘎详细的三维变换详细讲解,包括视图变换、投影变换等,超级通俗易懂!

前置二维空间的各种变换笔记:二维变换

三维空间中的齐次坐标

  • 从二维变换开始引申,可得到三维中的一个点的表达方式为 ( x , y , z , 1 ) ⊤ (\mathbf{x}, \mathbf{y}, \mathbf{z}, 1)^{\top} (x,y,z,1),也就是w=1,而三维的向量则表达为 ( x , y , z , 0 ) ⊤ (\mathbf{x}, \mathbf{y}, \mathbf{z}, 0)^{\top} (x,y,z,0),也就是w=0
  • 由于三维空间的一个点是上述格式的,若其中的w由于两点相加或者其他原因超过了1,则我们令这个点的xyz都除以w,那么w就会变成1了,也就是xyz所表达的位置坐标为 ( x / w , y / w , z / w ) (x / w, y / w, z / w) (x/w,y/w,z/w)
  • 而在三维空间中的齐次变换矩阵则如 ( x ′ y ′ z ′ 1 ) = ( a b c t x d e f t y g h i t z 0 0 0 1 ) ⋅ ( x y z 1 ) \left(\begin{array}{l} x^{\prime} \\ y^{\prime} \\ z^{\prime} \\ 1 \end{array}\right)=\left(\begin{array}{lllc} a & b & c & t_x \\ d & e & f & t_y \\ g & h & i & t_z \\ 0 & 0 & 0 & 1 \end{array}\right) \cdot\left(\begin{array}{l} x \\ y \\ z \\ 1 \end{array}\right) xyz1 = adg0beh0cfi0txtytz1 xyz1 所示
  • 其中矩阵的abcdefghi表达为线性变换,tx、ty、tz表达为平移变换,总体表达为一种仿射变换。
  • 同样,矩阵的最后一行也是(0, 0, 0, 1)
  • 其中线性变换和平移变换的执行顺序是先执行线性变换,再执行平移变换,具体可以从我们二维仿射变换公式看 ( x ′ y ′ ) = ( a b c d ) ⋅ ( x y ) + ( t x t y ) \binom{x^{\prime}}{y^{\prime}}=\left(\begin{array}{ll} a & b \\ c & d \end{array}\right) \cdot\binom{x}{y}+\binom{t_x}{t_y} (yx)=(acbd)(yx)+(tytx),先乘线性变换矩阵,再加平移变换。

三维齐次变换

  • 由二维向外引申,便可得到三维的各种变换矩阵形式
  • 缩放变换: S ( s x , s y , s z ) = ( s x 0 0 0 0 s y 0 0 0 0 s z 0 0 0 0 1 ) \mathbf{S}\left(s_x, s_y, s_z\right)=\left(\begin{array}{cccc} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) S(sx,sy,sz)= sx0000sy0000sz00001
  • 平移变换: T ( t x , t y , t z ) = ( 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ) \mathbf{T}\left(t_x, t_y, t_z\right)=\left(\begin{array}{cccc} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{array}\right) T(tx,ty,tz)= 100001000010txtytz1
  • 旋转变换:
    • 绕x轴旋转: R x ( α ) = ( 1 0 0 0 0 cos ⁡ α − sin ⁡ α 0 0 sin ⁡ α cos ⁡ α 0 0 0 0 1 ) \mathbf{R}_x(\alpha)=\left(\begin{array}{cccc} 1 & 0 & 0 & 0 \\ 0 & \cos \alpha & -\sin \alpha & 0 \\ 0 & \sin \alpha & \cos \alpha & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) Rx(α)= 10000cosαsinα00sinαcosα00001
    • 绕y轴旋转: R y ( α ) = ( cos ⁡ α 0 sin ⁡ α 0 0 1 0 0 − sin ⁡ α 0 cos ⁡ α 0 0 0 0 1 ) \mathbf{R}_y(\alpha)=\left(\begin{array}{cccc} \cos \alpha & 0 & \sin \alpha & 0 \\ 0 & 1 & 0 & 0 \\ -\sin \alpha & 0 & \cos \alpha & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) Ry(α)= cosα0sinα00100sinα0cosα00001
    • 绕z轴旋转: R z ( α ) = ( cos ⁡ α − sin ⁡ α 0 0 sin ⁡ α cos ⁡ α 0 0 0 0 1 0 0 0 0 1 ) \mathbf{R}_z(\alpha)=\left(\begin{array}{cccc} \cos \alpha & -\sin \alpha & 0 & 0 \\ \sin \alpha & \cos \alpha & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right) Rz(α)= cosαsinα00sinαcosα0000100001
    • 上述旋转都是简单的绕轴旋转,但是如果是一般性的旋转又该怎么处理呢?
    • 图形学有一个大佬,就写了一个矩阵,可以把任意一个轴的旋转写成一个矩阵,这个旋转公式就是著名的Rodrigues旋转公式,公式为 R ( n , α ) = cos ⁡ ( α ) I + ( 1 − cos ⁡ ( α ) ) n n T + sin ⁡ ( α ) ( 0 − n z n y n z 0 − n x − n y n x 0 ) ⏟ N \mathbf{R}(\mathbf{n}, \alpha)=\cos (\alpha) \mathbf{I}+(1-\cos (\alpha)) \mathbf{n} \mathbf{n}^T+\sin (\alpha) \underbrace{\left(\begin{array}{ccc} 0 & -n_z & n_y \\ n_z & 0 & -n_x \\ -n_y & n_x & 0 \end{array}\right)}_{\mathbf{N}} R(n,α)=cos(α)I+(1cos(α))nnT+sin(α)N 0nznynz0nxnynx0
    • 其中n代表要绕着的旋转轴向量

图形变换

  • 模型变换:类比于在一个场景中,模型的摆放,也就是拍照时所拍的物体放在哪

  • 视图变换:类比于,找到一个相机的角度,也就是相机在哪里拍照

  • 投影变换: 从模型和视图变换之后做一个3d到2d的投影,类似与相机和拍摄物体都确定好了,拍照的这么个过程

视图变换如何做?

  • 也就是怎么定义一个相机视角

  • 首先需要相机的位置 e ⃗ \vec{e} e ,其次还需要相机的朝向 g ^ \hat{g} g^,也就是往哪看,最后需要一个向上方向 t ^ \hat{t} t^来定义相机是往上看还是往下看。至此,即可确定一个相机的视角了。

  • 由于只要能保住相机和其所拍摄的物体所有的相对位置都是固定的,那么无论相机和这个物体被怎样移动,那么最后拍摄下来的照片应该都是一样的才对,所以为了方便运算,有一个约定俗成的规定,就是将相机永远摆放至原点

  • 假设当前相机视角如图所示,应该怎样将其变换到原点出呢

    image-20240710090850635

    image-20240710091101643

    • 首先做一个平移变换将相机移动到原点
    • 再将相机朝向 g ^ \hat{g} g^做旋转变换移动到-Z上
    • 最后将向上朝向 t ⃗ \vec{t} t 移动到Y上,那么 g × t g \times t g×t也就自动朝向X了
    • 我们可以定义整个变换矩阵为M,也就是用M来表达刚刚的所有操作,那么就有 M view  = R view  T view  M_{\text {view }}=R_{\text {view }} T_{\text {view }} Mview =Rview Tview 
    • 也就是先乘平移变换再乘旋转变换即可得到总的M变换矩阵,而这个变换矩阵T很好写,为 T view  = [ 1 0 0 − x e 0 1 0 − y e 0 0 1 − z e 0 0 0 1 ] T_{\text {view }}=\left[\begin{array}{cccc} 1 & 0 & 0 & -x_e \\ 0 & 1 & 0 & -y_e \\ 0 & 0 & 1 & -z_e \\ 0 & 0 & 0 & 1 \end{array}\right] Tview = 100001000010xeyeze1 ,也就是将自己的所在点各减去自己点离原点的距离即可
    • 而旋转R矩阵则相对较难,很难直观的知道怎样从一个轴变换到X、Y、-Z轴上,但是我们如果反过来思考,如果要把X、Y、-Z轴变换到某一个轴上,就很简单了,这就是前文提到的逆变换,而我们知道,逆变换矩阵是一个正交矩阵,而正交矩阵有一个性质就是他的逆是他自己的转置 R − θ = R θ T \mathbf{R}_{-\theta}=\mathbf{R}_{\theta}^T Rθ=RθT,于是我们只需要求出X、Y、Z如何变换到 g × t g\times t g×t t t t − g -g g上,再对该矩阵转置一下,就能得到从 g × t g\times t g×t t t t g g g变换到X、Y、-Z的变换矩阵了。
    • 比如要将X轴 [ 1 0 0 0 ] \begin{bmatrix} 1\\ 0\\ 0\\ 0 \end{bmatrix} 1000 旋转到 g × t g \times t g×t [ x g ^ × t ^ y g ^ × t ^ z g ^ × t ^ 0 ] \begin{bmatrix} x_{\hat{g} \times \hat{t} }\\ y_{\hat{g} \times \hat{t} }\\ z_{\hat{g} \times \hat{t} }\\ 0 \end{bmatrix} xg^×t^yg^×t^zg^×t^0 上,则旋转矩阵为 [ x g ^ × t ^ 0 0 0 y g ^ × t ^ 0 0 0 z g ^ × t ^ 0 0 0 0 0 0 1 ] \left[\begin{array}{cccc} x_{\hat{g} \times \hat{t}} & 0 & 0 & 0 \\ y_{\hat{g} \times \hat{t}} & 0 & 0 & 0 \\ z_{\hat{g} \times \hat{t}} & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right] xg^×t^yg^×t^zg^×t^0000000000001 ,同理可得Y、Z轴,将其合并一下,即可得到总的逆旋转矩阵 R v i e w − 1 = [ x g ^ × t ^ x t x − g 0 y g ^ × t ^ y t y − g 0 z g ^ × t ^ z t z − g 0 0 0 0 1 ] R_{view}^{-1}=\left[\begin{array}{cccc} x_{\hat{g} \times \hat{t}} & x_t & x_{-g} & 0 \\ y_{\hat{g} \times \hat{t}} & y_t & y_{-g} & 0 \\ z_{\hat{g} \times \hat{t}} & z_t & z_{-g} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right] Rview1= xg^×t^yg^×t^zg^×t^0xtytzt0xgygzg00001 ,则转置后的旋转矩阵为 R v i e w = [ x g ^ × t ^ y g ^ × t ^ z g ^ × t ^ 0 x t y t z t 0 x − g y − g z − g 0 0 0 0 1 ] R_{view}=\left[\begin{array}{cccc} x_{\hat{g} \times \hat{t}} & y_{\hat{g} \times \hat{t}} & z_{\hat{g} \times \hat{t}} & 0 \\ x_t & y_t & z_t & 0 \\ x_{-g} & y_{-g} & z_{-g} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right] Rview= xg^×t^xtxg0yg^×t^ytyg0zg^×t^ztzg00001 ,这便得到了从任意轴旋转到原点X、Y、-Z轴的旋转矩阵了,再和前面的平移矩阵T相乘,即可得到最终的变换矩阵M。
  • 也就是,只要相机和所拍摄关联到的物体都按照这个M矩阵进行变换,那么在变换前和变换后所拍摄到的内容应该都是一样的。

投影变换如何做?

  • 正交投影:投影前后无透视扭曲,即无近大远小的特性

    image-20240710101540574

    • 而想要将三维物体在无透视变化的情况下投影到二维平面上其实很简单,只需要去除这个物体的z轴就行了

      image-20240710133905868

    • 假设我们要投影的物体如上所示,可以发现,只要将他俩的z轴去掉,那么剩下的x,y自然就是他在二维平面上的投影。

    • 但是一般情况下,需要先将这个物体通过变换矩阵转移到原点xy轴的-1到1之间的矩形之中,这样做的目的是为了简化后续操作,也就是大家都遵守这套规范,后续api啊各方面的开发就会很简便。

    • 但是这样做就会出现一个问题,就是物体的前后信息丢失了,你无法显示出物体的深度信息,为了解决这个问题,通常会保留下这个z轴,也就是说先将物体通过各种变换转移到原点处xyz都在-1到1的一个立方体中,这个立方体也叫做标准化空间,这样的话物体之间的深度信息就会保留下来,也就是x和y坐标会被用来确定物体在屏幕上的位置,而z坐标则用于深度测试等目的。而最终的三维到二维的投影呢则是对这个标准化空间里做一个切片,z坐标被用来进行深度测试和裁剪,而x和y坐标则被用来确定最终在屏幕上的位置。也就是如下图所示。

      image-20240710135747981

    • 其中l、r为物体的左右(left、right),b、t为下上(bottom、top),f、n为远近(far,near)。

    • 而将被拍摄物体通过变换矩阵到原点的-1到1的空间内也就很简单了,先平移变换,再缩放变换即可(对应着上图的二图和三图)。

    • 平移变换可以直接将物体的中心处移动到原点处即可,而物体的中心计算方法就很简单,x轴的中心就是 r + l 2 \frac{r+l}{2} 2r+l,yz轴同理,那么将物体最终移动到中心就是自身每个轴减去这个值即可,于是平移变换矩阵为 [ 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 1 − n + f 2 0 0 0 1 ] \left[\begin{array}{cccc} 1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{array}\right] 1000010000102r+l2t+b2n+f1

    • 而缩放变换呢就是要将物体规范化到-1到1的空间内,-1到1的长度为2,那么x轴的缩放就是用2除以物体的宽度,也就是 2 r − l \frac{2}{r-l} rl2(具体数学推理就是求一个线性变换y=ax+b,将x等于l和r代入即可得到a和b的值,其中a就是缩放因子,b就是平移因子,最后解的a就是这个2/(r-l)),其他轴同理,于是缩放矩阵为 [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ] \left[\begin{array}{cccc} \frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right] rl20000tb20000nf200001

    • 而最终的正交投影变换矩阵为他俩相乘 M ortho  = [ 2 r − l 0 0 0 0 2 t − b 0 0 0 0 2 n − f 0 0 0 0 1 ] [ 1 0 0 − r + l 2 0 1 0 − t + b 2 0 0 1 − n + f 2 0 0 0 1 ] = [ 2 r − l 0 0 − r + l 2 0 2 t − b 0 − t + b 2 0 0 2 n − f − n + f 2 0 0 0 1 ] M_{\text {ortho }}=\left[\begin{array}{cccc} \frac{2}{r-l} & 0 & 0 & 0 \\ 0 & \frac{2}{t-b} & 0 & 0 \\ 0 & 0 & \frac{2}{n-f} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right]\left[\begin{array}{cccc} 1 & 0 & 0 & -\frac{r+l}{2} \\ 0 & 1 & 0 & -\frac{t+b}{2} \\ 0 & 0 & 1 & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{array}\right]=\left[\begin{array}{cccc} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{2} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{2} \\ 0 & 0 & \frac{2}{n-f} & -\frac{n+f}{2} \\ 0 & 0 & 0 & 1 \end{array}\right] Mortho = rl20000tb20000nf200001 1000010000102r+l2t+b2n+f1 = rl20000tb20000nf202r+l2t+b2n+f1

    • 最后通过这个矩阵M就可以将任意物体规范化到原点处-1到1的标准空间中啦~

  • 透视投影:有近大远小的特性

    image-20240710101525589

    • 将三维物体通过透视投影到二维平面上有一个办法,由于透视投影他可以理解成沿着一个点,向外延申出四条线,如上图,那么所包裹住的物体就是一个四棱台,而我们知道,正交投影所包裹住的是一个长方体,那我们就可以先将这个四棱台压成长方体,再按照正交投影的办法去变换即可。

      image-20240710144540819

    • 也就是将上面左图的远平面在xy轴处压成近平面的矩形,最终呈现右图的样子。显然,在这个变化当中,近平面的x、y、z都不会发生改变,而远平面的z和远平面中心点也不会发生改变。

      image-20240710150424063

    • 如上图所示((x’,y’,z’)是近平面的点,(x,y,z)是远平面的点),根据相似三角形原则,若点(x,y,z)想变换到点(x’,y’,z’)上,y和y’的比值一定等于n和z的比值,于是可得 y ′ = n z y y^{\prime}=\frac{n}{z} y y=zny,同理可得 x ′ = n x y x^{\prime}=\frac{n}{x} y x=xny

    • 也就是说原本(x,y,z,1)和一个矩阵相乘后,会得到(nx/z,ny/z,不知道,1)这样的向量,而我们知道,在齐次坐标中,一个点同乘任何非0常数,所表达的矩阵依然一致,也就是(nx/z,ny/z,不知道,1)和(nx,ny,不知道,z)他俩所表达的点都是(x,y,z),也就是 M persp  →  ortho  ( 4 × 4 ) ( x y z 1 ) = ( n x n y  unknown  z ) M_{\text {persp } \rightarrow \text { ortho }}^{(4 \times 4)}\left(\begin{array}{l} x \\ y \\ z \\ 1 \end{array}\right)=\left(\begin{array}{c} n x \\ n y \\ \text { unknown } \\ z \end{array}\right) Mpersp  ortho (4×4) xyz1 = nxny unknown z

    • 很容易就能得到这个M矩阵为 M persp ortho  = ( n 0 0 0 0 n 0 0 ? ? ? ? 0 0 1 0 ) M_{\text {persp ortho }}=\left(\begin{array}{cccc} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ ? & ? & ? & ? \\ 0 & 0 & 1 & 0 \end{array}\right) Mpersp ortho = n0?00n?000?100?0

    • 而上述矩阵中的第三行的值可以通过前面所说的两个条件来计算,就是“近平面的x、y、z都不会发生改变,而远平面的z和远平面中心点也不会发生改变。”

    • 设近平面的z轴值为n,也就是上面的M矩阵乘上近平面的(x,y,n,1)后仍然是(x,y,n,1),然后在这个齐次坐标同乘一个n,也就是 M persp  →  ortho  ( 4 × 4 ) = ( x y n 1 ) = = ( n x n y n 2 n ) M_{\text {persp } \rightarrow \text { ortho }}^{(4 \times 4)}=\left(\begin{array}{l} x \\ y \\ n \\ 1 \end{array}\right)==\left(\begin{array}{c} n x \\ n y \\ n^2 \\ n \end{array}\right) Mpersp  ortho (4×4)= xyn1 == nxnyn2n

    • 那么此时我们将M矩阵的第三行当个向量提取出来,也就是 ( 0 0 A B ) ( x y n 1 ) = n 2 \left(\begin{array}{llll} 0 & 0 & A & B \end{array}\right)\left(\begin{array}{l} x \\ y \\ n \\ 1 \end{array}\right)=n^2 (00AB) xyn1 =n2,前面两个数之所以为0是因为很明显最后的这个 n 2 n^2 n2肯定和xy无关,相乘后也就是 A n + B = n 2 A n+B=n^2 An+B=n2

    • 而远平面的中心点在变换中不会发生改变,设远平面的z轴值为f,而远平面中心点则表示为 ( 0 0 f 1 ) \left(\begin{array}{l} 0 \\ 0 \\ f \\ 1 \end{array}\right) 00f1 ,同时乘个f,则为 ( 0 0 f 2 f ) \left(\begin{array}{c} 0 \\ 0 \\ f^2 \\ f \end{array}\right) 00f2f ,和前面的 ( 0 0 A B ) \left(\begin{array}{llll} 0 & 0 & A & B \end{array}\right) (00AB)相乘后也就是 A f + B = f 2 A f+B=f^2 Af+B=f2,解两式可得 A = n + f B = − n f \begin{aligned} & A=n+f \\ & B=-n f \end{aligned} A=n+fB=nf

    • 这样就得到了最终的变换矩阵 M persp ortho  = ( n 0 0 0 0 n 0 0 0 0 n + f − n f 0 0 1 0 ) M_{\text {persp ortho }}=\left(\begin{array}{cccc} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 & n+f & -nf \\ 0 & 0 & 1 & 0 \end{array}\right) Mpersp ortho = n0000n0000n+f100nf0 ,这个矩阵可以将任意物体从透视投影的四棱台挤压成正交投影的正方形

    • 最后再按照正交投影的方法来完成后续步骤即可完成透视投影 M persp  = M ortho  M persp  →  ortho  M_{\text {persp }}=M_{\text {ortho }} M_{\text {persp } \rightarrow \text { ortho }} Mpersp =Mortho Mpersp  ortho 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/790805.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WPF 制作一个文字漂浮提示框

WPF好像没有自带的文字提示漂浮&#xff0c;我们可以定制一个。 效果如下&#xff1a; xaml xaml如下&#xff1a; <Window x:Class"GroupServer.MsgTip"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://sc…

【三维向量旋转】基于Matlab的三维坐标旋转

一、问题描述 若空间中存在三个点A,B,C&#xff0c;其中A点是不动点&#xff0c;B点是当前方向向量上的一个点&#xff0c;C是目标方向上的一个点。如果要让AB向量沿着BC方向进行旋转&#xff0c;使得AB最终旋转到AC。这个过程就是三维向量的旋转过程。我们关注的是这个过程&am…

【音频特征提取】傅里叶变换算法源码学习记录

目录 背景快速理解FFT&#xff08;快速傅里叶变换&#xff09;IFFT&#xff08;逆傅里叶变换&#xff09;STFT&#xff08;短时傅里叶变换&#xff09; 代码实现FFT源代码IFFT源代码FFT、IFFT自己实验STFT源代码STFT自己实验 总结 背景 最近用到了相关操作提取音频信号特征&am…

松下的台灯值得入手吗?书客|飞利浦护眼台灯真实测评PK

在追求高效阅读与舒适生活的今天&#xff0c;一盏好的台灯不仅是照明的工具&#xff0c;更是呵护双眼的伴侣。它不仅能够提供额外的光线&#xff0c;还能减少眼睛疲劳&#xff0c;提高我们的工作和学习效率。随着市场的不断发展&#xff0c;护眼台灯品牌款式愈发丰富。因此我们…

MYSQL 四、mysql进阶 8(索引优化与查询优化)

都有哪些维度可以进行数据库调优&#xff1f;简言之&#xff1a; 索引失效、没有充分利用到索引——建立索引关联查询太多JOIN&#xff08;设计缺陷或不得已的需求&#xff09;——SQL优化服务器调优及各个参数设置&#xff08;缓冲、线程数等&#xff09;——调整my.cnf数据过…

【C++】C++11(三)

我们在C11&#xff08;2&#xff09;中已经很好的解释了右值引用&#xff0c;这次来看看右值引用剩余的一些话题&#xff1a;可变参数包与emplace_back。 目录 可变参数模板&#xff1a;可变参数的sizeof&#xff1a;可变参数的展开&#xff1a;递归函数方式展开参数包&#x…

通过Arcgis从逐月平均气温数据中提取并计算年平均气温

通过Arcgis快速将逐月平均气温数据生成年平均气温数据。本次用2020年逐月平均气温数据操作说明。 一、准备工作 &#xff08;1&#xff09;准备Arcmap桌面软件&#xff1b; &#xff08;2&#xff09;准备2020年逐月平均气温数据&#xff08;NC格式&#xff09;、范围图层数据&…

k8s 部署RuoYi-Vue-Plus之server部署

1.先使用项目编排构建镜像, 修改prod使用的mysql, redis地址 获取运行的服务 kubectl get svc -n ruoyi对应连接修改 然后运行打包package命令, 生成jar包, 再打包为docker容器, 上传到所有节点上, 也可以上传到个人私有仓库 2.部署server-deploy.yaml 镜像名自行修改, apiV…

你知道的和你不知道的DOM操作技巧

你知道的和你不知道的DOM操作技巧 亲爱的前端小伙伴们&#xff0c;今天我们来聊聊那些你可能知道或者不知道的DOM操作技巧。作为一名前端开发者&#xff0c;如果你还在为DOM操作头疼&#xff0c;那么这篇文章绝对能让你茅塞顿开。让我们一起来探索一下DOM的奥秘吧&#xff01;…

【开源合规】开源许可证风险场景详细解读

文章目录 前言关于BlackDuck许可证风险对比图弱互惠型许可证举个例子具体示例LGPL系列LGPL-2.0-onlyLGPL-2.0-or-laterLGPL-2.1-onlyLGPL-2.1-or-laterLGPL-3.0-onlyLGPL-3.0-or-laterMPL系列MPL-1.0MPL-1.1MPL-2.0EPL系列EPL-1.0EPL-2.0互惠型许可证GPL系列GPL-1.0GPL-2.0GPL-…

Mac系统清理工具:您的数字生活杂务处理师

有没有觉得您的Mac有时候像是需要一个好的春季大扫除一样&#xff1f;随着我们不断使用电脑&#xff0c;各种不需要的文件、老旧的数据和忘记的安装包就像家里的灰尘一样慢慢积累。幸运的是&#xff0c;有了一些出色的Mac系统清理工具&#xff0c;我们可以轻松将这些数字灰尘拂…

Java中实现二维数组(矩阵)的转置

在矩阵运算中&#xff0c;矩阵的转置是一个基本操作&#xff0c;即将矩阵的行变成列&#xff0c;列变成行。在Java中&#xff0c;我们可以通过编写一个方法来实现二维数组的转置。下面&#xff0c;我将详细介绍如何在Java中完成这一任务&#xff0c;并提供完整的代码示例。 编…

【Linux】命令执行的判断依据:;,,||

在某些情况下&#xff0c;很多命令我想要一次输入去执行&#xff0c;而不想要分次执行时&#xff0c;该如何是好&#xff1f; 基本上有两个选择&#xff0c; 一个是通过shell脚本脚本去执行&#xff0c;一种则是通过下面的介绍来一次入多个命令。 1.cmd&#xff1a;cmd&#…

AR增强现实汽车装配仿真培训系统开发降低投入费用

随着互联网的无处不在&#xff0c;AR增强现实技术正逐步融入我们生活的每一个角落。深圳华锐视点作为一家引领行业潮流的AR内容开发的技术型公司&#xff0c;正以其卓越的技术实力和专业的服务团队&#xff0c;推动着国内AR技术向更加成熟和多元化的方向迈进。 深圳华锐视点提供…

成都晨持绪:抖音电商带货需要交钱吗

在抖音这个充满创意与可能的平台上&#xff0c;电商带货成为了一种新兴而又时尚的职业。然而&#xff0c;伴随着无数的点击与转发&#xff0c;有一个问题始终萦绕在人们心头——抖音电商带货需要交钱吗? 如画卷展开&#xff0c;抖音平台以其独特的算法和庞大的用户基础构建了一…

GDidees CMS v3.9.1 本地文件泄露漏洞(CVE-2023-27179)

前言 CVE-2023-27179 是一个影响 GDidees CMS v3.9.1 及更低版本的任意文件下载漏洞。这个漏洞存在于 /_admin/imgdownload.php 文件中&#xff0c;攻击者可以通过向 filename 参数传递恶意输入来下载服务器上的任意文件。 漏洞的根源在于对用户输入的 filename 参数处理不当…

前后端如何实现非对称加解密-使用RSA为例讲解!

写在最前面&#xff0c;RSA是一种非对称加密算法&#xff0c;使用不同的公钥和私钥进行加密和解密。 下面是使用RSA进行加密和解密的代码示例&#xff1a; 前端&#xff1a;使用CryptoJS进行RSA加密 在前端JavaScript中&#xff0c;使用jsencrypt库来进行RSA加密&#xff1a…

网络安全----防御----防火墙安全策略组网

防火墙组网 要求&#xff1a; 1&#xff0c;DMz区内的服务器&#xff0c;办公区仅能在办公时间内(9:00-18:00)可以访问&#xff0c;生产区的设备全天可以访问。 2&#xff0c;生产区不允许访问互联网&#xff0c;办公区和游客区允许访问互联网 3&#xff0c;办公区设备10.0.…

【AI前沿】深度学习:技术、发展与前沿应用

文章目录 一、深度学习的背景与发展1.1 背景1.2 早期发展1.3 突破性进展1.4 近年发展 二、深度学习的基本概念2.1 神经网络2.2 多层感知器&#xff08;MLP&#xff09;2.3 卷积神经网络&#xff08;CNN&#xff09;2.4 循环神经网络&#xff08;RNN&#xff09;2.5 生成对抗网络…

【C++修行之道】string类练习题

目录 387. 字符串中的第一个唯一字符 125. 验证回文串 917. 仅仅反转字母 415. 字符串相加&#xff08;重点&#xff09; 541. 反转字符串 II 387. 字符串中的第一个唯一字符 字符串中的第一个唯一字符 - 力扣&#xff08;LeetCode&#xff09; 给定一个字符串 s &#…