如何在three.js中画3D圆弧及半圆弧组成圆

在three.js中画圆弧以及画圆,首先会想到的是ArcCurve,这个曲线API,经过使用发现,他是一个二维平面的,也就是说只在X-Y轴组成的平面可以使用,三维坐标使用的时候不生效,比如说:我期望的圆弧是平行于X-Z这个平面,可能有时候会想到让他沿着某一个轴旋转不就好了么。经过测试发现,首先数据是XYZ的三维坐标,在XY这个平行平面绘制圆弧是二维坐标,因此一开始的位置偏移量就很大,即使计算出需要旋转的角度以及旋转轴,跟预期的效果也是不一样的。

最后经过AI辅助,选择了CatmullRomCurve3 进行圆弧的绘制。首先获取的数据是CAD之类的建模软件导出的,这类的数据画圆弧以及画圆,就和小学的时候算圆柱体表面积类似,只不过,圆柱变面积计算是把柱体部分看成是一个长方体,而这一类的是分为对称的两个,因此拿到的起止点两两一组组成的圆弧面。

这个API中需要传入的是三维坐标数组,首先在获取到的数据有两个点是起止点,通过方法

javascript 复制代码
 function getFullCirclePointsFromArc(centre, start, end, segments) {
                      // 计算半圆的半径
                      let radius = Math.sqrt(Math.pow(start.x - centre.x, 2) + Math.pow(start.y - centre.y, 2));

                      // 计算半圆的起始角度和结束角度
                      let startAngle = Math.atan2(start.y - centre.y, start.x - centre.x);
                      let endAngle = Math.atan2(end.y - centre.y, end.x - centre.x);

                      // 确保角度是顺时针方向
                      if (startAngle > endAngle) {
                        [startAngle, endAngle] = [endAngle, startAngle];
                      }

                      // 计算完整圆的起始角度和结束角度
                      // 如果半圆是顺时针方向,则完整圆也是顺时针方向
                     
                          let fullCircleStartAngle = startAngle;
                          let fullCircleEndAngle = endAngle + Math.PI; // 半圆到完整圆需要增加180度
                          let points = [];
                          for (let i = 0; i <= segments; i++) {
                            let angle = fullCircleStartAngle + (i / segments) * (fullCircleEndAngle - fullCircleStartAngle);
                           
                            let x = centre.x + radius * Math.cos(angle);
                            let y = centre.y + radius * Math.sin(angle);
                            let z = centre.z; // 假设完整圆在同一个平面
                            points.push(new THREE.Vector3(x, y, z));
                
                          }
                          return points;
                     
             }

计算出半径 起止角度 以及这两个点之间需要渲染的等分数 组成一个点数组。然后

javascript 复制代码
            const segments = 50; // 曲线分段数
             pointsA[i] = getFullCirclePointsFromArc(linex[i].centre, linex[i].start,linex[i].end, segments);
             curveA[i] = new THREE.CatmullRomCurve3(pointsA[i]);
             curvePointsA[i] =  curveA[i].getSpacedPoints(segments);

           for (let j = 0; j <  curvePointsA[i].length-1; j++) {
              const distance =  curvePointsA[i][j].distanceTo(curvePointsA[i][j+1]);
              // 创建矩形几何体
              boxGeometryA[j] = new THREE.BoxGeometry(1, 1, distance);
              boxMeshA[j] = new THREE.Mesh(boxGeometryA[j], material);

              // 设置矩形的位置和旋转
               boxMeshA[j].position.copy(curvePointsA[i][j]);
               boxMeshA[j].lookAt(curvePointsA[i][j+1]); // 调整矩形的方向
               boxMeshA[j].name = "line_";

              blinkMaterial(material);

              // 将矩形网格添加到场景中
              scene.add(boxMeshA[j]);
            }

将得到的点每一个都创建一个几何体并将他们连接到一起 就绘制出了三维的圆弧 。

以上代码存在一定的BUG,画圆的时候的endAngle只正对了给出的坐标是半圆弧,其实这里应该是Math.PI*2 这样下面分割的点就不会因为平面的原因不展示了。

虽然实现了画圆弧的需求,但是发现存在很大的性能问题,由于是多次点击生成对应的圆弧线条,因此在点击很多次后就明显觉得页面卡顿,尝试了网上很多介绍,销毁材质,销毁mesh 等发现不生效,只有刷新页面才会回收。。。

相关推荐
杀生丸学AI3 小时前
【三维重建】QuerySplat:在 3DGS 预测中解耦几何与外观表征
人工智能·3d·三维重建·扩散模型·高斯泼溅·空间智能·室内重建
杀生丸学AI21 小时前
【世界模型】Lyra 2.0:可探索的生成式3D世界(NVIDIA)
人工智能·深度学习·3d·数据挖掘·transformer·世界模型·高斯泼溅
毕安格 - BimAngle1 天前
国家电网 GIM 格式模型一键输出 3D Tiles (for Cesium) 和 glTF/glb 更新时间:2026-08-18
3d·gis·cesium·gltf·glb·3d tiles·gim
LateFrames2 天前
3D Slicer 5.13 能力边界清单(87项)
3d·3d slicer
电子云与长程纠缠2 天前
UE5 Lyra PocketWorld进行3D内容UI预览 - 上
开发语言·学习·3d·ue5·游戏引擎
玖玥拾2 天前
Unity3D RPG 入门项目(八)游戏设置面板、帧率控制、快捷技能药品栏、技能解锁系统
游戏·3d·unity·游戏引擎
探索前端2 天前
3dtiles加载时被地形遮挡问题研究及处理思路
前端·3d·cesium
进哥AI研习社3 天前
从像素到3D开放世界:Kimi K3在游戏开发中的引擎级能力实测
3d
小宇的天下3 天前
3D IC 与 TSV:设计挑战与需求
3d
杀生丸学AI4 天前
【稀疏重建】StructSplat:基于非校准稀疏视图的可泛化3DGS
深度学习·3d·音视频·transformer·三维重建·空间智能