Tagged with geospatial

Sneak Peak

While it’s really exciting that the release of QGIS 2.0 is just around the corner, I’m finding it just as exciting that work is already under way on version 2.1! Some great new features have already landed and I can’t wait to see what else is planned. Personally, I’ve got plans for a raft of improvements relating to print composers with the goal of making the print composer behave as much like a full-blown DTP package as possible. In the meantime, here’s a quick teaser of a feature I’ve been working on that will hopefully be landing in master soon:

A sneak peak...

Tagged , , , ,

VicMap data now freely available!

This is pretty huge – it seems the majority of the VicMap dataset is now freely available on data.vic.gov.au! I haven’t found an official release announcement but it includes the entire address, roads, property, public transport and administrative boundary data, plus much more. In fact, the only missing data I’ve found so far is the features of interest dataset. I’m not sure why that one didn’t make the cut.

One of the best things about this is that the data has been released under a very permissive CC-BY 3.0 license. With any luck, we’ll be able to merge this data with Victoria’s OpenStreetMap data. (There’s just a small licensing issue which needs clarifying).

(A bit of advice if you are trying to export large amounts of this data – the quickest format to export in is using “ESRI ArcSDE Shape Export” with “Geographicals on GDA-94” projection. Other formats can take a long time to process before they’re available for download.)

Tagged , ,

Detecting key states in MapBasic

Here’s another neat little MapBasic function I’ve been using recently. I needed a way of detecting whether a key on the keyboard was currently pressed or not. My intention was to show a hidden debugging dialog if a user shift-clicked on a specific button control, but there’s no in-built functions in MapBasic for detecting key states. Fortunately it’s possible to hook into the Windows User32.dll to use the GetAsyncKeyState call. Here’s how this all works in MapBasic…

First, we’ve got to define the GetASyncKeyState call and a bunch of related constants which map keys to a numeric value. Copy and paste the contents below to a .def file (or download a pre-made version later in this post).

asynckeys.def:

Declare Function GetAsyncKeyState Lib "User32.dll" Alias "GetAsyncKeyState" (ByVal vKey As Integer) As Integer
DEFINE vbKeyShift 16
DEFINE vbKey1 49
DEFINE vbKey2 50
DEFINE vbKey3 51
DEFINE vbKey4 52
DEFINE vbKey5 53
DEFINE vbKey6 54
DEFINE vbKey7 55
DEFINE vbKey8 56
DEFINE vbKey9 57
DEFINE vbKey0 48
DEFINE vbKeyBack 8
DEFINE vbKeyTab 9
DEFINE vbKeyReturn 13
DEFINE vbKeyControl 17
DEFINE vbKeyMenu 18
DEFINE vbKeyPause 19
DEFINE vbKeyEscape 27
DEFINE vbKeySpace 32
DEFINE vbKeyEnd 35
DEFINE vbKeyHome 36
DEFINE vbKeyLeft 37
DEFINE vbKeyRight 39
DEFINE vbKeyUp 38
DEFINE vbKeyDown 40
DEFINE vbKeyInsert 45
DEFINE vbKeyDelete 46
DEFINE vbKeyMultiply 106
DEFINE vbKeyDivide 111
DEFINE vbKeyAdd 107
DEFINE vbKeySubtract 109
DEFINE vbKeyDecimal 110
DEFINE vbKeyF1 112
DEFINE vbKeyF2 113
DEFINE vbKeyF3 114
DEFINE vbKeyF4 115
DEFINE vbKeyF5 116
DEFINE vbKeyF6 117
DEFINE vbKeyF7 118
DEFINE vbKeyF8 119
DEFINE vbKeyF9 120
DEFINE vbKeyF10 121
DEFINE vbKeyF11 122
DEFINE vbKeyF12 123
DEFINE vbKeyNumlock 144
DEFINE vbKeyScrollLock 145
DEFINE vbKeySnapshot 44
DEFINE vbKeyPageUp 33
DEFINE vbKeyPageDown 34
DEFINE vbKeyNumpad1 97
DEFINE vbKeyNumpad2 98
DEFINE vbKeyNumpad3 99
DEFINE vbKeyNumpad4 100
DEFINE vbKeyNumpad5 101
DEFINE vbKeyNumpad6 102
DEFINE vbKeyNumpad7 103
DEFINE vbKeyNumpad8 104
DEFINE vbKeyNumpad9 105
DEFINE vbKeyNumpad0 96
DEFINE vbKeyPressed -32767
DEFINE vbKeyWasPressed 1

