05-ArcGIS For JavaScript-RenderNode后处理效果

news2024/11/15 23:21:39

05-ArcGIS For JavaScript-RenderNode后处理效果

  • 综述
  • 代码解析
  • 代码实现
    • 颜色混合
      • 完整代码
      • 结果
      • 高亮处理
      • 完整代码
      • 结果
  • 结语

综述

ArcGIS For JavaScript 4.9版本提供了很多优秀的功能,其中提供了RenderNode类,既可以支持第三方渲染引擎的植入,例如webgl、threejs等三维引擎,同时也支持对当前场景中的渲染进行后处理操作。

ArcGIS官网中描述支持可实现的几种后处理操作:混合颜色、深度渲染、高亮及法线操作等后处理。

在这里插入图片描述
今天这里会简单描述下混合颜色和高亮的处理。

代码解析

const LuminanceRenderNode = RenderNode.createSubclass({
  consumes: { required: ["composite-color"] }
  produces: ["composite-color"]
  render(inputs) {
     // custom render code
  }
});

要实现后处理功能,需要通过RenderNode.createSubclass去创建渲染对象。其中主要包括了:

  • consumes: 声明渲染需要引擎的哪些输入。
  • produces: 定义呈现函数产生的输出。

例如,要请求composite-color和法线,函数consume()被指定如下:consume: {required: [“composite-color”, “normals”], optional: [“highlights”]}。

输出总是作为渲染函数的输入之一给出。例如,后处理渲染函数可以声明生成复合色输出: produces: “composite-color”。

代码实现

颜色混合

颜色混合需要做两点改动:

  • 初始化参数设置
	  this.consumes = { required: ["composite-color"] };
      this.produces = "composite-color";
  • shader代码修改,主要是对fragColor颜色值的修改。
            const vshader = `#version 300 es

                    in vec2 position;
                    out vec2 uv;

                    void main() {
                        gl_Position = vec4(position, 0.0, 1.0);
                        uv = position * 0.5 + vec2(0.5);
                    }`;

            // The fragment shader program applying a greyscsale conversion
            const fshader = `#version 300 es

                    precision highp float;
                    out lowp vec4 fragColor;

                    in vec2 uv;
                    uniform sampler2D colorTex;

                    void main() {
                        vec4 color = texture(colorTex, uv);
                        fragColor = vec4(vec3(dot(color.rgb, vec3(0.2126, 0.7152, 0.0722))), color.a);
                    }`;

