Threejs - Offfset Border + On Curves

by black strings

HTML

<script src="https://rawgit.com/mrdoob/three.js/dev/build/three.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/controls/OrbitControls.js"></script>

CSS

/* fix mouse click offset errors when doing drags */
body {
  margin: 0;
}

JavaScript

class Utils {
  static convertVec3sToVec2s(point3ds){
    var point2ds = [];
    if(point3ds){
      point3ds.forEach(v3 => {
        point2ds.push( new THREE.Vector2(v3.x, v3.y) );
      });
    }
    return point2ds;
  }
  static convertVec2sToVec3s(point2ds){
    var point3ds = [];
    if(point2ds){
      point2ds.forEach(v2 => {
        point3ds.push( new THREE.Vector3(v2.x, v2.y, 0) );
      });
    }
    return point3ds;
  }
  static offsetContour(offset, contour) {

    let result = [];

    offset = new THREE.BufferAttribute(new Float32Array([offset, 0, 0]), 3);
    console.log("offset", offset);

    for (let i = 0; i < contour.length; i++) {
      let v1 = new THREE.Vector2().subVectors(contour[i - 1 < 0 ? contour.length - 1 : i - 1], contour[i]);
      let v2 = new THREE.Vector2().subVectors(contour[i + 1 == contour.length ? 0 : i + 1], contour[i]);
      let angle = v2.angle() - v1.angle();
      let halfAngle = angle * 0.5;

      let hA = halfAngle;
      let tA = v2.angle() + Math.PI * 0.5;

      let shift = Math.tan(hA - Math.PI * 0.5);
      let shiftMatrix = new THREE.Matrix4().set(
        1, 0, 0, 0,
        -shift, 1, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
      );

      let tempAngle = tA;
      let rotationMatrix = new THREE.Matrix4().set(
        Math.cos(tempAngle), -Math.sin(tempAngle), 0, 0,
        Math.sin(tempAngle),  Math.cos(tempAngle), 0, 0,
        0,                    0, 1, 0,
        0,                    0, 0, 1
      );

      let translationMatrix = new THREE.Matrix4().set(
        1, 0, 0, contour[i].x,
        0, 1, 0, contour[i].y,
        0, 0, 1, 0,
        0, 0, 0, 1,
      );

      let cloneOffset = offset.clone();
      console.log("cloneOffset", cloneOffset);
      shiftMatrix.applyToBufferAttribute(cloneOffset);
      rotationMatrix.applyToBufferAttribute(cloneOffset);
      translationMatrix.applyToBufferAttribute(cloneOffset);

      result.push(new THREE.Vector2(cloneOffset.getX(0),...