Wolf in Sheep's Clothings (Part IV)

(continued from part III)

Over the last year I had hardly time to advance my Perl client to the AllegroGraph tuple server. Which is a shame, as it is fun to take the existing REST interface and to offer it in a perlish mindset.

So when the Perl hackathon (report) was in Vienna these days, and coincidentally also the RDF Perl hackathon Geilo next week, I thought I should use the opportunity to a rub shoulders with the Perl illuminaries, at least for half a day. But when I arrived, everyone was already in deep hacking mode, so I had no excuse but to do programming myself.

Aside from the trivial additions of registering namespaces at the server, I added geo-spatial support.

Getting Going

As usual, I had started my AG server with the options:

... --new-http-port 8080 --new-http-catalog /tmp/scratch

so that setting up a model within a Perl app looks like this:

my $AG_SERVER = 'http://ag:8080';
use RDF::AllegroGraph::Easy;
my $storage = new RDF::AllegroGraph::Easy ($AG_SERVER);

use Fcntl;
my $model   = $storage->model ('/scratch/catlitter',
                               mode => O_CREAT);

After that, the repository catlitter will be created underneath the catalog scratch mentioned above.

Cartesian Coordinates

Before being able to add triples with locations to the model, you will have to register a coordinate system at the server:

my $cs = $model->cartesian ("100x100", 10);

The first parameter defines a rectangle (here a square), whereby all coordinates are unitless. The origin defaults to (0,0). If that does not match your use case, then you can specify your origin like so

"100x100+20+30"

The second parameter is used internally by the server to optimize large numbers of spatial objects.

That coordinate system is not only registered within your model, you also get a handle in form of a URI:

http://franz.com/.../cartesian/0.0/100.0/0.0/100.0/10.0

Keep that, we'll need it later. But alone the fact that you get an identifier means that you can register more than one such coordinate system, maybe also in different resolutions.

Adding Location Data

Locations in a given coordinate system are also encoded in URIs. In order to help you here, a helper function creates such a coordinate, say for (30, 30):

use RDF::AllegroGraph::Utils qw(coord2literal);
my $loc = coord2literal ($cs, 30, 30);

With that it is trivial to add a few cats into the catlitter model:

$model->add (
['<urn:x-me:sacklpicker>', '<urn:x-me:location>',
                           coord2literal ($cs, 30, 30)],
['<urn:x-me:catbert>',     '<urn:x-me:location>',
                           coord2literal ($cs, 40, 40)],
['<urn:x-me:tomcat>',      '<urn:x-me:location>',
                           coord2literal ($cs, 60, 60)]
);

Obviously I am too lazy to register namespaces here. Shame on me.

To check whether everything is stored, we simply iterate over the triples with

@ss = $model->match ([undef, '<urn:x-me:location>', undef]);

So far, so good.

Querying

AllegroGraph offers specialized functionality to ask for triples within a bounding box, within a circle or a polygon. I have only implemented the first two:

@ss = $model->inBox    ($cs, '<urn:x-me:location>', 0, 0, 35, 35);
@ss = $model->inCircle ($cs, '<urn:x-me:location>', 30, 30, 1);

Unsurprisingly, we have to pass in the coordinate system, but also the RDF predicate which should be looked up. For the bounding box, the two corner points are good enough; the circle is defined via its center and the radius.

More time it took me to figure out, how the geo-spatial property can be queried within SPARQL:

@cats = $model->sparql (q{
PREFIX  geo:  <http://franz.com/ns/allegrograph/3.0/geospatial/fn/>
SELECT ?cat
WHERE
   { ?cat <urn:x-me:location> ?pos
     FILTER ( geo:cartesian-distance (?pos, POINT (30, 30)) < 1.0 )
   }
});

At the bottom of the AG documentation you find more primitives. Make sure you define the prefix geo, even though the documentation insinuates otherwise.

Wrapping Up

As a good citizen, I usually clean up the model afterwards:

$model->disband;


Obviously, there is still much left to do for the client, especially if you compare it to the Python client being shipped as part of the official distribution. Still, I try to reduce the programmatic noise which is associated with it, so that a developer can concentrate more on the issues at hand.

Posted In

Geilo is not Oslo (but both

Geilo is not Oslo (but both are in Norway) :)

Jan Schreiber (not verified) | Wed, 04/14/2010 - 15:11

Re: Geilo is not Oslo...

Right. Will fix!

rho | Wed, 04/14/2010 - 15:15

Oh wow, if I'd known you're

Oh wow, if I'd known you're hacking on allegrograph in Vienna, I'd have come out to up with meet you. I'm working with Allegro CL on the lisp side of things, and live in Vienna.

Pretty amazing bit of synchronicity there (-:

Andreas Fuchs (not verified) | Mon, 04/26/2010 - 22:02

Re: Oh wow, if I'd known you're

I'd have come out to up with meet you.

We sure should do. Maybe for a coffee? Even though, I read that you prefer a different delivery vector. ;-)

Hanging out in #lisp.

rho | Tue, 04/27/2010 - 07:02