完整代码

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
    <title>Custom RenderNode - Color modification | Sample | ArcGIS Maps SDK for JavaScript 4.30</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.30/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.30/"></script>
    <script type="module" src="https://js.arcgis.com/calcite-components/2.8.5/calcite.esm.js"></script>
    <link rel="stylesheet" type="text/css" href="https://js.arcgis.com/calcite-components/2.8.5/calcite.css" />

    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>
    <script>
      require(["esri/Map", "esri/views/SceneView", "esri/views/3d/webgl/RenderNode"], function (
        Map,
        SceneView,
        RenderNode
      ) {
        const view = new SceneView({
          container: "viewDiv",
          map: new Map({ basemap: "satellite" })
        });

        // Create and compile WebGL shader objects
        function createShader(gl, src, type) {
          const shader = gl.createShader(type);
          gl.shaderSource(shader, src);
          gl.compileShader(shader);
          return shader;
        }

        // Create and link WebGL program object
        function createProgram(gl, vsSource, fsSource) {
          const program = gl.createProgram();
          if (!program) {
            console.error("Failed to create program");
          }
          const vertexShader = createShader(gl, vsSource, gl.VERTEX_SHADER);
          const fragmentShader = createShader(gl, fsSource, gl.FRAGMENT_SHADER);
          gl.attachShader(program, vertexShader);
          gl.attachShader(program, fragmentShader);
          gl.linkProgram(program);
          const success = gl.getProgramParameter(program, gl.LINK_STATUS);
          if (!success) {
            // covenience console output to help debugging shader code
            console.error(`Failed to link program:
                      error ${gl.getError()},
                      info log: ${gl.getProgramInfoLog(program)},
                      vertex: ${gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)},
                      fragment: ${gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)}
                      vertex info log: ${gl.getShaderInfoLog(vertexShader)},
                      fragment info log: ${gl.getShaderInfoLog(fragmentShader)}`);
          }
          return program;
        }

        // Derive a new subclass from RenderNode called LuminanceRenderNode
        const LuminanceRenderNode = RenderNode.createSubclass({
          constructor: function () {
            // consumes and produces define the location of the the render node in the render pipeline
            this.consumes = { required: ["composite-color"] };
            this.produces = "composite-color";
          },
          // Ensure resources are cleaned up when render node is removed
          destroy() {
            if (this.program) {
              this.gl?.deleteProgram(this.program);
            }
            if (this.positionBuffer) {
              this.gl?.deleteBuffer(this.positionBuffer);
            }
            if (this.vao) {
              this.gl?.deleteVertexArray(this.vao);
            }
          },
          properties: {
            // Define getter and setter for class member enabled
            enabled: {
              get: function () {
                return this.produces != null;
              },
              set: function (value) {
                // Setting produces to null disables the render node
                this.produces = value ? "composite-color" : null;
                this.requestRender();
              }
            }
          },

          render(inputs) {
            // The field input contains all available framebuffer objects
            // We need color texture from the composite render target
            const input = inputs.find(({ name }) => name === "composite-color");
            const color = input.getTexture();

            // Acquire the composite framebuffer object, and bind framebuffer as current target
            const output = this.acquireOutputFramebuffer();

            const gl = this.gl;

            // Clear newly acquired framebuffer
            gl.clearColor(0, 0, 0, 1);
            gl.colorMask(true, true, true, true);
            gl.clear(gl.COLOR_BUFFER_BIT);

            // Prepare custom shaders and geometry for screenspace rendering
            this.ensureShader(this.gl);
            this.ensureScreenSpacePass(gl);

            // Bind custom program
            gl.useProgram(this.program);

            // Use composite-color render target to be modified in the shader
            gl.activeTexture(gl.TEXTURE0);
            gl.bindTexture(gl.TEXTURE_2D, color.glName);
            gl.uniform1i(this.textureUniformLocation, 0);

            // Issue the render call for a screen space render pass
            gl.bindVertexArray(this.vao);
            gl.drawArrays(gl.TRIANGLES, 0, 3);

            // use depth from input on output framebuffer
            output.attachDepth(input.getAttachment(gl.DEPTH_STENCIL_ATTACHMENT));
            return output;
          },

          program: null,
          textureUniformLocation: null,
          positionLocation: null,
          vao: null,
          positionBuffer: null,

          // Setup screen space filling triangle
          ensureScreenSpacePass(gl) {
            if (this.vao) {
              return;
            }

            this.vao = gl.createVertexArray();
            gl.bindVertexArray(this.vao);
            this.positionBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
            const vertices = new Float32Array([-1.0, -1.0, 3.0, -1.0, -1.0, 3.0]);
            gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

            gl.vertexAttribPointer(this.positionLocation, 2, gl.FLOAT, false, 0, 0);
            gl.enableVertexAttribArray(this.positionLocation);

            gl.bindVertexArray(null);
          },

          // Setup custom shader programs
          ensureShader(gl) {
            if (this.program != null) {
              return;
            }
            // The vertex shader program
            // Sets position from 0..1 for fragment shader
            // Forwards texture coordinates to fragment shader
            const vshader = `#version 300 es

                    in vec2 position;
                    out vec2 uv;

                    void main() {
                        gl_Position = vec4(position, 0.0, 1.0);
                        uv = position * 0.5 + vec2(0.5);
                    }`;

            // The fragment shader program applying a greyscsale conversion
            const fshader = `#version 300 es

                    precision highp float;
                    out lowp vec4 fragColor;

                    in vec2 uv;
                    uniform sampler2D colorTex;

                    void main() {
                        vec4 color = texture(colorTex, uv);
                        fragColor = vec4(vec3(dot(color.rgb, vec3(0.2126, 0.7152, 0.0722))), color.a);
                    }`;

            this.program = createProgram(gl, vshader, fshader);
            this.textureUniformLocation = gl.getUniformLocation(this.program, "colorTex");
            this.positionLocation = gl.getAttribLocation(this.program, "position");
          }
        });

        // Initializes the new custom render node and connects to SceneView
        const luminanceRenderNode = new LuminanceRenderNode({ view });

        // Toggle button to enable/disable the custom render node
        const renderNodeToggle = document.getElementById("renderNodeToggle");
        renderNodeToggle.addEventListener("calciteSwitchChange", () => {
          luminanceRenderNode.enabled = !luminanceRenderNode.enabled;
        });

        view.ui.add("renderNodeUI", "top-right");
      });
    </script>
  </head>
  <body>
    <calcite-block open heading="Toggle Render Node" id="renderNodeUI">
      <calcite-label layout="inline">
        Color
        <calcite-switch id="renderNodeToggle" checked> </calcite-switch>
        Grayscale
      </calcite-label>
    </calcite-block>
    <div id="viewDiv"></div>
  </body>
