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