Skip to content

Using pgsql2shp and reproject by ogr2ogr

Basically, this is no big deal…but the purpose of this blog is also to collect snippets…so here they are.

Getting the ‘Rhein’ from PostGIS:

(OSM-data from Geofabrik, imported by osm2pgsql)

pgsql2shp -f osm_rhein.shp -h localhost -p 5432 -P my_password -u gisadmin planet "select * from germany_line where name = 'Rhein'"

Change to LngLat Projection:

ogr2ogr -f 'ESRI Shapefile' osm_rhein.shp osm_rhein.shp -t_srs '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs' -overwrite -skipfailures

More will surely follow…

Understanding the TopoJSON data format

This extension of the, meanwhile standardised, GeoJSON dataformat encodes topology of a GeoJSON dataset and reduces file size up do 80% (see authors description).

In order to use this dataformat, it can be usefull to understand the structure of a TopoJSON file. That is why I will break it appart and analyse each element in the following. A more detailed description of the dataformat can be found here.

Let’s begin with the creation of a TopoJSON file.

In an earlier post, I have concluded how to make a map of germany from such a file by using D3.js. So in conclusion, you take one or more GeoJSON file(s) and convert it(them) to one compact TopoJSON file. This could look as follows:

topojson \
 --id-property postal \
 -p postal \
 -p name \
 -o de-data.json \
 states.json

What are the different parts responsible for?

  • “–id-property” –> specifies which attribute will be used as ID(entifier) … in this example it is the attribute ‘postal’
  • “-p” –> specifies which attributes will be preserved respectively transfered from source to the TopoJSON file … in this example it is the ‘postal’ & ‘name’ attribute
  • “-o” –> specifies the name of the output TopoJSON file
  • “nothing” –> there is(are) the input file(s) specified .. in this example only the german states

Now, let’s have a look at the resulting file (as abstract):