</html>

结果

在这里插入图片描述

高亮处理

高亮是设置其实和颜色混合差不多,只是需要在声明consumes的时候,设置optional: [“highlights”] 。

this.consumes = { required: ["composite-color"], optional: ["highlights"] };

完整代码

<html lang="en">

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
    <title>Custom RenderNode - Color modification | Sample | ArcGIS Maps SDK for JavaScript 4.30</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.30/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.30/"></script>
    <script type="module" src="https://js.arcgis.com/calcite-components/2.8.5/calcite.esm.js"></script>
    <link rel="stylesheet" type="text/css" href="https://js.arcgis.com/calcite-components/2.8.5/calcite.css" />

    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>
    <script>
        require(["esri/Map",
            "esri/views/SceneView",
            "esri/views/3d/webgl/RenderNode",
            "esri/layers/SceneLayer"], function (
                Map,
                SceneView,
                RenderNode,
                SceneLayer
            ) {

            const layer = new SceneLayer({
                url:'https://tiles.arcgis.com/tiles/V6ZHFr6zdgNZuVG0/arcgis/rest/services/campus_buildings/SceneServer'
                // url: "https://tiles.arcgis.com/tiles/z2tnIkrLQ2BRzr6P/arcgis/rest/services/SanFrancisco_Bldgs/SceneServer",
                // outFields:["NAME",""]
            });

            const view = new SceneView({
                container: "viewDiv",
                map: new Map({ basemap: "satellite", 
                // ground: "world-elevation" 
            }),
                highlightOptions: {
                    haloColor: [255, 38, 150],
                    color: [255, 255, 255],
                    fillOpacity: 0.3
                }
            });

            view.map.add(layer);
            view.popupEnabled = false;
            let layerView = null;
            let highlight = null;

            view.when(function () {
                view.extent = layer.fullExtent;

                view.whenLayerView(layer).then((_layerView) => {
                    layerView = _layerView;
                })
            })



            view.on('click', function (event) {
                view.hitTest(event).then(function (response) {
                    let result = response.results[0];
                    if(result == undefined){
                        if(highlight){
                            highlight.remove();
                            highlight = null;
                        }
                        return;
                    }
                    // let objectId = result.graphic.attributes.OBJECTID;
                    let objectId = result.graphic.attributes.OID;

                    if (highlight) {
                        highlight.remove();
                        highlight = null;
                    }
                    // highlight the feature with the returned objectId
                    highlight = layerView.highlight([objectId]);
                })

            })

            // Create and compile WebGL shader objects
            function createShader(gl, src, type) {
                const shader = gl.createShader(type);
                gl.shaderSource(shader, src);
                gl.compileShader(shader);
                return shader;
            }

            // Create and link WebGL program object
            function createProgram(gl, vsSource, fsSource) {
                const program = gl.createProgram();
                if (!program) {
                    console.error("Failed to create program");
                }
                const vertexShader = createShader(gl, vsSource, gl.VERTEX_SHADER);
                const fragmentShader = createShader(gl, fsSource, gl.FRAGMENT_SHADER);
                gl.attachShader(program, vertexShader);
                gl.attachShader(program, fragmentShader);
                gl.linkProgram(program);
                const success = gl.getProgramParameter(program, gl.LINK_STATUS);
                if (!success) {
                    // covenience console output to help debugging shader code
                    console.error(`Failed to link program:
                      error ${gl.getError()},
                      info log: ${gl.getProgramInfoLog(program)},
                      vertex: ${gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)},
                      fragment: ${gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)}
                      vertex info log: ${gl.getShaderInfoLog(vertexShader)},
                      fragment info log: ${gl.getShaderInfoLog(fragmentShader)}`);
                }
                return program;
            }

            // Derive a new subclass from RenderNode called LuminanceRenderNode
            const LuminanceRenderNode = RenderNode.createSubclass({
                constructor: function () {
                    // consumes and produces define the location of the the render node in the render pipeline
                    this.consumes = { required: ["composite-color"], optional: ["highlights"] };
                    this.produces = "composite-color";
                },
                // Ensure resources are cleaned up when render node is removed
                destroy() {
                    if (this.program) {
                        this.gl?.deleteProgram(this.program);
                    }
                    if (this.positionBuffer) {
                        this.gl?.deleteBuffer(this.positionBuffer);
                    }
                    if (this.vao) {
                        this.gl?.deleteVertexArray(this.vao);
                    }
                },
                properties: {
                    // Define getter and setter for class member enabled
                    enabled: {
                        get: function () {
                            return this.produces != null;
                        },
                        set: function (value) {
                            // Setting produces to null disables the render node
                            this.produces = value ? "composite-color" : null;
                            this.requestRender();
                        }
                    }
                },

                render(inputs) {
                    // The field input contains all available framebuffer objects
                    // We need color texture from the composite render target
                    const input = inputs.find(({ name }) =>
                        name === "composite-color"
                    );

                    const input1 = inputs.find(({ name }) =>
                        name === "highlights"
                    );

                    if (input1 == undefined) {
                        return;
                    }

                    // const color = input1.getTexture();

                    // Acquire the composite framebuffer object, and bind framebuffer as current target
                    const output = this.acquireOutputFramebuffer();

                    const gl = this.gl;

                    // Clear newly acquired framebuffer
                    gl.clearColor(0, 0, 0, 1);
                    gl.colorMask(true, true, true, true);
                    gl.clear(gl.COLOR_BUFFER_BIT);

                    // Prepare custom shaders and geometry for screenspace rendering
                    this.ensureShader(this.gl);
                    this.ensureScreenSpacePass(gl);

                    // Bind custom program
                    gl.useProgram(this.program);

                    gl.activeTexture(gl.TEXTURE0);
                    gl.bindTexture(gl.TEXTURE_2D, input?.getTexture().glName);
                    gl.uniform1i(this.textureUniformLocation, 0);

                    // Use composite-color render target to be modified in the shader
                    gl.activeTexture(gl.TEXTURE1);
                    gl.bindTexture(gl.TEXTURE_2D, input1?.getTexture().glName);
                    gl.uniform1i(this.textureUniformLocation, 1);

             

                    // Issue the render call for a screen space render pass
                    gl.bindVertexArray(this.vao);
                    gl.drawArrays(gl.TRIANGLES, 0, 3);

                    // use depth from input on output framebuffer
                    output.attachDepth(input.getAttachment(gl.DEPTH_STENCIL_ATTACHMENT));
                    return output;
                },

                program: null,
                textureUniformLocation: null,
                positionLocation: null,
                vao: null,
                positionBuffer: null,

                // Setup screen space filling triangle
                ensureScreenSpacePass(gl) {
                    if (this.vao) {
                        return;
                    }

                    this.vao = gl.createVertexArray();
                    gl.bindVertexArray(this.vao);
                    this.positionBuffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
                    const vertices = new Float32Array([-1.0, -1.0, 3.0, -1.0, -1.0, 3.0]);
                    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

                    gl.vertexAttribPointer(this.positionLocation, 2, gl.FLOAT, false, 0, 0);
                    gl.enableVertexAttribArray(this.positionLocation);

                    gl.bindVertexArray(null);
                },

                // Setup custom shader programs
                ensureShader(gl) {
                    if (this.program != null) {
                        return;
                    }
                    // The vertex shader program
                    // Sets position from 0..1 for fragment shader
                    // Forwards texture coordinates to fragment shader
                    const vshader = `#version 300 es

                    in vec2 position;
                    out vec2 uv;

                    void main() {
                        gl_Position = vec4(position, 0.0, 1.0);
                        uv = position * 0.5 + vec2(0.5);
                    }`;

                    // The fragment shader program applying a greyscsale conversion
                    const fshader = `#version 300 es

                    precision highp float;
                    out lowp vec4 fragColor;

                    in vec2 uv;
                    uniform sampler2D colorTex;

                    void main() {
                        vec4 color = texture(colorTex, uv);
                        fragColor = vec4(color);
                        // fragColor = vec4(vec3(dot(color.rgb, vec3(0.2126, 0.7152, 0.0722))), color.a);
                    }`;

                    this.program = createProgram(gl, vshader, fshader);
                    this.textureUniformLocation = gl.getUniformLocation(this.program, "colorTex");
                    this.positionLocation = gl.getAttribLocation(this.program, "position");
                }
            });

            // Initializes the new custom render node and connects to SceneView
            const luminanceRenderNode = new LuminanceRenderNode({ view });

            // Toggle button to enable/disable the custom render node
            const renderNodeToggle = document.getElementById("renderNodeToggle");
            renderNodeToggle.addEventListener("calciteSwitchChange", () => {
                luminanceRenderNode.enabled = !luminanceRenderNode.enabled;
            });

            view.ui.add("renderNodeUI", "top-right");
        });
    </script>
