【WebGis开发 - Cesium】三维可视化项目教程---图层管理基础

news2024/12/26 21:06:29

目录

  • 引言
  • 一、功能设计
    • 1. 主体功能
    • 2. 细节问题
  • 二、代码实现
    • 1. 树形控件
    • 2. 全局状态准备
    • 3. 创建图层控制方法
      • 3.1 加载、卸载方法编写
      • 3.2 统一对外暴露入口
      • 3.3 提供图层类别的可拓展性
      • 3.1 完整代码
    • 4. 效果展示
    • 5. hooks函数使用方法
  • 三、总结

引言

本教程主要是围绕Cesium这一开源三维框架开展的可视化项目教程。总结一下相关从业经验,如果有什么疑问或更好的见解,欢迎评论、私聊探讨,共同进步。

本篇主要讨论如何管理二三维图层,仅以wmts和3dtiles做图层管理示例。我会在接下来的教程里专门针对其他各类图层加载方式做详细介绍。

二三维图层管理是三维可视化项目里重要的组成部分,通过树结构管理图层,根据模块设计加载对应二三维数据。


一、功能设计

1. 主体功能

  1. 设计图层数据结构,使用任意树形结构插件或是自行开发图层树。
  2. 编写图层分类加载、卸载方法,暴露统一接口,配合图层数据进行图层操作。
  3. 存储数据至全局状态,方便管理。

2. 细节问题

图层数据大致上可以分为二维图层和三维图层

在三维引擎中针对这两者的表达方式有所不同

  • 二维图层没有高度,按照加载先后顺序重叠在一起。如果内容存在遮挡,则只显示最后加载的图层。(好比一摞画册)
  • 三维图层具备高度,没有加载先后顺序重叠遮挡一说,只会根据三维模型的实际物理尺寸决定遮挡关系。
  • 所以在开发图层树的时候,要注意区分二三维图层。

二、代码实现

1. 树形控件

树形控件采用 element-plus 组件库的 tree 组件。细节查阅:Tree 树形控件

几个需要注意的点:

  • 根据需求设置 check-on-click-node ,我希望不论点击选择框或是点击树节点内容,都可以触发选中节点。
  • 根据需求设置 :expand-on-click-node="false" ,我不希望在点击包含有子节点的节点时,一边加载子节点图层内容,一边把树折叠起来。或是反过来卸载子节点图层内容,同时把树伸展开。
  • 点击事件我选择 check-change ,只有这一个点击事件返回的数据符合我的需求。根据不同的设计理念,可以查阅组件库文档,选择适合自己项目的点选事件。
  • 图层管理核心在图层加载、卸载和全局数据管理,图层树可以根据自己喜好选择任意UI框架的树形结构,或是自行开发。满足展示树形图层以及选中、取消功能即可。

html部分

    <div class="layerManager">
      <div>图层管理</div>
      <el-tree
        :data="dataSource"
        show-checkbox
        node-key="id"
        default-expand-all
        check-on-click-node
        @check-change="checkChange"
        :expand-on-click-node="false"
      >
      </el-tree>
    </div>

数据部分

二维数据使用天地图影像、矢量、注记三种。三维数据使用本地3dtiles数据(有在线数据替换一下)。
天地图wmts图层引用示例可以参考:天地图服务 ,在页面最下方有请求示例。
在这里插入图片描述

树节点数据主要包含几个内容

  • 只有叶子节点存在url属性,实际控制图层的加载、卸载。其父级节点只作为文件夹管理功能,不实际控制图层。
  • type属性,表面当前图层属于哪种类型,根据类型分类后,调用指定方法加载、卸载图层。
  • id属性,值必须唯一。用于检索全局状态中存储的图层重要信息。
  • label属性,图层树显示名称。
