title: Construct a smooth curve from mouse coordinates
body: <p>In a project I'm working on, i get mouse coordinates every X milliseconds. I would like to draw the most likely path between these coordinates.</p>
  
  <p>By example : 
  - After X ms, i could get these (x,y) coordinates : (0, 0), (3, 1), (5, 4), (6, 7)
  - After 2*X ms i could have this : (0, 0), (3, 1), (5, 4), (6, 7), (8, 5), (11, -7)
  - etc.</p>
  
  <p>I would like to draw step by step a path between these points, once I've drawn a path i can't change it (i can't wait to have all the coordinates to draw the line).</p>
  
  <p>I started to think about a solution where I draw lines between pair of coordinates by calculating a polynomial fit:</p>
  
  <pre><code>import numpy as np
  import matplotlib.pyplot as plt
  
  def construct_path(points):
      x = points[:,0]
      y = points[:,1]
  
      (x_new,y_new) = ([],[])
      for i in range(0,len(x) - 2):
          (x_tmp, y_tmp) =  get_new_points(x[i:(i+3)], y[i:(i+3)], (i+3) == len(x))
          (x_new,y_new) = (x_new + x_tmp.tolist(), y_new + y_tmp.tolist())
          previous_points = [x_tmp,y_tmp]
  
      return (x_new, y_new)
  
  def get_new_points(x,y, end):
      x = np.array(x)
      y = np.array(y)
  
      # calculate polynomial
      z = np.polyfit(x, y, 2)
      f = np.poly1d(z)
  
      # calculate new x's and y's
  
      if not end:
          x_new = np.linspace(x[0], x[1], 11)
      else:
          x_new = np.linspace(x[0], x[1], 10, endpoint=False).tolist() + np.linspace(x[1], x[2], 11).tolist()
          x_new = np.array(x_new)
      y_new = f(x_new)
  
      print(x_new, y_new)
      return (x_new, y_new)
  
  
  points = np.array([(0, 0), (3, 1), (5, 4), (6, 7), (8, 5), (11, -7) ])
  
  x = points[:,0]
  y = points[:,1]
  (x_new, y_new) = construct_path(points)
  
  plt.plot(x,y,'o',np.array(x_new),np.array(y_new))
  plt.xlim([-2, 12])
  plt.ylim([-10, 10])
  plt.show()
  </code></pre>
  
  <p>The result is ok :
  <a href="https://i.stack.imgur.com/xEFpQ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/xEFpQ.png" alt="smooth curve"></a></p>
  
  <p>But it doesn't work when points have close x's or y's (ex : (0, 0), (3, 1), (5.8, 4), (6, 7), (8, 5), (11, -7))</p>
  
  <p><a href="https://i.stack.imgur.com/wipLC.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wipLC.png" alt="smooth_curve2"></a></p>
  
  <p>EDIT : found some interesting leads :</p>
  
  <pre><code>from __future__ import division
  import numpy as np
  import matplotlib.pyplot as plt
  import scipy.interpolate
  
  def range_spline(x,y):
      t = np.arange(x.shape[0], dtype=float)
      t /= t[-1]
      nt = np.linspace(0, 1, 100)
      new_x = scipy.interpolate.spline(t, x, nt)
      new_y = scipy.interpolate.spline(t, y, nt)
      return (new_x,new_y)
  
  def dist_spline(x,y):
      t = np.zeros(x.shape)
      t[1:] = np.sqrt((x[1:] - x[:-1])**2 + (y[1:] - y[:-1])**2)
      t = np.cumsum(t)
      t /= t[-1]
      nt = np.linspace(0, 1, 100)
      new_x = scipy.interpolate.spline(t, x, nt)
      new_y = scipy.interpolate.spline(t, y, nt)
      return (new_x, new_y)
  
  x = np.array([ 0,  3,  6,  6,  8,  11, 8, 6, 6])
  y = np.array([ 0,  1,  4,  7,  5,  -7, -10, -10, -5])
  #x = np.array([ 0, 2, 4])
  #y = np.array([ 0, 2, 0])
  
  
  (x1, y1) = range_spline(x,y)
  (x2,y2) = dist_spline(x,y)
  
  plt.plot(x,y, 'o')
  plt.plot(x1, y1, label='range_spline')
  plt.plot(x2, y2, label='dist_spline')
  
  plt.legend(loc='best')
  plt.show()
  </code></pre>
  
  <p>It works well when there are many points :
  <a href="https://i.stack.imgur.com/GhRf9.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/GhRf9.png" alt="splines"></a></p>
  
  <p>But not so well when there are less than 5 points (which is what i'd like) :
  <a href="https://i.stack.imgur.com/wxIfy.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/wxIfy.png" alt="enter image description here"></a></p>