Now, you can test for the state of any key by calling getASyncKeyState( vKey ), where vKey is an integer value corresponding to the key you want to test. So getASyncKeyState( vbKeyControl ) will test the state of the control key. The value returned will reflect whether the key is currently pressed (vbKeyPressed), or has been pressed since the last call to the function (vbKeyWasPressed). Easy! Here’s a little sample program to demonstrate how this all works:

Include "asynckeys.def"
Declare Sub Main
Declare Sub KeyCheck

Sub KeyCheck
    ' Store the pressed state of the SHIFT key
    Dim iState As Integer
    iState = getASyncKeyState( vbKeyShift )

    ' Check what the state was
    Do Case iState
        Case vbKeyPressed
            Print "SHIFT is being pressed!"
        Case vbKeyWasPressed
            Print "SHIFT has been pressed since last check"
        Case Else
            Print "Nothing to report..."
    End Case

    ' Keep the dialog around
    Dialog Preserve
End Sub

Sub Main
    Dialog
        Title "ASync Key State"
        Control OKButton
            Title "Check"
            Calling KeyCheck
        Control CancelButton
            Title "Quit"
End Sub

Both the asynckeys.def definition file and the sample program are contained in this archive.

Tagged , , , , ,

Regular expressions in MapBasic

I’m going to take a break from all my recent QGIS posts to talk about some MapBasic news… I’m proud to announce the release of MbRegEx, an open-source library for using regular expressions in MapBasic scripts!

If you’re not familiar with regular expressions, they’re an extremely powerful tool for string manipulation. They can be somewhat daunting at first, but with a bit of practice they’ll open up all kinds of string processing which would otherwise be extremely convoluted or impossible.

Up until now there’s been no way of using the beauty of regular expressions within MapInfo. Now, with MbRegEx, all their mighty power can be fully utilised within your MapBasic scripts!

Included Functions

The library contains 5 functions for use in MapBasic scripts:

RegExTest(string, regex): returns true or false depending on whether string contains the specified regular expression. For example, RegExTest( “ABC123”, “[A-Z]{3}\d{3}” ) returns true, RegExTest( “AB12”, “[A-Z]{3}\d{3}” ) returns false. This function really comes in handy when selecting records, eg:

SELECT * FROM address WHERE RegExTest( street, "MAIN (ST|RD)( [NESW])?$")

to select all addresses where the street is either “MAIN ST” or “MAIN RD” and which may have an optional N/E/S/W suffix.

RegExMatch(string, regex): returns the first part of string which matches the specified regular expression. Great for quickly extracting specific parts of a string. Let’s say we’ve got an address field, and we’d like to grab just the street number from it. We could use the regular expression “^(\d+[A-Z]*)”, which will match any leading numbers with optional letter suffixes. So RegExMatch( “12A Main St”,  “^(\d+[A-Z]*)” ) returns “12A”,  whereas RegExMatch( “Upper Main St”,  “^(\d+[A-Z]*)”) will return an empty string. Trying to achieve this same task using built-in MapBasic functions alone would be extremely tedious and error-prone!

RegExMatchAll(string, regex, array) and RegExMatchMultiple(string, regex, array) will fill array with all the parts of string which pass the specified regular expression. RegExMatchAll is used when you have just one capturing group in your regular expression, and RegExMatchMultiple is used for multiple capturing groups.

This is probably best demonstrated with some examples:

RegExMatchAll( "12A Main St", "\b(\w+?)\b", sMatches )

will fill the sMatches array with all the individual words from “12A Main St”. So sMatches(1) = “12A”, sMatches(2) = “Main”, etc.

RegExMatchMultiple( "10.5.2", "(\d+)\.(\d+)\.(\d+)", sMatches )

fills sMatches with the results of the three capturing groups (the bracketed parts) of the regular expression. Thus sMatches(1) = “10”, sMatches(2) = “5” and sMatches(3) = “2”.

Again, these two functions are great for splitting a string into its component parts or doing something fancy like extracting all the phone numbers from a paragraph of text.

Lastly, RegExReplace(string, regex, replacement, destination) replaces the parts of string which match the regular expression with replacement, and stores the result in destination. One handy use for this is removing invalid characters from a string, such as

