You should be automatically redirected . If not, visit
http://newlisper.wordpress.com
and update your bookmarks.

10/06/2007

A passing phase

I know enough newLISP to be dangerous. I've got to the stage where I'm not thinking about the language too much, but concentrating on the problem in front of me. This is probably as close as I'll get to 'programming', although I wish there was a more suitable verb than that to describe it. It's not 'hacking', which implies (to me) a bit of serious skill. Perhaps 'kludging' is a better word.

Whatever it's called, it's good to be able to solve practical programming problems with relative ease. When I was writing AppleScripts, I was always hitting restrictions: "Now we'll just sort the list. Oh, there's no sort function. I'll have to write my own." Or "Finally we'll replace all those spaces with a - oh, there's no search and replace function either." Using newLISP, the only restriction I regularly encounter is my own limited skill as a programmer. There are very few basic tasks that you can't do with newLISP's built-in library.

To give an example, I recently ran off some printed calendars showing the moon phase for each day of the year. This is June's page:

This isn't a task that taxes newLISP of course. But it took a few hours of kludging to get the equations to generate the correct answers, and another hour or so of kludging to figure out the PostScript required to do the drawing. The script(s) started off being quite well organized, but in the rush towards the deadline I confess that the quality control went out the window. As I inserted more and more adjustments and fixes, it looked like it was going to end in a mess of spaghetti. Eventually it got to the stage where I didn't want to touch certain bits of code in case it fell apart! I don't want to look at some parts of it...

Probably not production code, then. :-)

Now that I've finished, I should, of course, go back and rewrite it all from scratch, and design it in a more structured function before coding it. But I suspect that's not going to happen.

This function, at least, doesn't look too bad. It draws a moon, given a radius (pixels), phase (degrees), declination, and angle:

(define (draw-moon radius ph decl (angle 0)) 
    ; draw moon at current x-pos and y-pos
    (let 
       ((moon-centre-x 
          (add x-pos  (div box-half-width 2)))
        (moon-centre-y 
          (add y-pos  (div decl 10) (div box-half-height 2)))
        (phase (mod (int ph 0 10) 360))) 
; start (ps (format {gsave})) (ps (format {%f %f translate} moon-centre-x moon-centre-y)) (ps (format {%f rotate } angle))

; draw dark coloured background (set-backgroundcolour) (ps (format {%f %f %f %f rectfill } (mul -1 *box-half-width*) (mul -1 *box-half-height*) (mul 2 *box-half-width*) (mul 2 *box-half-height*))) ; draw phase (cond ((or (= phase 0) (= phase 360)) ; new moon (set-mask-colour) (ps (format {newpath %f %f %f 360 0 arcn fill} 0 0 radius))) ((and (> phase 0) (<= phase 90)) ; waxing to first quarter (set-moon-colour) (ps (format {newpath %f %f %f 90 270 arcn fill} 0 0 radius)) (set-mask-colour) (set 'moon-width (mul radius (div (sub 90 phase) 90))) (ps (format {newpath %f %f %f %f %f %f ellipse fill} 0 0 moon-width radius 0 360))) ((and (> phase 90) (< phase 180)) ; half to full (set-moon-colour) (ps (format {newpath %f %f %f 90 270 arcn fill} 0 0 radius)) (set 'moon-width (mul radius (div (sub 90 phase) 90))) (ps (format {newpath %f %f %f %f %f %f ellipse fill} 0 0 moon-width radius 0 360))) ((= phase 180) (set-moon-colour) (ps (format {newpath %f %f %f 270 90 arcn fill} 0 0 radius)) (set 'moon-width (mul radius 2 (div phase 360))) (ps (format {newpath %f %f %f %f %f %f ellipse fill} 0 0 moon-width radius 0 360))) ((and (> phase 180) (<= phase 270)) ; waning full to half (set-moon-colour) (ps (format {newpath %f %f %f 270 90 arcn fill} 0 0 radius)) (set 'moon-width (mul radius (div (sub 90 (mod phase 180)) 90))) (ps (format {newpath %f %f %f %f %f %f ellipse fill} 0 0 moon-width radius 0 360))) ((and (> phase 270) (< phase 360)) ; waning to new (set-moon-colour) (ps (format {newpath %f %f %f 270 90 arcn fill} 0 0 radius)) (set 'moon-width (mul radius (div (sub 90 (mod phase 180)) 90))) (set-mask-colour) (ps (format {newpath %f %f %f %f %f %f ellipse fill} 0 0 moon-width radius 0 360)))) (ps {grestore})))

This function draws the moon's phase using circular arcs and ellipses - this is probably not scientifically accurate, but sufficient, at least graphically for my purposes. I was struggling to find a way to draw crescents and bulging moons, but then I realised that I could just draw ellipses and circles on top of each other to get shapes which looked OK.

At first, each square had more astronomical data in it, and the moon was drawn at an angle, because the "position angle of the bright limb", as it's called, can be calculated with reasonable accuracy. Unfortunately, I had trouble getting accurate results, and couldn't make it work graphically in time for my deadline.

The thing that occurs to me, though, is that I'm not being distracted by the language I'm using (even though I'm not using it that wisely), but thinking solely about the task in hand.

2 Comments:

At 23:30, Anonymous Anonymous said...

You reached the kluding state ;-) welcome to to world of automation, where the brain does the thinking and newlisp the drinking ;-)

Nice work cormullion...hope you put it into guiserver too because i like an applet like that on my desktop ;-)

Enjoy !

 
At 00:43, Blogger Jeff said...

Nice, cormullion. Forget about rewriting. Only do that if you need a new feature in the code that the old code base won't permit. Refactoring (rewriting parts of the code to clean them up or make them more efficient, expressive, or both) is what you need.

Jeff
http://artfulcode.nfshost.com

 

Post a Comment

Links to this post:

Create a Link

<< Home