const dataSource = ref([
  {
    id: "1",
    label: "二维地图",
    children: [
      {
        id: "1-1",
        label: "天地图影像",
        type: "wmts",
        url: "https://t0.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=你申请的天地图key",
      },
      {
        id: "1-2",
        label: "天地图矢量",
        type: "wmts",
        url: "https://t0.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=你申请的天地图key",
      },
      {
        id: "1-3",
        label: "天地图矢量注记",
        type: "wmts",
        url: "https://t0.tianditu.gov.cn/cva_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cva&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=你申请的天地图key",
      },
    ],
  },
  {
    id: "2",
    label: "三维地图",
    children: [
      {
        id: "2-1",
        label: "测试3dtiles模型",
        type: "3dtiles",
        // 我这里准备一份本地3dtiles数据在 `public/3dtiles/` 目录下
        url: "/3dtiles/test/tileset.json",
      },
    ],
  },
]);

2. 全局状态准备

使用 pinia 来管理全局状态

pinia的安装引入操作不过多赘述,自行查阅。

src/stores/ 目录下创建文件 layer.js

根据cesium提供的加载图层方法,可以发现

  • 常规二维图层都是以 imageryLayers 形式存储在全局变量 viewerimageryLayers 属性中。
  • 3dtiles图层是以 primitive 形式存储在 viewer.sceneprimitives 属性中。

所以我们创建两个全局状态数组 imageryLayersprimitiveLayers ,分别存储二维图层和三维图层。同时对应创建添加和查询两个action方法,用于保存和查询图层的重要信息(不需要把所有信息都存起来,只要存储特征值可以确保能在viewer中查询到对应图层即可)

import { defineStore } from "pinia";
export const useLayerStore = defineStore("LayerStore", {
  state: () => ({ imageryLayers: [], primitiveLayers: [] }),
  actions: {
    addImageryLayer(data) {
      this.imageryLayers.push(data);
    },
    getImageryLayer(id) {
      return this.imageryLayers.find((item) => item.id === id);
    },
    addPrimitiveLayer(data) {
      this.primitiveLayers.push(data);
    },
    getPrimitiveLayer(id) {
      return this.primitiveLayers.find((item) => item.id === id);
    },
  },
});

3. 创建图层控制方法

出于功能的可复用性考虑,将图层管理的方法封装为hooks函数

主要包含几个内容:

  1. 编写各类图层的加载和卸载方法。
  2. 集成加载和卸载的入口方法,对外暴露行为统一。
  3. 提供hooks函数的可拓展性。

3.1 加载、卸载方法编写

