Step one: axis-align your two points so that one of them's on (0,0), and the other's on ([...],0). Let's say we have two points,
P1 = {a,b)
P2 = {c,d}
we translate them so that p1's on 0,0:
P1 = {0,0}
P2 = {c-a,d-b}
then we rotate p2 about (0,0) so that it ends up lying on the x-axis:
a = -atan2(dy,dx) = -atan2(d-b, c-a)
P2ʹ = {
p2.x * cos(a) - p2.y * sin(a),
p2.x * sin(a) + p2.y * cos(a)
}
note the - in front of the atan2
call because we don't want to know the angle "from axis to point", but from point to x-axis. We now have two axis-aligned points (let's call that rotated x-coordinate for the new P2 "v"):
P1 = { 0 , 0 }
P2ʹ = { v , 0 }
We can now do whatever we want in terms of curve construction. While usually pretty ugly, we can construct a quadratic curve with a control point that's at (v/2, ...)
and has a height "whatever you want based on how strong you want the curvature to be. This will give us a coordinate relative to the transform-invariant coordinates, so we just apply the rotation/translation in reverse:
C = (v/2,h), then rotate by -a, then translate by (a,b)
(note that - sign again). We already know where P1 and P2 were, so we don't need to do any computing there. Bezier curves are defined by their "hull points" and well-behaved with regards to linear transformations so all this translation/rotation business makes not difference to the algorithm that draws the curves. Just plug the six values into the quadratic draw functions and presto. A curve from P1 to P2 controlled by C.
Of course you probably want a cubic curve instead because quadratic curves are quite ugly, so instead of defining a C, we can define a C1 and C2:
C1 = (v/3, 0)
C2 = (2*v/3, 0)
and then raise/lower them both by the same amount; then we anti-rotate and anti-translate them and plug the P1, C1, C2, P2 we now have into a cubic bezier drawing function: done. Pretty curves.