1
votes

I can't even remember since when I've been looking for a way to draw a curved line between two points.

I've tried many things like QuadCurves2D, Bezier Curve, etc..., but I'm failing to find a control point.

The idea here is to draw a curved line between two points independently where they are or which angle between them(user can change the points' position by clicking alt and dragging it over the screen)

This is what I've got so far... Wrong curve between two points

As you can see above, the curve is absolutely wrong.

What I expect is something like this:

Correct curve

1
Two points only define a line. If you want a smooth curve, you need more than two points to define it.user149341
@duskwuff I see.. But what I'm trying to understand is exactly what you're saying. I want to find a Control Point between these two points so I can have a curved line.Gabriel Câmara
You need to choose the control point! Consider the two lines you have between 0 and 5 — how is your program supposed to decide which of the two to draw?user149341

1 Answers

3
votes

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.