photos

15/Apr/2010 PA
12/Apr/2009 Sunrise Circus
15/Mar/2009 Lego
08/Mar/2009 Moomba
13/Feb/2009 Car Smokey Sunset
26/Jan/2009 Fireworks
26/Oct/2008 Synchrotron
07/Jun/2008 Model Trains
06/Jun/2008 Wedding
04/Jun/2008 Central Coast Trip
more photos...

lavtools

03/Nov/2011 yuvvalues
03/Nov/2011 yuvrfps
03/Nov/2011 yuvdiff
03/Nov/2011 yuvaddetect
03/Nov/2011 yuv2jpeg
more lavtools...

Creativity

The TRIP is the mental projection of my digital self. Including all areas of digital work I have been involved with, including Music, video, photography...

All good web pages must have the collection of absolutely useless pictures. Designed for no purpose other than to consume kilobits. And hopefully show off some of my Photographic skills. Web design skills, and uses one php script to drive the whole index. Also see the Photography section of the Silicontrip Website.

The Creative section of the TRIP is my imagination trying to run free. I have a fascination with sexual, spiritual and meta physical abilities, and these stories show it.

Part of the images directory contains some of my digital artwork. These images have been created or enhanced by myself, with the help of the 1s and 0s machine.

album

23/Feb/2011 Trace
17/Jan/2010 Food
30/Oct/2009 Airbrush
18/Jun/2009 Focal
01/Jun/2009 Transport
01/Jun/2009 Misc
31/May/2009 Artwork
24/Apr/2009 AirbrushScales
18/Apr/2009 Probe
10/Jan/2009 Scanimation
more album...

blog

27/Jan/2012 ZFS for OSX
14/Dec/2011 Scripting Bridge
02/Dec/2011 Core Audio Units
01/Mar/2011 A useful bit of code
22/Dec/2010 Larger than 4G files on FAT for OSX
08/Dec/2009 Time machine on non HFS drives
21/Oct/2009 My Strengths
27/Aug/2009 Train Hitchiking
11/Jul/2009 A litre of onions
19/Jun/2009 FSCK for NTFS
18/Jun/2009 Automated Focal Deconstruction
12/Jun/2009 Perl code to write BMPs
07/Jun/2009 More Lego
01/Jun/2009 Latest Airbrushing
30/May/2009 Happy Birthday to me
24/May/2009 Comments Engine
09/May/2009 Skills Matrix
24/Apr/2009 Airbrush simulator
19/Apr/2009 Ben 10 Board game
29/Mar/2009 How fresh is your fresh food?
more blog...

BACK

28/Sep/2007

Train Map

I recently decided to honour my inner child and program a graphical train network, showing the timetable data. As the project progressed I realised I needed a real time graphic display using CamelBones and perl.

Perl Cocoa Custom NSViews

I'm a bit of an old school programmer, growing up on a 12 character Casio Computer then Commodore 64 and Amiga.

Graphics on computers were for showing results, fancy animations and demos. You run your program, it processes for a bit and displays a nice shiny graphic when it's done.

Very few of the courses I did made much mention of how to program a GUI. Even when doing X11 programming at Uni, using Motif, the interface was defined programmatically. openWindow, drawWidget, register callback.

Even my more recent java projects have been, do some processing, draw something on the screen, wait for user input, do more processing. All follows on from my experience of programming CLI based systems. So you can tell that I'm not really an event driven GUI kinda guy.

Recently I decided to honour my inner child who always wanted to program a train map program, displaying a map of the train network and showing where the trains *should* be on the network from the timetable information, I don't have access to any real time data so the time table is as real as it gets.

Unfortunately when I first wanted to write this, some 20 years ago, I didn't have the experience to manipulate time table data into something that says; "A train should be halfway between Blackburn and Nunawading", so although I had made some cute train graphics and a full screen representation of the train network, I couldn't work out where the trains should be.