{
 "type":"Topology",
 "transform":{"scale":[0.0009170486546988356,0.0007794992965075303],
 "translate":[5.852489868512635,47.27112091110115]},
 "objects":{
   "states":{"type":"GeometryCollection",
    "geometries":[
     {"type":"Polygon","arcs":[[0,1,2,3]],"id":"NW","properties":{"name":"Nordrhein-Westfalen","postal":"NW"}},
     ...
     {"type":"Polygon","arcs":[[8,9,-6,10,-1,11]],"id":"HE","properties":{"name":"Hessen","postal":"HE"}},
     ...
     {"type":"MultiPolygon","arcs":[[[59]],[[60]],[[61]],[[-58,-26,-44,62]],[[63]],[[64]]],"id":"MV","properties":{"name":"Mecklenburg-Vorpommern","postal":"MV"}}
    ]
   }
  },
  "arcs":[
     [[3912,5616],[-17,-22],[-7,-6],[-79,-19],[-9,-4],[-5,-3],[1,-2],[4,-3],[2,-1],[14,-7],[2,-1],[1,-2],[0,-2],[0,-2],[0,-2],[-5,-8],[-2,-4],[-2,-5],[-3,-7],[0,-2],[-1,-2],[-3,-8],[-4,-10],[-5,-5],[-6,-5],[-11,-8],[-6,-5],[-4,-6],[-5,-10],[-3,-4],[-4,-3],[-14,-6],[-14,-10],[-8,-4],[-12,-3],[-21,-10],[-5,-3],[-4,-4],[-3,-4],[-2,-4],[-1,-5],[0,-2],[0,-3],[0,-4],[0,-1],[-1,-3],[-1,-4],[-3,-6],[-2,-2],[-3,-1],[-12,2],[-6,-2],[-39,-22],[-4,-1],[-9,0],[-40,6],[-21,13],[-5,5],[-1,2],[0,2],[1,13],[1,1],[1,3],[-3,12],[-6,7],[-4,4],[-4,1],[-5,-1],[-3,0],[-16,6],[-21,12],[-10,3],[-6,2],[-17,-7],[-45,-8],[-57,-21],[-4,-4],[-2,-2],[-1,-4],[-2,-5],[0,-4],[1,-2],[1,-2],[10,-10],[1,-2],[3,-5],[2,-5],[2,-12],[0,-3],[0,-12],[0,-3],[1,-2],[1,-1],[2,-1],[23,-2],[3,-1],[3,-2],[3,-4],[0,-5],[-2,-5],[-6,-11],[-4,-4],[-4,-2],[-45,-2],[-11,-3],[-28,-16],[-2,0],[-3,-1],[-3,0],[-23,6],[-5,2],[-5,1],[-6,0],[-6,0],[-14,-1],[-26,-7],[-22,-2],[-19,1],[-8,-2],[-25,-8],[-21,-4],[-4,-2],[-2,-2],[0,-2],[-7,-9],[-12,-5],[-9,-5],[-1,-2],[0,-2],[-1,-1],[-1,-4],[-3,-3],[-36,-27],[-24,-23],[-6,-7],[-11,-18],[-2,-5],[-1,-3],[1,-1],[1,-2],[1,-2],[2,-1],[5,-4],[7,-3],[4,-3],[1,-2],[1,-1],[1,-5],[1,-5],[1,-1],[1,-2],[2,-2],[2,-1],[5,-2],[10,-1],[5,0],[3,1],[3,1],[3,3],[5,8],[1,1],[2,1],[3,1],[5,2],[22,1],[22,5],[24,13],[6,2],[4,1],[3,-1],[2,-1],[2,-2],[1,-1],[0,-2],[0,-2],[-4,-9],[0,-2],[0,-1],[2,-1],[8,-3],[2,-2],[1,-1],[5,-16],[1,-4],[1,-3],[6,-22],[1,-5],[4,-16],[1,-1],[0,-2],[2,-7],[1,-3],[0,-5],[0,-8],[-1,-4],[-1,-3],[-35,-29],[-22,-22],[-3,-3],[0,-2],[0,-1],[1,-2],[1,-2],[9,-11],[2,-4],[0,-6],[-1,-3],[-2,-2],[-28,-11],[-14,-9],[-3,-1],[-3,0],[-2,0],[-34,7],[-112,-1],[-5,-10],[4,-6],[5,-5],[7,-12],[3,-5],[1,-4],[-3,-5],[-1,-8],[2,-8],[6,-17],[2,-8],[1,-5],[-7,-9],[-12,-10],[-2,-2],[-3,-6],[-4,-8],[-5,-7],[-3,-6],[-1,-2],[-2,-2],[-2,-1],[-3,0],[-8,-2],[-7,-6],[-14,-23],[-9,-14],[-1,-3],[0,-7],[-1,-20],[-2,-5],[-3,-3],[-2,0],[-13,2],[-6,0],[-18,-9],[-29,-21],[-4,-5],[0,-6],[1,-6],[-2,-3],[-2,-3],[-22,-13],[-6,-2],[-5,-2],[-14,0],[-16,-2],[-18,2],[-6,4],[-9,16],[-4,3],[-4,2],[-13,-1],[-4,-1],[-3,-2],[-14,-12],[-47,-32],[-2,-2],[-5,-6],[-2,-2],[-21,-11],[-2,-2],[-1,-2],[-8,-16],[-52,-34],[-6,-5],[-1,-2],[0,-2],[0,-2],[0,-1],[2,-2],[2,-1],[2,-1],[2,-1],[2,-2],[0,-1],[-1,-4],[1,-2],[1,-1],[2,-2],[24,-14],[5,-4],[2,-2],[1,-2],[1,-2],[0,-2],[-6,-34],[-3,-10],[-3,-3],[-3,-2],[-12,-2],[-4,-3],[-3,-3],[-11,-18]],
     ...
     [[8238,8925],[-31,3],[-35,9],[-38,17],[8,7],[6,15],[12,20],[-16,-7],[-8,-5],[-6,-6],[4,-4],[3,-4],[-22,1],[-11,-1],[-8,-5],[-10,-4],[-11,5],[-10,8],[-7,4],[-16,2],[-19,6],[-12,11],[6,17],[-15,3],[-34,-11],[-11,-1],[-7,10],[6,8],[15,4],[17,-5],[0,8],[-68,36],[15,28],[21,22],[28,9],[33,-15],[8,9],[13,-9],[15,2],[32,15],[-17,2],[-13,8],[-5,13],[5,13],[0,8],[-15,1],[-8,6],[-7,7],[-11,4],[-49,-9],[19,27],[8,6],[30,6],[33,11],[22,3],[0,9],[1,0],[7,3],[7,6],[-30,8],[-14,6],[-8,11],[3,3],[4,2],[2,5],[-1,9],[-32,-9],[-20,-2],[-8,6],[-3,4],[-5,1],[-5,3],[-2,10],[-2,11],[-4,7],[-7,3],[-10,0],[25,8],[84,9],[18,-3],[6,-8],[13,-3],[12,-7],[6,-17],[5,-9],[8,5],[4,14],[-9,20],[16,15],[20,14],[20,11],[19,5],[-12,-26],[-8,-11],[-10,-8],[7,1],[6,-1],[5,-3],[5,-6],[-5,-6],[-11,-19],[16,-1],[13,4],[10,8],[6,14],[-9,2],[-10,5],[-10,2],[0,9],[15,10],[12,-17],[19,-17],[13,-18],[-7,-19],[22,-22],[27,-6],[56,1],[-8,9],[10,17],[6,6],[7,4],[0,9],[-9,18],[-6,9],[-8,7],[0,9],[6,3],[4,3],[4,2],[9,2],[0,8],[-14,-1],[-8,-5],[-7,-7],[-8,-5],[-12,-1],[-38,1],[-5,4],[-6,9],[-8,9],[-10,4],[-17,3],[-6,6],[-4,9],[-7,9],[-13,12],[-2,6],[-15,-9],[-9,-6],[-17,-17],[-26,-10],[-18,-14],[-20,-10],[-22,5],[-4,15],[8,24],[14,21],[16,10],[3,5],[5,12],[2,12],[-3,6],[-49,-9],[-16,-8],[-7,2],[1,15],[6,8],[11,9],[14,6],[149,30],[31,0],[28,-10],[0,-8],[-16,-9],[-23,-9],[-20,-12],[-8,-18],[3,-23],[9,-18],[15,-14],[18,-11],[46,-11],[141,19],[48,-7],[33,-25],[8,-33],[-29,-31],[-48,-23],[-24,-16],[-10,-18],[4,-22],[9,-22],[12,-19],[12,-12],[22,-8],[52,-8],[22,-12],[29,-36],[19,-17],[27,-7],[-15,-7],[-14,-13],[-11,-16],[-4,-21],[0,-21],[-3,-8],[-12,1],[-24,6],[13,0],[10,4],[5,9],[-5,13],[-7,0],[-11,-8],[-17,-5],[-18,0],[-13,5],[0,8],[41,12],[16,9],[9,15],[-56,-3],[-26,-5],[-21,-10],[60,29],[20,6],[0,9],[-29,1],[-15,-1],[-11,-5],[-14,-12],[-10,3],[-8,9],[-12,5],[-109,-9],[-20,-9],[-57,-35],[-12,-13],[-13,-20],[-27,-4],[-24,-8],[-4,-35],[15,9],[0,7],[-2,1],[-3,0],[-2,2],[52,6],[8,-2],[8,-30],[-3,-13],[-17,-6]]
  ]
}