RegExReplace("T/:e@st!i~n&g#1,^2}3", "[^A-Za-z0-9]", "_", sDest)

This results in sDest = “T__e_st_i_n_g_1__2_3”.

Getting Started

There’s a few extra examples and full instructions for using these functions in the “test.mb” file included with MbRegEx. You can use these as a starting point for your own MapBasic scripts. If regular expressions are new to you, I recommend regular-expressions.info as a great resource together with an online regex visualiser such as debuggex.

Also, a quick warning – MbRegEx does no validation or testing of your regular expressions, so be careful with badly formatted expressions as they’ll cause MapInfo to crash. If in doubt, run the expression through an online tool to validate it first.

Downloads

The full source code is available on GitHub, under a public domain license. If you’re looking for the easiest way to get started, just download this zip which contains both the MbRegEx DLL and a sample MapBasic program demonstrating all the different regular expression functions which are available in the library.

End note – building the MbRegEx DLL file

I’ve included a CodeBlocks project file with the source, but building the MbRegEx.dll file can be difficult – you’ll need to first compile the boost libraries using mingw on your system. Then, make sure that in the CodeBlocks project build options, under Linker settings you have your “stage\lib\libboost_regex-mgw46-1_52.a” (or similar) correctly linked. Also, under Search directories add your boost folder to the Compiler tab. 

Tagged , , , ,

A neat trick in QGIS 2.0 – images in atlas prints

Here’s a cool trick which you can do in QGIS 2.0. It builds on two new features introduced in version 2.0 – atlas prints and html labels.

Atlas prints (previously available as a plugin, now integrated into QGIS core) were developed by Oslandia, and allow you to create data driven map layouts from a specified coverage layer. You can read more about them here.

Another new feature in QGIS 2.0 is the ability to render composer labels as html (courtesy of Olivier Dalang). This allows all kinds of fantastic effects, such as formatting text in the middle of a label (using <b>, <i>, and <font> tags) or creating labels which contain HTML tables. You can even use CSS stylesheets and rules to format the HTML! I’ve been told JavaScript also works inside the labels, but I’ve yet to try this out.

You can combine these two new features for some great tricks. Let’s say we’d like to create a set of maps of local councils, and we want each map to have a watermarked logo of the council on it. For this example I’ve created a basic basemap of Victorian councils, and I’ve downloaded all the council logos (in a variety of formats) to a local folder. Next, I’ll add an extra column to the council layer containing the name of the logo image:

adding_logo_column

Adding a logo column to the table

Then, we’ll throw together a simple composition containing the map and set it up as an atlas print:

setting_up_atlas

Generating an atlas

Now for the fun bit. I’ll add a label item to the composer, set it to “Render as HTML”, and insert some specially-crafted html:

The magic HTML label...

The magic HTML label…

For copy/paste purposes here’s the label contents again:

<style>
* {margin: 0px; padding: 0px}
</style>
<img src="file:///home/nyall/GIS/council_logos/[% "logo" %]"
style="width: auto; height: 100%; display: block; margin: 0px 0px 0px auto;" />

