Catmull-Rom P5 ThreeJs与前端

文章目录

    • 问题
      • Echarts 3D如何让曲线变得平滑?
      • Echarts 2D图中平滑效果是如何实现的?
      • 如何在一个Echarts 3D图中画一个圆圈?
      • 如何在Echarts 3D图中画一个立方体?
    • Catmull-Rom插值算法
      • 先来回答第二个问题
      • 回到第一个问题
      • 在Echarts 3D图中画一个圆圈
      • 在Echarts 3D图中画一个立方体

问题

Echarts 3D如何让曲线变得平滑?

假设,你遇到了如下需求:
将如下数据,在Echarts 3D图中展示出来

lineData: [
        [0, 30, 5],
        [10, 20, 10],
        [20, 50, 13],
        [30, 15, 25],
        [40, 20, 33],
        [50, 33, 50],
        [60, 24, 66],
        [70, 10, 80],
        [80, 28, 90],
      ],

这个需求很常规,最终呈现的效果是这样的:
请添加图片描述
可以看到,在Echarts 3D图中,line3D模式下,上述数据集的成图效果是折线。现在再变更一个需求:要求折线数据端点处的过渡要平滑。
于是,我们立刻想到了Echarts 2D图中series中是可以配置smooth: true,这个属性的,通过这个属性,可以让折线在Echarts 2D图上的过渡变得平滑。然而很遗憾,当你在Echarts 3D图中进行上述设置时,并没有任何效果。

Echarts 2D图中平滑效果是如何实现的?

再比如,上述数据集,只取每个元素的前两个数据,不做平滑处理,它在Echarts 2D图上成图效果是这样的:
请添加图片描述
开启数据平滑之后,它的成图效果是这样的:
请添加图片描述
那么,Echarts 2D图中的平滑效果,是如何实现的?

如何在一个Echarts 3D图中画一个圆圈?

如何在Echarts 3D图中画一个立方体?

Catmull-Rom插值算法

先来回答第二个问题

实际上,在Echarts 2D图中,使用的是Catmull-Rom插值算法,它的绘图规则,是每个点 ( P_i ) 的切线方向等于其相邻两个控制点 ( P_{i-1} ) 和 ( P_{i+1} ) 连线的方向。下图为了说明Catmull-Rom插值算法的绘图规则,使用P5js curve方法,绘制的一个有两个控制点c1和c2经过平面上p1和p2的曲线。而P5js curve方法的底层,就是使用的Catmull-Rom插值算法。但是P5js对这个方法的文档描述可能有点问题,后半部分参数对照有问题,参数的意义应该分别是 控制点、途经点、途经点和控制点。
P25 Curve

在这里插入图片描述
回到Echarts 2D图中平滑曲线的实现,为了证明Echarts 2D图中使用的是Catmull-Rom插值算法,我们把smooth:true的配置去掉,然后使用ThreeJs中的SplineCurve构建曲线(SplineCurve使用的是Catmull-Rom插值算法),然后通过增加细分数(也就是调用getPoints(pointCount)方法时,增加pointCount的值),进行验证。

在这里插入图片描述
SplineCurve

const v2Array = this.lineData.map((value) => {
        return new THREE.Vector2(value[0], value[1]);
      });
const curve = new THREE.SplineCurve(v2Array);
const points = curve.getPoints(this.pointsCount);
// series
series: [
  {
    type: "line",
    data: points.map((point) => {
      return [point.x, point.y];
    }),
  },
],

在这里插入图片描述
可以看到,当细分数增加时,同样的数据集,最终和Echarts 2D图中平滑曲线的效果是一致的。

回到第一个问题

通过Catmull-Rom插值算法,可以进行二维空间曲线的平滑效果,同样的,在三维空间中,也是可以进行运算的。ThreeJs的CatmullRomCurve3这个曲线,就是进行空间曲线Catmull-Rom插值的对象。

 // 把关键点,变成三维Vector
const keyPoints = this.lineData.map((point) => {
return new THREE.Vector3(point[0], point[1], point[2]);
});
// 根据关键点,生成贝塞尔曲线
const curve = new THREE.CatmullRomCurve3(keyPoints);
// 构建series
series: [
  {
    type: "line3D",
    data: curve.getPoints(300).map((point) => {
      return [point.x, point.y, point.z];
    }),
    lineStyle: {
      width: 2,
      color: "red",
    },
  },
],

最终呈现的三维空间平滑曲线效果:
在这里插入图片描述

在Echarts 3D图中画一个圆圈

在Echarts 2D图中,我们通过自定义序列和graphic等API,是可以绘制基本几何图形的,然而,在Echarts 3D图中,却没有这个概念。
那么,要想在Echarts 3D图中画出一个圆,我们通过ThreeJs构建一个圆形,然后获取这个圆形每个点的坐标,最终通过line3D的方式,来画出一个圆:

const curve = new THREE.EllipseCurve(
    40,
    40, // ax, aY
    20,
    20 // xRadius, yRadius
  );
