当前位置: 首页 > news >正文

计算机图形学:实验一 OpenGL基本绘制

1.OpenGL的环境配置

集成开发环境Visual Studio Community 2019的安装 

在Windows一栏选择使用C++的桌面开发;再转到“单个组件”界面,在“编译器、生成工具和运行时”一栏选择用于“Windows的C++ CMake工具”;然后转到“语言包”勾选“英语”。

2.CMake的安装:

下载对应平台的CMake安装包,打开安装包,按流程安装CMake。

3.Git的安装:

下载对应平台的Git安装包,打开安装包,按流程安装Git,其中有选择编辑器的选项,有安装VSCode的建议选择VSCode作为默认的编辑工具。

4.Vcpkg的安装:

在github使用Git克隆仓库到安装目录;进入到vcpkg文件,使用管理员身份打开Powershell;运行bootstrap引导脚本,执行 .\bootstrap-vcpkg.bat ,构建vcpkg;构建完成后,执行.\vcpkg integrate install命令,将vcpkg聚合到visual stuido。

5.系统环境变量设置:

验证路径是否添加成功,随便一个文件夹内开一个终端输入:vcpkg,执行后没用跳出错误就说明vcpkg环境配置成功。

6.OpenGL库安装:GLFW,GLAD,GLM

7.构建并运行实验1.1

在项目文件夹下打开命令行,然后执行 cmake -B . ,执行后会在当前项目文件夹内生成main.sln文件,点击打开;在出现的VS界面中,可以看到“解决方案管理器”里面右键点击 “main”项目,将其设置为启动项,之后即可编译运行程序。

8.绘制出参考图片样式二维图形

增加顶点数组对象VAO,由3个增到5个(包括新增的圆形和椭圆)。

GLuint vao[5], program;//由3增到5(加了圆形和椭圆)

  1. VAO是顶点数组对象(Vertex Array Object)的缩写。它是OpenGL中的一个对象,用于存储一组顶点属性的状态。简单来说,VAO能够保存多个VBO(顶点缓冲对象)和EBO(元素缓冲对象)的配置,使得在绘制图形时,只需绑定相应的VAO即可直接使用之前设置好的顶点数据和属性配置,从而简化了绘图过程。
  2. GLuint vao[5]: 声明了一个长度为5的无符号整数数组vao,用于存储5个顶点数组对象的句柄(即vao),这些对象可以用于绘制几何图形。最初只有3个VAO用来绘制三角形、矩形、线,现在增加到5个,其中包括了用于绘制圆形和椭圆的VAO。
  3. GLuint program: 声明了一个无符号整数变量program,用于存储一个OpenGL着色器程序的句柄,用于控制图形的渲染。

 在init初始函数中定义生成椭圆和圆形的点。

// 定义椭圆的点

glm::vec2 ellipse_vertices[ELLIPSE_NUM_POINTS];

glm::vec3 ellipse_colors[ELLIPSE_NUM_POINTS];

// 定义圆形的点

glm::vec2 circle_vertices[CIRCLE_NUM_POINTS];

glm::vec3 circle_colors[CIRCLE_NUM_POINTS];

  1. glm::vec2表示一个二维向量,用于存储二维坐标(顶点位置)。
  2. glm::vec3表示一个三维向量,包含红、绿、蓝三个分量,用于存储颜色值(RGB)。
  3. 定义数组来存储绘制椭圆和圆形所需的顶点位置和颜色数据,数组的大小由预先定义的常量ELLIPSE_NUM_POINTS(椭圆顶点数量)和CIRCLE_NUM_POINTS(圆形顶点数量)决定。

 义完后,调用生成椭圆和圆形形状顶点位置的函数。

  1. 函数 generateEllipsePoints 用于生成椭圆或圆的顶点位置和颜色。

void generateEllipsePoints(glm::vec2 vertices[], glm::vec3 colors[], int startVertexIndex, int numPoints,glm::vec2 center, double scale, double verticalScale)