</head>

<body>
    <calcite-block open heading="Toggle Render Node" id="renderNodeUI">
        <calcite-label layout="inline">
            Color
            <calcite-switch id="renderNodeToggle" checked> </calcite-switch>
            Grayscale
        </calcite-label>
    </calcite-block>
    <div id="viewDiv"></div>
</body>

</html>

结果

在这里插入图片描述

结语

对于ArcGIS来说,后处理为Web开发提供了更多的可能性。但是这里对于opengl和shader的要求会比较高,所以需要更多的技术储备,才能更好的去实现后处理的开发。

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

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

相关文章

PowerShell报错 about_Execution_Policies 解决方法

在用express创建项目中显示项目创建失败&#xff0c;报错如图所示&#xff0c;显示无法加载文件&#xff0c;按照提示地址https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies看到页面显示是PowerShell执行策略的问题。有问题评论区留言&#xff0c;…

前端构建工具Vite

前端主流框架Vue大家应该都耳熟能详&#xff0c;很多的公司和项目都在使用&#xff0c;以前前端构建工具用的比较多的是webpack&#xff0c;后面渐渐地出现了Vite&#xff0c;它受到大家的喜爱和使用&#xff0c;那大家是否也很想知道它的由来以及优势&#xff0c;为什么越来越…