There’s a couple of things to note here. First, the magic happens in the image’s src attribute (“file:///home/nyall/GIS/council_logos/[% “logo” %]”). When the composer is exported, QGIS will replace the [% “logo” %] part with the contents of the logo field for each row in the councils table. This means the image source will then point to the local copy of the council’s logo, eg “file:///home/nyall/GIS/council_logos/glen_eira.jpg” for the first row.

Secondly, I’ve styled the image with the css:

width: auto; height: 100%; display: block;

This allows the image to resize to 100% of the height of the label while maintaining its correct aspect ratio. I’ve also added the rule

margin: 0px 0px 0px auto;

to force the image to right align within the html label. This ensures that all the watermarked logos will appear in a consistent size and position for each map.

Lastly, I’ll remove the label’s frame and background by unchecking these options, then set its transparency to 80% under the new “Rendering” section:

Yet another new feature in QGIS 2.0...

Yet another new feature in QGIS 2.0…

Ok, we’re all done. Now, when I select Composer -> “Export as Image”, we’ll get a lovely set of council maps complete with watermarked council logo!

A watermarked atlas!

A watermarked atlas!

There we go — all ready for print, with no manipulation in external programs required at all!

Bonus post-credits section

Here’s a kicker — the linked images don’t need to be local. That means you can even piggy-back off an existing web service to generate an image on the fly! Let’s say you were asked to add QR codes to your maps to link directly to the council website. All it takes is adding a new column to the table, then modifying the image src to read:

src="http://qrfree.kaywa.com/?l=1&s=8&d=[% "url" %]"

Now when we export the maps we’ll also get a QR image generated on the fly and inserted into the layout!

Complete with dynamically generated QR code!

Complete with dynamically generated QR code!

Combining HTML labels and atlas prints in this way is extremely powerful. This example is just touching the tip of the iceberg – I’m keen to see what the community can do with this when QGIS 2.0 is released!

Tagged , , , , , , ,

Coming soon in QGIS Part 2 – Color control for raster layers

Continuing on from part 1, another feature I’ve recently pushed to QGIS is the ability to control the hue, saturation and colour of a raster layer. This builds off the excellent work done by Alexander Bruy (who added brightness and contrast controls for raster layers), and it’s another step in my ongoing quest to cut down the amount of map design tweaking required outside of QGIS. Let’s step through these new features and see what will be available when version 2.0 is released in June…

First up is the ability to tweak the saturation of a layer. Saturation basically refers to the intensity of a colour, with low saturation resulting in a more washed out, greyer image, and high saturation resulting in more vibrant and colourful images. Here’s a WMS layer showing an aerial view of Victoria at its driest, least appealing and most bushfire ready state:

Original layer

Raster layer before saturation controls…

Let’s tweak the saturation a bit to see if we can make it more appealing. In the Style tab under raster layer properties, you’ll see a new “Saturation and hue” section. For this layer I’ll bump the saturation up from its default value of zero:

Saturation settings

Saturation settings

Which results in something like this:

Resultant layer!

… and after increasing the saturation!

Ah, much better. This actually looks like somewhere I’d like to live. A bit over-the-top perhaps, but it IS handy to make quick adjustments to raster colours in this way without the need for any external programs.

How about turning an image grayscale? I regularly have to do this with street directory basemaps, and until now couldn’t find a satisfactory way of doing this in QGIS. Previously I’ve tried using various command line utilities, but never found one which could turn an image grayscale without losing embedded georeferencing tags. (I did manage to achieve it once in QGIS using a convoluted approach involving the raster calculator and some other steps I’ve thankfully forgotten.)

But now, you can forget about all that frustration and quickly turn a raster grayscale by using a control right inside the layer properties! You even get a choice of desaturation methods, including lightness, luminosity or average. Best part about this is you can then right click on the layer to save the altered version out to a full-resolution georeferenced image.

grayscale

Street map in grayscale… woohoo!

Lastly, there’s the colourise option. As expected, this behaves in a similar fashion to the colourise tools in GIMP and Photoshop. It allows you to tint a layer to a specified colour. Let’s take a WMS layer of Melbourne, tweak the brightness and contrast, and colourise it blue…

colorize_settings

Tweaking the colourize settings

… and the end result wouldn’t be out of place in Ingress or some mid 90’s conspiracy flick!

colorized

Colorized WMS layer

These changes are just a tiny, tiny part of what QGIS 2.0 has to offer. It’s looking to be a sensational release and I can’t wait for final version in June!

Tagged , , , , , , , ,

Coming soon in QGIS 2.0 – blend modes for layers

I’ve just pushed my first major contribution to QGIS — the ability to set the compositing mode for a layer. Compositing is a technique widely used by cartographers and graphic artists to fine tune how layers are blended together, and it allows for some spectacular results! Until now, the only way to get these effects would be to export a map to a separate editor like Photoshop or GIMP and playing with the layer modes there. But with QGIS 2.0, blending can be controlled via a simple drop down menu for both raster and vector layers:

Blending modes for a raster layer

Woohoo… blending modes in QGIS!

So what makes this so great? Well, in previous versions the only option for compositing layers in QGIS was by setting a layer’s opacity. This approach has some limitations. Let’s say you want to overlay two raster layers – a basemap layer and a heatmap. You could place the heatmap layer over the basemap and set its transparency at 50% so that the basemap shows through, but then both the basemap and heatmap layers will be partially faded out:

Overlaying layers with transparency

Overlaying layers by altering transparency – see how both the heatmap and basemap are partially faded

With QGIS 2.0, you’ll be able to use the “multiply” blend mode to overlay these layers. This means both the heatmap and underlying basemap will be shown with full intensity:

Overlaying rasters with multiply

Overlaying rasters with “multiply” blend mode – both layers are shown in their full intensity!

Ok… perhaps that’s not the prettiest example, but it is something I have to do a lot in my job. Until now it’s only been possible by exporting the map to GIMP or Photoshop/Illustrator and setting the blend modes there. That’s always fiddly, time consuming and generally frustrating all round. Much easier to just change it with a dropdown within QGIS itself.

Let’s move on to some more impressive example. First, here’s a terrain map using a combination of a landcover thematic with ‘overlay’ blending and a hillshade set to ‘multiply‘ blending. The graticule lines are also set to overlay – note how they aren’t visible over the lighter water areas and brighter hillshade regions.

Hill shading with advanced compositing

Hill shading with advanced compositing… Hal Shelton would be proud!

Ok, that’s nice, but let’s try something a little different. Using a combination of darkenscreenhard light and overlay:

Stamen-style watercolors directly within QGIS!

Live Stamen-style watercolors within QGIS – sweet!

These a just some rough examples — I’m keen to see what results others get using this feature (feel free to post links to your work in the comments).

One final note: I’m really appreciative of the efforts of the QGIS dev team, who’ve been really supportive and helpful while I find my way around the QGIS codebase. A big thank you has to go to Nathan Woodrow for taking the time to review this commit and answering all the questions I’ve had!

Tagged , , , , ,

Fuzzy string matching and geocoding

One of the biggest problems encountered when trying to geocode a table is how to handle variations in spelling and naming between points. Databases are often messy, filled with spelling and typing mistakes – and this makes it impossible to simply match one table against another. That’s when we need to resort to the concept of “fuzzy string matching” – the “technique of finding strings that match a pattern approximately (rather than exactly)” 1.

The traditional method for fuzzy string matching during geocoding is the Levenshtein distance. The Levenshtein distance is perfect for automatically correcting spelling mistakes and small variations in spelling (eg  “Frankston-Flinders Rd” as opposed to “Frankston Flinders Rd“). When geocoding, you can automatically match any results with a distance of just 1 or 2 characters, or which is within a set percentage of the length of a string. For instance, the Levenshtein distance between “Swanton St” and “Swanston St” is one character (10% of the length of the first string), and the distance between “Box Hil Railway-Station”  and “Box Hill Railway Station” is two characters (~8.5% of the length of the first string). I’ve found that automatically matching distances between 1 character and 10% of the string length covers most simple typing errors with almost no false matches.

Unfortunately, the Levenshtein distance isn’t perfect. While it works well when the strings only contain small differences, it fails when trying to match two very different strings. This becomes critical when we’re trying to match the names of features. There’s often a huge variety in possible names for features. A train station could be entered as any number of different names, ranging from  “Box Hill Railway Station“, “Box Hill Train Station“, “Box Hill Station“, all the way to “Railway Station, Box Hill” or just “Railway Station“.

Let’s try a possible example. Trying to match the string “coles” to the name “coles supermarket” will have the high Levenshtein distance of 12 characters. By comparison, the Levenshtein distance between “coles” and “fat apes” is only six characters. If we are ranking matches by Levenshtein distance alone we’ll end up choosing the match “fat apes” over the obviously more relevant match of “coles supermarket“. Not terribly effective at all…

A better technique to use for matching these feature names is the the algorithm called “longest common substring2. This algorithm returns the longest string which is common to both input strings. Taking our previous examples, when matching “coles” to “coles supermarket” the longest common substring (LCS) is “coles“. Comparing “box hill railway station” to “railway station, box hill“, the LCS is “railway station“.

I’ve found that using the longest common substring for geocoding works best interactively. First, you take the string you’re trying to match, and sort a list of possible candidates by the length of the LCS, with longest matches first. This sorted list is then presented to the user to manually choose the most appropriate match.

Why not just do this automatically, without bothering the user? While most times the best match will be the first one in the list, there’s a few times when it may be second or third. Let’s say we’re trying to match the string “coles supermarket, westfields shopping centre”, and our feature database contains a specific point for “coles supermarket” and a general point for “westfields shopping centre”. If we were to automatically match to the point with the largest LCS, we’ll end up matching to the general point “westfields shopping centre” (LCS length of 26), rather then the slightly more accurate point for “coles supermarket” (LCS length of 17). Unfortunately, I can’t think of an automated way of prioritising the specific point over the general point in this case, so it’s safest to leave that choice to the user. (Let me know if you’ve got any clever ideas for this!)

This method can be taken one step further by padding both strings with a space. This has the effect of increasing the length of the LCS if both input strings match on a full word. For example, the LCS between “coles supermarket” and “coles” has length 5, while the longest common substring between “coles supermarket” and “dandenong markets” has length 6. If we just choose to use the standard LCS method on these strings we’ll incorrectly prioritise “dandenong markets” over “coles“. However, if we append spaces to the start and end of the strings, then we get:

" coles supermarket " and " coles ", LCS = " coles ", length 7
" coles supermarket " and " dandenong markets ", LCS = "market", length 6

Effectively, this process bumps up the length of an LCS by two characters if both input strings match with word breaks, rather than a portion of a word. It’s also possible to replace every space in the input strings by multiple spaces, if you’d like to further prioritise whole word matches.

In summary – Levenshtein distance is great for small variations in names, but for large possible variations in naming I’ve found LCS to be much more effective.

Notes:

  1. http://en.wikipedia.org/wiki/Approximate_string_matching
  2. Watch out, there’s a similarly named algorithm called “longest common sub sequence”. You don’t want this one at all.
Tagged , , , ,

RMIT Crime Mapping and Analysis Conference 2012

This is just a quick plug for the first RMIT Crime Mapping and Analysis Conference, which is happening in Melbourne next week (13-14 November). There’s some great international speakers like Spencer Chainey presenting. I’ll also be giving a short talk on predictive mapping in policing, using a residential burglary forecasting model as a case study. More details and pricing is available on the conference site.

Tagged

Leaflet and Vicgrid (EPSG:3111) projection

While Leaflet is a fantastic mapping library, there’s not a lot of info out there on how to use it with different projections. I thought I’d share some tips I discovered while trying to get Leaflet working with a WMS server that only supports the projected VICGRID94 (EPSG:3111) CRS. Leaflet’s documentation is generally OK, but there’s a few potential roadblocks which took me a while to understand.

First you’ll need Leaflet, proj4js and Proj4Leaflet all installed on your server and linked to your page.

Before you initialise the map instance you’ll need to set up the CRS transform, which goes along the lines of:

// Coordinate to grid transformation matrix
var transformation = new L.Transformation(1, 0, -1, 0);
// Official Spatial Reference from http://www.spatialreference.org/ref/epsg/3111/
var crs = L.CRS.proj4js('EPSG:3111',
'+proj=lcc +lat_1=-36 +lat_2=-38 +lat_0=-37 +lon_0=145 +x_0=2500000 +y_0=2500000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs',
transformation);

You’ll also need to set up scale function, and assign it to your crs object.

// Scale for each level
var res = [2116.670900008467, 1058.3354500042335, 529.1677250021168, 264.5838625010584, 132.2919312505292, 66.1459656252646, 26.458386250105836, 13.229193125052918, 6.614596562526459, 2.6458386250105836, 1.3229193125052918, 0.6614596562526459, 0.33072982812632296, 0.21166709000084669];

var scale = function(zoom) {
 return 1 / res[zoom];
}
crs.scale = scale;

It took me a while to track this one down, but when you’re creating your layers, make sure you set “continuousWord: true” . Failing to set this will result in no tiles being loaded. Here’s an example WMS layer:


var cartolayer = L.tileLayer.wms("http://x.x.x.x/map/wms", {
 layers: 'basemap',
 format: 'image/png',
 continuousWorld: true,
});

Lastly, when initialising the map:

  • You must again set the option continuousWorld: true
  • You must set “worldCopyJump: false”, or you’ll have problems with the map jumping to a random location when you attempt to drag it (see Leaflet issue #1003)
  • Set the crs to the one created earlier
</pre>
var map = new L.Map('map', {
 crs: crs,
 continuousWorld: true,
 center: new L.LatLng(-37.8, 144.9),
 zoom: 5,
 minZoom: 0,
 maxZoom: 13,
 worldCopyJump: false
});

Now you should be right to go and take advantage VICGRID with all that Leaflet goodness!

Some information which might be useful is available at:

Tagged , , , , ,