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

3d行政区划-中国地图

前言

技术调研:做底代码平台的3d行政区组件 写的demo

效果图:
在这里插入图片描述

实现的功能项
地标、打点、飞线、three.js 3d 中国地图的一些基础配置

补充
geo中国地图文件获取

其他项:包

 "dependencies": {"d3": "^7.9.0","d3-geo": "^3.1.0","three": "^0.142.0","vue": "^3.3.4"},

源码

以下代码所需的图片可以在iconfont官网进行搜索,这里不做提供

<script setup>
import * as THREE from "three";import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Stats from "three/examples/jsm/libs/stats.module.js";
import { FontLoader } from "three/examples/jsm/loaders/FontLoader.js";
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry.js";import { Line2 } from 'three/examples/jsm/lines/Line2.js';
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js';
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js';import * as d3 from "d3";// 渲染性能监测工具
const stats = new Stats();
document.body.appendChild(stats.dom);// 初始化场景
const scene = new THREE.Scene();// 创建透视相机
const camera = new THREE.PerspectiveCamera(90,window.innerHeight / window.innerHeight,0.1,100000
);
// 设置相机位置
camera.position.set(0, 0, 120);
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
// 更新摄像机的投影矩阵
camera.updateProjectionMatrix();
scene.add(camera);// // 加入辅助轴,帮助我们查看3维坐标轴
// const axesHelper = new THREE.AxesHelper(10);
// scene.add(axesHelper);// 添加环境光和直射光
const light = new THREE.AmbientLight(0xffffff, 100); // soft white light
scene.add(light);
const directionalLight = new THREE.DirectionalLight(0xffffff, 100);
scene.add(directionalLight);// 初始化渲染器
const renderer = new THREE.WebGLRenderer({ alpha: false, antialias: true });
// 设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染器添加到body
document.body.appendChild(renderer.domElement);// 初始化控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼
controls.enableDamping = true;// 监听屏幕大小改变的变化,动态设置渲染的尺寸
window.addEventListener("resize", () => {// 更新摄像头camera.aspect = window.innerWidth / window.innerHeight;// 更新摄像机的投影矩阵camera.updateProjectionMatrix();// 更新渲染器renderer.setSize(window.innerWidth, window.innerHeight);// 设置渲染器的像素比例renderer.setPixelRatio(window.devicePixelRatio);
});const canvas = renderer.domElement;
// 构造生成三维物体对象
const map = new THREE.Object3D();// 地图geojson的json文件得到的坐标点是经纬度数据,需要把它转为坐标数据,
// 这里使用插件d3 geoMercator()方法转换
// .center: 以北京经纬度坐标(116.23, 39.54)为中心点
// .translate 移动地图位置
const projection = d3.geoMercator().center([103.8, 35.0]).translate([0, 0, 0]);
const fileLoader = new THREE.FileLoader();
fileLoader.load("../public/中华人民共和国.geojson", (data) => {const loader = new FontLoader();loader.load("Alibaba PuHuiTi_Regular.json", (font) => {const chinaJsonData = JSON.parse(data);handleData(chinaJsonData, font);})
})/*** 处理地图数据* @param {Object} jsonData */
function handleData(jsonData, font) {// createPlane()// 全国信息const features = jsonData.features;features.forEach((feature) => {// 单个省份 对象const province = new THREE.Object3D();// 地址province.propertiesName = feature.properties.name;const coordinates = feature.geometry.coordinates;const color = "#ffffff"; // if (feature.geometry.type === "MultiPolygon") {// 多个,多边形const text = drawText(feature.properties, projection, font)if (text) {province.add(text)}coordinates.forEach((coordinate) => {// coordinate 多边形数据coordinate.forEach((coord) => {const mesh = drawExtrudeMesh(coord, 0x3a6877, projection, {depth: 6, borderColor: 0xffffff, borderWidth: 0.1, code:feature.properties.code});// const line = drawLine(coord, color, projection);// 唯一标识mesh.name = feature.properties.name;mesh.userData.originalColor = 0x3a6877; // 初始颜色province.add(mesh);// province.add(line);});});}if (feature.geometry.type === "Polygon") {const text = drawText(feature.properties, projection, font)if (text) {province.add(text)}// 多边形coordinates.forEach((coordinate) => {const mesh = drawExtrudeMesh(coordinate, 0x3a6877, projection, {depth: 6, borderColor: 0xffffff, borderWidth: 0.1, code: feature.properties.code||feature.properties.filename});// const line = drawLine(coordinate, color, projection);// 唯一标识mesh.userData.originalColor = 0x3a6877; // 初始颜色mesh.name = feature.properties.name;province.add(mesh);// province.add(line);});}map.add(province);map.rotation.x = -Math.PI / 5;});scene.add(map);createLine(projection)}
function createPlane() {var gridHelper = new THREE.GridHelper(300, 15, 0xff0000, 0x003333);gridHelper.material.depthWrite = false; // 禁止写入深度缓冲区gridHelper.material.depthTest = false;gridHelper.position.y = -10.1gridHelper.rotateX(Math.PI / 3);scene.add(gridHelper);// 创建一个平面作为地面var geometry = new THREE.PlaneGeometry(310, 310);var material = new THREE.MeshLambertMaterial({color: 0xffffff, // 白色transparent: true, // 开启透明效果opacity: 0.1, // 设置透明度side: THREE.DoubleSide, // 双面渲染});var mesh = new THREE.Mesh(geometry, material);scene.add(mesh);mesh.position.y = -10mesh.rotateX(-Math.PI / 6);
}function drawText(properties, projection, font) {// console.log('properties', properties)let center = properties.centroid || properties.centerlet name = properties.nameconst geometry = new TextGeometry(name, {font,depth: 0.1,size: 1, // 文本大小,默认为100width: 16,height:0.2 // 文字厚度});geometry.computeBoundingBox(); // 计算包围盒const boundingBox = geometry.boundingBox;const xOffset = (boundingBox.max.x - boundingBox.min.x) / 2; // X 方向偏移const yOffset = (boundingBox.max.y - boundingBox.min.y) / 2; // Y 方向偏移geometry.translate(-xOffset, -yOffset, 0);const textMaterial = new THREE.MeshBasicMaterial({color: 0x00fff0||0xb0c4ca,});const mesh = new THREE.Mesh(geometry, textMaterial);if (center) {let [x, y] = projection(center)mesh.position.set(x, -y, 6.5);return mesh}return null
}/*** 根据经纬度坐标生成几何物体* @param {Array} polygon 经纬度坐标数据* @param {string} color 物体颜色* @param {Function} projectionFun 经纬度转平面坐标函数* @returns THREE.Mesh*/
function drawExtrudeMesh(polygon, color, projectionFun, options = {}) {const { depth = 6, borderColor = 0xffffff, borderWidth = 0.1 } = options;// 创建形状const shape = new THREE.Shape();polygon.forEach((row, i) => {const [x, y] = projectionFun(row);if (i === 0) {shape.moveTo(x, -y);}shape.lineTo(x, -y);});// 挤压缓冲几何体const geometry = new THREE.ExtrudeGeometry(shape, {depth: depth, // 这里是高度参数bevelEnabled: true,bevelSegments: 10,steps: 1, // 用于分段的数量,默认 1bevelSize: 0.5, // 倒角大小bevelThickness: 0.5 // 倒角深度});// 材质const randomColor = (Math.random() * 0.5 + 0.5) * 0xffffff;const material = new THREE.MeshBasicMaterial({color: 0x3a6877 || randomColor,transparent: true,opacity: 0.5,});const mesh = new THREE.Mesh(geometry, material);// 添加边界const edges = new THREE.EdgesGeometry(geometry);const lineMaterial = new THREE.LineBasicMaterial({color: borderColor, // 边界颜色linewidth: borderWidth,    // 边界线宽度});const edgeLines = new THREE.LineSegments(edges, lineMaterial);mesh.add(edgeLines);mesh.userData = {originalColor: color,fillMaterial: material, // 默认材质originalBorderMaterial: lineMaterial, // 保存默认材质edgeLines: edgeLines, // 保存边界线};return mesh;
}/*** 根据坐标点一条连续的线* @param {*} polygon 经纬度坐标数据* @param {*} color 线的颜色* @param {*} projectionFun 经纬度转平面坐标函数* @returns THREE.Line*/
function drawLine(polygon, color, projectionFun) {const lineGeometry = new THREE.BufferGeometry();const pointsArr = [];polygon.forEach((row) => {const [x, y] = projectionFun(row);// 创建三维点pointsArr.push(new THREE.Vector3(x, -y, 6.4));});// console.log(pointsArr, 'pointsArr')// 放入多个点lineGeometry.setFromPoints(pointsArr);// 生成随机颜色const lineColor = new THREE.Color(Math.random() * 0.5 + 0.5,Math.random() * 0.5 + 0.5,Math.random() * 0.5 + 0.5);const lineMaterial = new THREE.LineBasicMaterial({color: '#ffffff',linewidth: 200});return new THREE.Line(lineGeometry, lineMaterial);
}// 地标
const rippleMaterial = new THREE.ShaderMaterial({uniforms: {uTime: { value: 0.0 },  // 时间uColor: { value: new THREE.Color(0xff00ff) },  // 气泡颜色},vertexShader: `varying vec2 vUv;void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragmentShader: `uniform float uTime;uniform vec3 uColor;varying vec2 vUv;void main() {float dist = length(vUv - 0.5);  // 计算像素到中心的距离float ripple = sin(dist * 10.0 - uTime) * 0.5 + 0.5;  // 波纹效果gl_FragColor = vec4(uColor, ripple * (1.0 - 0.0));}`,transparent: true,  // 使气泡透明
});
let pos = [[116.23, 39.54], [117.2857, 31.8612]]
for (let p of pos) {const geometry = new THREE.CircleGeometry(3, 64); // 半径1,分段64const ripple = new THREE.Mesh(geometry, rippleMaterial);const [x, y] = projection(p);console.log(x, y, 'xy')ripple.position.set(x, -y, 7)map.add(ripple);
}// 创建圆形波纹的几何体 引入图片 打点
let pos2 = [[116.4074, 39.9042],  // 北京[117.3616, 39.3434],  // 天津[112.9834, 28.1127],  // 湖南[113.4244, 23.3417],  // 广东[108.7880, 23.8298],  // 广西[110.3492, 20.0174],  // 海南[104.0665, 30.5723],  // 四川
];
for (let p of pos2) {const texture = new THREE.TextureLoader().load('../public/坐标-fill.png');const material = new THREE.MeshBasicMaterial({ map: texture, color: 0x7777ff, transparent: true, side: THREE.DoubleSide });const plane = new THREE.Mesh(new THREE.PlaneGeometry(4, 4), material);const [x, y] = projection(p);plane.position.set(x, -y, 8.5);plane.rotateX(Math.PI / 2) // 将平面旋转到水平位置// plane.rotateY(Math.PI / 4); // 旋转 Y 轴,增加立体感plane.lookAt(camera.position); // plane.renderOrder = 1;map.add(plane);
}
// 创建圆形波纹的几何体function getPoint(startPoint, endPoint, projection) {// const startPoint = [116.4074, 39.9042]// const endPoint = [87.6177, 43.7928]let [sx, sy] = projection(startPoint)let [ex, ey] = projection(endPoint)// 定义起始点和终止点const sp = new THREE.Vector3(sx, -sy, 7.5);const ep = new THREE.Vector3(ex, -ey, 7.5);return [sp, ep]
}let curvature = 0.3;
const curveList = []
function createCurve(endPoint, startPoint) {// 计算起点到终点的方向向量和距离const direction = new THREE.Vector3().subVectors(endPoint, startPoint).normalize(); // 单位方向向量const distance = startPoint.distanceTo(endPoint); // 两点间距离// 计算垂直于方向向量的偏移向量(用来确定控制点)// const perpendicular = new THREE.Vector3(-direction.y, direction.x, 0).normalize();// 计算控制点位置:沿垂直方向偏移,偏移量与距离和曲率相关const controlPoint = new THREE.Vector3().addVectors(startPoint.clone().add(endPoint).multiplyScalar(0.5),  // 中点new THREE.Vector3(0, 0, curvature * distance)// perpendicular.multiplyScalar(curvature * distance * 0.5)  // 曲率控制的偏移量);// 创建二次贝塞尔曲线const curve = new THREE.QuadraticBezierCurve3(startPoint, controlPoint, endPoint);const points = curve.getPoints(500);if (points.some(point => isNaN(point.x) || isNaN(point.y) || isNaN(point.z))) {console.error("生成的点数组包含无效值");}return {curve,points};
}
function createLine(projection) {let pointList = [[[116.4074, 39.9042], [117.2857, 31.8612]], [[110.3492, 20.0174], [117.2857, 31.8612]],[[87.6177, 43.7928], [117.2857, 31.8612]], [[91.1164, 29.6500], [117.2857, 31.8612]],[[126.6617, 45.7421], [117.2857, 31.8612]], [[120.0934, 29.1828], [117.2857, 31.8612]], [[102.7097, 25.0453], [117.2857, 31.8612]]]for (let point of pointList) {let [sp, ep] = pointlet [startPoint, endPoint] = getPoint(sp, ep, projection)const texture = new THREE.TextureLoader().load('飞机-客机.png');texture.center.set(0.5, 0.5);const material = new THREE.MeshBasicMaterial({ map: texture, transparent: true, side: THREE.DoubleSide });const planeMesh = new THREE.Mesh(new THREE.PlaneGeometry(6, 6), material);planeMesh.position.set(endPoint.x, endPoint.y, 8.5);map.add(planeMesh);// 创建线材质和几何体const lineMaterial = new LineMaterial({color: 0xffffff,linewidth: 4, // 设置线条宽度opacity: 0,transparent: true,depthWrite: false,depthTest: false});lineMaterial.needsUpdate = true;lineMaterial.resolution.set(window.innerWidth, window.innerHeight);// 创建线对象const lineGeometry = new LineGeometry();let { points, curve } = createCurve(startPoint, endPoint);let plane = createFlyLine(points)curveList.push({points,curve,plane,planeMesh})let pr = []for (let p of points) {pr.push(p.x, p.y, p.z)}lineGeometry.setPositions(pr); // 设置点的位置const line = new Line2(lineGeometry, lineMaterial);line.computeLineDistances(); // 计算线段的距离line.renderOrder = 1;map.add(line);}
}const uniforms = {// uTime: { value: 0.0 },// uSColor: { value: new THREE.Color(0xff0000) },// uEColor: { value: new THREE.Color(0xffffff) },// uWidth: { value: 5.0 },// uSpeed: { value: 1 },// uLength: { value: 0.8 }uTime: { value: 0.0 }, // 用于控制时间的 uniformuScale: { value: 1.0 }, // 点的缩放比例uColor: { value: new THREE.Color(0xffffff) }, // 颜色数组
};const commonUniforms = {u_time: {value: 0.0}
}
function initLineMaterial(setting) {let number = setting ? (Number(setting.number) || 1.0) : 4.0; // 在一个路径中同时存在的个数let speed = setting ? (Number(setting.speed) || 1.0) : 0.6;// 速度约大越快let length = setting ? (Number(setting.length) || 0.5) : 0.3;// 单根线的长度0-1之间1代表全满let size = setting ? (Number(setting.size) || 3.0) : 6.0;// 在最大的地方的大小 默认为3像素let color = setting ? setting.color || new THREE.Vector3(0, 1, 1) : new THREE.Vector3(0, 1, 1);// 颜色此处以Vector3的方式传入分别为RBG值 都是0-1的范围let singleUniforms = {u_time: commonUniforms.u_time,number: { type: 'f', value: number },speed: { type: 'f', value: speed },length: { type: 'f', value: length },size: { type: 'f', value: size },color: { type: 'v3', value: color },initialOpacity: { value: 1 }};let lineMaterial = new THREE.ShaderMaterial({uniforms: singleUniforms,vertexShader: `varying vec2 vUv;attribute float percent;varying float opacity;uniform float u_time;uniform float number;uniform float speed;uniform float length;uniform float size;void main(){vUv = uv;vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );float l = clamp(1.0-length,0.0,1.0);//空白部分长度占比gl_PointSize = clamp(fract(percent*number + l - u_time*number*speed)-l ,0.0,1.) * size * (1./length);opacity = gl_PointSize/size;gl_Position = projectionMatrix * mvPosition;}`,//顶点着色器部分fragmentShader: `precision mediump float;varying float opacity;uniform vec3 color;uniform float initialOpacity;void main(){if(opacity <=0.1){discard;}gl_FragColor = vec4(color,1.0);}`,// 片元着色器部分transparent: true,blending:THREE.AdditiveBlending,});return lineMaterial;
}function createFlyLine(points) {var geometry = new THREE.BufferGeometry().setFromPoints(points);let length = points.length;var percents = new Float32Array(length);for (let i = 0; i < points.length; i += 1) {percents[i] = (i / length);}geometry.setAttribute('percent', new THREE.BufferAttribute(percents, 1));let lineMaterial = initLineMaterial({color: new THREE.Color(0xffffff),});var flyLine = new THREE.Points(geometry, lineMaterial);// let euler = new THREE.Euler(Math.random() * Math.PI, Math.random() * Math.PI, 0);// flyLine.setRotationFromEuler(euler);map.add(flyLine)
}let t = 0
function animate(time) {controls.update();stats.update();if(rippleMaterial&&rippleMaterial.uniforms){rippleMaterial.uniforms.uTime.value += 0.1;}requestAnimationFrame(animate);// console.log(uniforms, 'uniforms')const speed = 0.001for (let obj of curveList) {// obj.planeMesh.uTime.value += 0.001;const curve = obj.curve;const position = curve.getPointAt(t);const tangent = curve.getTangentAt(t).normalize();const axis = new THREE.Vector3(0, 1, 0);const quaternion = new THREE.Quaternion().setFromUnitVectors(axis, tangent);// planeMesh.position.copy(position); // 更新位置obj.planeMesh.lookAt(position.clone().add(tangent)); // 设置朝向obj.planeMesh.position.set(position.x, position.y, position.z + 0.2)obj.planeMesh.quaternion.copy(quaternion);}t += speed;if (t > 1) t = 0;// uniforms.uTime.value += 0.01;if(commonUniforms&&commonUniforms.u_time){commonUniforms.u_time.value += 0.01;}// 使用渲染器渲染相机看这个场景的内容渲染出来renderer.render(scene, camera);}
animate();</script>

相关文章:

3d行政区划-中国地图

前言 技术调研&#xff1a;做底代码平台的3d行政区组件 写的demo 效果图&#xff1a; 实现的功能项 地标、打点、飞线、three.js 3d 中国地图的一些基础配置补充 geo中国地图文件获取 其他项:包 "dependencies": {"d3": "^7.9.0","d3-…...

适合存储时序数据的数据库和存储系统

时序数据的存储通常要求高效地处理大量按时间排序的数据&#xff0c;同时支持快速查询、实时分析和高并发写入。以下是一些适合存储时序数据的数据库和存储系统&#xff1a; 1. InfluxDB 概述&#xff1a;InfluxDB 是一个开源的时序数据库&#xff0c;专门为处理时序数据而设…...

dolphinscheduler集群服务一键安装启动实现流程剖析

1.dolphinscheduler的安装部署 dolphinscheduler服务的安装部署都是非常简单的&#xff0c;因为就服务本身而言依赖的服务并不多。 mysql / postgresql。由于需要进行元数据及业务数据的持久化存储所以需要依赖于数据库服务&#xff0c;数据库服务支持mysql、postgresql等&am…...

深入了解Linux —— 学会使用vim编辑器

前言 学习了Linux中的基本指令也理解了权限这一概念&#xff0c;但是我们怎么在Linux下写代码呢&#xff1f; 本篇就来深入学习Linux下的vim编辑器&#xff1b;学会在Linux下写代码。 软件包管理器 1. 软件包&#xff1f; 在Linux下安装软件&#xff0c;通常是下载程序的源码…...

C05S01-Web基础和HTTP协议

一、Web基础 1. Web相关概念 1.1 URL URL&#xff08;Uniform Resource Locator&#xff0c;统一资源定位符&#xff09;&#xff0c;是一种用于在互联网上标识和定位资源的标准化地址&#xff0c;提供了一种访问互联网上特定资源的方法。URL的基本格式如下所示&#xff1a;…...

MIT工具课第六课任务 Git基础练习题

如果您之前从来没有用过 Git&#xff0c;推荐您阅读 Pro Git 的前几章&#xff0c;或者完成像 Learn Git Branching 这样的教程。重点关注 Git 命令和数据模型相关内容&#xff1b; 相关内容整理链接&#xff1a;Linux Git新手入门 git常用命令 Git全面指南&#xff1a;基础概念…...

计算机网络安全

从广义来说&#xff0c;凡是涉及到网络上信息的机密性、报文完整性、端点鉴别等技术和理论都是网络安全的研究领域。 机密性指仅有发送方和接收方能理解传输报文的内容&#xff0c;而其他未授权用户不能解密&#xff08;理解&#xff09;该报文报文完整性指报文在传输过程中不…...

Delphi 实现键盘模拟、锁定键盘,锁定鼠标等操作

Delphi 模拟按键的方法 SendMessageA 说明: 调用一个窗口的窗口函数&#xff0c;将一条消息发给那个窗口。除非消息处理完毕&#xff0c;否则该函数不会返回SendMessage所包含4个参数: 1. hwnd 32位的窗口句柄窗口可以是任何类型的屏幕对象&#xff0c;因为Win32能够维护大多数…...

RTK数据的采集方法

采集RTK&#xff08;实时动态定位&#xff09;数据通常涉及使用高精度的GNSS&#xff08;全球导航卫星系统&#xff09;接收器&#xff0c;并通过基站和流动站的配合来实现。本文给出RTK数据采集的基本步骤 文章目录 准备设备设置基站设置流动站数据采集数据存储与处理应用数据…...

Next.js 入门学习

一、引言 在现代 Web 开发领域&#xff0c;Next.js 已成为构建高性能、可扩展且用户体验卓越的 React 应用程序的重要框架。它基于 React 并提供了一系列强大的特性和工具&#xff0c;能够帮助开发者更高效地构建服务器端渲染&#xff08;SSR&#xff09;、静态站点生成&#…...

2024年认证杯SPSSPRO杯数学建模B题(第一阶段)神经外科手术的定位与导航解题全过程文档及程序

2024年认证杯SPSSPRO杯数学建模 B题 神经外科手术的定位与导航 原题再现&#xff1a; 人的大脑结构非常复杂&#xff0c;内部交织密布着神经和血管&#xff0c;所以在大脑内做手术具有非常高的精细和复杂程度。例如神经外科的肿瘤切除手术或血肿清除手术&#xff0c;通常需要…...

安卓底层相机流的传输方式

这是安卓 相机流的定义 typedef enum {CAM_STREAMING_MODE_CONTINUOUS, /* continous streaming */CAM_STREAMING_MODE_BURST, /* burst streaming */CAM_STREAMING_MODE_BATCH, /* stream frames in batches */CAM_STREAMING_MODE_MAX} cam_streaming_mode_t; 在ca…...

【单链表】(更新中...)

一、 题单 206.反转链表203.移除链表元素 876.链表的中间结点BM8 链表中倒数最后k个结点21.合并两个有序链表 二、题目简介及思路 206.反转链表 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 思路简单&#xff0c;但是除了要两个指针进…...

开源堡垒机JumpServer配置教程:使用步骤与配置

开源堡垒机JumpServer配置教程&#xff1a;使用步骤与配置 上一篇文章星哥讲了如何安装JumpServer堡垒机&#xff0c;本篇文章来讲如何配置和使用JumpServer。 安装成功后&#xff0c;通过浏览器访问登录 JumpServer 地址: http://<JumpServer服务器IP地址>:<服务运…...

上门服务小程序开发,打造便捷生活新体验

随着互联网的快速发展&#xff0c;各种上门服务成为了市场的发展趋势&#xff0c;不管是各种外卖、家政、美甲、维修、按摩等等&#xff0c;都可以提供上门服务&#xff0c;人们足不出户就可以满足各种需求&#xff0c;商家也能够获得新的拓展业务渠道&#xff0c;提高整体收益…...

iOS中的类型推断及其在Swift编程语言中的作用和优势

iOS中的类型推断及其在Swift编程语言中的作用和优势 一、iOS中的类型推断 类型推断&#xff08;Type Inference&#xff09;是编程语言编译器或解释器自动推断变量或表达式的类型的能力。在支持类型推断的语言中&#xff0c;开发者在声明变量时无需显式指定其类型&#xff0c…...

工业检测基础-缺陷形态和相机光源选型

缺陷形态与相机选择依据 微小点状缺陷&#xff08;如微小气泡、杂质颗粒&#xff09; 相机选择依据&#xff1a; 分辨率&#xff1a;需要高分辨率相机&#xff0c;无论是面阵还是线阵相机&#xff0c;以确保能够清晰地分辨这些微小的点。对于面阵相机&#xff0c;像元尺寸要小&…...

Python100道练习题

Python100道练习题 BIlibili 1、两数之和 num1 20 num2 22result num1 num2print(result)2、一百以内的偶数 list1 []for i in range(1,100):if i % 2 0:list1.append(i) print(list1)3、一百以内的奇数 # 方法一 list1 [] for i in range(1,100):if i % 2 ! 0:lis…...

2024年华中杯数学建模A题太阳能路灯光伏板的朝向设计问题解题全过程文档及程序

2024年华中杯数学建模 A题 太阳能路灯光伏板的朝向设计问题 原题再现 太阳能路灯由太阳能电池板组件部分&#xff08;包括支架&#xff09;、LED灯头、控制箱&#xff08;包含控制器、蓄电池&#xff09;、市电辅助器和灯杆几部分构成。太阳能电池板通过支架固定在灯杆上端。…...

【JavaWeb后端学习笔记】Java上传文件到阿里云对象存储服务

阿里云对象存储 1、创建阿里云对象存储节点2、上传文件2.1 修改项目配置文件2.2 定义一个Properties类获取配置信息2.3 准备一个alioss工具类2.4 创建注册类&#xff0c;将AliOssUtil 注册成Bean2.5 使用AliOssUtil 工具类上传文件2.6 注意事项 使用阿里云对象存储服务分为以下…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...

[拓扑优化] 1.概述

常见的拓扑优化方法有&#xff1a;均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有&#xff1a;有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...