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

2023-11-26 03:50

本文主要是介绍threejs:两点坐标绘制贝赛尔曲线遇到的坑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

坑1:

ray的at方法参数变更:

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

坑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代码如下:

<template><div><!-- 本案例演示两点绘制贝塞尔曲线--><div id="container"></div></div></template><script>import * as THREE from 'three'// 注意OrbitControls要加{},注意路径是jsmimport {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';import {createFlyLine,timerFlyLine} from './flyLine.js';export default {name: "hello",props: {},components: {},data() {return {scene: null,renderer: null,camera: null,orbitControls: null}},created() {},mounted() {this.init();this.animate();},//后续还要在beforeDestory中进行销毁beforeDestroy() {this.scene = null;this.renderer = null;this.camera = null;this.orbitControls = null;clearInterval(timerFlyLine);},methods: {// 场景初始化init() {let container = document.getElementById('container');this.camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 特别注意,相机的位置要大于几何体的尺寸this.camera.position.x = 10;this.camera.position.y = 10;this.camera.position.z = 10;this.scene = new THREE.Scene();this.renderer = new THREE.WebGLRenderer({// alpha: true, // canvas是否包含alpha (透明度) 默认为 falseantialias: true,// precision: 'highp',})// this.renderer.setClearAlpha(0.0); // 设置alpha,合法参数是一个 0.0 到 1.0 之间的浮点数// 设置背景色this.renderer.setSize(window.innerWidth, window.innerHeight);container.appendChild(this.renderer.domElement);// 添加三维坐标轴// 红色代表x轴,绿色代表y轴,蓝色代表z轴// let axesHelper = new THREE.AxesHelper(30);// this.scene.add(axesHelper);// 环境光不能用来投射阴影,因为它没有方向。var ambienLight = new THREE.AmbientLight(0xcccccc);this.scene.add(ambienLight);// 初始化轨道控制器// 还需要配合animate,不断循环渲染,达到用鼠标旋转物体的作用。this.orbitControls = new OrbitControls(this.camera, this.renderer.domElement);// 窗口大小自适应window.addEventListener('resize', this.onWindowResize, false);this.addObjects();},// 添加物体addObjects(){// var v0 = new THREE.Vector3(-3, 4, 0);// var v3 = new THREE.Vector3(3, 4, 0);var v0 = new THREE.Vector3(- 1.7049594735603837, 3.208354470512221, - 3.4350509144786985);var v3 = new THREE.Vector3(0.5738958419746141, - 0.44114968930852216, 4.9473255920938985);var sphere = createFlyLine(v0,v3);this.scene.add(sphere);},animate() {requestAnimationFrame(this.animate);this.renderer.render(this.scene, this.camera);},onWindowResize() {this.camera.aspect = window.innerWidth / window.innerHeight;this.camera.updateProjectionMatrix();this.renderer.setSize(window.innerWidth, window.innerHeight);}}}
</script><style scoped>#container {width: 100%;height: 600px;outline: none;/* background-image: linear-gradient(rgb(255, 255, 255), rgb(119, 119, 237)); */}
</style>

 

这篇关于threejs:两点坐标绘制贝赛尔曲线遇到的坑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/425080

相关文章

使用Python绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

mysql主从及遇到的问题解决

《mysql主从及遇到的问题解决》本文详细介绍了如何使用Docker配置MySQL主从复制,首先创建了两个文件夹并分别配置了`my.cnf`文件,通过执行脚本启动容器并配置好主从关系,文中还提到了一些... 目录mysql主从及遇到问题解决遇到的问题说明总结mysql主从及遇到问题解决1.基于mysql

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math

【WebGPU Unleashed】1.1 绘制三角形

一部2024新的WebGPU教程,作者Shi Yan。内容很好,翻译过来与大家共享,内容上会有改动,加上自己的理解。更多精彩内容尽在 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信号:digital_twin123 在 3D 渲染领域,三角形是最基本的绘制元素。在这里,我们将学习如何绘制单个三角形。接下来我们将制作一个简单的着色器来定义三角形内的像素

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。

Anaconda 中遇到CondaHTTPError: HTTP 404 NOT FOUND for url的问题及解决办法

最近在跑一个开源项目遇到了以下问题,查了很多资料都大(抄)同(来)小(抄)异(去)的,解决不了根本问题,费了很大的劲终于得以解决,记录如下: 1、问题及过程: (myenv) D:\Workspace\python\XXXXX>conda install python=3.6.13 Solving environment: done.....Proceed ([y]/n)? yDownloa

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87

PR曲线——一个更敏感的性能评估工具

在不均衡数据集的情况下,精确率-召回率(Precision-Recall, PR)曲线是一种非常有用的工具,因为它提供了比传统的ROC曲线更准确的性能评估。以下是PR曲线在不均衡数据情况下的一些作用: 关注少数类:在不均衡数据集中,少数类的样本数量远少于多数类。PR曲线通过关注少数类(通常是正类)的性能来弥补这一点,因为它直接评估模型在识别正类方面的能力。 精确率与召回率的平衡:精确率(Pr