当前位置: 首页 > 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 注意事项 使用阿里云对象存储服务分为以下…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...