ThreeJS-3D教学二:基础形状展示

three中提供了22 个基础模型,此案例除了 EdgesGeometry、ExtrudeGeometry、TextGeometry、WireframeGeometry,涵盖 17 个形状。

 Fog  雾化设置,这是scene场景效果EdgesGeometry , WireframeGeometry 更多地可能作为辅助功能去查看几何体的边和线框ExtrudeGeometry 则是将一个二维图形沿 z 轴拉伸出一个三维图形TextGeometry 则需要从外部加载特定格式的字体文件(可在 typeface.js_three 网站上进行转换)进行渲染,其内部依然使用 ExtrudeGeometry 对字体进行拉伸,从而形成三维字体。另外,该类字体的本质是一系列类似SVG 的指令。所以,字体越简单(如直线越多),就越容易被正确渲染。planeGeometry  底层BoxGeometry(长方体)CircleGeometry(圆形)ConeGeometry(圆锥体)CylinderGeometry(圆柱体)DodecahedronGeometry(十二面体)IcosahedronGeometry(二十面体)LatheGeometry(让任意曲线绕 y 轴旋转生成一个形状,如花瓶)OctahedronGeometry(八面体)ParametricGeometry(根据参数生成形状)PolyhedronGeometry(多面体)RingGeometry(环形)ShapeGeometry(二维形状)SphereGeometry(球体)TetrahedronGeometry(四面体)TorusGeometry(圆环体)TorusKnotGeometry(换面纽结体)TubeGeometry(管道)

