three.js开发3D地图记录(一)

关键代码部分:

<template><div class="center-map-box" id="contant"></div>
</template><script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import {CSS2DRenderer,CSS2DObject,
} from "three/addons/renderers/CSS2DRenderer.js";
import * as d3 from "d3";
import jsondata from "@/api/420000_full.json";let textureLoader = new THREE.TextureLoader(); //纹理贴图加载器
let WaveMeshArr = []; //所有波动光圈集合
let rotatingApertureMesh, rotatingPointMesh;export default {data() {return {scene: null,camera: null,renderer: null,contant: null,spotLight: null,map: null,centerPos: [114.255221, 30.619014], // 地图中心经纬度坐标raycaster: null, // 光线投射 用于进行鼠标拾取mouse: null, // 鼠标位置labelRenderer: null, //CSS2DRenderer渲染器对象};},mounted() {// 第一步新建一个场景this.scene = new THREE.Scene();this.contant = document.getElementById("contant");// 辅助线const axesHelper = new THREE.AxesHelper(10);this.scene.add(axesHelper);//环境光const ambient = new THREE.AmbientLight("#ffffff", 4);this.scene.add(ambient);this.setCamera();this.setRenderer();this.generateGeometry();this.setClickFn();this.setController();this.animate();window.onresize = () => {this.renderer.setSize(this.contant.clientWidth,this.contant.clientHeight);this.camera.aspect = this.contant.clientWidth / this.contant.clientHeight;this.camera.updateProjectionMatrix();};this.initFloor();},methods: {// 新建透视相机setCamera() {this.camera = new THREE.PerspectiveCamera(45,this.contant.clientWidth / this.contant.clientHeight,0.1,1000);// 设置相机位置this.camera.position.set(20, 20, 20);},// 设置渲染器setRenderer() {this.renderer = new THREE.WebGLRenderer();// 设置画布的大小this.renderer.setSize(this.contant.clientWidth,this.contant.clientHeight);this.contant.appendChild(this.renderer.domElement);// 创建CSS2DRenderer渲染器(代替鼠标射线检测)this.labelRenderer = new CSS2DRenderer();// 设置labelRenderer渲染器宽高this.labelRenderer.setSize(this.contant.clientWidth,this.contant.clientHeight);this.labelRenderer.domElement.style.position = "absolute";this.labelRenderer.domElement.style.top = "0px";this.labelRenderer.domElement.style.pointerEvents = "none";// 将渲染器添加到页面this.contant.appendChild(this.labelRenderer.domElement);},render() {this.renderer.render(this.scene, this.camera);this.labelRenderer.render(this.scene, this.camera);},generateGeometry() {// 创建环境贴图let textureMap = textureLoader.load(require("./mapimg/gz-map.jpeg"));let texturefxMap = textureLoader.load(require("./mapimg/gz-map-fx.jpeg"));textureMap.wrapS = THREE.RepeatWrapping; //纹理水平方向的平铺方式textureMap.wrapT = THREE.RepeatWrapping; //纹理垂直方向的平铺方式textureMap.flipY = texturefxMap.flipY = false; // 如果设置为true,纹理在上传到GPU的时候会进行纵向的翻转。默认值为true。textureMap.rotation = texturefxMap.rotation =THREE.MathUtils.degToRad(45); //rotation纹理将围绕中心点旋转多少度const scale = 0.01;textureMap.repeat.set(scale, scale); //repeat决定纹理在表面的重复次数texturefxMap.repeat.set(scale, scale);textureMap.offset.set(0.5, 0.5); //offset贴图单次重复中的起始偏移量texturefxMap.offset.set(0.5, 0.5);// 初始化一个地图对象this.map = new THREE.Object3D();// 地理坐标数据 转换为3D坐标数据// 墨卡托投影转换const projection = d3.geoMercator().center(this.centerPos).scale(200).translate([0, 0]);jsondata.features.forEach((elem) => {//this.renderer.render(this.scene, this.camera);const coordinates = elem.geometry.coordinates;//这里创建光柱、文字坐标this.initLightPoint(elem.properties, projection);// 循环坐标数组coordinates.forEach((multiPolygon) => {multiPolygon.forEach((polygon, index) => {const province = new THREE.Object3D();// 创建一个多边形轮廓const shape = new THREE.Shape();// 线材质对象 创建地图边界线 白色const lineMaterial = new THREE.LineBasicMaterial({color: "white",});// 创建一个空的几何体对象const lineGeometry = new THREE.BufferGeometry();const pointsArray = new Array();// 循环多边形坐标数组  polygon是地图区块的经纬度坐标数组for (let i = 0; i < polygon.length; i++) {const [x, y] = projection(polygon[i]);if (i === 0) {shape.moveTo(x, -y);}shape.lineTo(x, -y);// 三维向量对象  用于绘制边界线pointsArray.push(new THREE.Vector3(x, -y, 4.02));}// setFromPoints方法从pointsArray中提取数据改变几何体的顶点属性vertices// 如果几何体是BufferGeometry,setFromPoints方法改变的是.attributes.position属性lineGeometry.setFromPoints(pointsArray);// 拉伸参数const extrudeSettings = {depth: 1, // 拉伸度 (3D地图厚度)bevelEnabled: false, // 是否使用倒角};// 将多边形 拉伸扫描成型  //shape二维轮廓  //extrudeSettings拉伸参数const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);// 创建高光材质const material = new THREE.MeshPhongMaterial({map: textureMap, //颜色贴图normalMap: texturefxMap, //用于创建法线贴图的纹理// normalScale: new THREE.Vector2(12.2, 2.2),//法线贴图对材质的影响程度color: "#7bc6c2",combine: THREE.MultiplyOperation, //如何将表面颜色的结果与环境贴图transparent: true,opacity: 1,});// 创建基础网格材质const material1 = new THREE.MeshBasicMaterial({color: "#3480C4",transparent: true,opacity: 0.4,});// 多边形添加材质const mesh = new THREE.Mesh(geometry, [material, //表面材质material1, //侧面材质]);mesh.rotateX(-Math.PI / 2); //x轴旋转mesh.position.set(0, 1.5, -3); //设置放置位置const line = new THREE.Line(lineGeometry, lineMaterial);//this.materialArr.push(material);province.properties = elem.properties;province.add(mesh);line.rotateX(-Math.PI / 2); //x轴旋转line.position.set(0, -1.5, -3); //设置放置位置province.add(line);this.map.add(province);this.render();});});});this.map.position.set(4, 0, 6);this.scene.add(this.map);//this.spotLight.target = this.map;//this.camera.position.set(0, -0.7, 2.5);this.renderer.render(this.scene, this.camera);},/*** @description // 创建光柱* @param {*} x d3 - 经纬度转换后的x轴坐标* @param {*} z d3 - 经纬度转换后的z轴坐标* @param {*} heightScaleFactor*/createLightPillar(x, z, heightScaleFactor = 1) {let group = new THREE.Group();// 柱体高度const height = heightScaleFactor;// 柱体的geo,6.19=柱体图片高度/宽度的倍数const geometry = new THREE.PlaneGeometry(height / 6.219, height);// 柱体旋转90度,垂直于Y轴// geometry.rotateX(Math.PI / 2)// 柱体的z轴移动高度一半对齐中心点geometry.translate(0, height / 2, 0);// 柱子材质const material = new THREE.MeshBasicMaterial({map: textureLoader.load(require("./mapimg/光柱.png")),color: 0x00ffff,transparent: true,depthWrite: false,// depthTest:false,side: THREE.DoubleSide,});// 光柱01let light01 = new THREE.Mesh(geometry, material);light01.renderOrder = 2;light01.name = "createLightPillar01";// 光柱02:复制光柱01let light02 = light01.clone();light02.renderOrder = 2;light02.name = "createLightPillar02";// 光柱02,旋转90°,跟 光柱01交叉light02.rotateY(Math.PI / 2);// 创建底部标点const bottomMesh = this.createPointMesh(0.5);// 创建光圈const lightHalo = this.createLightHalo(0.5);WaveMeshArr.push(lightHalo);// 将光柱和标点添加到组里group.add(bottomMesh, lightHalo, light01, light02);// 设置组对象的姿态// group = setMeshQuaternion(group, R, lon, lat)group.position.set(x, 2.6, z);return group;},/*** @description 创建底部标点* @param {number} size 缩放大小*/createPointMesh(size) {// 标记点:几何体,材质,const geometry = new THREE.PlaneGeometry(1, 1);const material = new THREE.MeshBasicMaterial({map: textureLoader.load(require("./mapimg/标注.png")),color: 0x00ffff,side: THREE.DoubleSide,transparent: true,depthWrite: false, //禁止写入深度缓冲区数据});let mesh = new THREE.Mesh(geometry, material);mesh.renderOrder = 2;mesh.rotation.x = Math.PI / 2;mesh.name = "createPointMesh";// 缩放const scale = 1 * size;mesh.scale.set(scale, scale, scale);return mesh;},/*** @description 创建底部标点的光圈* @param {number} size 缩放大小*/createLightHalo(size) {// 标记点:几何体,材质,const geometry = new THREE.PlaneGeometry(1, 1);const material = new THREE.MeshBasicMaterial({map: textureLoader.load(require("./mapimg/标注光圈.png")),color: 0x00ffff,side: THREE.DoubleSide,opacity: 0,transparent: true,depthWrite: false, //禁止写入深度缓冲区数据});let mesh = new THREE.Mesh(geometry, material);mesh.renderOrder = 2;mesh.name = "createLightHalo";mesh.rotation.x = Math.PI / 2;// 缩放const scale = 1.5 * size;mesh.size = scale; //自顶一个属性,表示mesh静态大小mesh.scale.set(scale, scale, scale);return mesh;},random(min, max) {return Math.floor(Math.random() * (max - min + 1)) + min;},/*** @description 创建光柱、文字坐标* @param {*} properties 属性、详情* @param {Function} projection  d3-geo转化坐标*/initLightPoint(properties, projection) {// 创建光柱let heightScaleFactor = 2 + this.random(1, 5) / 5;let lightCenter = properties.centroid || properties.center;let areaName = properties.name;// projection用来把经纬度转换成坐标const [x, y] = projection(lightCenter);let light = this.createLightPillar(x, y, heightScaleFactor);light.position.z -= 3;this.map.add(light);//这里创建文字坐标this.createTextPoint(x, y, areaName);},/*** @description 创建文字坐标* @param {*} x d3 - 经纬度转换后的x轴坐标* @param {*} z d3 - 经纬度转换后的z轴坐标* @param {*} areaName 地名*/createTextPoint(x, z, areaName) {let tag = document.createElement("div");tag.innerHTML = areaName;tag.style.color = "#fff";tag.style.pointerEvents = "auto";tag.style.position = "absolute";tag.addEventListener("mousedown", this.clickLabel, false); // 有时候PC端click事件不生效,不知道什么原因,就使用mousedown事件tag.addEventListener("touchstart", this.clickLabel, false);let label = new CSS2DObject(tag);//label.element.innerHTML = areaName;label.element.style.visibility = "visible";label.position.set(x, 3, z);label.position.x += 4;label.position.z += 3;this.scene.add(label);},/*** @description 文字坐标点击* @param {*} e*/clickLabel(e) {console.log("🚀 ~ clickLabel ~ e:", e);},/*** @description 添加底部旋转背景*/initFloor() {const geometry = new THREE.PlaneGeometry(80, 80);let texture = textureLoader.load(require("./mapimg/地板背景.png"));const material = new THREE.MeshPhongMaterial({color: 0xffffff,map: texture,// emissive:0xffffff,// emissiveMap:Texture,transparent: true,opacity: 1,depthTest: true,// roughness:1,// metalness:0,depthWrite: false,// side: THREE.DoubleSide});let plane = new THREE.Mesh(geometry, material);plane.rotateX(-Math.PI / 2);this.scene.add(plane);// 旋转装饰圆环1let rotatingApertureTexture = textureLoader.load(require("./mapimg/rotatingAperture.png"));let rotatingApertureerial = new THREE.MeshBasicMaterial({map: rotatingApertureTexture,transparent: true,opacity: 1,depthTest: true,depthWrite: false,});let rotatingApertureGeometry = new THREE.PlaneGeometry(25, 25);rotatingApertureMesh = new THREE.Mesh(rotatingApertureGeometry,rotatingApertureerial);rotatingApertureMesh.rotateX(-Math.PI / 2);rotatingApertureMesh.position.y = 0.02;rotatingApertureMesh.scale.set(1.2, 1.2, 1.2);this.scene.add(rotatingApertureMesh);// 旋转装饰圆环2let rotatingPointTexture = textureLoader.load(require("./mapimg/rotating-point2.png"));let material2 = new THREE.MeshBasicMaterial({map: rotatingPointTexture,transparent: true,opacity: 1,depthTest: true,depthWrite: false,});rotatingPointMesh = new THREE.Mesh(rotatingApertureGeometry, material2);rotatingPointMesh.rotateX(-Math.PI / 2);rotatingPointMesh.position.y = 0.04;rotatingPointMesh.scale.set(1, 1, 1);this.scene.add(rotatingPointMesh);// 背景小圆点let circlePoint = textureLoader.load(require("./mapimg/circle-point.png"));let material3 = new THREE.MeshPhongMaterial({color: 0x00ffff,map: circlePoint,transparent: true,opacity: 1,depthWrite: false,// depthTest: false,});let plane3 = new THREE.PlaneGeometry(30, 30);let mesh3 = new THREE.Mesh(plane3, material3);mesh3.rotateX(-Math.PI / 2);mesh3.position.y = 0.06;this.scene.add(mesh3);},//加事件setClickFn() {this.raycaster = new THREE.Raycaster();this.mouse = new THREE.Vector2();const onMouseMove = (event) => {var marginLeft = this.contant.offsetLeft;var marginTop = this.contant.offsetTop + 92;// 如果该地图不是占满全屏需要减去margintop和marginleft// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)// this.mouse.x = (event.clientX / this.contant.clientWidth) * 2 - 1;// this.mouse.y = -(event.clientY / this.contant.clientHeight) * 2 + 1;this.mouse.x =((event.clientX - marginLeft) / this.contant.clientWidth) * 2 - 1;this.mouse.y =-((event.clientY - marginTop) / this.contant.clientHeight) * 2 + 1;};let clickPosition;window.addEventListener("mousemove", onMouseMove, false);// 鼠标点击事件const onclick = (event) => {var marginLeft = this.contant.offsetLeft;var marginTop = this.contant.offsetTop;// let x = (event.clientX / this.contant.clientWidth) * 2 - 1;// let y = -(event.clientY / this.contant.clientHeight) * 2 + 1;// 如果该地图不是占满全屏需要减去margintop和marginleftlet x =((event.clientX - marginLeft) / this.contant.clientWidth) * 2 - 1;let y =-((event.clientY - marginTop) / this.contant.clientHeight) * 2 + 1;clickPosition = { x: x, y: y };this.raycaster.setFromCamera(clickPosition, this.camera);// 算出射线 与当场景相交的对象有那些const intersects = this.raycaster.intersectObjects(this.scene.children,true);let clickObj = intersects.find((item) => item.object.material && item.object.material.length === 2);// 点击区县if (clickObj && clickObj.object) {console.log(clickObj);// this.$emit('clickAreaCheck',clickObj)}};window.addEventListener("mousedown", onclick, false);},// 设置最大旋转的角度setController() {const controls = new OrbitControls(this.camera, this.renderer.domElement);controls.maxPolarAngle = 2.5;controls.minPolarAngle = 1;controls.maxAzimuthAngle = 1;controls.minAzimuthAngle = -1;controls.addEventListener("change", () => {this.renderer.render(this.scene, this.camera);});},animate() {// 背景圆环 转动if (rotatingApertureMesh) {rotatingApertureMesh.rotation.z += 0.0005;}if (rotatingPointMesh) {rotatingPointMesh.rotation.z -= 0.0005;}// 圆柱底部 波纹if (WaveMeshArr.length) {WaveMeshArr.forEach(function (mesh) {mesh._s += 0.007;mesh.scale.set(mesh.size * mesh._s,mesh.size * mesh._s,mesh.size * mesh._s);if (mesh._s <= 1.5) {//mesh._s=1,透明度=0 mesh._s=1.5,透明度=1mesh.material.opacity = (mesh._s - 1) * 2;} else if (mesh._s > 1.5 && mesh._s <= 2) {//mesh._s=1.5,透明度=1 mesh._s=2,透明度=0mesh.material.opacity = 1 - (mesh._s - 1.5) * 2;} else {mesh._s = 1.0;}});}window.requestAnimationFrame(this.animate);// 通过摄像机和鼠标位置更新射线this.raycaster.setFromCamera(this.mouse, this.camera);this.labelRenderer.render(this.scene, this.camera);this.renderer.render(this.scene, this.camera);},},
};
</script><style>
.center-map-box {width: 100%;height: 100%;position: relative;font-size: 14px;
}
</style>

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

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

相关文章

springboot小型超市商品展销系统-计算机毕业设计源码01635

摘 要 科技进步的飞速发展引起人们日常生活的巨大变化&#xff0c;电子信息技术的飞速发展使得电子信息技术的各个领域的应用水平得到普及和应用。信息时代的到来已成为不可阻挡的时尚潮流&#xff0c;人类发展的历史正进入一个新时代。在现实运用中&#xff0c;应用软件的工作…

EIQ-ABC 分析法在配送中心储位分配中的应用

配送中心运作效率的高低主要取决于仓储业务流程的作业效率&#xff0c;在配送作业流程中&#xff0c;储位分配的是否合理性成为影响配送运作效率的重要因素。为实现储位的合理分配&#xff0c;提出通过对订单信息的分析&#xff0c;并应用 EIQ-ABC 分析法&#xff0c;以此实现缩…

白酒:茅台镇白酒的品牌合作与跨界营销案例

云仓酒庄豪迈白酒&#xff0c;作为茅台镇的知名品牌&#xff0c;在品牌合作与跨界营销方面也有着杰出的表现。通过与不同领域品牌的合作&#xff0c;豪迈白酒进一步拓宽了市场渠道&#xff0c;提升了品牌曝光度和影响力。 首先&#xff0c;云仓酒庄豪迈白酒与品质餐产品牌的合作…

量子革命 “不负众望“!即将见证首个商业量子应用案例?

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨沛贤/浪味仙 排版丨沛贤 深度好文&#xff1a;1000字丨5分钟阅读 摘要&#xff1a;雀巢、联合利华和德国能源巨头 E.ON 表示&#xff0c;距离首个商用量子案例出现可能只需三年时间。 近…

tracetcp下载 安装 使用 网络工具 windows trace工具 tcp协议

省流 Tracetcp是一个类似于Tracert的工具&#xff0c;使用如下&#xff1a; 1. 安装winpcap &#xff0c; 下载链接&#xff1a;WinPcap Download 2.下载tracetcp软件&#xff0c;下载链接&#xff1a; https://github.com/0xcafed00d/tracetcp/releases 命令&#xff1a;…

期末考试老师怎样发成绩

期末成绩的公布&#xff0c;总是让老师感到焦虑。成绩&#xff0c;这一张张的数字&#xff0c;承载着学生一学期的努力&#xff0c;也牵动着家长们的心。 传统的成绩公布方式&#xff0c;写成绩条让学生带回家&#xff0c;或是通过私发家长的方式&#xff0c;都存在一定的弊端。…

六、Nginx-正向代理和反向代理

目录 一、正向代理 1、参数详解 2、常用变量详解 3、配置示例 二、反向代理 三、 Nginx的安全控制 1、如何使用SSL对流量进行加密 2、nginx添加SSL的支持 3、 Nginx的SSL相关指令 &#xff08;1&#xff09;ssl &#xff08;2&#xff09;ssl_certificate &#xff0…

【Kaggle量化比赛】Top讨论

问: 惊人的单模型得分,请问您使用了多少个特征来获得如此高的得分?我也在使用LGB模型。 答 235个特征(180个基本特征+滚动特征) 问: 您是在使用Polars进行特征工程还是仅依赖于Pandas+Numba/多进程?即使进行了Numba优化,我也发现当滚动特征过多时,推理速度会非常慢。在…

淘宝商品评论API接口测试实例(获取淘宝商品评论,翻页展示、支持并发)

item_review-获得淘宝商品评论 测试页 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_shop…

设计灵感源泉!7个令人赞叹的网页界面设计展示

网页的界面设计主要是指视觉设计和风格设计。高质量的界面更容易吸引用户的注意力&#xff0c;从而更准确地向用户传达信息。对于设计师来说&#xff0c;他们需要从高质量的作品中获得稳定的灵感&#xff0c;以帮助他们更高效地实现设计目标。在本文中&#xff0c;梳理了7个高质…

人工智能抢走了他们的工作。现在他们得到报酬,让它听起来像人类

人工智能抢走了他们的工作。现在他们得到报酬&#xff0c;让它听起来像人类 如果你担心人工智能会如何影响你的工作&#xff0c;那么广告文案的世界或许能让你窥见未来。 作家本杰明米勒(化名)在2023年初非常红火。他领导了一个由60多名作家和编辑组成的团队&#xff0c;发表博…

一文了解Java 中的String、StringBuffer 与StringBuilder

String结构剖析 String是final 类&#xff0c;不能被其他的类继承 String有属性private final char vaLue[]; 用于存放字符串内容 注意: value 是个final类型&#xff0c; 不可以修改: 即value不能指向新的地址&#xff0c;但是单个字符内容是可以变化 两种创建String对象的区…

24执业药师报名时间汇总及报名流程!

24执业药师报名时间汇总&#xff01;报名流程&#xff01; &#x1f55b;️各省市报名时间汇总&#xff08;共9地&#xff09; 西藏&#xff1a;6月29日-7月8日 新疆&#xff1a;6月25日10:30-7月9日19:00 内蒙古&#xff1a;6月20日9:00-7月3日24:00 新疆兵团&#xff1a;6月2…

RPG游戏完整指南

环境&#xff1a;unity2021urp 本教程教大家如何使用Unity创建一个RPG游戏&#xff0c;玩家可以在城镇场景中进行导航并寻找战斗&#xff0c;并在战斗中遇到不同类型的敌人。玩家可以向敌人施加不同的动作&#xff0c;如&#xff1a;常规攻击和撤离。这会是一个十分有趣的体验。…

git将代码提交到github

第一次代码提交 1.在github新建一个空白仓库 2、当前在文件下 3、git init 5、git add .(当前目录下所有代码全部提交) 6、git commit -n "init" 这次提交的备注信息 7、git branch -M main 8、git remote add origin (address) 9、git push -u origin main 第…

格雷母线在无人天车定位中的应用

随着工业自动化的不断发展&#xff0c;实现无人天车的精准定位与高效运行&#xff0c;一套高精度的位移测量系统显得至关重要。格雷母线高精度位移测量系统&#xff0c;凭借其卓越的定位性能&#xff0c;成为无人天车的理想选择。 格雷母线高精度位移测量系统由武汉市微深节能科…

如何使用视频文案提取帮手将手机上视频里的声音转成文字?

在自媒体短视频日益增加的时候不少自媒体创作者如何将视频转文字的需求日益增加。本次将给大家分享一款针对广大职场青年用户群体的视频转文字工具&#xff0c;旨在为用户提供高效、准确的视频转文字服务。 如何将手机上的视频转成文字呢 视频转文字工具具有转换速度快&#…

轮式机器人Swiss-Mile城市机动性大提升:强化学习引领未来城市物流

喜好儿小斥候消息&#xff0c;苏黎世联邦理工学院的研究团队成功开发了一款革命性的机器人控制系统&#xff0c;该系统采用强化学习技术&#xff0c;使轮式四足机器人在城市环境中的机动性和速度得到了显著提升。 喜好儿网 这款专为轮腿四足动物设计的控制系统&#xff0c;能…

机械臂抓取物体整体的开发流程

开发一个机械臂抓取物体的系统涉及多个步骤和不同领域的知识&#xff0c;包括机械设计、控制系统、传感器集成、软件开发等。以下是一个全面的开发流程概述&#xff1a; 1. 需求分析与系统设计 需求分析&#xff1a; 明确机械臂需要抓取的物体类型&#xff08;大小、重量、材…

618必抢清单:内存升级国货更强,DDR5劲爆大白菜

随着数字时代的加速发展&#xff0c;平时在PC上玩游戏、办公的时候&#xff0c;电脑性能对我们的影响越来越打。相比于CPU、显卡等硬件&#xff0c;内存对于电脑性能的重要性也很高&#xff0c;而且可以通过更低的成本来升级。内存就像是电脑的神经网络&#xff0c;影响着CPU数…