As part of incorporating three.js into a d3 viz, I wanted to be able to draw the nice smooth curves that d3 generates. It turns out that three.js has a CubicBezierCurve3 that matches nicely with the output of the d3.svg.diagonal function.

The short video below shows it in action - details are included further below.

Transitioning from 2D/svg in a D3 Viz to 3D in Three.js:

Mapping Bezier Curves

Mapping Bezier Curves

How to Map Bezier Curves from d3.js to Three.js

To map from the d3 2d world to the three.js world, we:

- get the svg "d" attribute of the d3-generated path for the curve
- from the "d" attribute, parse out the four points for the cubic Bezier function - here are two little (non-optimized!) helper functions to do that:
`function getPointsFromBezierD(d) { var firstSplit = d.split('C'); //split off the 'M' var startPoint_all=firstSplit[0].replace('M',''); var P0 = getXY(startPoint_all); var otherPoints = firstSplit[1].split(' '); var P1 = getXY(otherPoints[0]); var P2 = getXY(otherPoints[1]); var P3 = getXY(otherPoints[2]); return {P0:P0, P1:P1, P2:P2, P3:P3}; } function getXY(s) { var pieces = s.split(','); var x = Number(pieces[0]); var y = Number(pieces[1]); return{x:x, y:y}; }`

- use these four points to generate a THREE.CubicBezierCurve in the $z=0$ plane that is added to the scene:

Note that I am flipping the y values here - in general, the scaling could be more involved.`var material = new THREE.LineBasicMaterial( { color: whatever}); var geometry = new THREE.Geometry(); var thePoints = getPointsFromBezierD(d); var curve = new THREE.CubicBezierCurve3( new THREE.Vector3(thePoints.P0.x, height-thePoints.P0.y,0), new THREE.Vector3(thePoints.P1.x, height-thePoints.P1.y,0), new THREE.Vector3(thePoints.P2.x, height-thePoints.P2.y,0), new THREE.Vector3(thePoints.P3.x, height-thePoints.P3.y,0)); geometry.vertices = curve.getPoints(20); var curveObject = new THREE.Line(geometry, material); scene.add(curveObject);`

Of course, you don't have to put the 3D curve in the $z=0$ plane - that's just what I'm doing here initially.

## No comments:

## Post a Comment