I'm currently working on a python library to extract pen strokes from TrueType fonts - Here I'm defining a stroke as a midline running between a test point and its reflected point. I'm using the term reflected point to refer to the closest point on the opposite side of the 'ink' region which under normal circumstances (apart from say at a serif stem) would also have a tangent in the opposite direction to the test point.
I'm working in python using fontTools and a bezier library that I rolled from the processing code described at http://pomax.github.io/bezierinfo/#extremities .
Where I'm stuck stuck at the moment is on how to find the point on a quadratic bezier curve that has a given tangent, my mathematics skills are pretty rudimentary on a good day with a clear head [which it is not rite now] so I was hoping someone with a sharper mind could point out a birds eye overview on how to achieve this.
At the moment the only thing I can think of is to approach it numerically with something similar to the Newton-Raphson root finding algorithm but evaluating the 1st derivative against the target direction values. I am hoping however there is a symbolic solution as this needs to be run on every other curve for each curve in the glyphs contours.
Using the notation given in http://pomax.github.io/bezierinfo/#extremities, a quadratic Bezier curve is given by:
B(t) = P1*(1-t)**2 + 2*P2*(1-t)*t + P3*t**2
Therefore, (by taking the derivative of B with respect to t) the tangent to the curve is given by
B'(t) = -2*P1*(1-t) + 2*P2*(1-2*t) + 2*P3*t
= 2*(P1 - 2*P2 + P3)*t + 2*(-P1 + P2)
Given some tangent direction V, solve
B'(t) = V
for t. If there is a solution, t = ts, then the point on the Bezier curve which has tangent direction V is given by B(ts).
We essentially want to know if two vectors (B'(t) and V) are parallel or anti-parallel. There is a trick to doing that.
Two vectors, X and Y, are perpendicular if their dot product is zero. If X = (a,b) and Y = (c,d) then the dot product of X and Y is given by
a*c + b*d
So, X and Y are parallel if X and Y_perp are perpendicular, where Y_perp is a vector perpendicular to Y.
In 2-dimensions, if in coordinates Y = (a,b) then Y_perp = (-b, a). (There are two perpendicular vectors possible, but this one will do.) Notice that -- using the formula above -- the dot product of Y and Y_perp is
a*(-b) + b*(a) = 0
So indeed, this jibes with the claim that perpendicular vectors have a dot product equal to 0.
Now, to solve our problem: Let
B'(t) = (a*t+b, c*t+d)
V = (e, f)
Then B'(t) is parallel (or anti-parallel) to V if or when
B'(t) is perpendicular to V_perp, which occurs when
dot product((a*t+b, c*t+d), (-f, e)) = 0
-(a*t+b)*f + (c*t+d)*e = 0
We know a, b, c, d, e and f. Solve for t. If t lies between 0 and 1, then B(t) is part of the Bezier curve segment between P1 and P3.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With