首页 >> 大全

threejs:两点坐标绘制贝赛尔曲线遇到的坑

2023-11-26 大全 25 作者:考证青年

飞机从武汉飞往背景,根据起点终点,需要绘制飞机航线,网上搜来的通用代码运行后一直找不到copy属性。

坑1:

ray的at方法参数变更:

仔细排查发现,是ray的at方法修改了,现在必须要两个参数了,只需要增加一个临时变量来充当at方法的 参数,只需要修改一点点就可以了。

坑2:

并非所有的起点和终点都可以绘制贝塞尔曲线

代码跑通后,我随便设置了如下图的一组起点和终点,结果绘制的是一条直线

v0和v3设置成下图,甚至还报NAN的错!

直到我把v0和v3设置得更加随机一些,才终于出现了曲线!

总结一下两点绘制贝塞尔曲线的方法:

创建一条平滑的三维三次贝塞尔曲线, 由起点、终点和两个控制点所定义。

但是基于我们日常的需求,比如飞机航线,我们只知道起点和终点,也就是v0和v3,所以我们需要通过一系列算法,得到中间的两个控制点,也就是v1和v2,但是v0和v3需要符合一定条件,目前我通过经验,只能找到两个反例:

1、v0和v3不可以是原点,也就是坐标不能为(0,0,0),否则绘制出来的将是一条直线。

2、v0和v3组成的直线,不可以贴在一条轴线上,比如(-5,0,0)和(5,0,0),就是一条贴在x轴的直线,这样我们的算法会报NaN的错。

既然如此,那就让v0和v3随机一点吧。

修改后的js代码如下:

import * as THREE from 'three'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js';
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js';
import { Line2 } from 'three/examples/jsm/lines/Line2.js';
export function createFlyLine( v0, v3 ) {// 夹角var angle = ( v0.angleTo( v3 ) * 1.8 ) / Math.PI / 0.1; // 0 ~ Math.PIvar aLen = angle * 0.4, hLen = angle * angle * 12;var p0 = new THREE.Vector3( 0, 0, 0 );// 法线向量var rayLine = new THREE.Ray( p0, getVCenter( v0.clone(), v3.clone() ) );// ray的at方法现在必须要两个参数才能执行,所以需要加入临时变量tempvar temp = new THREE.Vector3();// 顶点坐标var vtop = rayLine.at( hLen / rayLine.at( 1,temp).distanceTo( p0 ),temp);// 控制点坐标var v1 = getLenVcetor( v0.clone(), vtop, aLen );var v2 = getLenVcetor( v3.clone(), vtop, aLen );// 绘制三维三次贝赛尔曲线var curve = new THREE.CubicBezierCurve3( v0, v1, v2, v3 );var geometry = new LineGeometry();var points = curve.getSpacedPoints( 5000 );var positions = [];var colors = [];var color = new THREE.Color();/*** HSL中使用渐变* h — hue value between 0.0 and 1.0* s — 饱和度 between 0.0 and 1.0* l — 亮度 between 0.0 and 1.0*/for (var j = 0; j < points.length; j ++) {// color.setHSL( .31666+j*0.005,0.7, 0.7); //绿色color.setHSL( .81666+j,0.88, 0.715+j*0.0025); //粉色colors.push( color.r, color.g, color.b );positions.push( points[j].x, points[j].y, points[j].z );}geometry.setPositions( positions );geometry.setColors( colors );var matLine = new LineMaterial( {linewidth: 0.0006,vertexColors: true,dashed: false} );var lineMesh = new Line2( geometry, matLine );return lineMesh;
}
// 计算v1,v2 的中点function getVCenter( v1, v2 ) {const v = v1.add( v2 );return v.divideScalar( 2 );}// 计算V1,V2向量固定长度的点function getLenVcetor( v1, v2, len ) {const v1v2Len = v1.distanceTo( v2 );return v1.lerp( v2, len / v1v2Len );}

vue代码如下:


关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了