You can script this functionality with python and install it as an addon. I have created such a script.
Github download link
To use the addon, press I in the Edit Mode of a curve. You'll be prompted into a modal operation where you can slide a new control point along the curve.
The original answer is below, it doesn't cover all the features of the current addon, even the point sampling will be replaced soon. The revision history shows the old addon for 2.7x.
The first step is to import some modules.
bpy
Interaction with Blenders data and operations
bgl
Blenders OpenGL wrapper
blf
Module for font drawing
numpy as np
Matrix handling, used for mathematical vector operations
mathutils
Use to create the mathutils.Vector
Create a Bezier class
A Cubic Bézier is a very simple mathematical construct.
It needs four points.
- first control point.
- first handle (right_handle)
- second handle (left_handle of second point)
- second control point
$$
b(t) = \sum_{i=0}^{3} \binom{3}{i} t^i (1-t)^{3-i} b_i \\
= (1-t)^3 b_0 + 3t(1-t)^2 b_1 + 3t^2(1-t) b_2 + t^3 b_3 \\
= (-b_0 + 3b_1 - 3b_2 + b_3)t^3 + (3b_0 - 6b_1 + 3b_2)t^2 + (-3b_0 + 3b_1)t + b_0, \quad t \in [0,1]
$$
The De Casteljau's algorithm illustrates how points on the curve are found. The formula takes a $t$ in $[0,1]$.
To split the curve at a specific $t$, we can use the method from this answer. Since we use numpy
, we can use the points as points.
class CubicBezier(object):
def __init__(self, points):
self.points = np.array(points).astype(np.float32)
def at(self, t):
pt = 1 * (1 - t)**3 * self.points[0]
pt += 3 * t**1 * (1 - t)**2 * self.points[1]
pt += 3 * t**2 * (1 - t)**1 * self.points[2]
pt += 1 * t**3 * self.points[3]
return pt
def split(self, t):
p1, p2, p3, p4 = self.points
p12 = (p2-p1)*t+p1
p23 = (p3-p2)*t+p2
p34 = (p4-p3)*t+p3
p123 = (p23-p12)*t+p12
p234 = (p34-p23)*t+p23
p1234 = (p234-p123)*t+p123
return [p1,p12,p123,p1234,p234,p34,p4]
Next, we need to sample the point closest to the mouse position. Using this algorithm, pick discrete samples and convert them into the 2d region
Thats basically everything from the maths side, now just wrap it in a modal operator.
Here is an example of a modal operator drawing in the 3D View.