这里不深究对应图层加载api的使用方法,我会在之后的文章里详细介绍各图层加载方法的api使用方法以及常用属性填写。
描述一下我的编写逻辑:

  1. 加载方法
    • 先通过树节点 id 到全局状态中查询图层信息是否已经存在。
    • 如果已经加载过了,就通过保存的特殊标识查询到对应图层数据,将 show 属性改写为 true 即可。
    • 如果没有加载过,则调用对应api加载图层,加载完成后返回对应图层数据。
    • 创建图层特殊标识,用于查询到指定图层,将特殊标识添加到返回图层数据的自定义属性中,我这里设置的是layerId,确保标识值唯一。
    • layerId 以及树节点信息保存至全局状态中。
  2. 卸载方法
    • 先通过树节点 id 到全局状态中查询图层信息是否已经存在。
    • 如果存在,就通过保存的特殊标识查询到对应图层数据,将 show 属性改写为 false 即可。
    • 不存在则不进行操作。
  import { useLayerStore } from "@/stores/layer.js";
  import { GenerateId } from "@/utils/cesium/common.js";
  const layerStore = useLayerStore();
  /**
   * @description: 添加wmts图层
   * @param {*} data
   * @return {*}
   */
  const addWmtsLayer = (data) => {
    // 先查询是否已经加载图层
    const layerData = layerStore.getImageryLayer(data.id);
    // 存在图层数据直接显示图层, 并返回
    if (layerData) {
      const layer = viewer.imageryLayers._layers.find(
        (item) => item.layerId === layerData.layerId
      );
      layer.show = true;
      layerData.show = true;
      return;
    }
    // 不存在图层数据则重新加载图层
    const imageMap = new Cesium.WebMapTileServiceImageryProvider({
      url: data.url
    });
    // 添加图层
    const layer = viewer.imageryLayers.addImageryProvider(imageMap);
    // 添加图层标识
    layer.layerId = GenerateId(18);
    // 向全局状态输入图层数据
    layerStore.addImageryLayer({ ...data, show: true, layerId: layer.layerId });
  };
  /**
   * @description: 移除wmts图层
   * @param {*} data
   * @return {*}
   */
  const removeWmtsLayer = (data) => {
    const layerData = layerStore.getImageryLayer(data.id);
    if (layerData) {
      //  获取图层数据并设置显示为false
      const layer = viewer.imageryLayers._layers.find(
        (item) => item.layerId === layerData.layerId
      );
      layer.show = false;
      layerData.show = false;
    }
  };
  /**
   * @description: 添加3dtiles图层
   * @param {*} data
   * @return {*}
   */
  const add3dtilesLayer = async (data) => {
    // 先查询是否已经加载图层
    const layerData = layerStore.getPrimitiveLayer(data.id);
    // 存在图层数据直接显示图层, 并返回
    if (layerData) {
      const layer = viewer.scene.primitives._primitives.find(
        (item) => item.layerId === layerData.layerId
      );
      layer.show = true;
      layerData.show = true;
      return;
    }
    const tileset = await Cesium.Cesium3DTileset.fromUrl(data.url);
    // 添加图层标识
    tileset.layerId = GenerateId(18);
    viewer.scene.primitives.add(tileset);
    // 向全局状态输入图层数据
    layerStore.addPrimitiveLayer({
      ...data,
      show: true,
      layerId: tileset.layerId,
    });
    viewer.flyTo(tileset);
  };
  /**
   * @description: 移除3dtiles图层
   * @param {*} data
   * @return {*}
   */
  const remove3dtilesLayer = (data) => {
    const layerData = layerStore.getPrimitiveLayer(data.id);
    if (layerData) {
      const layer = viewer.scene.primitives._primitives.find(
        (item) => item.layerId === layerData.layerId
      );
      layer.show = false;
      layerData.show = false;
    }
  };

3.2 统一对外暴露入口

继续在3.1编写的hooks函数内添加子方法及变量。

将不同类型的方法按照加载和卸载分为两类,以图层类别和方法作为 键值对 存储起来。
编写统一加载、卸载入口,通过图层类别去选择指定方法对图层进行加载和卸载操作。

  /**
   * @description: 添加图层方法map,用于存储不同图层加载方法
   * @return {*}
   */
  const addLayerFunctions = {
    "wmts": addWmtsLayer,
    "3dtiles": add3dtilesLayer,
    // 其他类型对应的类别和方法
    // ...
  };
  /**
   * @description: 移除图层方法map,用于存储不同图层卸载方法
   * @return {*}
   */
  const removeLayerFunctions = {
    "wmts": removeWmtsLayer,
    "3dtiles": remove3dtilesLayer,
    // 其他类型对应的类别和方法
    // ...
  };

  /**
   * @description: 添加图层入口函数,根据图层类型,分配对应加载函数
   * @param {*} data
   * @return {*}
   */
  const addLayer = (data) => {
    return addLayerFunctions[data.type](data);
  };
  /**
   * @description: 移除图层入口函数,根据图层类型,分配对应卸载函数
   * @param {*} data
   * @return {*}
   */
  const removeLayer = (data) => {
    return removeLayerFunctions[data.type](data);
  };

3.3 提供图层类别的可拓展性

继续在3.1编写的hooks函数内添加子方法及变量。

提供查询和注入两个方法

  • 通过查询方法获取已经支持的图层类别。
  • 通过注入方法,可以自定义类别和加载、卸载方法,将自定义内容按照统一格式注入 addLayerFunctionsremoveLayerFunctions