用户提交订单业务

文章目录 概要整体架构流程技术细节小结 概要 我们通常指的是在电子商务或在线零售环境中&#xff0c;顾客通过互联网完成商品或服务购买的过程。随着互联网技术的发展和普及&#xff0c;越来越多的消费者选择在线购物&#xff0c;这不仅因为其便捷性&#xff0c;还因为它提供…

Linux网络-小结

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注我&#xff0c;我尽量把自己会的都分享给大家&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 Linux服务器作为一个常用的网络服务器&#xff0c;主要的作用就是向客户端提供网络…

MySQL基础练习题14-产品销售分析1

题目&#xff1a;获取 Sales 表中所有 sale_id 对应的 product_name 以及该产品的所有 year 和 price 。 准备数据 分析数据 题目&#xff1a;获取 Sales 表中所有 sale_id 对应的 product_name 以及该产品的所有 year 和 price 。 准备数据 ## 创建库 create database db;…

实战:深入了解JDBC和分享JDBCUtil

Java 数据库连接 (JDBC) 是一个功能强大的 API&#xff0c;它弥补了 Java 应用程序与关系数据库之间的差距。通过利用 JDBC&#xff0c;您可以无缝地与数据库交互以存储、检索和操作数据。但是&#xff0c;要有效使用 JDBC&#xff0c;需要遵循最佳实践&#xff0c;以确保代码的…

GitHub Revert Merge Commit的现象观察和对PR的思考

文章目录 前言Pull Request 为什么会是这样&#xff1f;Pull Request Branch的差异 ?Two Dot Diff和Three Dot Diff 老生常谈&#xff1a; Merge 和 Rebasegit mergegit rebase Revert Main分支中的一个Merge Commit现象描述解决方案: Revert Feature分支中的一个Merge Commi…

RocketMQ入门到精通

RocketMQ入门到精通 一、介绍1.对比2.基础概念 二、环境搭建1.下载rocket2.新增系统变量&#xff1a;ROCKETMQ_HOME3.启动命名服务 nameserver4.启动broker服务器5.安装可视面板6.手动创建Topic7.手动创建消费者组 三、使用Springboot实现消息的收发1.引入jar包2.配置yml文件3.…