我们先看下效果图
在这里插入图片描述
看代码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>body {width: 100%;height: 100%;}* {margin: 0;padding: 0;}.label {font-size: 20px;color: #000;font-weight: 700;}</style>
</head>
<body>
<div id="container"></div>
<script type="importmap">{"imports": {"three": "../three-155/build/three.module.js","three/addons/": "../three-155/examples/jsm/"}}
</script>
<script type="module">
import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GPUStatsPanel } from 'three/addons/utils/GPUStatsPanel.js';
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
import { createMultiMaterialObject } from 'three/addons/utils/SceneUtils.js';
import { ParametricGeometry } from 'three/addons/geometries/ParametricGeometry.js';
import { ParametricGeometries } from 'three/addons/geometries/ParametricGeometries.js';
let stats, labelRenderer, gpuPanel;
let camera, scene, renderer, mesh, target, controls, meshs = [];
const group = new THREE.Group();
/**在 Three.js 中可以渲染着色器的材质有两种:RawShaderMaterial 和 ShaderMaterial,它们之间的区别是 ShaderMaterial 会自动将一些初始化着色器的参数添加到代码中(内置 attributes 和 uniforms),而 RawShaderMaterial 则什么都不会添加。*/
init();
initHelp();
initLight();
axesHelperWord();
animate();meshs = addGeometries();
addPlane();function addPlane() {// 创建一个平面 PlaneGeometry(width, height, widthSegments, heightSegments)const planeGeometry = new THREE.PlaneGeometry(120, 140, 1, 1);// 创建 Lambert 材质:会对场景中的光源作出反应,但表现为暗淡,而不光亮。const planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});const plane = new THREE.Mesh(planeGeometry, planeMaterial);// 以自身中心为旋转轴,绕 x 轴顺时针旋转 45 度plane.rotation.x = -0.5 * Math.PI;plane.position.set(0, -4, 0);scene.add(plane);
}function addGeometries() {const geoms = [];const meshs = [];// 共 22 个形状,除了 EdgesGeometry、ExtrudeGeometry、TextGeometry、WireframeGeometry,下面涵盖 17 个(PlaneGeometry在上面)// Box 长方体geoms.push(new THREE.BoxGeometry(8, 8, 8));// Circle 圆形geoms.push(new THREE.CircleGeometry(8, 32));// Cone 圆锥体geoms.push(new THREE.ConeGeometry(8, 20, 32));// Cylinder 圆柱体geoms.push(new THREE.CylinderGeometry(5, 5, 20, 32));// Dodecahedron 十二面体geoms.push(new THREE.DodecahedronGeometry(8));// Icosahedron 二十面体geoms.push(new THREE.IcosahedronGeometry(8));// Lathe 让任意曲线绕 y 轴旋转生成一个形状,如花瓶const lathePoints = [];for (let i = 0; i < 10; i++) {lathePoints.push(new THREE.Vector2(Math.sin(i * 0.2) * 5 + 2.5, (i - 5) * 2));}geoms.push(new THREE.LatheGeometry(lathePoints));// Octahedron 八面体geoms.push(new THREE.OctahedronGeometry(8));// Parametric:根据参数生成形状,THREE.ParametricGeometries.klein 是 ParametricGeometries.js_three 库提供geoms.push(new ParametricGeometry(ParametricGeometries.klein, 10, 10));const verticesOfCube = [-1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1,-1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1,];const indicesOfFaces = [2, 1, 0, 0, 3, 2,0, 4, 7, 7, 3, 0,0, 1, 5, 5, 4, 0,1, 2, 6, 6, 5, 1,2, 3, 7, 7, 6, 2,4, 5, 6, 6, 7, 4];// Polyhedron 多面体geoms.push(new THREE.PolyhedronGeometry(verticesOfCube, indicesOfFaces, 8, 1));// Ring 环形geoms.push(new THREE.RingGeometry(3, 8, 16));// Shape 二维形状(心形)let x = 0, y = 0;let heartShape = new THREE.Shape();heartShape.moveTo(x + 5, y + 5);heartShape.bezierCurveTo(x + 5, y + 5, x + 4, y, x, y);heartShape.bezierCurveTo(x - 6, y, x - 6, y + 7, x - 6, y + 7);heartShape.bezierCurveTo(x - 6, y + 11, x - 3, y + 15.4, x + 5, y + 19);heartShape.bezierCurveTo(x + 12, y + 15.4, x + 16, y + 11, x + 16, y + 7);heartShape.bezierCurveTo(x + 16, y + 7, x + 16, y, x + 10, y);heartShape.bezierCurveTo(x + 7, y, x + 5, y + 5, x + 5, y + 5);geoms.push(new THREE.ShapeGeometry(heartShape));// Sphere 球体geoms.push(new THREE.SphereGeometry(8, 24, 24));// Tetrahedron 四面体geoms.push(new THREE.TetrahedronGeometry(8));// Torus 圆环体geoms.push(new THREE.TorusGeometry(6, 2, 16, 100));// TorusKnot 环面纽结体geoms.push(new THREE.TorusKnotGeometry(6, 2, 100, 16));// Tube 管道const points = [];for (let i = 0; i < 5; i++) {const randomX = -10 + Math.round(Math.random() * 20);const randomY = -7 + Math.round(Math.random() * 20);const randomZ = -10 + Math.round(Math.random() * 20);points.push(new THREE.Vector3(randomX, randomY, randomZ));}geoms.push(new THREE.TubeGeometry(new THREE.CatmullRomCurve3(points), 20, 2, 8, false));let j = 0;// 为几何体添加材质for (let i = 0; i < geoms.length; i++) {let materials = [// 内侧new THREE.MeshLambertMaterial({color: Math.random() * 0xffffff,flatShading: true, // 定义是否使用平面着色渲染材质side: THREE.DoubleSide,wireframe: true // 将几何体渲染为线框。默认值为false(即渲染为平面多边形)}),// 外侧new THREE.MeshBasicMaterial({color: Math.random() * 0xffffff,wireframe: false})];let mesh = createMultiMaterialObject(geoms[i], materials);meshs.push(mesh);// 设置每个物体的位置mesh.position.x = -36 + ((i % 4) * 24);mesh.position.y = 4;mesh.position.z = -36 + (j * 24);if ((i + 1) % 4 == 0) {j++}scene.add(mesh)}return meshs
}function init() {camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 10, 2000 );camera.position.set(0, 125, 125);camera.up.set(0, 1, 0);camera.lookAt(0, 0, 0);scene = new THREE.Scene();scene.background = new THREE.Color( '#ccc' );// Fog( hex, near, far ),线性雾化。// near 表示哪里开始应用雾化效果// far 表示雾化效果在哪里结束scene.fog = new THREE.Fog(0xffffff, 0.015, 100);// FogExp2( hex, density ),指数雾化// density 是雾化强度scene.fog = new THREE.FogExp2(0xffffff, 0.005); //0.01 雾化就很重了// 雾化效果默认是全局影响的,若某个材质不受雾化效果影响,则可为材质的 fog 属性设置为 false(默认值 true)// var material = new THREE.Material({//   fog: false// });renderer = new THREE.WebGLRenderer( { antialias: true } );renderer.setPixelRatio( window.devicePixelRatio );renderer.setSize( window.innerWidth, window.innerHeight );document.body.appendChild( renderer.domElement );labelRenderer = new CSS2DRenderer();labelRenderer.setSize( window.innerWidth, window.innerHeight );labelRenderer.domElement.style.position = 'absolute';labelRenderer.domElement.style.top = '0px';labelRenderer.domElement.style.pointerEvents = 'none';document.getElementById( 'container' ).appendChild( labelRenderer.domElement );window.addEventListener( 'resize', onWindowResize );controls = new OrbitControls( camera, renderer.domElement );controls.minDistance = 10;controls.maxDistance = 1000;// 设置为true可启用阻尼(惯性),可用于为控件提供重量感。默认值为false。// 请注意,如果启用了此选项,则必须在动画循环中调用.update()。controls.enableDamping = false;controls.screenSpacePanning = false; // 定义平移时如何平移相机的位置 控制不上下移动stats = new Stats();stats.setMode(1); // 0: fps, 1: msdocument.body.appendChild( stats.dom );gpuPanel = new GPUStatsPanel( renderer.getContext() );stats.addPanel( gpuPanel );stats.showPanel( 0 );scene.add( group );
}function initLight() {const light = new THREE.DirectionalLight(new THREE.Color('rgb(253,253,253)'));light.position.set(100, 100, -10);light.intensity = 3; // 光线强度light.castShadow = true; // 是否有阴影light.shadow.mapSize.width = 2048; // 阴影像素light.shadow.mapSize.height = 2048;// 阴影范围const d = 80;light.shadow.camera.left = -d;light.shadow.camera.right = d;light.shadow.camera.top = d;light.shadow.camera.bottom = -d;light.shadow.bias = -0.0005; // 解决条纹阴影的出现// 最大可视距和最小可视距light.shadow.camera.near = 0.01;light.shadow.camera.far = 2000;const AmbientLight = new THREE.AmbientLight(new THREE.Color('rgb(255, 255, 255)'));scene.add( light );scene.add( AmbientLight );
}function initHelp() {// const size = 100;// const divisions = 5;// const gridHelper = new THREE.GridHelper( size, divisions );// scene.add( gridHelper );// The X axis is red. The Y axis is green. The Z axis is blue.const axesHelper = new THREE.AxesHelper( 100 );scene.add( axesHelper );
}function axesHelperWord() {let xP = addWord('X轴');let yP = addWord('Y轴');let zP = addWord('Z轴');xP.position.set(50, 0, 0);yP.position.set(0, 50, 0);zP.position.set(0, 0, 50);
}function addWord(word) {let name = `<span>${word}</span>`;let moonDiv = document.createElement( 'div' );moonDiv.className = 'label';// moonDiv.textContent = 'Moon';// moonDiv.style.marginTop = '-1em';moonDiv.innerHTML = name;const label = new CSS2DObject( moonDiv );group.add( label );return label;
}function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize( window.innerWidth, window.innerHeight );
}function animate() {requestAnimationFrame( animate );// 各个网格(mesh)绕自身中心的 y 轴自转if (meshs.length > 0) {for (let i = 0; i < meshs.length; i++) {meshs[i].rotation.y += 0.01;}}stats.update();controls.update();labelRenderer.render( scene, camera );renderer.render( scene, camera );
}
</script>
</body>
</html>

