webgl入门-矩阵变换

矩阵变换

前言

变换有三种状态:平移、旋转、缩放。

当我们变换一个图形时,实际上就是在移动这个图形的所有顶点。

课堂目标

  1. 掌握图形变换的三种方式。
  2. 可以对图像进行复合变换。

知识点

  1. 平移
  2. 旋转
  3. 缩放

第一章 平移

对图形的平移就是对图形所有顶点的平移。

1-举个例子

image-20210315105508042

已知:

  • 顶点p(x,y,z)
  • 在x、y、z 三个方向上,分别将点p 移动tx、ty、tz

求:点p 移动后的位置p’(x’,y’,z’)

解:

x'=x+tx
y'=y+ty
z'=z+tz

如果这个图形中并非只有一个顶点,而是有三个,或者更多,那么所有的顶点也是按照同样原理进行位移。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2-向量加法

在实际代码中,我们要有一个向量的概念。

比如 (x,y,z) ,我们既可以说它是一个顶点位置,也可以说它是一个向量。

至于 (x,y,z) 到底是什么,要看我们拿它做什么。

比如,把点p(x,y,z) 作为点位时,那它就是点p(x,y,z)

我们把p 的移动距离tx、ty、tz 封装成一个对象pt(tx,ty,tz),那么pt 就是一个向量,一个为点p 指明移动方向和距离的向量。

因此:点p 的移动结果 p’ 就可以这么写:

p'=p+pt

由上可知,顶点的位移就是向量的加法。

3-代码实现

3-1-GLSL ES 语言里的向量运算

在GLSL ES 语言里,是可以直接进行向量运算。

下面的顶点着色器里的代码:

attribute vec4 a_Position;
vec4 translation=vec4(0,0.2,0,0);
void main(){gl_Position = a_Position+translation;
}
  • a_Position 是原始点位,属于attribute 变量
  • translation 是顶点着色器里的私有变量,没有向外部暴露,属于4维向量
  • a_Position+translation 便是着色器内的向量加法,这里是对原始点位进行位移

之后,我们也可以把translation 变量暴露出去,让js可以修改图形位置:

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;uniform vec4 u_Translation;void main(){gl_Position = a_Position+u_Translation;}
</script>

在js 中修改uniform 变量的方法,我们之前已经说过:

const u_Translation=gl.getUniformLocation(gl.program,'u_Translation');
gl.uniform4f(u_Translation,0,0.5,0,0);

整体代码:

<canvas id="canvas"></canvas>
<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;uniform vec4 u_Translation;void main(){gl_Position = a_Position+u_Translation;}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">void main(){gl_FragColor=vec4(1,1,0,1);}
</script>
<script type="module">import {initShaders} from '../jsm/Utils.js';const canvas = document.getElementById('canvas');canvas.width=window.innerWidth;canvas.height=window.innerHeight;const gl = canvas.getContext('webgl');const vsSource = document.getElementById('vertexShader').innerText;const fsSource = document.getElementById('fragmentShader').innerText;initShaders(gl, vsSource, fsSource);const vertices=new Float32Array([0,  0.1,-0.1,-0.1,0.1, -0.1])const vertexBuffer=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);gl.bufferData(gl.ARRAY_BUFFER,vertices,gl.STATIC_DRAW);const a_Position=gl.getAttribLocation(gl.program,'a_Position');gl.vertexAttribPointer(a_Position,2,gl.FLOAT,false,0,0);gl.enableVertexAttribArray(a_Position);const u_Translation=gl.getUniformLocation(gl.program,'u_Translation');gl.uniform4f(u_Translation,0,0.5,0,0);gl.clearColor(0, 0, 0, 1);gl.clear(gl.COLOR_BUFFER_BIT);// gl.drawArrays(gl.POINTS, 0, 3);gl.drawArrays(gl.TRIANGLES, 0, 3);</script>

image-20201019140550020

在最后面我们还可以加一段逐帧动画:

let y=0;
!(function ani(){y+=0.02if(y>1){y=-1}gl.uniform4f(u_Translation,0,y,0,0);gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, 3);requestAnimationFrame(ani)
})()

效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

接下来咱们说旋转。

第二章 旋转

1-旋转的概念

三维物体的旋转要比位移复杂一点,因为三维物体的旋转需要知道以下条件:

  • 旋转轴
  • 旋转方向
  • 旋转角度

我们可以想象一个场景:

一个小人站在旋转轴的起点进行旋转。

小人要往左转还是往右转,就是旋转的方向。