这样做的好处是保证了hooks函数的封闭性同时可拓展,遵循了封装函数的开闭原则。

  /**
   * @description: 获取已有的图层加载类型
   * @return {*}
   */
  const getAvialableLayerTypes = () => {
    return Object.keys(addLayerFunctions);
  };
  /**
   * @description: 手动添加特殊图层加载、卸载方法以及图层类别
   * @param {*} type
   * @param {*} addFunc
   * @param {*} removeFunc
   * @return {*}
   */
  const addLayerType = (type, addFunc, removeFunc) => {
    if (addLayerFunctions[type]) {
      console.warn("图层方法已存在: " + type);
      return;
    }
    addLayerFunctions[type] = addFunc;
    removeLayerFunctions[type] = removeFunc;
  };

3.1 完整代码

import { useLayerStore } from "@/stores/layer.js";
import { GenerateId } from "@/utils/cesium/common.js";
export const useLayerManager = () => {
  const layerStore = useLayerStore();
  /**
   * @description: 添加wmts图层
   * @param {*} data
   * @return {*}
   */
  const addWmtsLayer = (data) => {
    // 先查询是否已经加载图层
    const layerData = layerStore.getImageryLayer(data.id);
    // 存在图层数据直接显示图层, 并返回
    if (layerData) {
      const layer = viewer.imageryLayers._layers.find(
        (item) => item.layerId === layerData.layerId
      );
      layer.show = true;
      layerData.show = true;
      return;
    }
    // 不存在图层数据则重新加载图层
    const imageMap = new Cesium.WebMapTileServiceImageryProvider({
      url: data.url
    });
    // 添加图层
    const layer = viewer.imageryLayers.addImageryProvider(imageMap);
    layer.layerId = GenerateId(18);
    // 向全局状态输入图层数据
    layerStore.addImageryLayer({ ...data, show: true, layerId: layer.layerId });
  };
  /**
   * @description: 移除wmts图层
   * @param {*} data
   * @return {*}
   */
  const removeWmtsLayer = (data) => {
    const layerData = layerStore.getImageryLayer(data.id);
    if (layerData) {
      //  获取图层数据并设置显示为false
      const layer = viewer.imageryLayers._layers.find(
        (item) => item.layerId === layerData.layerId
      );
      layer.show = false;
      layerData.show = false;
    }
  };
  /**
   * @description: 添加3dtiles图层
   * @param {*} data
   * @return {*}
   */
  const add3dtilesLayer = async (data) => {
    // 先查询是否已经加载图层
    const layerData = layerStore.getPrimitiveLayer(data.id);
    // 存在图层数据直接显示图层, 并返回
    if (layerData) {
      //  获取图层数据并设置显示为false
      const layer = viewer.scene.primitives._primitives.find(
        (item) => item.layerId === layerData.layerId
      );
      layer.show = true;
      layerData.show = true;
      return;
    }
    const tileset = await Cesium.Cesium3DTileset.fromUrl(data.url);
    // 添加标识
    tileset.layerId = GenerateId(18);
    viewer.scene.primitives.add(tileset);
    // 向全局状态输入图层数据
    layerStore.addPrimitiveLayer({
      ...data,
      show: true,
      layerId: tileset.layerId,
    });
    viewer.flyTo(tileset);
  };
  /**
   * @description: 移除3dtiles图层
   * @param {*} data
   * @return {*}
   */
  const remove3dtilesLayer = (data) => {
    const layerData = layerStore.getPrimitiveLayer(data.id);
    if (layerData) {
      const layer = viewer.scene.primitives._primitives.find(
        (item) => item.layerId === layerData.layerId
      );
      layer.show = false;
      layerData.show = false;
    }
  };
  /**
   * @description: 添加图层方法map,用于存储不同图层加载方法
   * @return {*}
   */
  const addLayerFunctions = {
    "wmts": addWmtsLayer,
    "3dtiles": add3dtilesLayer,
  };
  /**
   * @description: 移除图层方法map,用于存储不同图层卸载方法
   * @return {*}
   */
  const removeLayerFunctions = {
    "wmts": removeWmtsLayer,
    "3dtiles": remove3dtilesLayer,
  };

  /**
   * @description: 添加图层入口函数,根据图层类型,分配对应加载函数
   * @param {*} data
   * @return {*}
   */
  const addLayer = (data) => {
    return addLayerFunctions[data.type](data);
  };
  /**
   * @description: 移除图层入口函数,根据图层类型,分配对应卸载函数
   * @param {*} data
   * @return {*}
   */
  const removeLayer = (data) => {
    return removeLayerFunctions[data.type](data);
  };
  /**
   * @description: 获取已有的图层加载类型
   * @return {*}
   */
  const getAvialableLayerTypes = () => {
    return Object.keys(addLayerFunctions);
  };
  /**
   * @description: 手动添加特殊图层加载、卸载方法以及图层类别
   * @param {*} type
   * @param {*} addFunc
   * @param {*} removeFunc
   * @return {*}
   */
  const addLayerType = (type, addFunc, removeFunc) => {
    if (addLayerFunctions[type]) {
      console.warn("图层方法已存在: " + type);
      return;
    }
    addLayerFunctions[type] = addFunc;
    removeLayerFunctions[type] = removeFunc;
  };

  return {
    addLayer,
    removeLayer,
    getAvialableLayerTypes,
    addLayerType,
  };
};