【Python机器学习】朴素贝叶斯——使用朴素贝叶斯过滤垃圾邮件

使用朴素贝叶斯解决一些现实生活中的问题时&#xff0c;需要先从文本内容中得到字符串列表&#xff0c;然后生成词向量。 使用朴素贝叶斯对电子邮件进行分类的过程&#xff1a; 1、收集数据&#xff1a;提供文本文件 2、准备数据&#xff1a;将文本文件解析成词条向量 3、分析…

推荐5款好用的将pdf翻译成中文的工具。

像word&#xff0c;PPT,Excel等这些文档如果要翻译的话&#xff0c;即使没有合适的工具也可以复制粘贴内容。可PDF有的时候是不可以编辑的&#xff0c;很难用这种方法实现翻译。但是这5款翻译工具就可以做到直接将PDF文件进行翻译。 1、365pdf在线翻译 直达&#xff1a;https:…

力扣Hot100-543二叉树的直径

给你一棵二叉树的根节点&#xff0c;返回该树的 直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的 长度 由它们之间边数表示。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,4,5] 输出&a…

零基础入门转录组数据分析——机器学习算法之lasso(筛选特征基因)

零基础入门转录组数据分析——机器学习算法之lasso&#xff08;筛选特征基因&#xff09; 目录 零基础入门转录组数据分析——机器学习算法之lasso&#xff08;筛选特征基因&#xff09;1. Lasso基础知识2. Lasso&#xff08;Rstudio&#xff09;——代码实操2. 1 数据处理2. 2…

结构体的引入

结构体也是一种数据组合&#xff0c;它和数组的区别是&#xff0c;数组的元素类型是一样的数据集合体&#xff0c;如果元素类型不一样&#xff0c;就要用到结构体了 下面定义一个学生结构体 struct Student {int num;char name[32];int age;double score;char addr[32]; }; …

谷粒商城实战笔记-88~91-商品发布保存

文章目录 一&#xff0c;基本信息二&#xff0c;规格参数三&#xff0c;销售属性四&#xff0c;SKU信息五&#xff0c;代码分析1&#xff0c;Spu信息的保存2&#xff0c;Sku信息的保存 这一篇包含三节内容&#xff1a; 88-商品服务-API-新增商品-保存SPU基本信息89-商品服务-AP…

Redis缓存穿透、击穿和雪崩的理解和解决思路

Redis的缓存穿透 缓存穿透是指那些查询请求所要获取的数据既不在缓存&#xff08;Redis&#xff09;中&#xff0c;也不在数据库&#xff08;例如&#xff1a;MySQL&#xff09;中&#xff0c;因此每次请求都会直接访问数据库。这种情况通常由以下几种情形引起&#xff1a; 恶…

C++:类进阶之继承与派生

一、基本概念&#xff1a;继承、基类、派生类 继承&#xff1a;在定义一个新的类B时&#xff0c;如果该类与某个已有的类A相似 (指的是B拥有A的全部特点)&#xff0c;那么就可以把A作为一个基类&#xff0c;而把B作为基类的一个派生类 (也称子类)。 派生类&#xff1a;通过对…

微前端技术预研 - bit初体验

1.关于什么是微前端以及微前端的发展&#xff0c; 当前主流框架以及实现技术等&#xff0c;可参考这篇总结(非常全面)&#xff0c; 微前端总结&#xff1a;目录详见下图 本文内容主要针对bit框架的实时思路以及具体使用。 1.什么是Bit? &#xfeff;Bit 是可组合软件的构建…

《C语言实现各种排序算法》

文章目录 一、排序1、排序的各种方式分类 二、插入排序1、直接插入排序2、希尔排序3、希尔排序时间复杂度分析 三、选择排序1、直接选择排序2、堆排序 四、交换排序1、冒泡排序2、快速排序3、快速排序hoare找基准值4、快排挖坑法找基准值5、前后指针法6、快速排序非递归实现 五…

甄选范文“论数据分片技术及其应用”软考高级论文,系统架构设计师论文

论文真题 数据分片就是按照一定的规则,将数据集划分成相互独立、正交的数据子集,然后将数据子集分布到不同的节点上。通过设计合理的数据分片规则,可将系统中的数据分布在不同的物理数据库中,达到提升应用系统数据处理速度的目的。 请围绕“论数据分片技术及其应用”论题…