小人旋转的大小就是旋转角度。

1

2-旋转方向的正负

物体的旋转方向是有正负之分的。

那何时为正,何时为负呢?

在webgl 中,除裁剪空间之外的大部分功能都使用了右手坐标系。

所以,在我们初学webgl 的时候,可以暂且将其当成右手坐标系,等讲到裁剪空间的时候,我再跟大家说左手坐标系。

下图就是右手坐标系:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

以上图为例:

  • 当物体绕z 轴,从x轴正半轴向y轴正半轴逆时针旋转时,是正向旋转,反之为负。
  • 当物体绕x 轴,从y轴正半轴向z轴正半轴逆时针旋转时,是正向旋转,反之为负。
  • 当物体绕y 轴,从z轴正半轴向x轴正半轴逆时针旋转时,是正向旋转,反之为负。

如下图就是正向旋转:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3-旋转公式

先举一个让顶点围绕z 轴旋转的例子。

image-20210106142031447

已知:

  • 点A的位置是(ax,ay,az)
  • 点A要围绕z轴旋转β度,转到点B的位置

求:点A旋转后的bx、by位置

解:

我们由结果逆推一下解题思路。

因为∠β是已知的,∠α 可以通过点A 得出。

所以我们可以得出:

∠xOB=α+β

那我们通过三角函数就可以推出bx、by

设∠xOB=θ,则:

bx=cosθ*|OA|
by=sinθ*|OA|

上面的|OA|是点O到点A的距离,可以直接用点A求出:

|OA|=Math.sqrt(ax*ax+ay*ay)

那我们接下来只需要知道cosθ和sinθ的值即可

因为:θ=α+β

所以,我们可以利用和角公式求cosθ和sinθ的值:

cosθ=cos(α+β)
cosθ=cosα*cosβ-sinα*sinβ
sinθ=sin(α+β)
sinθ=cosβ*sinα+sinβ*cosα

所以:

bx=cosθ*|OA|
bx=(cosα*cosβ-sinα*sinβ)*|OA|
bx=cosα*cosβ*|OA|-sinα*sinβ*|OA|
by=sinθ*|OA|
by=(cosβ*sinα+sinβ*cosα)*|OA|
by=cosβ*sinα*|OA|+sinβ*cosα*|OA|

因为:

cosα*|OA|=ax
sinα*|OA|=ay

所以我们可以简化bx、by的公式

bx=ax*cosβ-ay*sinβ
by=ay*cosβ+ax*sinβ

上面的bx、by就是我们要求的答案。

那接下来咱们可以测试一下,如何让一个三角形绕z轴转起来

4-在着色器中旋转

我们可以直接在着色器里写旋转公式:

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;float angle=radians(80.0);float sinB=sin(angle);float cosB=cos(angle);void main(){gl_Position.x=a_Position.x*cosB-a_Position.y*sinB;gl_Position.y=a_Position.y*cosB+a_Position.x*sinB;gl_Position.z=a_Position.z;gl_Position.w=1.0;}
</script>
  • radians(float degree) 将角度转弧度
  • sin(float angle) 正弦
  • cos(float angle) 余弦

我们也可以用js控制图形的旋转。

5-用js旋转图形

我们将顶点着色器里的正弦值和余弦值暴露给js,便可以用js旋转图形了。

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;uniform float u_SinB;uniform float u_CosB;void main(){gl_Position.x=a_Position.x*u_CosB-a_Position.y*u_SinB;gl_Position.y=a_Position.y*u_CosB+a_Position.x*u_SinB;gl_Position.z=a_Position.z;gl_Position.w=1.0;}
</script>

在js 中修改uniform 变量

const u_SinB = gl.getUniformLocation(gl.program, 'u_SinB')
const u_CosB = gl.getUniformLocation(gl.program, 'u_CosB')
let angle = 0.3
gl.uniform1f(u_SinB, Math.sin(angle))
gl.uniform1f(u_CosB, Math.cos(angle))

之后也可以让图形转起来:

!(function ani() {angle += 0.01gl.uniform1f(u_SinB, Math.sin(angle))gl.uniform1f(u_CosB, Math.cos(angle))gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, 3);requestAnimationFrame(ani)
})()

第三章 缩放

1-缩放的基本概念

缩放可以理解为对向量长度的改变,或者对向量坐标分量的同步缩放

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

已知:

  • 点A的位置是(ax,ay,az)
  • 点A基于原点內缩了一半

求:点A內缩了一半后的bx、by、bz位置

