Biarcs, how to find two arcs that define a path between two points and two tangents

wduk

New member
Joined
Dec 11, 2016
Messages
46
Hello

I am trying to find a simple way to find two arcs that connect two points with their two tangents.

Things i know from the start:

A = start point vector,
A' = tangent / direction vector at A (magnitude 1)
B = end point vector,
B' = tangent / direction vector at B (magnitude 1)

So it looks like this:

1587604095891.png

I'm aware there is also probably many solutions so i am looking to find one where the control points at each end point are equal in magnitude as a constraint to find the midpoint and the two arcs which should force a single solution ( i think? ).

I have already found how to get a circle from a start point, start tangent direction and end point. But solving for 2 tangents is a little beyond my math abilities.

I am trying to eventually find the two arcs with the following data:

Origin
Radius
StartAngle from counter clockwise travel
EndAngle from counter clockwise travel.
 
I've done a couple of diagrams that I hope will help you.

The center of each arc must be somewhere on a line that is perpendicular to the direction vectors and the "arcs join point" (in order for the double arc to join continuously). See the right angles in the diagrams below.

Did you consider the case A to I (blue arcs). It looks a bit strange to me. I recommend that you don't start working deeply on this until you've drawn several mock-up diagrams of the results that you'll obtain in different scenarios, to make sure that you're aware of all the results you'd get. Perhaps consider using a Bézier curve if it transpires that you don't like the arcs idea after all.

arcs.png

Anyway, in order to construct the green A to E, then length AB=BC=CD=DE=r (you would need to find r) and then the two arcs would be radius r with centres at B and D. NOTE: you could also try splitting this into different r1 and r2 where r1=AB=BC and r2=CD=DE.

Even though it appears that C might be a midpoint of AE in my diagram, this isn't necessarily so.

To do the maths, I'd write expressions for the positions of points B and D in terms of "r". Then you can say the distance from B to D must be "2r". Simplifying this should give you an expression for "r".

If the direction at E is reversed:-

arcs2.png

Then length AB=BC and separately CD=DE
 
I'm confused, the arc in the first drawing does not match the tangent at E?

I have bezier curves already, but they are problematic as they are not constant curves like arcs. (I am trying to program roads for a game). Arcs simply look better.

To find r where each very is equal in length - seems like there needs to be some extra information needed to solve it ?

You mention:
AB=BC=CD=DE=r

But all of these are unknown...so surely thats unsolvable ? Unless i am missing something ?
 
I've made an interactive graph (click).

You can move the points around on the graph and the arcs will be re-drawn. PLEASE ignore the title since it IS made from arcs not Bézier curves. Scroll the left panel to see the variables and calculations performed. Hopefully it will give you enough information to give you a starting point.

I'm confused, the arc in the first drawing does not match the tangent at E?

The green arcs go from A to E, and this matches doesn't it? The blue (purple) arcs go from A to I

EDIT: The graph isn't perfect for every case. Keep the [x0,y0] and [x1.y1] points below the other two. In your code you'll just need to do a simple point swap if the points are the other way up. And there are some cases when you'd probably want to switch to an alternative calculation corresponding to my second picture in post #2
 
