code: def bezier_by_line_intersections(bezier, line):
      
      # The method here is to translate (shift) then rotate the complex plane so
      # that line starts at the origin and proceeds along the positive real axis.
      # After this transformation, the intersection points are the real roots of
      # the imaginary component of the bezier for which the real component is
      # between 0 and abs(line[1]-line[0])].
      assert len(line[:]) == 2
      assert line[0] != line[1]
      if not any(p != bezier[0] for p in bezier):
          raise ValueError("bezier is nodal, use "
                           "bezier_by_line_intersection(bezier[0], line) "
                           "instead for a bool to be returned.")
  
      # First let's shift the complex plane so that line starts at the origin
      shifted_bezier = [z - line[0] for z in bezier]
      shifted_line_end = line[1] - line[0]
      line_length = abs(shifted_line_end)
  
      # Now let's rotate the complex plane so that line falls on the x-axis
      rotation_matrix = line_length/shifted_line_end
      transformed_bezier = [rotation_matrix*z for z in shifted_bezier]
  
      # Now all intersections should be roots of the imaginary component of
      # the transformed bezier
      transformed_bezier_imag = [p.imag for p in transformed_bezier]
      coeffs_y = bezier2polynomial(transformed_bezier_imag)
      roots_y = list(polyroots01(coeffs_y))  # returns real roots 0 <= r <= 1
  
      transformed_bezier_real = [p.real for p in transformed_bezier]
      intersection_list = []
      for bez_t in set(roots_y):
          xval = bezier_point(transformed_bezier_real, bez_t)
          if 0 <= xval <= line_length:
              line_t = xval/line_length
              intersection_list.append((bez_t, line_t))
      return intersection_list
docs: Returns tuples (t1,t2) such that bezier.point(t1) ~= line.point(t2).