The necessary parts are the information, that are included in the objects.

On the one hand it contains a condensed form of the original GeoJSON file(s)…here only one, the ‘states’ element. Therein are all geometries, described by ‘arcs’, ‘id’ and ‘properties’. Here you can find the initially specified attributes again…do you remember, we wanted to preserve ‘name’ & ‘postal’. And you see also, that the ‘id’ is equal with the ‘postal’ attribute, as we have initially specified. The ‘arcs’ – element is an GeoJSON geometry specified array of all arcs that have to be used to rebuild this geometry. In our example, you can see the ‘arcs’ element is exactly the same syntax as in the GeoJSON specification, for Polygon or MultiPolygon. The elements within that array are just a pointer to the appropriate arc in the arcs-list.

On the other hand it contains an array, containing all geometries (arcs) of the original geometries. To get the geometry of “Nordrhein-Westfalen”, we only have to get the corresponding 4 arcs ([0,1,2,3]) of the arcs-object.

TopoJSON is used to avoid redundancy by saving redundant geometries only once. You can see that in the example. “Hessen” shares one border with “Nordrhein-Westfalen”. Therefore it is not specified as an additional arc in the geometrical definition of “Hessen”. No, it is described by the same “arc-id” with a negative sign…this is ‘-1’ in the example. You can see “Hessen” seems to share also another border with another german state…-6…but this one is not listed in this abstracted example.

Ubuntu package operations

They are pretty simple, but I always forget them 😉

To not always search for them, I will now collect the most used in this post!

Add new package:

sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable

Install

sudo apt-get install qgis

Update and upgrade

sudo apt-get update
sudo apt-get upgrade

Remove installed software

sudo apt-get remove grass

Remove also the related package

sudo apt-get --purge remove grass

Detect and correct dependencies

sudo apt-get -f upgrade

Edit sources list manually

gedit /etc/apt/sources.list

…more to come!

Developing D3.js applications in Chrome

So far I developed my D3.js applications using Firefox and Firebug, what worked really good.

But today I made this tutorial and they suggest to use Chrome and the pre-installed Web Inspector Developer Tools.And this is a bit more useful than Firebug, especially because of the possibility to add code directly within the console. So I decided to give it a try and develop for the next time in Chrome.

But when I opened my already developed applications…the first error occurred! Doh!

XMLHttpRequest cannot load file:///directory/of/my/JSON/document/germany.json. Cross origin requests are only supported for HTTP.

…as well as some related errors!

I was surprised about this, as there was no failure in Firefox. So I exerted my good old friend…Google. S/He said:

“It’s not related to D3, any XMLHTTPRequest you make to another domain will throw this error if access is not allowed.” (Source)

Aha…I never heard of this…let’s find the solution!

“Note: Chrome has strict permissions for reading files out of the local
file system. Some examples use AJAX which works differently via HTTP
instead of local files. For the best experience, load the D3 examples
from your own machine via HTTP. Any static file web server will work;”

Ok…so let’s set up a simple static Python server (on Ubuntu 12.04):

Ctrl+Alt+T (opens a terminal)
cd /Path/to/my/application
python -m SimpleHTTPServer 8888

Tip: I personally prefer to open terminal directly from directory, to avoid the “cd” stuff and search. Therefore I have nautilus-open-terminal installed.

And that’s it. Now I just have to open the application from the localhost:

http://localhost:8888

Tip: You can additionally, define an index.html on the main folder, to have a simple navigation!

Interactivity using GeoJSON vs. UTFGrid (vs. MapBox)

During the last days I was playing a little bit with interactivity within tile based maps. I began to learn programming in JavaScript and tried different modestmaps.js, mapbox.js, leaflet.js and some offers I do not remember at this moment. My first statement that I have to make on interactive web maps and its possibilities: Oh my god…the possibilities seem to be endless!!! There are so many different scripts developed by so many different projects that it seems to be impossible to stay tuned on the latest developments.

To get at least a small overview/insight, I will begin to test some technical possibilities and describe them here. Lets start with the interactive visualisation of additional data attributes.

The data:

I want to visualise the world wide press freedom. A corresponding ranking was published last week by “Reporter ohne Grenzen“. To visualise this list I used the “ne_50m_admin_0_countries” shapefile from Natural Earth, defined a new attribute ‘rank’ within that shapefile and defined the ranking position for each object.

Therefore I wrote I simple python script, which helped me to define the new attribute in a semi-automatic manner…readList

The easiest way…using MapBox

The easiest way for applying interactive functionalities to tile-based maps is to define a map with TileMill and upload this as *.mbtiles to the MapBox upload portal. The big advantage of that is that TileMill provides a good GUI for defining the interactivity and you don’t have to care for an server administration. How did I do it:

1. Styling the map with TileMill – I decided for a very simple styling of the map by this CartoCSS definition:

Map { background-color: #b3c5c9; }

#ranking { 
  ::polygon_good[rank>0][rank<=21]{
    polygon-fill: #4bcf15; } 
  ::polygon_goodmid[rank>21][rank<=41]{
    polygon-fill: #ffcc00; } 
  ::polygon_mid[rank>41][rank<=120]{
    polygon-fill: #f0681a; }
  ::polygon_midbad[rank>120][rank<=165]{
    polygon-fill: #ff0000; }
  ::polygon_bad[rank>165][rank<=200]{
    polygon-fill: #410404; }
  ::polygon_nothing[rank=-1]{
    polygon-fill: #ffffff; }

    line-color: #434346;
    line-width: 1;
    line-join: round;
}

I kept the categorisation of the original source, where they define the countries between:1-21 = good…22-41 = satisfactory…42-120 = noticeable…121-165 = difficult…166+ = very serious……situation

Additionally, I made an overlay with a kind of paper structure. This is very similar to the structure in the ‘geography class’ example:

#paper { 
  polygon-pattern-file:url(textures/paper_folded_512.png);}

After these basics…you can now define the interactive part within the map, which is called “Teaser” in TileMill. Very easy…choose a layer which should provide the data for interactivity and copy-paste the attribute field of which the information will be provided to the user. In my case it looks this way:

<b>{{{name}}}</b>
<hr>
Ranking position: 
<strong>{{rank}}</strong>

As you can see, you can improve the visualisation of this information with basic html-coding. In my case, I show the name of the land (by the field ‘name’) and the corresponding ranking position (by the field ‘rank’).

That’s all for interacitvity! You can now export the map as *.mbtiles and upload it to MapBox. The resulting map can now be viewed online, like my example.

That was really easy, right? But for me it is not satisfying to not know the backend and have no idea of the corresponding processes that run in background. Additionally, you are limitted to 50MB at Mapbox when having just a free account,…

So I would like to do this on my own…but how.

The most interactive way…using Leaflet and GeoJSON

So how can I implement this by just using leaflet? On the main page you can find an examplary implementation of choropleth maps that seems to have the same interactive functionalities like my TileMill map.

Following the given instructions, you define a tile-based map with a background layer, using tiles from cloudemade, and an GeoJSON-overlay providing the statistical informations for the choropleth map.

How does it look for my map of world wide press freedom?

Necessary scripts and stylings:

<link rel="stylesheet" href="scripts/leaflet.css" />
<script src="scripts/leaflet.js"></script>
<script type="text/javascript" src="scripts/press.json"></script>
<style>
    #map { height: 400px; width:600px; }
    .info {
        padding: 6px 8px;
        font: 14px/16px Arial, Helvetica, sans-serif;
        background: white;
        background: rgba(255,255,255,0.8);
        box-shadow: 0 0 15px rgba(0,0,0,0.7);
        border-radius: 10px;
    }
    .info h4 {
        margin: 0 0 5px;
        color: #777;
    }
</style>

That is all for the head. Now let’s go to the body:

The map element.

<div id="map"></div>

And the content of the script, that contains all processing:

Load map and set the view

var map = L.map('map').setView([0, 0], 2)

Load the background layer

var cloudmade = L.tileLayer('http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png', {
 attribution: 'Map data &copy; 2011 OpenStreetMap contributors, Imagery &copy; 2011 CloudMade, Data &copy; 2013 <a href="http://www.reporter-ohne-grenzen.de/ranglisten/rangliste-2013/">ROG/RSF</a>',
 key: 'BC9A493B41014CAABB98F0471D759707',
 styleId: 22677
 }).addTo(map);

Load the GeoJSON file which I made using gdal by converting the shapefile containing the rank-attribute (using this command: ogr2ogr -f geoJSON press.json pf_rank.shp):

var geojson = L.geoJson(statesData, {
 style: style,
 onEachFeature: onEachFeature
 }).addTo(map)

There is already the request for styling (‘style’) and interactivity (‘onEachFeature’) included. Delete that for running before adding the functions!

!The geoJSON file is loaded by the command “statesDate”. So xou have to define the corresponding file as script (e.g. press.json) and define within this file the variable name…originary it has no…so set a new one. For this example: just add “var statesData = ” to the the beginning of the file ‘press.json’!

Define the functions that make a choropleth map from the GeoJSON data:

function style(feature) {
        return {
        fillColor: getColor(feature.properties.rank),
        weight: 1,
        opacity: 1,
        color: 'white',
        dashArray: '3',
        fillOpacity: 0.7
        };
    }
function getColor(d) {
        var grades = [0, 21, 41, 120, 165];
        return d > grades[4]  ? ' #410404' :
           d > grades[3]  ? '#ff0000' :
           d > grades[2]   ? '#f0681a' :
           d > grades[1]   ? '#ffcc00' :
                      '#4bcf15';
    }

Now you just have to add the functions that provide interactivity:

    function highlightFeature(e) {
        var layer = e.target;

        layer.setStyle({
        weight: 2,
        color: '#666',
        dashArray: '',
        fillOpacity: 0.7
        });

        if (!L.Browser.ie && !L.Browser.opera) {
        layer.bringToFront();
        }
        info.update(layer.feature.properties);
    }
    function resetHighlight(e) {
        geojson.resetStyle(e.target);
        info.update();
    }
    function zoomToFeature(e) {
        map.fitBounds(e.target.getBounds());
    }
    function onEachFeature(feature, layer) {
        layer.on({
        mouseover: highlightFeature,
        mouseout: resetHighlight,
        click: zoomToFeature
        });
    }

    var info = L.control();

    info.onAdd = function (map) {
        this._div = L.DomUtil.create('div', 'info'); // create a div with a class "info"
        this.update();
        return this._div;
    };

    // method that we will use to update the control based on feature properties passed
    info.update = function (props) {
        this._div.innerHTML = '<h4>World wide press freedom</h4>' +  (props ?
        '<b>' + props.name + '</b><br />Ranking position: ' + props.rank 
        : 'Hover over a state');
    };

    info.addTo(map);

In result we have an interactive map of the press freedom, which should look like this!

The advantages this way of visualising interactively informations is:

– the direct access to geometries

– the possibility for defining styling of geometries

The disadvantage are:

– the huge file size

– and the corresponding processing time of the map, especially processing is done in the browser –> my Netbook has problems while displaying the map while my PC displays it without any delay!

But how is this implemented for the MapBox map?

An individual and fast way…using the UTFGrid independently in a Leaflet script

When exporting a map from TileMill to *.mbtiles it compresses not only all png-images (tiles) to a SQLite database, it also (when you have defined something for the Teaser) exports an UTFGrid to the database.

When the TileMill map is uploaded to a MapBox account, is also the corresponding UTFGrid accessable: see an example

This is the original source that helped me a lot: https://github.com/danzel/Leaflet.utfgrid

What has to be done?

Download the leaflet – UTFGrid extension and import it to your script:

<script src="static/leaflet.utfgrid.js"></script>

We need a new UTFGrid-object:

var utfGrid = new L.UtfGrid('http://{s}.tiles.mapbox.com/v3/milkator.press_freedom/{z}/{x}/{y}.grid.json?callback={cb}', {
            resolution: 4
        });

and have to add this to the map:

map.addLayer(utfGrid)

The rest is pretty simple and is very similar to the processing of the GeoJSON data.

Define which actions should be done and which functions have to be called on these actions:

utfGrid.on('click', clicking)
 .on('mouseover', hovering)
 .on('mouseout', function (e) {console.log("Nothing implemented!");}
);

This is equivalent to the “onEachFeature” function of the GeoJSON layer in the example above!

The corresponding functions look as follows:

function hovering(e){
    if (e.data) {
        document.getElementById('hover').innerHTML = "<h4>World wide press freedom</h4>" +  (e ?
    "<b>" + e.data.name + "</b><br />Ranking position: " + e.data.rank 
    : 'Hover over a state');} 
    else {
        document.getElementById('hover').innerHTML = 'hover: nothing';}
    var layer = e.target;
        info.update(e);    }

function clicking(e){
    if (e.data) {
        document.getElementById('click2').innerHTML = 'click: ' + e.data.rank;} 
    else {
        document.getElementById('click2').innerHTML = 'click: nothing'; }

Find an example and the corresponding source code here!

The UTFGrid can also be calculated on-the-fly served as tiles by using TileStache, but that will be described in another post!

Extension: I’ve made a new Gist-repository version! So you can directly clone the code from there: http://bl.ocks.org/milkbread/6449317!
Have much fun with it!

Debugging in JavaScript

Debugging in JavaScript seemed to be, in the first moment I began with it, to be very complicated. But with a closer look it is really simple.

I use Firebug as debugging tool to my Firefox! This provides basically the possibility to read debugs.

In JavaScript, you have very simple possibilities to print some informative values to the debug window using the “console” command (e.g.: console.log(“My output!”);)

The cool thing is that, similar to Pyhons integrated function “dir()”, you can also print ancillary methods and objects by “console.dir();”

By this I can get even all ancillary information on console by:

console.dir(console);

This command delivers all possible console – functions:

assert
clear
count
debug
dir
dirxml
error
exception
group
groupCollapsed
groupEnd
info
log
profile
profileEnd
table
time
timeEnd
timeStamp
tracewarn

An functional equivalent, that I used before recognising the coolness of “console”, looks like this:

function dir(object) {
    stuff = [];
    for (s in object) {
    stuff.push(s);
    }
    stuff.sort();
    return stuff;
}

I found this function here!

Cartography in music

This is a list, especially for me, on cartography in music.

It was not very seldom, that I realised that some of my favoured bands refer to cartographic contents or even have a reference in the band name.That is why I make now a list of all cartographic references, that I discover in music when listening to it. In consequence, will this post be open for a long time. But I publish it now…so when somebody has also some other cartographic references in its music library…you are welcome 🙂

Bands with reference to cartography in name

Band
Maps
Maps and Atlases
Maps and Diagrams
Charts and Maps
Swell Maps

Songs with reference to cartography in title

Song Album Band
Atlas Mirrored Battles
Maps Fever To Tell Yeah Yeah Yeahs
Maps of your hand Hullabaloo Soundtrack Muse

other References to cartography

Band Album Content Link
Dredg Leitmotif cover image = satellite imagery
Long Distance Calling Satellite Bay cover image = satellite imagery
Thurston Moore Trees Outside the Academy backcover image = Thurston in front of a map
Brokeback Field Recordings from the Cook County Water Table cover image = satellite imagery Last.fm
Spotify
The Dandy Warhols Earth to Dandy Warhols cover image = satellite image of the earth Last.fm
Spotify

When I look at the list, it is not as astonishing as I thought before beginning this list. But nevertheless I will go on…maybe it will become more impressive, when it grows 😉

Making a map of germany with topojson

Original Source: http://bost.ocks.org/mike/map/

Download data:

Tools:

Convert data:

  • get german states as geojson
ogr2ogr \
  -f GeoJSON \
  -where "sr_adm0_a3 IN ('DEU')" \
  subunits.json \
  ne_10m_admin_1_states_provinces_shp.shp
  • get populated places a geojson…I just want to have the capital cities of each german state
ogr2ogr \
  -f GeoJSON \
  -where "adm0_a3 = 'DEU' AND FEATURECLA = 'Admin-1 capital'" \
  places.json \
  ne_10m_populated_places.shp
  • combine both layers to one topojson
topojson \
  --id-property su_a3 \
  -p NAME=name \
  -p name \
  -o de.json \
  subunits.json \
  places.jso

Final visualisation of the newly created topojson

<!DOCTYPE html>
<!--    http://bost.ocks.org/mike/map/-->
<meta charset="utf-8">
<style>
.subunit{fill:#fff;}
.subunit.Nordrhein-Westfalen{ fill: #aba; }
.subunit.Baden-Württemberg{ fill: #bab; }
.subunit.Hessen{ fill: #bcb; }
.subunit.Niedersachsen{ fill: #cbc; }
.subunit.Thüringen{ fill: #cdc; }
.subunit.Hamburg{ fill: #dcd; }
.subunit.Schleswig-Holstein{ fill: #ded; }
.subunit.Rheinland-Pfalz{ fill: #ede; }
.subunit.Saarland{ fill: #efe; }
.subunit.Sachsen-Anhalt{ fill: #fef; }
.subunit.Brandenburg{ fill: #aaa; }
.subunit.Mecklenburg-Vorpommern{ fill: #bbb; }
.subunit.Bayern { fill: #ccc; }
.subunit.Sachsen { fill: #ddd; }
.subunit.Bremen { fill: #eee; }
.subunit.Berlin { fill: #fff; }

.subunit-boundary {
  fill: none;
  stroke-width:1px;
  stroke: #777;
  stroke-dasharray: 2,2;
  stroke-linejoin: round;
}
.place,
.place-label {
  fill: #444;
  font-size:14px;
}
text {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-size: 20px;
  pointer-events: none;
}
.subunit-label {
  fill: #777;
  fill-opacity: .5;
  font-size: 30px;
  font-weight: 200;
  text-anchor: middle;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v0.min.js"></script>
<script>

var width = 1050,
    height = 1400;

var path = d3.geo.path();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

d3.json("data/de.json", showData);

function showData(error, de) {
    var subunits = topojson.object(de, de.objects.subunits);

    var projection = d3.geo.mercator()
        .center([10.5, 51.35])
        .scale(40000)
        .translate([width / 2, height / 2]);

    var path = d3.geo.path()
        .projection(projection)
        .pointRadius(4);

    svg.append("path")
        .datum(subunits)
        .attr("d", path)

    svg.selectAll(".subunit")
        .data(topojson.object(de, de.objects.subunits).geometries)
      .enter().append("path")
        .attr("class", function(d) { return "subunit " + d.properties.name; })
        .attr("d", path)
        .on("click", click);

    function click(a){
        console.log(a.properties.name);}

    svg.append("path")
        .datum(topojson.mesh(de, de.objects.subunits, function(a,b) { if (a!==b || a.properties.name === "Berlin"|| a.properties.name === "Bremen"){var ret = a;}return ret;}))
        .attr("d", path)
        .attr("class", "subunit-boundary");

    svg.append("path")
        .datum(topojson.object(de, de.objects.places))
        .attr("d", path)
        .attr("class", "place");

    svg.selectAll(".place-label")
        .data(topojson.object(de, de.objects.places).geometries)
      .enter().append("text")
        .attr("class", "place-label")
        .attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; })
        .attr("dy", ".35em")
        .text(function(d) { if (d.properties.name!=="Berlin"&&d.properties.name!=="Bremen"){return d.properties.name;} })
        .attr("x", function(d) { return d.coordinates[0] > -1 ? 6 : -6; })
        .style("text-anchor", function(d) { return d.coordinates[0] > -1 ? "start" : "end"; });

    svg.selectAll(".subunit-label")
        .data(topojson.object(de, de.objects.subunits).geometries)
      .enter().append("text")
        .attr("class", function(d) { return "subunit-label " + d.properties.name; })
        .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
        .attr("dy", function(d){ 
        if(d.properties.name==="Sachsen"||d.properties.name==="Thüringen"||d.properties.name==="Sachsen-Anhalt"||d.properties.name==="Rheinland-Pfalz")
            {return ".9em"}
        else if(d.properties.name==="Brandenburg"||d.properties.name==="Hamburg")
            {return "1.5em"}
        else if(d.properties.name==="Berlin"||d.properties.name==="Bremen")
            {return "-1em"}else{return ".35em"}})
        .text(function(d) { return d.properties.name; });

}
</script>

Have a look at the final result!

Installing topojson on Ubuntu 12.04

Original Source: http://bost.ocks.org/mike/map/

Install Node.js: https://ariejan.net/2011/10/24/installing-node-js-and-npm-on-ubuntu-debian

cd ~/Software
git clone https://github.com/joyent/node.git
cd node
./configure
make
sudo make install
node -v

Install topojson:

sudo npm install -g topojson

Develop own OpenJUMP PlugIn with Eclipse

The initial side where I started

http://sourceforge.net/apps/mediawiki/jump-pilot/index.php?title=How_to_use_and_make_own_Plugins (cached)

This link on the side didn’t help, so I searched for another tutorial on how to set up OpenJUMP in Eclipse…

Setup OpenJUMP in Eclipse

http://www.youtube.com/watch?v=cDAs04QEuzU (cached)

Additionals for the video:

– download older version ‘openjump-src-1.4.2’

–> http://sourceforge.net/projects/jump-pilot/files/OpenJUMP/

–> http://sourceforge.net/projects/jump-pilot/files/OpenJUMP/1.4.2/openjump-src-1.4.2.zip/download
– the text that the tutor enters to ‘Run Configuration’

-plug-in-directory lib/ext
-properties ./scripts/workbench-properties.xml

-Dorg.xml.sax.driver=org.apache.xerces.parser.SAXParser
-Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel
-Dlog4j.configuration=file:./etc/log4j.xml
-Duser.language=ml

(leaf out the last line, as it is the language of the tutor)

Making a first HelloWorldPlugIn

…still using information on this side!

!Make sure the filename ends with ‘PlugIn’…with a majuscel ‘I’…it is case sensitive!!!

The described instructions can be applied without any additions!!!

Running the first PlugIn

…still on this side!

Version 1 works easily.

Exporting a *.jar file has to be done this way…(!Before you have to create the new ‘Extension file, as described’!)

right click on folder ‘Helloi18n/src’ … ‘Export…’ … ‘Java/Jar file’ … only export all ‘src’ resources … select destination … ‘Finish’

now you only have to put this *.jar file into the plugin folder of OpenJUMP –‘> for me: /home/klammer/osm/bin/openjump-bin-1.4.1/lib/ext

Version 2 is also simple, but you have to made more editing!

It is a note to have OpenJUMP as seperate project…I did so as described above!!!

–> the workbench-properties.xml looks in my case this way:

<workbench>
 <plug-in>tudresden.klammer.HelloWorldPlugIn</plug-in> 
</workbench>

…and has to be stored in the project of the HelloWorldPlugIn

–> I already have a run entry…cause I followed the descriptions above…so I have to change this one …ergo … change the ‘Run Configurations’ again

!!!it is necessary to remove the ‘Program arguments’ that I have added before…replace them with the new one…which are for me:

-properties /home/klammer/Software/WebGen-WPS/wps-eclipse-workspace/Helloi18n/workbench-properties.xml

-> that points to the properties file stored in the PlugIn project

-plug-in-directory /home/klammer/Software/WebGen-WPS/wps-eclipse-workspace/OpenJUMP/lib/ext

-> that points to the OpenJUMP set up in Eclipse (as described above)

–> Point 5 is described very complicated but is not so

…just go to the ‘classpath’ tab of the ‘Run Configuration’ … click on ‘Bootstrap Entries’ and add all jar files of the OpenJUMP project ‘lib’ folder

…and click on ‘user entries’ and add the Plugin project

Thats it…click on run…and you should find a new menu called ‘View’ containing the menuitem ‘HelloWorldPlugIn’!!!