const points = curve.getPoints(50);
// 构建series
series: [
  {
    type: "line3D",
    data: points.map((point) => {
      return [point.x, point.y, 40];
    }),
    lineStyle: {
      width: 2,
      color: "red",
    },
  },
],

效果:
在这里插入图片描述
EllipseCurve
注意:这种方法呈现的圆形曲线,是平行与xy平面的,由于Curve没有旋转API的,所以如果需要其他朝向的圆,需要使用其他方式。

在Echarts 3D图中画一个立方体

立方体在3d图中的绘制,如果基础数据齐全(比如知道8个顶点的位置关系),还是比较简单的;但是如果信息有限,8个点的数据,需要间接计算出来(比如只知道几何体几何中心的位置和长宽高,或者需要进行平移,旋转等操作),那就比较繁琐了。Echarts 3D图中,使用ThreeJs,能帮助我们绕开这些繁琐的计算。

 const geometry = new THREE.BoxGeometry(10, 20, 30);
  geometry.translate(10, 10, 40);
  //   边信息
  const linePoints = [];
  const edges = new THREE.EdgesGeometry(geometry);

  const lineSegments = new THREE.LineSegments(edges);

  const lineGeometry = lineSegments.geometry;
  const xyzValues = lineGeometry.attributes.position.array;
  const valuesPerLine = 6;
  for (let i = 0; i < xyzValues.length; i += valuesPerLine) {
    const chunk = xyzValues.slice(i, i + valuesPerLine);
    linePoints.push([chunk.slice(0, 3), chunk.slice(3, 6)]);
  }
  // 构建series
series: linePoints.map((pointArray) => {
  return {
    type: "line3D",
    data: pointArray.map((point) => {
      return [point[0], point[1], point[2]];
    }),
    lineStyle: {
      width: 2,
      color: "red",
    },
  };
}),

效果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

运维安全管理与审计系统(堡垒机)

一、什么是运维安全管理与审计系统 运维安全管理与审计系统&#xff08;俗称 “堡垒机”&#xff09;&#xff1a;是采用新一代智能运维技术框架&#xff0c;基于认证、授权、访问、审计的管理流程设计理念&#xff0c;实现对企事业IT中心的网络设备、数据库、安全设备、主机系…

Zustand极简的状态管理工具

介绍 一个小型、快速且可扩展的 Bearbones 状态管理解决方案。 Zustand 有一个基于 hooks 的舒适 API。它不是样板文件或固执己见&#xff0c;但有足够的惯例来明确和类似通量。 zustand官网 zustand使用方法及调试工具的安装使用 安装包 npm install zustand2.创建store仓…

【Unity投屏总结】投屏方案总结

【背景】 想方便自己在VR中工作&#xff0c;打算做一个能够挂多个屏幕的远程控制VR桌面。研究下来发现细分场景有很多&#xff0c;有点鱼和熊掌不可兼得的意味&#xff0c;细分如下。 【投屏场景与解决方案】 希望多人能够同时观看我的屏幕&#xff0c;也就是一屏投多屏&…

K8s的Pod出现Init:ImagePullBackOff问题的解决,(以calico网络插件为例)

问题描述&#xff1a; 对于这类问题的解决思路应该都差不多&#xff0c;本文以calico插件安装为例&#xff0c;发现有个Pod的镜像没有pull成功 第一步&#xff1a;查看这个pod的描述信息 kubectl describe pod calico-node-t9rql -n kube-system从上图发现是docker拉取"…

实体门店运营方案模板与策划技巧:轻松打造高效运营体系

在当今竞争激烈的商业环境中&#xff0c;实体门店的运营如同一场精密谋划的战役&#xff0c;需要精心策划和高效管理才能在市场中崭露头角。作为经营鲜奶吧5年时间的创业者&#xff0c;我深知成功的实体门店背后离不开一套完善的运营方案和策略。 在这篇文章中&#xff0c;我将…

基于java的宠物信息交流平台设计(含源文件)

随着世界经济信息化、全球化的到来和互联网的飞速发展&#xff0c;推动了各行业的改革。若想达到安全&#xff0c;快捷的目的&#xff0c;就需要拥有信息化的组织和管理模式&#xff0c;建立一套合理、动态的、交互友好的、高效的“多鱼”旧物交易平台。当前的信息管理存在工作…

精酿啤酒:一口啤酒,一份享受

在繁华的都市生活中&#xff0c;我们总是匆匆忙忙&#xff0c;追求着各种目标和成就。然而&#xff0c;在这个过程中&#xff0c;我们往往忽略了生活的本质&#xff0c;那就是享受。而Fendi Club 啤酒&#xff0c;正是为那些追求品质生活的都市精英们量身打造的。 Fendi Club啤…

Java多线程自定义线程池——线程池的七大参数和四大拒绝策略