函数的参数包括:

  • glm::vec2 vertices[]用于存储生成的椭圆或圆形的顶点位置。
  • glm::vec3 colors[]用于存储每个顶点的颜色信息。
  • int startVertexIndex为顶点数组的起始索引,即从数组的哪个位置开始填充顶点数据。
  • int numPoints是要生成的椭圆或圆形的顶点数量。
  • glm::vec2 center是椭圆或圆形的中心位置。
  • double scale是椭圆的水平半轴长度或圆的半径。
  • double verticalScale是椭圆的垂直半轴长度。如果 verticalScale 为 1.0,则生成的形状是一个圆;如果 verticalScale 不等于 1.0,则生成的是一个椭圆。 

// 调用生成椭圆和圆形形状顶点位置的函数

generateEllipsePoints(ellipse_vertices, ellipse_colors, 0, ELLIPSE_NUM_POINTS, glm::vec2(-0.5, 0.7), 0.2, 0.5);

generateEllipsePoints(circle_vertices, circle_colors, 0, CIRCLE_NUM_POINTS, glm::vec2(0.6, 0.7), 0.2, 1.0);

  1. 椭圆的生成:一个中心在 (-0.5, 0.7),水平半轴为 0.2,垂直半轴为 0.5 的椭圆的顶点位置,并将这些顶点及其对应的颜色值存储到 ellipse_vertices 和 ellipse_colors 数组中。
  2. 圆形的生成:一个中心在 (0.6, 0.7),半径为 0.2 的圆形的顶点位置,并将这些顶点及其颜色值存储到 circle_vertices 和 circle_colors 数组中。

 初始化圆和椭圆的数据。

生成和配置顶点数组对象 (VAO) 和顶点缓冲对象 (VBO),以将顶点数据(如位置和颜色)上传到 GPU,即在渲染中,GPU能够正确地访问和使用这些数据进行绘制。

  • 生成并绑定 VAO:

glGenVertexArrays(1, &vao[3]);  // 生成 VAO ID

glBindVertexArray(vao[3]);      // 绑定 VAO,使其成为当前操作的目标

  • 生成并绑定 VBO:

glGenBuffers(1, &vbo[0]);  // 生成位置数据的 VBO

glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);  // 绑定位置 VBO

glBufferData(GL_ARRAY_BUFFER, sizeof(ellipse_vertices), ellipse_vertices, GL_STATIC_DRAW);  // 将位置数据上传到 GPU

  • 配置顶点属性指针:

location = glGetAttribLocation(program, "vPosition");// 获取位置属性在着色器中的位置

glEnableVertexAttribArray(location);  // 启用位置属性

glVertexAttribPointer(

location,         // 属性位置

2,                // 每个顶点包含两个分量 (x, y)

GL_FLOAT,         // 数据类型为浮点数

GL_FALSE,         // 不需要归一化

sizeof(glm::vec2),// 步幅,即每两个顶点之间的字节间隔

BUFFER_OFFSET(0) ); // 数据从 VBO 开头开始读取

  • 类似的步骤也用于颜色数据的配置:

glGenBuffers(1, &vbo[1]);  // 生成颜色数据的 VBO

glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);  // 绑定颜色 VBO

glBufferData(GL_ARRAY_BUFFER, sizeof(ellipse_colors), ellipse_colors, GL_STATIC_DRAW);  // 上传颜色数据

cLocation = glGetAttribLocation(program, "vColor");  // 获取颜色属性在着色器中的位置

glEnableVertexAttribArray(cLocation);  // 启用颜色属性

glVertexAttribPointer(

cLocation,        // 属性位置

3,                // 每个颜色包含三个分量 (r, g, b)

GL_FLOAT,         // 数据类型为浮点数

GL_FALSE,         // 不需要归一化

sizeof(glm::vec3),// 步幅

BUFFER_OFFSET(0));// 数据从 VBO 开头开始读取

  • 重复上述步骤进行其他对象的初始化:

针对不同的形状(包括椭圆和圆形),需要分别生成和配置它们的 VAO 和 VBO。可以通过重复上述步骤来完成这些操作。

 在display函数中绘制椭圆和圆形。

// 画椭圆

glBindVertexArray(vao[3]);

glDrawArrays(GL_TRIANGLE_FAN, 0, ELLIPSE_NUM_POINTS);

// 画圆形

glBindVertexArray(vao[4]);

glDrawArrays(GL_TRIANGLE_FAN, 0, CIRCLE_NUM_POINTS);

  1. glBindVertexArray绑定 VAO,将编号为 vao[3] 的 VAO 绑定为椭圆,将编号为 vao[4] 的 VAO 绑定为圆,这两个VAO 是之前初始化椭圆和圆顶点和颜色数据时创建的,包含了椭圆和圆的顶点属性配置。
  2. glDrawArrays绘制椭圆和圆,其中GL_TRIANGLE_FAN指定绘制的图元类型为三角形扇形(Triangle Fan),即顶点数组中的第一个顶点将作为扇形的中心点,后续的顶点将围绕这个中心点形成多个相邻的三角形。对于椭圆和圆形,使用 GL_TRIANGLE_FAN 可以绘制出一个封闭的形状。0则表示从顶点数组的第一个顶点开始绘制。最后一个参数则指定绘制的顶点数量。

 代码填充后,点击运行,结果如下图所示。

整体程序代码运行的整体流程:

  • 初始化: 设置GLFW和OpenGL,生成图形数据,配置渲染管道。调用glfwInit()来初始化GLFW库,调用init()函数生成图形的顶点和颜色数据,并将这些数据发送到GPU,初始化OpenGL资源。
  • 渲染循环: 持续绘制图形并响应用户输入。main()函数中包含一个while循环,持续运行直到用户关闭窗口。在循环内,程序会处理输入,调用display()函数进行绘制,交换缓冲区,处理事件。
  • 清理和退出: 释放资源,结束程序。渲染循环结束后,程序退出,释放所有分配的资源,包括VAO、VBO和着色器程序。使用glfwTerminate()关闭GLFW并清理所有分配的资源。当用户关闭窗口或手动退出循环时,程序结束运行,返回到操作系统。

 9.自行设计不同的图形颜色效果:

整设计思路:

  1. 首先将背景分成左上(浅蓝色)、右上(浅黄色)、左下(浅紫色)、右下(浅绿色)四块。
  2. 左上是一条鱼的形状:一个黄色三角形是尾巴,一个红色菱形是身体,一个白色小圆形是眼睛。
  3. 右上是一棵树:从上往下是三层规模递增的绿色半圆形,树桩是一个棕色小矩形状。
  4. 左下是一个胡萝卜:三个倾斜的绿色小矩形是胡萝卜叶子,一个橘色倾斜三角形是胡萝卜肉体。
  5. 右下是一个棒棒糖:由多个渐变圆环形成糖果,一个灰色矩形是棒棒糖棍。

 背景绘制:

  • 定义和生成背景分割的四个矩形的点以及颜色。
  • 在init()函数中初始化背景数据,包括点以及颜色。
  • 在display()函数中绘制背景。(背景是四个不同颜色的矩形,每个矩形可以由6个三角形绘制而成)。

    //绘制背景

    glBindVertexArray(vao[0]);

    glDrawArrays(GL_TRIANGLES, 0, 6 * NUM_RECTANGLES);

10.左上鱼的绘制:

  • 定义和生成鱼眼睛(圆形)、鱼尾巴(三角形)、鱼身体(菱形)的点以及颜色。
  1. 在进行鱼尾巴的绘制时,我在原本生成三角形的每个顶点generateTrianglePoints这个函数,增添了rotationAngle旋转角度这个参数,使得绘制的三角形能够进行旋转。
  2. 旋转的原理:首先定义旋转矩阵:,用于计算点绕原点的旋转变换;然后应用旋转:,将顶点坐标通过旋转矩阵转换到新的位置;最后平移,将旋转后的顶点平移到目标中心位置。