直接复制粘贴到html文件即可看到效果,当然前提是已经提前下载了three的代码库,然后在script type="importmap"标签中改下路径就可以了。
到这一步,我们开始往场景 scene 中添加模型,也就是mesh,案例中用到了 SceneUtils.js 中的createMultiMaterialObject 创建 mesh,这个在官网中用法是这样的:
在这里插入图片描述
我们发现按官网看调用应该是SceneUtils.createMultiMaterialObject,但是这样会报错,我们看three 155版本中发现源码为:
在这里插入图片描述
看来新的版本已经更简洁了直接使用createMultiMaterialObject即可
从这个解错的过程中,我们可以总结一些规律,当我们发现有时官网提供的方法也会报错,解错思路是什么呢?
1、百度查问题,事实我也是这么做的,但由于这是最新版本,查询的结果大家也是推荐的官网用法,一通折腾没结果,这也是使用最新版本可能出现的一些无法预知的问题
2、这时大家可以调转思路,为什么不看一眼源码,虽然大部分源码晦涩难懂,多层嵌套,比较难发现问题,本身我也不喜欢读源码,但结果是看完源码几秒钟这个问题就解决了,所以当我们遇到问题,第一步不一定要百度,看一眼源码也是很好的

因为要写案例,在这个过程中遇到了一些问题,我就把解决问题的思路写下来分享给大家,我想这远比教会大家怎么实现效果更有助于大家成长。

