Drawing the clock-like indicators on the dashboard
The dashboard in Aviator is a thing of beauty that not only looks the part, but manages to convey a lot of complex information about the current flight model in a succinct and effective manner. The most common dashboard control is the clock-like dial used for the airspeed indicator, altitude indicator, compass, vertical speed indicator and slip-and-turn indicator, so let's see how this dial works under the hood.
The core is the GetHandVector routine, which performs a calculation to work out the vector for a dial indicator hand, given a value to show on the dial. It calculates this using a simple triangle model - there's no trigonometry here.
First, we work out which quadrant of the dial we want to draw the hand in, and set the direction in R accordingly. We do this by repeatedly subtracting the range of a single quadrant from the value to show, counting quadrants as we go, until we go past zero, at which point we know which quadrant the dial hand is in.
Then we work out the vector from the centre point of the dial to the end of the hand, using a simple triangle. Imagine the possible positions of the end of the dial hand as a vertical diamond shape, like this:
^ ^ .´ `. |`. (x, y) .´ `. r | /. .´ `. | / `. .´ `. |/ `. < + > +--------> `. .´ (0, 0) w `. .´ `. .´ `. .´ v
It doesn't necessarily look like it in in ASCII, but imagine that the diamond is a rotated square, so all the angles are right angles.
If the end of our hand is always on the outside of the diamond shape above, then if we consider the top-right quadrant, the equation of the edge line is given by y = - x + w. So as the hand goes from pointing straight up to pointing to the right (12 o'clock to 3 o'clock), x goes from 0 to w, y goes from w to 3, and y = x - w. For the next quadrant down, 3 to 6 o'clock, we can negate y to get y = -(x - w) = w - x, and we can do a similar sign switch for the other two quadrants.
So, given an x-coordinate for our hand, we can work out the y-coordinate using y = x - w or y = w - x, depending on the quadrant. And if we choose to set the origin at the centre of the dial, then the x- and y-coordinates are effectively x and y-deltas, which is what we need to generate in order to use the routine at DrawVectorLine to draw the hand on the dial.
Finally, if we apply a simple cap to the values of x and y, this has the effect of "blunting" the corners of the diamond, like this:
_______ .´ `. | | | + | | | `._______.´
It turns out that this kind of approximation for the movement of a dial hand is pretty good, even though it isn't describing anything like a perfect circle. If you look carefully, you can see the dial hands describe this exact shape as they move around their dials; it's a clever trick that makes life much simpler for the programmer, but without making it obvious.