// 获得三角形的每个顶点

void generateTrianglePoints(glm::vec2 vertices[], glm::vec3 colors[], int startVertexIndex, glm::vec2 center, glm::vec2 scale, glm::vec3 vertexColors[], double rotationAngle)

{

    for (int i = 0; i < 3; ++i) {

        double currentAngle = getTriangleAngle(i);

        glm::vec2 vertex = glm::vec2(sin(currentAngle), cos(currentAngle)) * scale;

        // 应用旋转矩阵

        double rotatedX = vertex.x * cos(rotationAngle) - vertex.y * sin(rotationAngle);

        double rotatedY = vertex.x * sin(rotationAngle) + vertex.y * cos(rotationAngle);

        // 计算旋转后的顶点位置

        vertices[startVertexIndex + i] = glm::vec2(rotatedX, rotatedY) + center;

        colors[startVertexIndex + i] = vertexColors[i];

    }

}

同样的,在进行鱼身体的绘制时,我也在原本生成矩形的每个顶点generateRectanglePoints这个函数,增添了rotationAngle旋转角度这个参数,使得绘制的矩形能够进行旋转(当正方形顺时针旋转45度时即可得到菱形)。

// 计算矩形每个顶点的函数

void generateRectanglePoints(glm::vec2 vertices[], glm::vec3 colors[], int startVertexIndex,

    glm::vec2 center, glm::vec2 scale, double rotationAngle, glm::vec3 color)

{

    int vertexIndex = startVertexIndex;

    for (int i = 0; i < 4; ++i) {

        double currentAngle = getSquareAngle(i);

        // 计算旋转后的坐标

        glm::vec2 point = glm::vec2(sin(currentAngle), cos(currentAngle)) * scale;

        glm::vec2 rotatedPoint = glm::vec2(

            point.x * cos(rotationAngle) - point.y * sin(rotationAngle),

            point.x * sin(rotationAngle) + point.y * cos(rotationAngle) );

        // 应用平移

        vertices[vertexIndex] = rotatedPoint + center;

        colors[vertexIndex] = color;

        vertexIndex++;

    }

}

  • 在init()函数中初始化鱼各个部分的数据,包括点以及颜色。使用 glGenVertexArrays 和 glGenBuffers 生成 VAO 和 VBO,再使用 glBindVertexArray 绑定 VAO,以及使用 glBindBuffer 绑定 VBO,并上传数据。
  • 在display()函数中绘制鱼。(在这里需要注意的是,由于鱼眼睛是在鱼身体上面的,一定要先画鱼身体,再画眼睛,这样才不会被覆盖。)

    //绘制鱼尾巴

    glBindVertexArray(vao[2]);

    glDrawArrays(GL_TRIANGLES, 0, TRIANGLE_NUM_POINTS);

    //绘制鱼身体

    glBindVertexArray(vao[3]);

    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    //绘制鱼眼睛

    glBindVertexArray(vao[1]);

    glDrawArrays(GL_TRIANGLE_FAN, 0, CIRCLE_NUM_POINTS);

11.其他图案同理绘制,最终效果如下:

相关文章:

计算机图形学:实验一 OpenGL基本绘制

1.OpenGL的环境配置&#xff1a; 集成开发环境Visual Studio Community 2019的安装&#xff1a; 在Windows一栏选择使用C的桌面开发&#xff1b;再转到“单个组件”界面&#xff0c;在“编译器、生成工具和运行时”一栏选择用于“Windows的C CMake工具”&#xff1b;然后转到…...

二分查找题目:快照数组

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;快照数组 出处&#xff1a;1146. 快照数组 难度 7 级 题目描述 要求 实现支持下列接口的快照数组&#xff1a; SnapshotArray(int length) \textt…...