4. 效果展示

在这里插入图片描述

5. hooks函数使用方法

<template>
  <div id="mapContainer">
    <div class="layermanager">
      <div>图层管理</div>
      <el-tree
        :data="dataSource"
        show-checkbox
        node-key="id"
        default-expand-all
        check-on-click-node
        @check-change="checkChange"
        :expand-on-click-node="false"
      >
      </el-tree>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from "vue";
import { initCesiumMap } from "@/utils/cesium/index.js";
import { useLayerManager } from "@/hooks/useLayerManager.js";
const dataSource = ref([
  {
    id: "1",
    label: "二维地图",
    children: [
      {
        id: "1-1",
        label: "天地图影像",
        type: "wmts",
        url: "https://t0.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=你申请的key",
      },
      {
        id: "1-2",
        label: "天地图矢量",
        type: "wmts",
        url: "https://t0.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=vec&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=你申请的key",
      },
      {
        id: "1-3",
        label: "天地图矢量注记",
        type: "wmts",
        url: "https://t0.tianditu.gov.cn/cva_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cva&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=你申请的key",
      },
    ],
  },
  {
    id: "2",
    label: "三维地图",
    children: [
      {
        id: "2-1",
        label: "测试3dtiles模型",
        type: "3dtiles",
        url: "/3dtiles/test/tileset.json",
      },
    ],
  },
]);

const { addLayer, removeLayer} = useLayerManager();
onMounted(() => {
  initCesiumMap();
});
const checkChange = (data, isCheck) => {
  // 判断是否为叶子节点
  if (data?.children && data?.children?.length > 0) {
    console.log("非子叶节点");
    return;
  } else {
    if (isCheck) {
      addLayer(data);
    } else {
      removeLayer(data);
    }
  }
};
</script>


三、总结

至此图层管理的基础实现脉络已经梳理完毕,但是这些还远远不够,我们仍需关心以下几个问题:

  • 二维图层的互相遮挡问题,需要拓展图层调换顺序功能。
  • 图层叠加使用场景,需要拓展图层透明度调整功能。
  • 当前场景下图层保存功能,用于场景切换时,关闭及初始化图层树。
  • 拓展其他重要图层类型的加载卸载方式。
  • 其他。

所以说一个完整的模块是亿点点优化而来的。由于篇幅问题,遗留的几个问题我将会在之后的文章中逐步闭环。

再接再厉~

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

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

相关文章

华为云服务器公网ip访问不通解决

问题&#xff1a;用弹性公网IP登录超时&#xff0c;ping不通&#xff0c;但是VNC方式可以登陆成功 解决&#xff1a;执行ifconfig&#xff0c;看到eth0网卡没有获取到 ifconfig 执行dhclient自动获取下网卡 &#xff1a; dhclient 再次执行ifconfig&#xff1a;网卡已经获…