解:

bx=ax*0.5
by=ay*0.5
bz=az*0.5

2-在着色器中缩放

我可以对gl_Position 的x、y、z依次缩放。

<script id="vertexShader" type="x-shader/x-vertex">
attribute vec4 a_Position;
float scale=1.2;
void main(){gl_Position.x= a_Position.x*scale;gl_Position.y= a_Position.y*scale;gl_Position.z= a_Position.z*scale;gl_Position.w=1.0;
}
</script>

也可以从a_Position中抽离出由x、y、z组成的三维向量,对其进行一次性缩放。

<script id="vertexShader" type="x-shader/x-vertex">
attribute vec4 a_Position;
float scale=1.2;
void main(){gl_Position=vec4(vec3(a_Position)*scale,1.0);
}
</script>

3-用js缩放图形

同样的我们也可以把缩放系数暴露给js,通过js 缩放图形。

1.建立uniform变量

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;uniform float u_Scale;void main(){gl_Position=vec4(vec3(a_Position)*u_Scale,1.0);}
</script>

2.使用js获取并修改uniform 变量

const u_Scale = gl.getUniformLocation(gl.program, 'u_Scale')
gl.uniform1f(u_Scale, 1.0)

3.继续来点动画

let angle = 0
!(function ani() {angle += 0.05const scale = Math.sin(n) + 1gl.uniform1f(u_Scale, scale)gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, 3);requestAnimationFrame(ani)
})()

第四章 矩阵

矩阵(Matrix)是一个按照矩形纵横排列的复数集合。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

矩阵就像一个矩形的阵盘,通过其中纵横排列的元素,我们可以摆出不同功能的阵法,比如位移矩阵、旋转矩阵、缩放矩阵……

image-20210326165809914

在矩阵中的每一行,或者每一列数字构成的集合,可以视之为向量。

所以咱们接下来要先从向量说起。

1-向量

向量,又叫矢量,它是一个用于表示方向和量的对象。

我另写了几篇可以从零基础认识向量的文章,大家可看一下,以便对向量有一个透彻的认知:

  • 漫谈直线之向量
  • 漫谈向量之坐标运算
  • 向量之点积
  • 向量之叉乘

在webgl 里的向量有1维向量、2维向量、3维向量和4维向量。

  • 1维向量中有1个数字,对应的是单轴坐标系里的点位。
  • 2维向量中有2个数字,对应的是2维坐标系里的点位。
  • 3维向量中有3个数字,对应的是3维坐标系里的点位。
  • 4维向量中有4个数字,对应的是3维坐标系里的点位,外加一个附加数据,至于这个数据是什么,要看我们的项目需求。

向量咱们就说到这,接下来咱们再说一下矩阵和向量的乘法。

2-矩阵和向量的乘法

首先,咱先看一个矩阵和向量的乘法图:

image-20210107184337749

矩阵乘以向量时,向量是几维的,那矩阵中就应该有几个向量。

如上图向量v 是2维的,那么矩阵中就有2组向量,这两组向量可以是横着的两组向量,也可以是竖着的两组向量。

  • 横着的两组向量是:向量(a,b)、向量(e,f)
  • 竖着的两组向量是:向量(a,e)、向量(b,f)

用专业术语来说:

  • 横着的两组遵循的规则是行主序,即将矩阵中的一行数据视之为一个向量。
  • 竖着的两组遵循的规则是列主序,即将矩阵中的一列数据视之为一个向量。

至于我们是使用行主序,还是列主序,这就得看规则的定制者了。

在webgl 里,矩阵元素的排列规则是列主序。

数学中常用的写法是行主序,所以我们接下来就用行主序举例子了。

矩阵和向量相乘的规则就是让矩阵中的每个向量和向量v相乘。

向量和向量相乘,就是在求向量的点积,其结果是一个实数,而不再是向量。

比如上图中,向量(a,b)乘以向量v(x,y)的结果是:

a*x+b*y

因为a、b、x、y都是实数,所以其结果也是实数。

上图中,矩阵m乘以向量v 会得到两个结果,即ax+by和ex+fy。

这两个结果会构成一个新的向量v’(x’,y’)

x'=a*x+b*y
y'=e*x+f*y

这时我们可以将其和数学里的旋转公式做一下比较。

点A(ax,ay)围绕z轴旋β度,其旋转后的位置是点B(bx,by),则:

bx=cosβ*ax-sinβ*ay
by=sinβ*ax+cosβ*ay

对比上面的两组公式,试想一下:

向量v是不是可以当成一个点位呢?

答案是可以的。

那我现在就让向量v代表的位置,就是点A的位置。

那么矩阵m乘以向量v,是不是可以让向量v代表的这个点位旋转β度呢?

如果可以,那么矩阵里的元素应该满足什么条件呢?

满足以下条件即可:

a=cosβ
b=-sinβ
e=sinβ
f=cosβ

这样,用矩阵乘以向量的方法得到的旋转结果和用数学公式得到的结果就是一样的,即;

a*x+b*y=cosβ*ax-sinβ*ay
e*x+f*y=sinβ*ax+cosβ*ay

最终我们就可以用矩阵乘以向量的方式让点p旋转β度

image-20210108120112541

那我们知道了上面的这种关系之后,要干什么,能干什么呢?接下来就是重点啦!

3-在着色器中写矩阵

我们是可以直接在着色器中建立矩阵对象的。

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;float angle=radians(40.0);float sinB=sin(angle);float cosB=cos(angle);mat2 m2=mat2(cosB, sinB,-sinB,cosB);void main(){gl_Position = vec4(m2*vec2(a_Position),a_Position.z,a_Position.w);}
</script>
  • mat2 是二维矩阵对象

4-用js建立矩阵对象并传递给着色器

1.在顶点着色器中建立uniform变量

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;uniform mat2 u_Matrix;void main(){gl_Position = vec4(u_Matrix*vec2(a_Position),a_Position.z,a_Position.w);}
</script>

2.获取并修改uniform 变量

const u_Matrix = gl.getUniformLocation(gl.program, 'u_Matrix')
let angle = 0.2
const [sinB, cosB] = [Math.sin(angle), Math.cos(angle)]
const matrix = [cosB, sinB,-sinB, cosB
]
gl.uniformMatrix2fv(u_Matrix, false, matrix)

3.后面我们也可以在其中添加动画

const u_Matrix = gl.getUniformLocation(gl.program, 'u_Matrix')
let angle = 0.2!(function ani() {angle += 0.02const [sinB, cosB] = [Math.sin(angle), Math.cos(angle)]const matrix = [cosB, sinB,-sinB, cosB]gl.uniformMatrix2fv(u_Matrix, false, matrix)gl.clear(gl.COLOR_BUFFER_BIT);gl.drawArrays(gl.TRIANGLES, 0, 3);requestAnimationFrame(ani)
})()

目前我们说的只是最简单的二维矩阵,我们可以直接给顶点着色器一个四维矩阵。

5-四维矩阵

四维矩阵在着色器里的应用原理和二维矩阵是一样的,只要理解了其运算原理就好。

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;float angle=radians(10.0);float cosB=cos(angle);float sinB=sin(angle);mat4 m4=mat4(cosB, sinB,0.0,0.0,-sinB,cosB,0.0,0.0,0.0,  0.0, 1.0,0.0,0.0,  0.0, 0.0,1.0);void main(){gl_Position = m4*a_Position;}
</script>

我们也可以用js向顶点着色器传递四维矩阵。

const u_Matrix = gl.getUniformLocation(gl.program, 'u_Matrix')
let angle = 0.1
const [sinB, cosB] = [Math.sin(angle), Math.cos(angle)]
const matrix = [cosB, sinB, 0.0, 0.0,-sinB, cosB, 0.0, 0.0,0.0, 0.0, 1.0, 0.0,0.0, 0.0, 0.0, 1.0
]
gl.uniformMatrix4fv(u_Matrix, false, matrix)

矩阵不仅可以用于旋转,还可以平移和缩放。

6-矩阵平移

比如我要让顶点的x移动0.1,y移动0.2,z移动0.3

顶点着色可以这样写:

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;//列主序mat4 m4=mat4(1.0, 0.0, 0.0,0.0,0.0, 1.0, 0.0,0.0,0.0, 0.0, 1.0,0.0,0.1, 0.2, 0.3,1.0);void main(){gl_Position = m4*a_Position;}
</script>

对于js 建立矩阵对象,并传递给着色器的方法,我之前已经说过,就不再赘述了。

7-矩阵缩放

以同样的原理,我们也可以写缩放矩阵。

比如我要让顶点在x轴向缩放2,y轴向缩放3,轴向缩放4

顶点着色可以这样写:

<script id="vertexShader" type="x-shader/x-vertex">attribute vec4 a_Position;//列主序mat4 m4=mat4(2.0, 0.0, 0.0,0.0,0.0, 3.0, 0.0,0.0,0.0, 0.0, 4.0,0.0,0.0, 0.0, 0.0,1.0);void main(){gl_Position = m4*a_Position;}
</script>