回到主题我们在讲createMultiMaterialObject做了什么时,先看下一般情况下mesh是怎么做的,在代码中有一个addPlane函数:

  // 创建一个平面  PlaneGeometry(width, height, widthSegments, heightSegments)const planeGeometry = new THREE.PlaneGeometry(120, 140, 1, 1);// 创建 Lambert 材质:会对场景中的光源作出反应,但表现为暗淡,而不光亮。const planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});// 这里new THREE.Mesh 大部分情况我们都是这样做的const plane = new THREE.Mesh(planeGeometry, planeMaterial);// 以自身中心为旋转轴,绕 x 轴顺时针旋转 45 度plane.rotation.x = -0.5 * Math.PI;plane.position.set(0, -4, 0);scene.add(plane);

Mesh

表示基于三角形多边形网格的对象的类。还可以作为其他类(如SkinnedMesh)的基础。

很显然PlaneGeometry 和 MeshLambertMaterial大家可能是第一次见到

Geometry

对原生WebGL中的顶点位置position、顶点法向量normal、顶点颜色color、顶点纹理坐标uv、顶点索引index等顶点数据进行了封装
立方体BoxGeometry、圆柱体CylinderGeometry、球体SphereGeometry等Three.js几何体类都是基于基类BufferGeometry二次封装

Materials

材质就像对象的蒙皮。它定义了几何图形的外观。Three.js提供了许多工作材料。我们应该根据我们的需要选择材料的类型。

Three.js中最常用的材料:

1、MeshBasicMateria
Three.js中非常基本的材料

2、MeshDepthMaterial
它使用与摄影机的距离来确定如何以灰度为网格着色

3、MeshNormalMaterial
此材质使用面法线向量的x/y/z值的大小来计算和设置面上显示的颜色的红/绿/蓝值

4、MeshLambertMaterial
您可以使用此材质创建外观暗淡、无光泽的表面

5、MeshPhongMaterial
此材质类似于MeshLambertMaterial,但可以创建更有光泽的曲面

6、MeshStandardMaterial
它与MeshLambertMaterial或MeshPhongMaterial类似,但提供了更准确、更逼真的外观结果。它有两个特性:粗糙度和金属性,而不是光泽

7、MeshPhysicalMaterial
它与MeshStandardMaterial非常相似。可以控制材质的反射率