线程池 2.1 线程池思想 我们使用线程的时候就去创建一个线程&#xff0c;这样实现起来非常简便&#xff0c;但是就会有一个问题&#xff1a; 如果并发的线程数量很多&#xff0c;并且每个线程都是执行一个时间很短的任务就结束了&#xff0c;这样频繁创建线程就会大大降低系统…

Claude3介绍

英文介绍链接&#xff1a;Introducing the next generation of Claude \ Anthropic Anthropic这家由OpenAI分裂出去的兄弟公司&#xff0c;悄无声息地、低调地将Claude3推出了 免费版claude 3 sonnet使用网站&#xff08;国内镜像站&#xff09;&#xff1a;Claude 3 AI&…

106 基于消息队列来做 mysql 大数据表数据的遍历处理

前言 最近有这样的一个需求, 我们存在一张 很大的 mysql 数据表, 数据量大概是在 六百万左右 然后 需要获取所有的记录, 将数据传输到 es 中 然后 当时 我就写了一个脚本来读取 这张大表, 然后 分页获取数据, 然后 按页进行数据处理 转换到 es 但是存在的问题是, 前面 还…

【Micropython ESP32】pwm脉宽调制技术

文章目录 前言一、PWM脉宽调制技术介绍二、machine.PWM 类2.1 machine.PWM 类的构造对象2.2 PWM 对象初始化2.3 关闭PWM设备2.4 设置pwm的周期2.5 设置占空比 三、pwm示例代码总结 前言 在嵌入式系统和物联网应用中&#xff0c;控制电机、LED灯和其他设备的亮度或速度是常见的…

汽车电子零部件(8):T_Box

前言: 网联汽车(Connected Vehicles ,CV)是一个广泛的概念,四个主要的CV线程已发展起来:互联、自主、共享和电动。这些应用于包括CV在内的垂直领域:汽车、通信、互联网和共享手机服务。中国汽车工程师学会(SAEC)提倡将车载ADAS(高级驾驶员辅助系统)与通信技术相结合…

基于单片机的模糊PID炉温控制系统设计

摘 要 电热炉是在工业热处理的生产中广泛使用的一种设备&#xff0c;电热炉的温度控制系统存在时变性&#xff0c;非线性&#xff0c;滞后性等特征&#xff0c;难以用常规PID的控制器对系统达到很好的控制效果。当控温精度的要求高时&#xff0c;使用传统的控制理论方法难以达…

医药工厂5G智能制造数字孪生可视化平台,推进医药企业数字化转型

医药工厂5G智能制造数字孪生可视化平台&#xff0c;推进医药企业数字化转型。随着科技的不断发展&#xff0c;数字化转型已成为医药企业不可或缺的一部分。5G智能制造医药工厂数字孪生可视化平台作为数字化转型的重要工具&#xff0c;正在逐步改变医药企业的生产方式和管理模式…

信息论相关知识简单整理

信息论相关知识 互信息 互信息(Mutual Information)是信息论里一种有用的信息度量&#xff0c;它可以看成是一个随机变量中包含的关于另一个随机变量的信息量&#xff0c;或者说是一个随机变量由于已知另一个随机变量而减少的不肯定性。 设两个随机变量&#xff08;X,Y)的联合…

嵌入式驱动学习第四周——platform总线

前言 platform是Linux内核抽象出来的软件代码&#xff0c;用于设备与驱动的连接&#xff0c;设备与驱动通过总线进行匹配&#xff1b;匹配成功后会执行驱动中的probe函数&#xff0c;在probe函数中可以获取到设备的信息&#xff1b; 嵌入式驱动学习专栏将详细记录博主学习驱动的…

3月份后半月比赛总结

VCTF web hackjs 就直接给了源码审计 const express require(express) const fs require(fs) var bodyParser require(body-parser); const app express() app.use(bodyParser.urlencoded({extended: true })); app.use(bodyParser.json());app.post(/plz, (req, res) …

VR历史建筑漫游介绍|虚拟现实体验店|VR设备购买

VR历史建筑漫游是一种利用虚拟现实技术&#xff0c;让用户可以身临其境地参观和探索历史建筑的体验。通过VR头显和相关设备&#xff0c;用户可以在虚拟环境中自由移动和互动&#xff0c;感受历史建筑的真实氛围和文化内涵。 在VR历史建筑漫游中&#xff0c;您可以选择不同的历史…

Android 之 GMS 认证知多少?

GMS认证 1.什么是GMS GMS全称Google Mobile Service&#xff0c;谷歌移动服务。 为什么要通过GMS认证 Android 系统是开源的&#xff0c;但是 Google 针对GMS所提供的服务却是收费的&#xff0c;比如Google Map&#xff0c;Google Play&#xff0c;Youtube&#xff0c;Gmai…

堆(数据结构)

堆的概念及结构 如果有一个关键码的集合K { &#xff0c; &#xff0c; &#xff0c;…&#xff0c; }&#xff0c;把它的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中&#xff0c;并满足&#xff1a; < 且 < ( > 且 > ) i 0&#xff0c;1&#xff…