More recently, I decided to try this again. First designing the thing in java, since I may be able to manipulate the data in a way that could solve what I once considered a difficult problem. My first problem was getting the time table data into the computer. I wasn't interested in typing station data for about 40 stations and 150 odd trains that ran throughout the day.

Fortunately, with the web and all, the timetable data is available, in a horridly table formatted html page. So I wrote a perl program to parse the web pages into something more computer friendly. While deciding on this intermediate format, I ended up finishing a text representation of the program, in perl.

13:36 FlindersStreet - SouthernCross 13:45 (Parliament)
13:44 Burnley (Parliament)
13:43 SurreyHills - Chatham 13:45 (Parliament)
13:44 Mitcham (Parliament)
13:44 Mooroolbark (Parliament)
13:43 FerntreeGully - UpperFerntreeGully 13:47 (Belgrave)
13:43 Heatherdale - Ringwood 13:46 (Lilydale)
13:44 MontAlbert (Belgrave)
13:43 Hawthorn - Glenferrie 13:45 (Lilydale)
13:42 FlindersStreet - SouthernCross 13:45 (Belgrave)

Showing 9 trains on the network and their current location. I was happy with this for a little while, as I saw how far behind Connex' trains were from their timetable data. Of course a graphical representation of this is what I really wanted.

I'm not a huge fan of graphical user interfaces, it's much easy to tell someone to type "clean" into a cli than it is to describe clicking on the icon which looks like a shower with a biscuit underneath it, no not the shower with the sponge...

There is a well defined way for displaying characters on a screen and how to get text input, but graphics? Every operating system and toolkit has it's own method for opening windows, making porting software difficult.

The only graphical display engine that seems to be almost everywhere is postscript. So I produced a network map based on Lat and Long coordinates taken from Google maps. Shamelessly ripped the train graphic from Connex' own network map. Re coded the perl script to output a percent.

FlindersStreet SouthernCross 0.886666666666667
FlindersStreet 
Chatham Canterbury 0.733333333333333
Heatherdale 
UpperFerntreeGully FerntreeGully 0.366666666666667
Boronia FerntreeGully 0.433333333333333
Mitcham Heatherdale 0.866666666666667
SurreyHills 
Burnley Hawthorn 0.733333333333333

Since I knew the locations of the station, I simply drew a straight line between them and displayed the location based on the percentage. Half of this was perl code the other graphic half was Postscript code.

Preview under OSX has a bug that it fails to re-read an open file even if it has been modified since, the window has to be closed and the new file reopened. So even some form of scripted update looked clunky as the window would close and open up somewhere else.

Time to see if I could get Perl to talk directly to Cocoa. I found a toolkit called camel bones which allows cocoa toolkit to be programmed in Perl. It wasn't exactly what I was after, which was Open Window, Display Graphics.

GUI toolkits take the opposite approach, the window needs something to display so I'll execute your draw window code, when I need to. Like a callback.

Since I just wanted to display arbitrary graphics and not need buttons or GUI interface elements, I needed to create my own custom NSView. Fortunately with version 1 of camel bones I was able to do this, but no where showed me how.

sub drawRect : Selector(drawRect:) ArgTypes({NSRect=ffff}) {
    my ($self, $rect) = @_;


	my $path = NSBezierPath->bezierPathWithRect($rect);
        NSColor->whiteColor()->setFill();
        $path->fill();

}

This example fills a white rectangle completely covering the NSCustomView.

Initialisation of the code can be put into the initWithFrame function. However this appears to be called twice. I put my timetable reading code in here and ended up with two trains at the exact same location, this was invisible to the eye but chewed up twice as much resources. I later discovered that this was due to instantiating the Custom view twice.

sub initWithFrame : Selector(initWithFrame:) ArgTypes({NSRect=ffff}) ReturnType(@) {
    my ($self, $frame) = @_;

    # Call NSView's version first
    $self = $self->SUPER::initWithFrame($frame);

    if ($self) {
        # Your initialization code goes here
    } # if ($self)


        return $self;

}


Comments

Your name:

Your comments: