I\'m trying to find a way to calculate the intersection between two arcs. I need to use this to determine how much of an Arc is visually on the right half of a circle, and h
This test can be resumed with a one-line test. Even if a good answer is already posted, let me present mine.
Let assume that the first arc is A:(a0,a1)
and the second arc is B:(b0,b1)
. I assume that the angle values are unique, i.e. in the range [0°,360°[
, [0,2*pi[
or ]-pi,pi]
(the range itself is not important, we will see why). I will take the range ]-pi,pi]
as the range of all angles.
To explain in details the approach, I first design a test for interval intersection in R. Thus, we have here a1>=a0
and b1>=b0
. Following the same notations for real intervals, I compute the following quantity:
S = (b0-a1)*(b1-a0)
If S>0
, the two segments are not overlapping, else their intersection is not empty. It is indeed easy to see why this formula works. If S>0
, we have two cases:
b0>a1
implies that b1>a0
, so there is no intersection: a0=<a1<b0=<b1
.
b1<a0
implies that b0<b1
, so there is no intersection: b0=<b1<a0=<a1
.
So we have a single mathematical expression which performs well in R.
Now I expand it over the circular domain ]-pi,pi]
. The hypotheses a0<a1
and b0<b1
are not true anymore: for example, an arc can go from pi/2
to -pi/2
, it is the left hemicircle.
So I compute the following quantity:
S = (b0-a1)*(b1-a0)*H(a1-a0)*H(b1-b0)
where H is the step function defined by H(x)=-1 if x<0 else H(x)=1
Again, if S>0
, there is no intersection between the arcs A and B. There are 16 cases to explore, and I will not do this here ... but it is easy to make them on a sheet :).
Remark: The value of S is not important, just the signs of the terms. The beauty of this formula is that it is independant from the range you have taken. Also, you can rewrite it as a logical test:
T := (b0>a1)^(b1>a0)^(a1>=a0)^(b1>=b0)
where ^
is logical XOR
EDIT
Alas, there is an obvious failure case in this formula ... So I correct it here. I realize that htere is a case where the intersection of the two arcs can be two arcs, for example when -pi<a0<b1<b0<a1<pi
.
The solution to correct this is to introduce a second test: if the sum of the angles is above 2*pi
, the arcs intersect for sure.
So the formula turns out to be:
T := (a1+b1-a0-b0+2*pi*((b1<b0)+(a1<a0))<2*pi) | ((b0>a1)^(b1>a0)^(a1>=a0)^(b1>=b0))
Ok, it is way less elegant than the previous one, but it is now correct.
I think this works, but I haven't tested it thoroughly. You have 2 arcs and each arc has a start angle and a stop angle. I'll work this in degrees measured clockwise from north, as you have done, but it will be just as easy to work in radians measured anti-clockwise from east as the mathematicians do.
First 'normalise' your arcs, that is, reduce all the angles in them to lie in [0,360)
, so take out multiples of 360deg and make all the angles +ve. Make sure that the stop angle of each arc lies to clockwise of the start angle.
Next, choose the start angle of one of your arcs, it doesn't matter which. Sort all the angles you have (4 of them) into numerical order. If any of the angles are numerically smaller than the start angle you have chosen, add 360deg to them.
Re-sort the angles into increasing numerical order. Your chosen start angle will be the first element in the new list. From the start angle you already chose, what is the next angle in the list ?
1) If it is the stop angle of the same arc then either there is no overlap or this arc is entirely contained within the other arc. Make a note and find the next angle. If the next angle is the start angle of the other arc there is no overlap and you can stop; if it is the stop angle of the other arc then the overlap contains the whole of the first arc. Stop
2) If it is the start angle of the other arc, then the overlap begins at that angle. Make a note of this angle. The next angle your sweep encounters has to be a stop angle and the overlap ends there. Stop.
3) If it is the stop angle of the other arc then the overlap comprises the angle between the start angle of the first arc and this angle. Stop.
This isn't particularly elegant and relies on ifs rather more than I generally like but it should work and be relatively easy to translate into your favourite programming language.
And look, no trigonometry at all !
EDIT
Here's a more 'mathematical' approach since you seem to feel the need.
For an angle theta in (-pi,pi]
the hyperbolic sine function (often called sinh
) maps the angle to an interval on the real line in the interval (approximately) (-11.5,11.5]
. Unlike arcsin
and arccos
the inverse of this function is also single-valued on the same interval. Follow these steps:
1) If an arc includes 0 break it into 2 arcs, (start,0)
and (0,stop)
. You now have 2, 3 or 4 intervals on the real line.
2) Compute the intersection of those intervals and transform back from linear measurement into angular measurement. You now have the intersection of the two arcs.