If I have three points that create an angle, what would be the best way to determine if a fourth point resides within the angle created by the previous three?
Currently, I determine the angle of the line to all three points from the origin point, and then check to see if the test angle is in between the two other angles but I’m trying to figure out if there’s a better way to do it. The function is run tens of thousands of times an update and I’m hoping that there’s a better way to achieve what I’m trying to do.
Let’s say you have angle
DEF(Eis the “pointy” part),EDis the left ray andEFis the right ray.Step 1. Build line equation for line
EDin the classic Al * x + Bl * y + Cl = 0 form, i.e. simply calculate(Pay attention to the subtraction order.)
Step 2. Build line equation for line
FE(reversed direction) in the classic Ar * x + Br * y + Cr = 0 form, i.e. simply calculate(Pay attention to the subtraction order.)
Step 3. For your test point
Pcalculate the expressionsYour point lies inside the angle if and only if both
SlandSrare positive. If one of them is positive and other is zero, your point lies on the corresponding side ray.That’s it.
Note 1: For this method to work correctly, it is important to make sure that the left and right rays of the angle are indeed left and right rays. I.e. if you think about
EDandEFas clock hands, the direction fromDtoFshould be clockwise. If it is not guaranteed to be the case for your input, then some adjustments are necessary. For example, it can be done as an additional step of the algorithm, inserted between steps 2 and 3Step 2.5. Calculate the value of
Al * Fx + Bl * Fy + Cl. If this value is negative, invert signs of all ABC coefficients:Note 2: The above calculations are made under assumption that we are working in a coordinate system with X axis pointing to the right and Y axis pointing to the top. If one of your coordinate axes is flipped, you have to invert the signs of all six ABC coefficients. Note, BTW, that if you perform the test described in step 2.5 above, it will take care of everything automatically. If you are not performing step 2.5 then you have to take the axis direction into account from the very beginning.
As you can see, this a precise integer method (no floating point calculations, no divisions). The price of that is danger of overflows. Use appropriately sized types for multiplications.
This method has no special cases with regard to line orientations or the value of the actual non-reflex angle: it work immediately for acute, obtuse, zero and straight angle. It can be easily used with reflex angles (just perform a complementary test).
P.S. The four possible combinations of
+/-signs forSlandSrcorrespond to four sectors, into which the plane is divided by linesEDandEF.By using this method you can perform the full “which sector the point falls into” test. For an angle smaller than 180 you just happen to be interested in only one of those sectors:
(+, +). If at some point you’ll need to adapt this method for reflex angles as well (angles greater than 180), you will have to test for three sectors instead of one:(+,+),(-,+),(+,-).