Line connecting two Objects

Hello I’ve been trying to recreate a sankey chart in threejs.
Currently im struggling with creating the lines that connect the different nodes.
I’ve tried using normal lines but it’s not possible to apply a width on them.
I’ve also tried using the fatLines example from threejs: three.js examples but since the width for those is applied in every direction the result looked strange.
I also tried using MeshLines: GitHub - spite/THREE.MeshLine: Mesh replacement for THREE.Line
They pretty much do what i need but its not possible to disable the billboarding on them.

Im running out of ideas right now and was wondering if i missed some other approaches.
Essentially i want to create lines as in the attached picture.
Where both ends of the lines are flat.
Any suggestions are appreciated.
Sankey-Chart

Hi!
You can deform/bend a plane :thinking:

Another approach could be to draw a curve from one box to the top of the next box. Get the points for this. Draw another curve from the bottom of one box to the bottom of the next box. Finally draw a shape connecting points from both curves to form a curved rectangle. The shape should be filled.

If this is a one-time thing (just a piece of art, no runtime changes), you could draw in a tool that supports exporting to SVG. Then just load and color the SVG version. It could be flat, or you could extrude to give it depth.

This code draws a ribbon between two points at startposition and endposition. Use width to vary the thickness.

You can increase above 25 to get smoother curves.

  width = 0.005;

  private updatecurve() {
    if (this.mesh.geometry) this.mesh.geometry.dispose();

    const startplus = start.clone()
    const endplus = end.clone()
    const diff = Math.abs(start.x - end.x)/4;

    startplus.x += diff;
    endplus.x -= diff;

    const points: Array<Vector2> = [start, startplus, endplus, end];

    const curve = new SplineCurve(points);

    const toppoints = curve.getPoints(25);
    const first = toppoints[0]

    const ribbon = new Shape()

    ribbon.moveTo(first.x, first.y + this.width);
    toppoints.forEach(point => {
      ribbon.lineTo(point.x, point.y + this.width);
    });
    toppoints.reverse().forEach(point => {
      ribbon.lineTo(point.x, point.y - this.width);
    });
    ribbon.closePath();

    this.mesh.geometry = new ShapeGeometry(ribbon);
  }

Hope this helps

Thanks for the responses.
I went with the SVG approach since im creating the chart with D3js as an SVG anyway.
Im extruding the nodes while keeping the links flat as @anidivr mentioned.
Im also able to make runtime changes thanks to D3js.

Heres what i ended up with for now:

2 Likes