以上介绍了const plane = new THREE.Mesh(planeGeometry, planeMaterial);各个部分的大概定义,
所以可以看到一个立方体就是由geometry(什么形状)、materia(什么样子),代入到Mesh中实现。
后面对各个材质大部分都会用到,具体的后面再说,想了解更深入些,大家可以用这个例子根据官方文档依次使用下,想学会这点主观能动性还是要有的

createMultiMaterialObject再看这个就按理解了,官方定义是
为材质中定义的每个材质创建一个包含新网格的新组。请注意,这与为1个网格定义多个材质的材质数组不同。这对于同时需要材质和线框实现的对象非常有用。其实就是可以实现一个模型同时具有两种材质的效果。

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

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

相关文章

学校安全用电管理系统解决方案

随着科技的发展和进步&#xff0c;电力已成为我们日常生活和学习的重要支柱。然而&#xff0c;电力的使用也带来了一定的安全风险。特别是对于学校这个复杂而又活跃的环境&#xff0c;安全用电管理系统的角色显得尤为重要。 一、学校用电管理系统的现状 目前&#xff0…

26593-2011 无损检测仪器 工业用X射线CT装置性能测试方法

声明 本文是学习GB-T 26593-2011 无损检测仪器 工业用X射线CT装置性能测试方法. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了工业用X 射线CT 装置(以下简称CT 装置)性能测试的术语、定义、缩略语以及空间 分辨力、密度分辨率…

linux 防火墙iptables

iptables 是 Linux 中比较底层的网络服务&#xff0c;它控制了 Linux 系统中的网络操作&#xff0c;CentOS 中的 firewalld 和 Ubuntu 中的 ufw 都是在 iptables 之上构建的&#xff0c;只为了简化 iptables 的操作。同时&#xff0c;iptables 不仅仅是防火墙这么简单&#xff…

Mysql8安装+重装的数据备份方法【提供Mysql8.0.27版本的压缩包】

文章目录 Mysql8压缩安装包下载安装流程压缩包解压配置环境变量 初始化数据库连接数据库修改密码Mysql重装/重装系统 的数据库备份方法数据备份数据还原 Mysql8压缩安装包下载 压缩包下载路径 安装流程 压缩包解压 首先将压缩包解压&#xff0c;下图是解压之后的文件目录&a…

Swift SwiftUI 修改 List 背景颜色

Preview: Code: .listRowBackground(Color(.yellow)).scrollContentBackground(.hidden) .background(.linearGradient(colors: [.white, .accentColor], startPoint: .top, endPoint: .bottom))喜欢或对你有帮助&#xff0c;点个赞吧&#xff0c;自己先点个嘿嘿。 有错误或者…

eNSP网络学习-v05

IP容量 ip地址一共是32位&#xff0c;/24就表示他的网络号是24位。 也就是说共有 2^&#xff08;32-24&#xff09;-2 个主机&#xff08;因为主机为全0和1的保留不用&#xff0c;所以需要减2&#xff09;&#xff0c;共254个ip。 /24&#xff1a;2的8次方-2 &#xff1a;254 …

Oracle 11g_FusionOS_安装文档

同事让安装数据库&#xff0c;查询服务器信息发现操作系统是超聚变根据华为openEuler操作系统更改的自研操作系统&#xff0c;安装过程中踩坑不少&#xff0c;最后在超聚变厂商的技术支持下安装成功&#xff0c;步骤可参数该文。 一、 安装环境准备 1.1 软件下载 下载地址:…

使用cpolar端口映射的方法轻松实现在Linux环境下SVN服务器的搭建与公网访问

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

从零开始之了解电机及其控制(11)实现空间矢量调制

广泛地说&#xff0c;空间矢量调制只是将电压矢量以及磁场矢量在空间中调制到任意角度&#xff0c;通常同时最大限度地利用整个电压范围。 其他空间矢量调制模式确实存在&#xff0c;并且根据您最关心的内容&#xff0c;它们可能值得研究。 如何实际执行这种所谓的交替反向序列…

【小余送书第一期】《数据要素安全流通》参与活动,即有机会中奖哦!!