Last edited:
From your graph it seems i have to choose a magnitude for the tangents arbitrarily rather than automatically calculating a solution where the two tangents have the same magnitude? Though this is a little over my skill level it seems compared to cubic bezier stuff :(

Also i think your calculates are backwards as the tangents imply direction, but your circles go the other direction. I draw on an example to show you what i mean though the dashed line is not a valid solution, it does how ever agree with the direction of the tangents:

1587709755560.png
 
From your graph it seems i have to choose a magnitude for the tangents arbitrarily rather than automatically calculating a solution where the two tangents have the same magnitude?

The tangent length doesn't change the resultant arcs. Try changing the length of a tangent while keeping it pointing in the same direction. The two dot system was just a convenient way to enter a direction. I could have used a single "slider" control for entering an angle but that didn't seem to be as user-friendly.

FYI: I calculate the length of the input tangents in the variables m1 and m2. This is only done so that the normal direction vectors can then be made unit length (variables adx and ady hold the normal direction vector for one point, and bdx and bdy for the other). These unit normals are used in the subsequent calculations.

Though this is a little over my skill level it seems compared to cubic bezier stuff :(

You can always improve. By attempting to write this game you're probably becoming more skilled !

Also i think your calculates are backwards as the tangents imply direction, but your circles go the other direction.

One of the problems with my Desmos implementation is that the lines AB and DE (refer to the diagram in post #2) always leave the tangent in the same relative direction (90 degrees clockwise). As a consequence of this, when rotating the tangents, it is possible to have these "normal lines" both pointing outwards. In this circumstance the normal lines should be flipped so that they both point toward each other again.

Moreover, in the circumstance that ONE of the normal lines points away from the other point, then you probably want to switch to using the scenario highlighted in second picture in post #2.

The implementation of biarcs seems to have a few "if this then do this" scenarios. This makes writing a solution that works in all circumstances a bit tricky/ tedious. Especially in Desmos.
 
... In this circumstance the normal lines should be flipped so that they both point toward each other again.

I fixed the above issue, see new version here

Moreover, in the circumstance that ONE of the normal lines points away from the other point, then you probably want to switch to using the scenario highlighted in second picture in post #2.

The above will be harder to fix. I might have a go at this later.
 
Also i think your calculates are backwards as the tangents imply direction, but your circles go the other direction. I draw on an example to show you what i mean though the dashed line is not a valid solution, it does how ever agree with the direction of the tangents:

View attachment 18148

By the way, please imagine that one of the tangents is pointing the other way. My intention with the graph is to show a continuous line, that's why I did the graph like it is. Note that it's VERY easy to get a vector pointing the opposite way, you just negate both the x and y components. Therefore if you decide to implement this as code, changing this behaviour will be VERY easy.
 
I will try to implement the math from your desmos graph and see will let you know how it goes or if i get stuck! Thanks for the help :)
 
I would hold off on implementing my solution, because it doesn't cope well in all cases.

Here is a decent page on the subject. There's an interactive demo half way down. It is better than my efforts, but still seems to be a little dodgy if you enter:- point1 (200,300) angle 90 and point2(400,300) angle 90... and then change angle2 slightly to 91 and you get a jump in the result.
 
I would hold off on implementing my solution, because it doesn't cope well in all cases.

Here is a decent page on the subject. There's an interactive demo half way down. It is better than my efforts, but still seems to be a little dodgy if you enter:- point1 (200,300) angle 90 and point2(400,300) angle 90... and then change angle2 slightly to 91 and you get a jump in the result.

Hmm you're right. It seems it might be a quirky issue due to the nature of circles in general which might be why so many people use cubic beziers. The only reason i don't like cubic bezier is because when i make the roads using them, the textures stretch or squish due to them not having a constant gradient like arcs do (plus arcs look a lot more accurate to how real roads are designed in real life).
 
the textures stretch or squish due to them not having a constant gradient like arcs do

To solve the texture problem with Beziers you could pre-compute a set of t values for each bend so that they are equally spaced when drawn. These points would be suitable for mapping textures onto and they wouldn't appear stretched. This could be done by splitting each curve into many (100?) t-slices, and calculating a linear distance between each on the curve. Then choose the t values that happen to be at, say, 1/5, 2/5, 3/5, and 4/5 of the total distance. As you know, the t value corresponding to 1/5 of the distance would probably not be at t=0.20. You could do this within your level editor and save it as part of the level's data.

The biarcs question is very interesting, but I think it's too hard to implement a fully flexible version in reasonable time. At least for me anyway, since I have no use for it myself!

Maybe someone else will be able to help you further.
 
Top