On 12-10-12 23:11, Johan Engelen wrote:
> On 12-10-2012 14:59, Jasper van de Gronde wrote:
>> To deal with zero-length handles, the easiest (and correct) method is
>> probably to specify that the curvature is zero at the endpoint with the
>> zero-length handle (if both handles are zero-length, then the Bézier
>> curve forms a line segment). That this is correct can be derived from
>> the fact that the unit tangent vector at the endpoint with a zero-length
>> handle points in the same direction as the second derivative (so locally
>> it's a straight line). This is a consequence of l'Hôpital's rule btw.
> I don't think this is correct.
That observation /is/ :)
Note that the case of two zero-length handles or two coinciding handles
of which one has zero-length gives a straight line (segment), though. So
for that case it makes perfect sense to have zero curvature throughout
(and this actually follows from the description below).
> It is possible to make segments with and
> without a zero-length handle that look exactly the same.
It should not be, in general. (Fewer degrees of freedom.)
> Also, as you
> are moving the handle closer and closer to the knot, it does not
> converge to zero curvature, in fact it tends to lead to higher curvature
> instead of lower curvature.
There is essentially a bit of instability here. Yes, if you approach it
from most angles, then the curvature increases. However, if you follow
l'Hôpital's rule to compute the unit tangent vector at t=0 (so the
derivative divided by the norm of the derivative), or (which is a bit
easier), the derivative of y w.r.t. x, then you see that the unit
tangent vector at t=0 points to the second handle. If you then take the
limit as P2 approaches P1 from the direction of P2 (or opposite), you
get zero curvature.
Also (just as an observation), as the handle gets smaller, its influence
decreases. So although locally you have a very large curvature, it's
only over a very small portion of the curve.
> Wouldn't l'Hopital imply that you can get
> away by using +1 higher derivs instead?
You're completely right. (If you intended taking the derivative of the
numerator and denominator and dividing those.) However, higher
derivatives can (and will) still be zero in this case, so this
complicates things a bit.
However, if you make the first handle zero-length, and then compute the
limit of the curvature as t goes to zero, then you find that the
curvature is equal to det([P3-P1,P4-P1]) divided by something that is
zero at t=0 and positive for t slightly above zero, as long as P3-P1 is
not zero-length. Thus, if det([P3-P1,P4-P1])=0, (all points and handles
on a line), then the curvature at t=0 is zero, and otherwise it is
infinite with the sign of det([P3-P1,P4-P1]).
So, I stand corrected, the rule isn't zero-length=zero-curvature, but
rather, a zero-length P1-P0 implies that the curvature at P0 is either
-infinity, zero or +infinity, depending on the sign of
det([P3-P1,P4-P1])=0. (Assuming at least some point does not coincide
>> One possible way to specify the restriction for this kind of join would
>> be to limit the arc-length on either side of the join. The main problem
>> is then joining the end points, as a line segment between the two is not
>> guaranteed to not intersect the circles. Some experimentation suggests
>> that it might be possible to define a sensible boundary using
>> interpolation between the two end points that is guaranteed not to
>> intersect either of the circles.
> I have no clue what you are saying here. :-)
Okay, turns out my assumption about how miterlimit worked was wrong, but
I still think it makes sense. Basically, when using a miter join, the
miter can get infinitely large. This causes all sorts of problems, so
"miterlimit" was introduced. Basically this says: "a miter larger than
so and so can't be good". The solution then is to fall back to a bevel
join... I had assumed it would just "cap" the miter (as this would still
prevent it from being insanely large, while preventing a sudden jump
from miter to bevel).
For the moment, assume that SVG had chosen to simply "cap" the miter.
For example, one could restrict the length of both sides of the miter to
the miterlimit and draw a straight line between the two. This should
cause no further problems (at least in rendering, maybe there are other
issues that caused the committee to not go down this route).
Now, when joining using arcs, it seems to make even more sense to simply
"cap" the join. Otherwise you can have a nice curved join one minute and
a bevel (or miter) join the next, seems a bit weird to me. So suppose
that you simply "cap" the join. How do you go about capping it?
That brings us back to what I was saying. Because both sides of the join
are curved, there is no guarantee that a straight line between the
endpoints (of the limited sides of the join) does not cross either side
of the join (which I think would look really weird). So you want some
other kind of "cap". This is why I took a short look into finding a
sensible cap by interpolating between both arcs. This looks promising,
but a straightforward interpolation between the two arcs still has some
problems. But feel free to ignore these fine points, the gist is that if
one wanted to "cap" the join instead of falling back to a miter or bevel
(and introducing discontinuous/unstable behaviour), then some thought
needs to go into how to actually cap it.
But of course it might just be simplest to fall back to a miter or bevel.