深度学习|表示学习|卷积神经网络|参数共享是什么?|07

如是我闻&#xff1a; Parameter Sharing&#xff08;参数共享&#xff09;是卷积神经网络&#xff08;CNN&#xff09;的一个重要特性&#xff0c;帮助它高效地处理数据。参数共享的本质就是参数“本来也没有变过”。换句话说&#xff0c;在卷积层中&#xff0c;卷积核的参数&…...

基于相机内参推导的透视投影矩阵

基于相机内参推导透视投影矩阵&#xff08;splatam&#xff09;&#xff1a; M c a m [ 2 ⋅ f x w 0.0 ( w − 2 ⋅ c x ) w 0.0 0.0 2 ⋅ f y h ( h − 2 ⋅ c y ) h 0.0 0 0 f a r n e a r n e a r − f a r 2 f a r ⋅ n e a r n e a r − f a r 0.0 0.0 − 1.0 0.0 ] M_…...

浅析Dubbo 原理:架构、通信与调用流程

一、Dubbo 简介 Dubbo 是阿里巴巴开源的高性能、轻量级的 Java RPC&#xff08;Remote Procedure Call&#xff0c;远程过程调用&#xff09;框架&#xff0c;旨在实现不同服务之间的远程通信和调用。在分布式系统中&#xff0c;不同服务可能部署在不同的服务器上&#xff0c;D…...

03垃圾回收篇(D3_垃圾收集器的选择及相关参数)

目录 学习前言 一、收集器的选择 二、GC日志参数 三、垃圾收集相关的常用参数 四、内存分配与回收策略 1. 对象优先在Eden分配 2. 大对象直接进入老年代 3. 长期存活的对象将进入老年代 4. 动态对象年龄判定 5. 空间分配担保 学习前言 本章主要学习垃圾收集器的选择及…...

一、引论,《组合数学(第4版)》卢开澄 卢华明

零、前言 发现自己数数题做的很烂&#xff0c;重新学一遍组合数学吧。 参考卢开澄 卢华明 编著的《组合数学(第4版)》&#xff0c;只打算学前四章。 通过几个经典问题来了解组合数学所研究的内容。 一、幻方问题 据说大禹治水之前&#xff0c;河里冒出来一只乌龟&#xff0c…...

Vue3+TS 实现批量拖拽文件夹上传图片组件封装

1、html 代码&#xff1a; 代码中的表格引入了 vxe-table 插件 <Tag /> 是自己封装的说明组件 表格列表这块我使用了插槽来增加扩展性&#xff0c;可根据自己需求&#xff0c;在组件外部做调整 <template><div class"dragUpload"><el-dialo…...

二叉树的所有路径(力扣257)

因为题目要求路径是从上到下的&#xff0c;所以最好采用前序遍历。这样可以保证按从上到下的顺序将节点的值存入一个路径数组中。另外&#xff0c;此题还有一个难点就是如何求得所有路径。为了解决这个问题&#xff0c;我们需要用到回溯。回溯和递归不分家&#xff0c;每递归一…...

Python OrderedDict 实现 Least Recently used(LRU)缓存

OrderedDict 实现 Least Recently used&#xff08;LRU&#xff09;缓存 引言正文 引言 LRU 缓存是一种缓存替换策略&#xff0c;当缓存空间不足时&#xff0c;会移除最久未使用的数据以腾出空间存放新的数据。LRU 缓存的特点&#xff1a; 有限容量&#xff1a;缓存拥有固定的…...

LabVIEW项目中的工控机与普通电脑选择

工控机&#xff08;Industrial PC&#xff09;与普通电脑在硬件设计、性能要求、稳定性、环境适应性等方面存在显著差异。了解这些区别对于在LabVIEW项目中选择合适的硬件至关重要。下面将详细分析这两种设备的主要差异&#xff0c;并为LabVIEW项目中的选择提供指导。 ​ 硬件设…...

Ansys Speos | Speos Meshing 网格最佳实践

