Thursday, February 08, 2007

Finessing, with Trig

Adventure in a rather flatter environment today; the cartesian plane. An interesting problem came my way this morning, and I found it so exquisitely satisfying to solve that I decided to set out my journey across said plane for the edification of my readership. I realise that many of you will be starting out rather sceptical that words like “elegant” belong on even the same page as a mathematical formula; what I want to give you is sense of my own wonder that such fearsome beasts as trigonometric functions can be whispered and coaxed into perfect co-operation, solving problems with no apparent relation to geometry – and the sheer pleasure of mathematical tinkering.

For anyone still reading, my problem was this: a certain object is to be drawn by a computer using two very different devices. This object has an opacity ranging between 1 (opaque) and zero (invisible); now, the artist has found that his favoured opacity value looks nice on one output device, but a little too solid on the other. He doesn't want to set the opacity twice - he just wants his picture to "look right" on the second device. Clearly, I need a "creative" way to interpret my picky artist's choice of opacity.

Perhaps I could simply halve the value used for the "too solid" device? No, that wouldn't do; a setting of "fully opaque" would give a solid rendering on one device, and a semi-transparent from the other.

Clearly, I needed a more elegant function; some formula that would "preserve" the start and end values (1 and 0), yet interpret intermediate values in a way that improves (increases) the transparency for the second device. Since the default(x) forms a straight line, I realised that I need a curve to get “under” x while still starting and ending at the same points. Below, you can see a chart like the one I used to hunt for my function; x and x/2 form straight lines, while the functions sine, cosine and tan form various curves. The tan (purple) gave me an “aha!” moment. True, it did not start precisely at 1; but it “dived” beautifully at first, before leveling out and settling gently onto zero.

Nearly there; to make my formula start at 1, I needed to “squash” it to fit my range: I scaled it by adding an extra term: now, I had tan(x) * 1 / tan(x). Much better! Now, my curve started and finished with the line for x – but I wasn't happy yet. Wouldn't an even steeper gradient be better? It occurred to me that squaring x might be the answer: numbers between 1 and 0 get smaller when squared. For example, 0.8 squares to 0.64, and 0.5 squares to 0.25 – while, handily, 1 squares to 1 and 0 to 0 – perfect! Adjusting our formula one last time, we arrive at tan(x^2) * 1 / tan(x) – or, visually, a curve which precisely fits the range we needed, swooping gracefully towards full transparency. If the (elegantly!) fudged transparency values still don't quite suit our artist, higher or lower powers of the first x in our formula can be used to “tune” the dip of our curve to his taste.

No comments: