Tuesday, May 20, 2008

Clock version 3 with Lunar Illumination

Version 3 of the clock (revised to 3.0.11 on 2-Nov-2008) brings lunar illumination indicators to the days of the month, and therefore includes a substantial amount code for astronomical calculations, all based on algorithms created by Jean Meeus, and described in his book Astronomical Algorithms, second edition, 1998. Therefore, credit for all of the astronomical data and algorithms goes to the good Mr. Meeus, while credit for this peculiar Javascript implementation, and any of its (as yet undetected) bugs, is mine – all mine.

One subtle new feature is the ability to rotate the clock. As of revision 3.0.8, drag anywhere, and the clock rotates accordingly, while continuing to update the time as usual. Click anywhere to restore the clock to its normal, upright position. If this feature has any actual utility, it is the ability to view the lunar illumination indicators in their correct orientations.

Unfortunately, even rotated to the proper vertical orientation, the lunar disks will not necessarily represent the orientation you'd see if you went outside and looked at the moon. The problem is the inability to calculate the parallactic angle, which depends on one unavailable piece of information: the viewer's latitude. Otherwise, the disk illuminations shown are quite accurate, based, as they are, on gratuitously precise calculation of the positions of the Sun, Earth and Moon. Basically, every time Meuus said "if no high accuracy is required, do it this way" I did it the other way. I think a clock should have precise and beautiful innards. And because this one is virtual, all of the gratuitous levers, springs and gears add nothing to the cost, and therefore neither economics, nor common sense, need be allowed to spoil the clock maker's fun.

On the off chance that anyone else has a use for all of those extra mechanics, I'm releasing the clock under the GNU General Public license, version 3 or later. (I've also written a much cleaner Java implementation, complete with unit tests, if anyone has a use for that.)

As always, the clock is best appreciated by opening it in a separate window, and making that window as large as possible.

Please enjoy.

Ideally, you'll see an active clock here, provided that your browser supports Javascript and the Scalable Vector Graphics (SVG) standard.

Lessons Learned

  • Fixed in clock version 3.0.11: The hour-of-day indicator now adjusts to the change from daylight savings time to normal time.
  • Firefox 3.0.1 renders neither the text on the clock face, nor the time indicators. There were no such problems in the earlier versions of Firefox 3, though I don't know at which build the problem was introduced.
  • Fixed in clock version 3.0.8: When using the Javascript methods for setting the fields of a Date object (year, month, day, hour, etc.), it is important to use those methods in order from least significant (milliseconds) to most significant (full year). Otherwise, the date may be corrupted.
  • No version of Firefox or Safari respects the zoomAndPan attribute of the svg element. According to section 16.7 of the SVG 1.1 specification, when the zoomAndPan attribute is set to magnify, “the user agent shall provide controls to allow the user to perform a "magnify" operation on the document fragment.” Sadly, that doesn't happen at present.
  • Safari 3.1.1 refused to execute the script in the clock when I initially embedded it in this post. After some experimentation, the problem was resolved by including the UTF-8 Byte-Order-Mark (BOM) at the start of the clock's source file. Firefox had no problem with the absence of the BOM, and Safari shouldn't have had a problem, either, as the XML specification is very clear about how to identify the character set of an XML file with, or without, a BOM. If I can implement that algorithm (and I have, in Qwicap), gosh darn it, so can Apple. (But perhaps Safari does implement it, and the addition of the BOM merely correlated with, rather than caused, the resolution to this problem. Right now, I don't care enough to perform all of the tests required to find out.)
  • Neither Firefox 3.0b5, nor, can cope with a negative X radius for the ellipse that defines an arc drawn by the "arc" command of the path element. Safari 3.1.1 handles this without any problem. Fortunately, it is possible to workaround the Firefox bug(s) by using the absolute value of the X radius in the arc definition, and then changing the arc's "large arc" flag to zero when the radius goes negative.
  • Firefox runs this clock very slowly. One might suspect that all of the additional astronomical computation associated with the lunar illumination indicators is responsible, but, in fact, that code runs only once when the clock begins running and then once more each time the month changes. My best guess is that the Firefox 2 SVG engine is of generally low performance (I believe that's widely acknowledged), and that it probably redraws more of the image than is strictly necessary whenever the image changes (for example, when the second hand moves). Those two factors combine with the increased graphic complexity of the new version of the clock to consume a startling amount of CPU time, sometimes so much that it takes much more than a second to redraw the clock after each "tick" of the second hand. While that looks awful, the clock still keeps perfectly good time; it just can't display it smoothly.
  • Firefox 3.0b5 has a dramatically faster SVG engine than its predecessor, and therefore has no trouble keeping the second hand moving steadily, while using very little CPU.
  • The SVG engine in Firefox 3.0b5 has bugs that the engine in does not. The failure to draw the names of the months in the clock is one such bug. (Strangely, the names put in a partial appearance when the clock is rotated.)
  • For the moment, the hands-down winner for SVG performance and correctness is Apple's Safari, version 3.1.1. Resize the clock to fill your screen and it'll not only draw correctly, but it will barely touch your CPU while doing so. Hopefully, the problems in Firefox 3's SVG engine will be resolved soon, and we'll have two cross-platform browsers with high-performance SVG engines in them. (Perhaps there already are two, or more, such browsers - I haven't investigated Opera, for instance.)
  • It's very difficult to think in Java, and implement in Javascript. Or, more specifically, to write the code in Java first, in order to get it clean and unit tested, and then to translate it into Javascript. I still have not grasped the "zen" of Javascript, and am just stumped when it comes to good ways to translate things like static methods and constants into something equally clean and usable in Javascript. So far, I just don't like the Javascript language one bit. Only its unique position as the embedded language of web browsers gives it any value to me. Nonetheless, until I do a decent job of thinking in Javascript, these judgements are premature.
  • Cross-compiling Java into Javascript, as the Google Web Toolkit does, sounds great, but GWT's current class library is too minimal for this clock's needs. If they port the Calendar and GregorianCalendar classes (a need they seem to acknowledge in their forums), I'll have to give it another try.
  • Getting the capabilities of the Java language into browsers without the current overhead of firing-up a Java Virtual Machine (JVM), makes the implementation of a JVM in Javascript intriguing.