概述 网格划分是在各种计算应用中处理3D几何的基本步骤&#xff1a; 表面和体积&#xff1a;网格允许通过将复杂的表面和体积分解成更简单的几何元素&#xff08;如三角形、四边形、四面体或六面体&#xff09;来表示复杂的表面和体积。 模拟和渲染&#xff1a;网格是创建离散…...

elasticsearch segment数量对读写性能的影响

index.merge.policy.segments_per_tier 是一个配置选项&#xff0c;用于控制 Elasticsearch 中段&#xff08;segment&#xff09;合并策略的行为。它定义了在每一层的段合并过程中&#xff0c;允许存在的最大段数量。调整这个参数可以优化索引性能和资源使用。 假设你有一个索…...

全同态加密理论、生态现状与未来展望(中2)

《全同态加密理论、生态现状与未来展望》系列由lynndell2010gmail.com和mutourend2010gmail.com整理原创发布&#xff0c;分为上中下三个系列&#xff1a; 全同态加密理论、生态现状与未来展望&#xff08;上&#xff09;&#xff1a;专注于介绍全同态加密理论知识。全同态加密…...

鸿蒙UI(ArkUI-方舟UI框架)-开发布局

返回主章节 → 鸿蒙UI&#xff08;ArkUI-方舟UI框架&#xff09; 开发布局 1、布局概述 1&#xff09;布局结构 2&#xff09;布局元素组成 3&#xff09;如何选择布局 声明式UI提供了以下10种常见布局&#xff0c;开发者可根据实际应用场景选择合适的布局进行页面开发。 …...

RPC是什么?和HTTP区别?

RPC 是什么&#xff1f;HTTP 是什么&#xff1f; 作为一个程序员&#xff0c;假设我们需要从A电脑的进程发送一段数据到B电脑的进程&#xff0c;我们一般会在代码中使用 Socket 进行编程。 此时&#xff0c;可选性一般就是 TCP 和 UDP 二选一&#xff0c;由于 TCP 可靠、UDP 不…...

Linux C\C++编程-建立文件和内存映射

【图书推荐】《Linux C与C一线开发实践&#xff08;第2版&#xff09;》_linux c与c一线开发实践pdf-CSDN博客 《Linux C与C一线开发实践&#xff08;第2版&#xff09;&#xff08;Linux技术丛书&#xff09;》(朱文伟&#xff0c;李建英)【摘要 书评 试读】- 京东图书 Linu…...

行政纠错——pycorrector学习

pycorrector是一个开源中文文本纠错工具&#xff0c;它支持对中文文本进行音似、形似和语法错误的纠正。此工具是使用Python3进行开发的&#xff0c;并整合了Kenlm、ConvSeq2Seq、BERT、MacBERT、ELECTRA、ERNIE、Transformer等多种模型来实现文本纠错功能。pycorrector官方仓库…...

Go的defer原理

Go 的 defer 原理 defer 是 Go 语言中的一个关键字&#xff0c;用于延迟执行一个函数调用。它通常用于处理资源释放、连接关闭等操作&#xff0c;确保这些操作在函数返回之前执行。 1. 什么是 defer&#xff1f; defer 关键字用于延迟执行一个函数调用&#xff0c;直到包含它…...

Windows 下本地 Docker RAGFlow 部署指南

Windows 下本地 Docker RAGFlow 部署指南 环境要求部署步骤1. 克隆代码仓库2. 配置 Docker 镜像加速(可选)3. 修改端口配置(可选)4. 启动服务5. 验证服务状态6. 访问服务7. 登录系统8. 配置模型8.1 使用 Ollama 本地模型8.2 使用在线 API 服务9. 开始使用10. 常见问题处理端…...

专题三_穷举vs暴搜vs深搜vs回溯vs剪枝_全排列

dfs解决 全排列&子集 1.全排列 link:46. 全排列 - 力扣&#xff08;LeetCode&#xff09; 全局变量回溯 code class Solution { public:vector<vector<int>> ans;vector<int> cur;vector<bool> used;vector<vector<int>> permute…...

