vectorthree.jsgeometrygeometry-surface

Threejs - How to offset all points on a 2d geometry by distance


Using Three.js, (although I believe this is more math related) I have a set of 2D points that can create a 2D geometry. such as square, rectangle, pentagon, or custom 2D shape. Based of the original 2D shape, I would like to create a method to offset the points inward or outward uniformly in such a way like the attached image.

I don't know if there is a simple way to offset/grow/shrink all the points (vector3) uniformly on the 2D shape inward or outward. And if so, it'll be cool if I can offset the points by X distance? Kinda of like saying offset the points on the 2D shape outward or inward by X distance.

And no, I'm not referring to scaling from a center point. While scaling may work for symmetrical shapes, it won't work when it comes to non-symmetrical shapes.

see image for example enter image description here

Thanks in advance.


Solution

  • You can read that forum thread.

    enter image description here

    I've made some changes with ProfiledContourGeometry and got OffsetContour, so I leave it here, just in case, what if it helps :)

      function 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), cloneOffset.getY(0)));
        }
    
    
        return result;
      }
    

    Feel free to modify it :)