第五章 矩阵库

像我们之前那样手写矩阵,其实是很麻烦的,我们可以将其模块化。

现在市面上已经有许多开源的矩阵库了,比如《WebGL 编程指南》里的cuon-matrix.js,three.js 的Matrix3和Matrix4对象。

接下我们就简单说一下three.js的Matrix4对象的用法。

1.引入Matrix4对象

import {Matrix4} from 'https://unpkg.com/three/build/three.module.js';

2.实例化矩阵对象,在其中写入旋转信息

const matrix=new Matrix4()
matrix.makeRotationZ(Math.PI/6)

3.基于matrix 对象的elements 属性,修改uniform 变量

const u_Matrix=gl.getUniformLocation(gl.program,'u_Matrix')
gl.uniformMatrix4fv(u_Matrix,false,matrix.elements)

总结

这一篇主要讲解了如何使用矩阵统一变换一个物体的多个顶点,下一篇我们会让矩阵包含多种变换信息,比如移动加旋转,旋转加缩放。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何快速从手动测试转向自动化测试

寻求具有无缝持续集成和持续交付 (CI/CD) 的高效 DevOps 管道比以往任何时候都更加重要。想象一下这样一个场景&#xff1a;您的软件组织显著减少了人工工作量、降低了成本&#xff0c;并更加自信地发布了软件更新。换句话说&#xff0c;通过将 Web UI 和 API 测试结合在一起&a…

【小白课程】如何在openKylin上个性化定制开关机动画

开关机动画是Linux系统的重要组成部分&#xff0c;其主要功能是在Linux内核启动的早期遮盖内核打印日志&#xff0c;并在内核刷新屏幕分辨率时保证屏幕显示的流畅性。 其中&#xff0c;openKylin操作系统使用plymouth组件作为开关机动画显示程序。Linux系统在启动时&#xff0…

计算机SCI期刊,中科院2区,收稿范围非常广泛!

一、期刊名称 Journal of Web Semantics 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;计算机科学 影响因子&#xff1a;2.5 中科院分区&#xff1a;2区 出版方式&#xff1a;开放出版 版面费&#xff1a;$1600 三、期刊征稿范围 《网络语义学杂志》…

【软件测试】5.测试用例

目录 1.测试用例 1.1概念 1.2测试的要素 2.测试用例的万能公式 2.1常规思考逆向思维发散性思维 2.2万能公式 2.2.1功能测试 2.2.2界面测试 2.2.3性能测试 2.2.4兼容性测试 2.2.5易用性测试 2.2.6安全测试 2.3弱网测试 1.测试用例 1.1概念 什么是测试用例&#xf…

Jenkins 构建 Web 项目:构建服务器和部署服务器分离的情况

构建命令 #!/bin/bash node -v pnpm -v pnpm install pnpm build:prod # 将dist打包成dist.zip zip -r dist.zip dist

软件项目运维方案-word原件2024

1. 文档介绍 1.1 文档目的 1.2 文档范围 1.3 读者对象 1.4 参考文献 1.5 术语与缩写解释 2. 人员与责任 2.1 项目建设管理机构 2.2 驻场人员工作时间 2.3 人员培训 2.3.1. 培训需求管理 2.3.2. 培训内容管理 2.4 绩效考核 3. 运维过程内容 3.1. 运维模型 3.2. P…

LangChain - 概念指南

文章目录 一、Architecture1、langchain-core2、partner-packages3、langchain4、langchain-community5、langgraph6、langserve7、langsmith 二、浪链表达语言&#xff08;LCEL &#xff09;可运行界面 runnable-interface 三、组件 components1、聊天模型 chat-models2、 LLM…

工程机械租赁平台数字化平台系统油耗与排放管理创新与应用

在快速发展的城市建设和基础设施项目中&#xff0c;工程机械扮演着举足轻重的角色。随着工程规模的扩大和施工技术的不断进步&#xff0c;工程机械租赁平台应运而生&#xff0c;为建设项目提供了灵活高效的解决方案。然而&#xff0c;随着租赁机械数量的增加&#xff0c;如何有…

【GO基础】GO基础语法一

GO基础语法一 一、编写第一个Go程序1、基本程序结构2、应用程序入口3、退出返回值4、获取命令行参数 二、变量&#xff0c;常量以及与其他语言的差异1、编写测试程序2、实现Fibonacci数列3、变量赋值4、常量定义 三、数据类型1、类型转化2、类型的预定义值3、指针类型 四、运算…

