当前位置:   article > 正文

three.js线转面。THREE.Line转Shape,line设置lineWidth无效_js如何将线扩展成面

js如何将线扩展成面

three.js线转面

项目中有遇到这个问题,在这里记录一下

threejs没有提供类似函数,可以使用第三方库 three-line-2dthree.meshline。这库怎么使用我也没试过,后来才找到的。当时使用自己的方法处理了, 怎么使用可以看npm官网。

  • https://www.npmjs.com/package/three-line-2d
  • https://www.npmjs.com/package/three.meshline

线转面,只需要计算出线上的点在扩散后的位置即可,每个点会生成2个点,再将点连起来形成Shape。

线转换后的Shage示意图
只是简单处理了一下,不能拐弯处实现圆滑效果,直接上代码。

/**
 * 线拉伸成平面
 * @param { {x: number, y: number}[] } points 点
 * @param { number } radius 拉伸半径(宽度)
 * @returns { THREE.Vector2[] }
 */
export function createShapeFromPoints(points, radius = 1) {
  let left = [];
  let right = [];

  for (let i = 0, len = points.length; i < len; i++) {
    let prev = points[i - 1] || {};
    let curr = points[i];
    let next = points[i + 1] || {};

    let v1 = [curr.x - prev.x, curr.y - prev.y];
    let v2 = [next.x - curr.x, next.y - curr.y];
    if (!prev.x && prev.x !== 0) {
      v1 = [...v2];
    } else if (!next.x && next.x !== 0) {
      v2 = [...v1];
    }

    let modelV1 = Math.sqrt(v1[0] ** 2 + v1[1] ** 2);
    let modelV2 = Math.sqrt(v2[0] ** 2 + v2[1] ** 2);
    // 单位向量
    v1 = [v1[0] / modelV1, v1[1] / modelV1];
    v2 = [v2[0] / modelV2, v2[1] / modelV2];
    // 方向和的单位向量
    let vector = [v1[0] + v2[0], v1[1] + v2[1]];
    let modelVector = Math.sqrt(vector[0] ** 2 + vector[1] ** 2);
    vector = [vector[0] / modelVector, vector[1] / modelVector];

    // 扩散点的方向和转角处的角度偏移
    let Lvector = rotateVector(vector, -Math.PI / 2);
    let Rvector = rotateVector(vector, Math.PI / 2);
    let deflection = vectorAngleCosHalf(v1, v2);

    left.push(
      new THREE.Vector2(
        curr.x + Lvector[0] * (radius / deflection),
        curr.y + Lvector[1] * (radius / deflection)
      )
    );
    right.unshift(
      new THREE.Vector2(
        curr.x + Rvector[0] * (radius / deflection),
        curr.y + Rvector[1] * (radius / deflection)
      )
    );

    prev = curr;
  }

  return left.concat(right);
}

/**
 * 向量夹角的cos值
 * @param { [number, number] } a
 * @param { [number, number] } b
 * @returns
 */
export function vectorAngleCos(a, b) {
  return (
    (a[0] * b[0] + a[1] * b[1]) /
    (Math.sqrt(a[0] ** 2 + a[1] ** 2) * Math.sqrt(b[0] ** 2 + b[1] ** 2))
  );
}

/**
 * 向量夹角的一半的cos值
 * @param { [number, number] } a
 * @param { [number, number] } b
 * @returns
 */
export function vectorAngleCosHalf(a, b) {
  return Math.sqrt((1 + vectorAngleCos(a, b)) / 2);
}

/**
 * 将点绕原点旋转
 * @param { [number, number] } param0
 * @param { number } angle
 * @returns { [number, number] }
 */
export function rotateVector([x1, y1], angle) {
  let x2 = x1 * Math.cos(angle) - y1 * Math.sin(angle);
  let y2 = y1 * Math.cos(angle) + x1 * Math.sin(angle);

  return [x2, y2];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

使用

let line = [
  { x: 0, y: 0 },
  { x: 20, y: 40 },
  { x: 40, y: 10 },
  { x: 100, y: 100 },
];
let points = createShapeFromPoints(line, 2);

let shape = new THREE.Shape(points);
let geometry = new THREE.ShapeGeometry(shape);
let material = new THREE.LineBasicMaterial({
  color: 0x7d5fff,
  transparent: true,
  opacity: 0.9,
});
let line = new THREE.Mesh(geometry, material);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

ok, 这样就得到line的Mesh了。

蓝色为原来的线,黑色是计算后的到的多边形points
在这里插入图片描述

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号