【AI论文精读3】RAG论文综述1-P1

AI知识点总结&#xff1a;【AI知识点】 AI论文精读、项目、思考&#xff1a;【AI修炼之路】 简介 论文中英文名 Retrieval-Augmented Generation for Large Language Models: A Survey 面向大型语言模型的检索增强生成&#xff1a;综述 论文地址 arxiv地址&#xff1a;http…

知识蒸馏介绍

一、知识蒸馏介绍 1.1 概念介绍 知识蒸馏&#xff08;knowledge distillation&#xff09;是模型压缩的一种常用的方法&#xff0c;不同于模型压缩中的剪枝和量化&#xff0c;知识蒸馏是通过构建一个轻量化的小模型&#xff0c;利用性能更好的大模型的监督信息&#xff0c;来…

项目经理是怎么慢慢废掉的?这些无意识行为可能会毁了你!

工作久了&#xff0c;每个人都或多或少会有一些无力感和疲惫感。如果没有调整过来&#xff0c;久而久之&#xff0c;会感觉自己好像废掉了&#xff0c;做什么事情都打不起精神。 如果你是项目经理&#xff0c;工作中有这样一些迹象&#xff0c;比如总是拖延时间、丧失自己的判…

【进程间通信(三)】【system V共享内存】

目录 1. 原理2. 编码通信2.1 创建共享内存2.2 shmat && shmdt && shmctl2.3 通信 3. 共享内存的特性3.1 共享内存的属性3.2 加入管道实现同步机制 前面的文章介绍了管道通信&#xff0c;其中包括匿名管道、命名管道。这篇文章介绍另一种进程间通信的方式 -----…

NVP的含义?如何理解其在AEM|FLUKE线缆认证测试中的意义?不同的NVP会出现怎样的结果?

在AEM|FLUKE铜缆认证测试中&#xff0c;有很多朋友对NVP设置有疑问&#xff0c;不知道应该怎么去设置它&#xff0c;并很好的应用它&#xff0c;那我们基于此&#xff0c;做一个简单的分析。 什么是NVP? NVP是Nominal Velocity of Propagation的缩写&#xff1f;简单直接译过…

Java基础-泛型机制

文章目录 为什么引入泛型泛型的基本使用泛型类泛型接口泛型方法泛型数组正确的数组声明使用场景如何理解Java中的泛型是伪泛型&#xff1f;泛型中类型擦除 泛型数组&#xff1a;如何正确的初始化泛型数组实例&#xff1f; 为什么引入泛型 引入泛型的意义在于&#xff1a; 适用…

KEYSIGHT B1500A 半导体器件参数分析仪

新利通 B1500A 半导体器件参数分析仪 ——一体化器件表征分析仪—— 简述 Keysight B1500A 半导体参数分析仪是一款一体化器件表征分析仪&#xff0c;能够测量 IV、CV、脉冲/动态 IV 等参数。 主机和插入式模块能够表征大多数电子器件、材料、半导体和有源/无源元器件。 B…

关于相机的一些零碎知识点

热成像&#xff0c;英文为Thermal Imaging&#xff0c;例如型号500T&#xff0c;其实指的就是热成像500分辨率。 相机的CMOS&#xff0c;英文为Complementary Metal Oxide Semiconductor&#xff0c;是数码相机的核心成像部件&#xff0c;是一种互补金属氧化物导体器件。 DPI…

PVC刻字膜高精度模切应用

PVC刻字膜是一种由聚氯乙烯&#xff08;PVC&#xff09;为主要成分制成的薄膜材料&#xff0c;具有耐磨、耐刮、耐水、耐油以及良好的化学稳定性等特点。这种薄膜在多个行业中得到广泛应用&#xff0c;特别是在服装、鞋业、箱包、汽车内饰等领域&#xff0c;用于制作各种标识、…

NDC美国药品编码目录数据库查询方法