微信小程序仿胖东来轮播和背景效果(有效果图)

效果图 .wxml <view class"swiper-index" style"--width--:{{windowWidth}}px;"><image src"{{swiperList[(cardCur bgIndex -1?swiperList.length - 1:cardCur bgIndex > swiperList.length -1?0:cardCur bgIndex)]}}" clas…

【四数之和】python,排序+双指针

四层循环&#xff1f;&#xff08;doge) 和【三数之和】题目很类似 class Solution:def fourSum(self, nums: List[int], target: int) -> List[List[int]]:nums.sort()#a,b,c,d四个数&#xff0c;先固定两个数&#xff0c;那就是双指针问题了&#xff0c;令ba1&#xff…

关于搜索引擎链路

一、搜索引擎的的链路 简单流程如下&#xff0c;一般都包括query理解&#xff0c;召回&#xff0c;粗排&#xff0c;精排&#xff0c;重排。 二、query理解&#xff0c;查询词处理 对于进来的query需要有很多道工序做处理。才能让搜索引擎的效果更好、更智能。 2.1 分词 分词…

Ubuntu18.04 OpenSSH升级

升级前版本&#xff1a; rootecs-m2eqyb:/opt# ll total 20912 drwxr-xr-x 2 root root 4096 May 10 16:23 ./ drwxr-xr-x 24 root root 4096 May 10 14:38 ../ -rw-r--r-- 1 root root 1848766 May 10 16:23 openssh-9.7p1.tar.gz -rw-r--r-- 1 root root 18038…

离散数学--图论

目录 1.简单概念 2.握手定理 3.点割集 4.边割集 5.点连通度和边连通度 6.Dijstra算法&&最短路径 7.有向图的连通性 8.图的矩阵表示 9.欧拉图问题 10.哈密尔顿图 1.简单概念 &#xff08;1&#xff09;这个里面的完全图比较重要&#xff0c;完全图是例如k3,k5这…

JMETER工具:以录制手机app为例

JMETER工具&#xff1a;以录制手机app为例子 JMETER安装和环境配置 pc需要安装jdk&#xff0c;并进行jdk的环境配置&#xff0c;安装好jdk并配置好后&#xff0c;通过命令行输入java –version出现以下界面就表示安装成功&#xff1a; &#xff08;对应的jdk版本不可太低&…

selenium环境安装和web自动化基础

webUI自动化背景 因为web页面经常会变化&#xff0c;所以UI自动化测试的维护成本很高。不如接口的适用面广&#xff0c;所以大部分公司会做接口自动化测试&#xff0c;但是未必会做UI自动化测试&#xff1b; UI自动化测试要做也是覆盖冒烟测试&#xff0c;不会到很高的覆盖率&a…

Flink常见面试题总结

文章目录 1. 简单介绍一下Flink2. Flink 的运行必须依赖Hadoop组件吗?3. Flink 和 Spark Streaming 的区别&#xff1f;4. Flink集群角色5. Flink核心概念5.1 并行度5.2 算子链&#xff08;Operator Chain&#xff09;5.3 任务槽&#xff08;Task Slots&#xff09;5.4 任务槽…

掌握Go语言中的net/http包:编写高性能Web服务

掌握Go语言中的net/http包&#xff1a;编写高性能Web服务 引言HTTP服务器构建基础服务器设置路由与处理函数中间件使用高级配置&#xff08;如TLS/SSL&#xff09; HTTP客户端开发创建与使用HTTP客户端处理响应 高级客户端特性 处理JSON与表单数据接收与解析JSON接收与解析表单…

实现一个自定义 hook,用于强制刷新当前组件

写在前面 在 react 中&#xff0c;如果 state 数据发生变化&#xff0c;我们知道&#xff0c;会重新渲染该组件。 但是这个前提是我们需要依赖 state 数据的变化&#xff0c;那比如我们并不想定义 state&#xff0c;又或者说我们的操作不能引起 state 的变化&#xff0c;此时…

无人机行业招投标技术详解

一、招标流程与原则 无人机行业的招投标流程通常包括招标公告发布、招标文件购买与审查、投标单位资格预审、投标书编制与递交、开标评标、中标公示与合同签订等步骤。在此过程中&#xff0c;必须遵循公开、公平、公正的原则&#xff0c;确保所有符合要求的投标单位都能获得平…