【IEEE Fellow 主讲报告| EI检索稳定】第五届机器学习与智能系统工程国际学术会议(MLISE 2025)

重要信息 会议时间地点&#xff1a;2025年6月13-15日 中国深圳 会议官网&#xff1a;http://mlise.org EI Compendex/Scopus稳定检索 会议简介 第五届机器学习与智能系统工程国际学术会议将于6月13-15日在中国深圳隆重召开。本次会议旨在搭建一个顶尖的学术交流平台&#xf…...

华为E9000刀箱服务器监控指标解读

美信监控易内置了数千种常见设备监测器&#xff0c;能够监测超过20万项指标。这些指标涵盖了从硬件设备到软件系统&#xff0c;从网络性能到安全状态等各个方面。如下基于美信监控易——IT基础监控模块&#xff0c;对华为E9000刀箱服务器部分监控指标进行解读。 一、华为E9000…...

【LC】2544. 交替数字和

题目描述&#xff1a; 给你一个正整数 n 。n 中的每一位数字都会按下述规则分配一个符号&#xff1a; 最高有效位 上的数字分配到 正 号。剩余每位上数字的符号都与其相邻数字相反。 返回所有数字及其对应符号的和。 示例 1&#xff1a; 输入&#xff1a;n 521 输出&…...

QT QTreeWidget控件 全面详解

本系列文章全面的介绍了QT中的57种控件的使用方法以及示例,包括 Button(PushButton、toolButton、radioButton、checkBox、commandLinkButton、buttonBox)、Layouts(verticalLayout、horizontalLayout、gridLayout、formLayout)、Spacers(verticalSpacer、horizontalSpacer)、…...

欧几里得算法求最小公倍数和最大公约数

一.最大公约数 gcd(a,b)gcd(b,a%b) 递归式,当且仅当b0&#xff0c;易得0和a的公约数为a.(可作为递归的出口) 证明&#xff1a; int gcd(int a, int b) {if (b 0) return a;else return gcd(b, a % b); } 二.最小公倍数 给定整数a b&#xff0c;求a b的最小公倍数 有图可知…...

Selenium配合Cookies实现网页免登录

文章目录 前言1 方案一&#xff1a;使用Chrome用户数据目录2 方案二&#xff1a;手动获取并保存Cookies&#xff0c;后续使用保存的Cookies3 注意事项 前言 在进行使用Selenium进行爬虫、网页自动化操作时&#xff0c;登录往往是一个必须解决的问题&#xff0c;但是Selenium每次…...

DeepSeek R1模型解读与使用

字节在春节前发布了doubao-1.5&#xff0c;它的官方介绍竟然是这样的&#xff1a; 这次发布了四个型号&#xff0c;doubao-1.5-pro-32k, doubao-1.5-pro-256k, doubao-1.5-lite-32k, doubao-1.5-vision-pro-32k&#xff0c;价格全部与上一个版本doubao模型一致&#xff0c;加量…...

Windows电脑不小心点击了关机,关机过程中如何阻止

如果电脑正在关机的过程中&#xff0c;想要阻止关机&#xff0c;可以尝试以下方法&#xff1a; 如果关机过程较慢&#xff0c;可以按下键盘组合键 Win R 打开运行窗口。输入 shutdown -a 后按回车键&#xff0c;这将中断关机操作&#xff08;适用于 Windows 系统&#xff09;…...

CNN-GRU卷积门控循环单元时间序列预测(Matlab完整源码和数据)

CNN-GRU卷积门控循环单元时间序列预测&#xff08;Matlab完整源码和数据&#xff09; 目录 CNN-GRU卷积门控循环单元时间序列预测&#xff08;Matlab完整源码和数据&#xff09;预测效果基本介绍CNN-GRU卷积门控循环单元时间序列预测一、引言1.1、研究背景与意义1.2、研究现状1…...