NDC&#xff08;National Drug Code&#xff09;翻译为“国家药品代码”&#xff0c;是美国食品药品监督管理局&#xff08;FDA&#xff09;制定的一种药品标识系统&#xff0c;用于唯一标识药品。这个编码系统主要目的是为精准识别和追踪不同药品而建设&#xff0c;行业人员和…

2024最新【Pycharm】史上最全PyCharm安装教程,图文教程(超详细)

1. PyCharm下载安装 完整安装包下载&#xff08;包含Python和Pycharm专业版注册码&#xff09;&#xff1a;点击这里 1&#xff09;访问官网 https://www.jetbrains.com/pycharm/download/#sectionwindows 下载「社区版 Community」 安装包。 2&#xff09;下载完成后&#…

【斯坦福CS144】Lab7

一、实验目的 在本课程中&#xff0c;你已经实现了互联网基础设施的重要部分。这个检查点不是关于实现&#xff0c;而是关于测量实际的互联网并报告特定路径的长期统计数据。 二、实验内容 1.收集数据 选择一个远程主机&#xff0c;其往返时间&#xff08;RTT&#xff09;从…

Unity3D相关知识点总结

Unity3D使用的是笛卡尔三维坐标系&#xff0c;并且是以左手坐标系进行展示的。 1.全局坐标系&#xff08;global&#xff09; 全局坐标系描述的是游戏对象在整个世界&#xff08;场景&#xff09;中的相对于坐标原点&#xff08;0&#xff0c;0&#xff0c;0&#xff09;的位置…

处理 Vue3 中隐藏元素刷新闪烁问题

一、问题说明 页面刷新&#xff0c;原本隐藏的元素会一闪而过。 效果展示&#xff1a; 页面的导航栏通过路由跳转中携带的 meta 参数控制导航栏的 显示/隐藏&#xff0c;但在实践过程中发现&#xff0c;虽然元素隐藏了&#xff0c;但是刷新页面会出现闪烁的问题。 项目源码&…

MLP优化KAN

一&#xff1a;spline概念介绍 在数学学科数值分析中&#xff0c;样条&#xff08;spline&#xff09;是一种特殊的函数&#xff0c;由多项式分段定义。样条的英语单词spline来源于可变形的样条工具&#xff0c;那是一种在造船和工程制图时用来画出光滑形状的工具 样条有两个特…

Adversarial and Adaptive Tone Mapping Operatorfor High Dynamic Range Images

Abstract 这项工作涉及色调映射&#xff0c;这是一种将高动态范围 (HDR) 图像转换为低动态范围 (LDR) 图像的常用方法。 我们通过使用自适应色调映射来解决这个问题。 我们建议部署条件生成对抗网络来构建对抗性和自适应色调映射算子&#xff08;adTMO&#xff09;&#xff0c…

游戏盾是如何解决游戏行业攻击问题

随着游戏行业的迅猛发展&#xff0c;其高额的利润和激烈的市场竞争吸引了众多企业和创业者的目光。然而&#xff0c;这一行业也面临着前所未有的业务和安全挑战&#xff0c;尤其是DDoS&#xff08;分布式拒绝服务&#xff09;攻击&#xff0c;已经成为游戏行业的一大威胁。今天…

Metasploit渗透测试之MSFvenom

简介 到目前为止&#xff0c;你应该已经对MSFvenom不陌生了&#xff0c;因为在之前的文章中已经介绍多次了。MSFvenom是用于生成有效攻击载荷和编码的工具。它由msfpayload和msfencode演变而来。并于2015年6月8日取代了这两者。 在本文中&#xff0c;我们将更深入地研究可用的…

MySQL进阶 - 索引

01 索引概述 【1】概念&#xff1a;索引就是一种有序的数据结构&#xff0c;可用于高效查询数据。在数据库表中除了要保存原始数据外&#xff0c;数据库还需要去维护索引这种数据结构&#xff0c;通过这种数据结构来指向原始数据&#xff0c;这样就可以根据这些数据结构实现高…