{"id":3063,"date":"2014-12-26T23:18:46","date_gmt":"2014-12-26T22:18:46","guid":{"rendered":"https:\/\/www.devco.net\/?p=3063"},"modified":"2014-12-26T23:35:45","modified_gmt":"2014-12-26T22:35:45","slug":"ruby-google-maps-and-kml","status":"publish","type":"post","link":"https:\/\/www.devco.net\/archives\/2014\/12\/26\/ruby-google-maps-and-kml.php","title":{"rendered":"Ruby, Google Maps and KML"},"content":{"rendered":"

Since 1999 I kept record of most places I’ve traveled to. In the old days I used a map viewer from PARC Xerox to view these travels, I then used XPlanet<\/a> which made a static image<\/a>. Back in 2005 as Google Maps became usable from Javascript I made something to show my travels on an interactive map<\/a>. It was using Gmaps EZ<\/a> and PHP to draw points from a XML file.<\/p>\n

Since then google made their v2 API defunct and something went bad with the old php code and so the time came to revisit all of this into the 4th iteration of a map tracking my travels.<\/p>\n

Google Earth<\/a> came out in 2005 as well – so just a bit late for me to use it’s data formats – but today it seems obvious that the data belong in a KML<\/a> file. Hand building KML files though is not on, so I needed something to build the KML file in Ruby.<\/p>\n

My new app maintains points in YAML files, have more or less an identical format to the old PHP system.<\/p>\n

First to let people come up with categories of points you define a bunch of types of points first:<\/p>\n

\r\n:types:\r\n  :visit:\r\n    :icon: http:\/\/your.site\/markers\/mini-ORANGE-BLANK.png\r\n  :transit:\r\n    :icon: http:\/\/your.site\/markers\/mini-BLUE-BLANK.png\r\n  :lived:\r\n    :icon: http:\/\/your.site\/markers\/mini-GREEN-BLANK.png\r\n<\/pre>\n

And then we have a series of points each referencing a type:<\/p>\n

\r\n:points:\r\n- :type: :visit\r\n  :lon: -73.961334\r\n  :title: New York\r\n  :lat: 40.784506\r\n  :country: United States\r\n  :comment: Sample Data\r\n  :href: http:\/\/en.wikipedia.org\/wiki\/New_York\r\n  :linktext: Wikipedia\r\n- :type: :transit\r\n  :lon: -71.046524\r\n  :title: Boston\r\n  :lat: 42.363871\r\n  :country: United States\r\n  :comment: Sample Data\r\n  :href: http:\/\/en.wikipedia.org\/wiki\/Boston\r\n  :linkimg: https:\/\/pbs.twimg.com\/profile_images\/430836891198320640\/_-25bnPr.jpeg\r\n<\/pre>\n

Here we have 2 points, both link to Wikipedia one using text and one using an image, one is a visit and one is a transit.<\/p>\n

I use the ruby_kml<\/a> Gem to convert this into KML:<\/p>\n

First we set up the basic document and we set up the types using KML styles:<\/p>\n

\r\nkml = KMLFile.new\r\ndocument = KML::Document.new(:name => \"Travlrmap Data\")\r\n\r\n@config[:types].each do |k, t|\r\n  document.styles << KML::Style.new(\r\n    :id         => \"travlrmap-#{k}-style\",\r\n    :icon_style => KML::IconStyle.new(:icon => KML::Icon.new(:href => t[:icon]))\r\n  )\r\nend\r\n<\/pre>\n

This sets up the types and give them names like travlrmap-visited-style<\/i>. <\/p>\n

We’ll now reference these in the KML file for each point:<\/p>\n

\r\nfolder = KML::Folder.new(:name => \"Countries\")\r\nfolders = {}\r\n\r\n@points.sort_by{|p| p[:country]}.each do |point|\r\n  unless folders[point[:country]]\r\n    folder.features << folders[point[:country]] = KML::Folder.new(:name => point[:country])\r\n  end\r\n\r\n  folders[point[:country]].features << KML::Placemark.new(\r\n    :name        => point[:title],\r\n    :description => point_comment(point),\r\n    :geometry    => KML::Point.new(:coordinates => {:lat => point[:lat], :lng => point[:lon]}),\r\n    :style_url   => \"#travlrmap-#{point[:type]}-style\"\r\n  )\r\nend\r\n\r\ndocument.features << folder\r\nkml.objects << document\r\n\r\nkml.render\r\n<\/pre>\n

The points are put in folders by individual country. So in Google Earth I get a nice list of countries to enable\/disable as I please etc.<\/p>\n

I am not showing how I create the comment html here - it's the point_comment<\/i> method - it's just boring code with a bunch of if's around linkimg<\/i>, linktext<\/i> and href<\/i>. KML documents does not support all of HTML but the basics are there so this is pretty easy.<\/p>\n

So this is the basics of making a KML file from your own data, it's fairly easy though the docs for ruby_kml<\/i> isn't that hot and specifically don't tell you that you have to wrap all the points and styles and so forth in a document<\/i> as I have done here - it seems a recent requirement of the KML spec though.<\/p>\n

Next up we have to get this stuff onto a google map in a browser. As KML is the format Google Earth uses it's safe to assume the Google Maps API support this stuff directly. Still, a bit of sugar around the Google APIs are nice because they can be a bit verbose. Previously I used GMapsEZ - which I ended up really hating as the author did all kinds of things like refuse to make it available for download instead hosting it on a unstable host. Now I'd say you must use gmaps.js<\/a> to make it real easy.<\/p>\n

For viewing a KML file, you basically just need this - more or less directly from their docs - there's some ERB template stuff in here to set up the default view port etc:<\/p>\n

\r\n