block by mgold e1b4859d5347e56b0183f27a952b3ae8

Ellipse Interpolation

Full Screen

Ellipse Interpolation

This block shows how the points on a circle can be smoothly expanded into an ellipse. Think of taking every unit vector and and multiplying it by the matrix

[ a 0 ]
[ 0 b ]

where a and b are the axis lengths of the ellipse.

Now, think of smoothly interpolating between that matrix and the identity…

Built with blockbuilder.org

index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://d3js.org/d3-path.v1.min.js"></script>
  <script src="https://d3js.org/d3-shape.v1.min.js"></script>
  <script src="https://d3js.org/d3-timer.v1.min.js"></script>
  <style>
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
  </style>
</head>

<body>
  <script>
    var w = 960;
    var h = 500
    var svg = d3.select("body").append("svg")
      .attr("width", w)
      .attr("height", h)

    var g = svg.append("g")
      .attr("transform", "translate("+w/2+","+h/2+"),scale(100)")
    
    var line = d3.line();
    var n = 100;
    var tau = Math.PI*2;
    var max_stretch_x = 4;
    var max_stretch_y = 1.8;
    
    var path = g.append("path")
      .attr("fill", "none")
    	.attr("stroke", "black")
      .style("stroke-width", "0.05px")
    
    // A sinusoid (on parameter t) that oscillates between 1 and k.
    function phase(k,t){
    	return ((1-k)*Math.cos(t) + k + 1)/2;
    }
    
    function render(t){
      t = t/1000;
      var phaseX = phase(max_stretch_x, t);
      var phaseY = phase(max_stretch_y, t)

      var data = d3.range(n).map(function(i){
      	var theta = i*tau/n;
      	return [Math.cos(theta)*phaseX, Math.sin(theta)*phaseY];
   		 })    	
      path.attr("d", line(data)+"z")
    }
    
    render(0);

    d3.timer(render, 1000)
   
  </script>
</body>