目录 1、背景介绍 2、本书编撰背景 3、本书亮点 4、本书主要内容 5、活动须知 1、背景介绍 随着大数据、云计算、人工智能等新兴技术的迅猛发展&#xff0c;数据已经成为我国经济社会发展的五大生产要素之一&#xff0c;《网络安全法》《个人信息保护法》《数据安全法》的…

如何将图片转为ico格式

这里主要是记录一个网站&#xff0c;如果你有更好的办法欢迎留言~ ico简介 ICO&#xff08;Icon&#xff09;是一种用于表示图标的文件格式&#xff0c;常用于Windows操作系统中。ICO格式的图片通常用于表示应用程序、文件夹、网站等的图标。 ICO文件可以包含多个图标&#x…

LINUX|ubuntu常用指令

文章目录 查看IP显示当前路径下所有文件安装编译工具GCC、调试工具GDB、连接工具SSHmkdir 创建目录export命令显示当前系统定义的所有环境变量echo $PATH命令输出当前的PATH环境变量的值当前命令行添加环境变量&#xff0c;关闭失效&#xff0c;防止多版本库冲突时使用sudo su打…

Python函数:chr()和ord()

两个函数是基于Unicode编码表进行进行字符与字码之间的转换。 chr()函数是通过字码转换成字符: 如图,坐标(1,4e10)丑 使用chr需要线将坐标相加得到&#xff1a;4e11 chr默认传入10进制的字码. 如图是各进制的字码。 也可以传入其他进制&#xff0c;不过需要在前面传入的参数最前…

Xcode 15 运行<iOS 14, 启动崩溃问题

如题. Xcode 15 启动 < iOS 14(没具体验证过, 我的问题设备是iOS 13.7)真机设备 出现启动崩溃 解决方案: Build Settings -> Other Linker Flags -> Add -> -ld64

Docker容器部署初学01

Docker容器就是个虚拟机&#xff0c;轻便微小&#xff0c;方便&#xff0c;代替了VM虚拟机的位置 当然&#xff0c;我会尽力以简单的方式为您解释如何从GitHub下载一个项目并使用Docker进行部署&#xff01;&#x1f60a; 步骤1: 下载项目 1. 打开您的浏览器并前往GitHub网站…

Stable Diffusion WebUI插件posex安装以及无法使用完美解决办法汇总

posex是一个很好用的3Dopenpose编辑器。 我们只需要去官网找到源码就可以查看其用法。 对于安装大家应该都知道怎么去安装。 1. 如何安装 (1)一体包安装方式 类似于秋叶一体包直接在webui界面搜索posex就可以直接install。 最新版本好像已经取消了。 (2)手动安装方式…

LeetCode 322.零钱兑换 完全背包 + 动态规划

322. 零钱兑换 - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff…

扫地机器人经营商城小程序的作用是什么

扫地机器人对人们生活大有帮助&#xff0c;近些年也有不少企业开创品牌&#xff0c;在电商平台每年销量也非常高&#xff0c;同行竞争激烈及私域化程度加深情况下&#xff0c;虽然第三方平台或线下方式也有生意&#xff0c;但互联网电商发展也为商家们带来了诸多痛点。 那么通…

Java列表查询Long(id)到前端转换出错

Java列表查询Long到前端转换出错 问题描述排查思路思路一&#xff1a;SQL问题思路二&#xff1a;Long类型转换出错 解决方法 问题描述 做了一个列表查询功能&#xff0c;本来不应该有啥大问题的&#xff0c;但是往往事与愿违。 诶&#xff0c;你越觉得不可能出问题&#xff0c…

蓝桥杯每日一题2023.9.28

AcWing 4409. 砍竹子 - AcWing 题目描述 题目分析 注&#xff1a;sqrtl的范围为long double&#xff0c;比sqrt更加精确 使用优先队列维护一段区间&#xff0c;如果连续一段相同就合并为一个区间&#xff0c;从大到小去枚举&#xff0c;每次先取出最大的一段&#xff0c;双…