thydzik Google Map v2.1 released – now with KML support

The release of thydzik Goole Map version 2.1 supports KML files which once displayed can even be downloaded as GPX files.

Download from the WordPress plugin repository.

The following example uses the included example.kml file.

thydzikgooglemap(example.kml)

The following examples use the included example.xml file.

<markers>
<!-- Marker Z has no html to show nonclickability-->
<marker lat="-31.9554" lng="115.85859"  icon="Z" color="c89bff"/>
<marker lat="-32.053128" lng="115.745869" html="Fremantle"  icon="1" color="6b98ff"/>
<!-- Standard marker with html-->
<marker lat="-32.036036" lng="115.92724" html="<b>Lynwood</b><br>Residence of the author" color="ffed5c"/>
<marker lat="-31.963013" lng="115.836239" html="Kings Park" icon="KP" color="97ec7d"/>
<!-- Character marker with html that includes link-->
<marker lat="-31.956659" lng="115.869906" html="<a href="http://perthmint.com.au" rel="nofollow">Perth Mint</a>" icon="$" color="ffffff"/>
<!-- Example of two lines-->
<line colour="#0000FF" width="2" opacity="0.75">
	<point lat="-32.027579" lng="115.751266" />
	<point lat="-31.987404" lng="115.769463" />
	<point lat="-31.957697" lng="115.852203" />
	<point lat="-31.963814" lng="115.879326" />
	<point lat="-32.026415" lng="115.942154" />
</line>
<points colour="#FF0000" width="4" opacity="0.75">
	<point lat="-32.053128" lng="115.745869" />
	<point lat="-31.963013" lng="115.836239" />
	<point lat="-31.9554" lng="115.85859" />
	<point lat="-31.956659" lng="115.869906" />
	<point lat="-32.036036" lng="115.92724" />
</points>
</markers>
  • Marker Z – no HTML, nonclickable.
  • Marker 1 – standard maker with some text.
  • Marker Default – no icon defaults to standard Google Maps marker.
  • Marker $ – symbols can even be displayed on a marker and links in the HTML.
  • Marker KP – up to two characters can be displayed.

To display a map, simply type;

thydzikgooglemap(example.xml)

For the more adventurous;

thydzikgooglemap(example.xml, width, height, zoom, maptype)

where;

  • example.xml is your xml file, and example xml file is included with thdyzikGoogleMap in the plugin directory.
  • width is the optional width parameter, if left out the default width defined in the thydzikgooglemap options will be used.
  • height is the optional height parameter, if left out the default height defined in the thydzikgooglemap options will be used.
  • zoom is the optional zoom level from 0 to 17 (0 being the furthest away), if left out zoom will be calculated automatically to fit all points.
  • maptype is the optional map type parameters, which can be (Normal, G_NORMAL_MAP, N), (SATELLITE, G_SATELLITE_MAP, S), (HYBRID, G_HYBRID_MAP, H), (PHYSICAL, G_PHYSICAL_MAP, P, TERRAIN or T) if left out Normal is defined.

Normal, G_NORMAL_MAP, N or left out; i.e. thydzikgooglemap(example.xml), thydzikgooglemap will produce a default styled map;

thydzikgooglemap(example.xml)

SATELLITE, G_SATELLITE_MAP, S; i.e. thydzikgooglemap(example.xml, 4, S), thydzikgooglemap will produce a satellite styled map. Note I have included a zoom of 4, and used the abreviation ‘S’;

thydzikgooglemap(example.xml, 4, S)

HYBRID, G_HYBRID_MAP, H; i.e. tHyDzIkGoOgLeMaP(example.xml,hYbRiD,450,225), thydzikGoolgeMap will produce a hybrid styled map. Note I have included a width and height, and proved that capitalisation is not of concern;

tHyDzIkGoOgLeMaP(example.xml, hYbRiD, 450,225)

PHYSICAL, G_PHYSICAL_MAP, P, TERRAIN or T; i.e thydzikgooglemap(example.xml,TERRAIN), thydzikgooglemap will produce a terrain styled map;

thydzikgooglemap(example.xml,TERRAIN)

Reading XML from different folder
The XML can be in any location, as long as the whole path is specified i.e. thydzikgooglemap(http://thydzik.com/geocaching/karratha-mar08/karratha-mar08.xml). Yes, even links in the marker text are preserved.

thydzikgooglemap(http://thydzik.com/geocaching/karratha-mar08/karratha-mar08.xml)

Reading XML from different domain
The XML can even be on a different domain, as long as the whole path is specified. i.e. thydzikgooglemap(http://sonyaandtravis.com/maps/our-nullarbor-adventure-clare-melbourne08.xml).

Convert from Google KML to GPS Exchange Format GPX with PHP

Here is a quick post on converting from KML files used in Google Earth/Maps to GPX Exchange Format (GPX) with PHP.

Code is quite explanatory, change $u with the location of the KML file, code will output GPX XML.

Alternatively, download the code here.

<?php
	//enter location of KML file here
	$u = "http://code.google.com/apis/kml/documentation/KML_Samples.kml";
	
	
	function utcdate() {
		return gmdate("Y-m-d\Th:i:s\Z");
	}

	
	$u_parts = pathinfo($u); //array of url parts
	$u_ext = strtoupper($u_parts['extension']);
	if ($u_ext== "KML") {

		$dom_kml = new DOMDocument();
		$dom_kml->load($u);

		$dom_gpx = new DOMDocument('1.0', 'UTF-8');
		$dom_gpx->formatOutput = true;
		
		//root node
		$gpx = $dom_gpx->createElement('gpx');
		$gpx = $dom_gpx->appendChild($gpx);
		
		$gpx_version = $dom_gpx->createAttribute('version');
		$gpx->appendChild($gpx_version);
		$gpx_version_text = $dom_gpx->createTextNode('1.0');
		$gpx_version->appendChild($gpx_version_text);
		
		$gpx_creator = $dom_gpx->createAttribute('creator');
		$gpx->appendChild($gpx_creator);
		$gpx_creator_text = $dom_gpx->createTextNode('http://thydzik.com');
		$gpx_creator->appendChild($gpx_creator_text);
		
		$gpx_xmlns_xsi = $dom_gpx->createAttribute('xmlns:xsi');
		$gpx->appendChild($gpx_xmlns_xsi);
		$gpx_xmlns_xsi_text = $dom_gpx->createTextNode('http://www.w3.org/2001/XMLSchema-instance');
		$gpx_xmlns_xsi->appendChild($gpx_xmlns_xsi_text);
		
		$gpx_xmlns = $dom_gpx->createAttribute('xmlns');
		$gpx->appendChild($gpx_xmlns);
		$gpx_xmlns_text = $dom_gpx->createTextNode('http://www.topografix.com/GPX/1/0');
		$gpx_xmlns->appendChild($gpx_xmlns_text);
		
		$gpx_xsi_schemaLocation = $dom_gpx->createAttribute('xsi:schemaLocation');
		$gpx->appendChild($gpx_xsi_schemaLocation);
		$gpx_xsi_schemaLocation_text = $dom_gpx->createTextNode('http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd');
		$gpx_xsi_schemaLocation->appendChild($gpx_xsi_schemaLocation_text);
		
		$gpx_url = $dom_gpx->createElement('url');
		$gpx_url = $gpx->appendChild($gpx_url);
		$gpx_url_text = $dom_gpx->createTextNode($u_parts['dirname']);
		$gpx_url->appendChild($gpx_url_text);
		
		$gpx_time = $dom_gpx->createElement('time');
		$gpx_time = $gpx->appendChild($gpx_time);
		$gpx_time_text = $dom_gpx->createTextNode(utcdate());
		$gpx_time->appendChild($gpx_time_text);
		
		// placemarks
		$names = array();
		foreach ($dom_kml->getElementsByTagName('Placemark') as $placemark) {
			//name
			foreach ($placemark->getElementsByTagName('name') as $name) {
				$name  = $name->nodeValue;
				//check if the key exists
				if (array_key_exists($name, $names)) {
					//increment the value
					++$names[$name];
					$name = $name." ({$names[$name]})";
				} else {
					$names[$name] = 0;
				}
			}
			//description
			foreach ($placemark->getElementsByTagName('description') as $description) {
				$description  = $description->nodeValue;
			}
			foreach ($placemark->getElementsByTagName('Point') as $point) {
				foreach ($point->getElementsByTagName('coordinates') as $coordinates) {
					//add the marker
					$coordinate = $coordinates->nodeValue;
					$coordinate = str_replace(" ", "", $coordinate);//trim white space
					$latlng = explode(",", $coordinate);
					
					if (($lat = $latlng[1]) && ($lng = $latlng[0])) {
						$gpx_wpt = $dom_gpx->createElement('wpt');
						$gpx_wpt = $gpx->appendChild($gpx_wpt);

						$gpx_wpt_lat = $dom_gpx->createAttribute('lat');
						$gpx_wpt->appendChild($gpx_wpt_lat);
						$gpx_wpt_lat_text = $dom_gpx->createTextNode($lat);
						$gpx_wpt_lat->appendChild($gpx_wpt_lat_text);
						
						$gpx_wpt_lon = $dom_gpx->createAttribute('lon');
						$gpx_wpt->appendChild($gpx_wpt_lon);
						$gpx_wpt_lon_text = $dom_gpx->createTextNode($lng);
						$gpx_wpt_lon->appendChild($gpx_wpt_lon_text);
						
						$gpx_time = $dom_gpx->createElement('time');
						$gpx_time = $gpx_wpt->appendChild($gpx_time);
						$gpx_time_text = $dom_gpx->createTextNode(utcdate());
						$gpx_time->appendChild($gpx_time_text);
						
						$gpx_name = $dom_gpx->createElement('name');
						$gpx_name = $gpx_wpt->appendChild($gpx_name);
						$gpx_name_text = $dom_gpx->createTextNode($name);
						$gpx_name->appendChild($gpx_name_text);
						
						$gpx_desc = $dom_gpx->createElement('desc');
						$gpx_desc = $gpx_wpt->appendChild($gpx_desc);
						$gpx_desc_text = $dom_gpx->createTextNode($description);
						$gpx_desc->appendChild($gpx_desc_text);
						
						//$gpx_url = $dom_gpx->createElement('url');
						//$gpx_url = $gpx_wpt->appendChild($gpx_url);
						//$gpx_url_text = $dom_gpx->createTextNode($ref);
						//$gpx_url->appendChild($gpx_url_text);
						
						$gpx_sym = $dom_gpx->createElement('sym');
						$gpx_sym = $gpx_wpt->appendChild($gpx_sym);
						$gpx_sym_text = $dom_gpx->createTextNode('Waypoint');
						$gpx_sym->appendChild($gpx_sym_text);
					}
				}
			}
			foreach ($placemark->getElementsByTagName('LineString') as $lineString) {
				foreach ($lineString->getElementsByTagName('coordinates') as $coordinates) {
					//add the new track
					$gpx_trk = $dom_gpx->createElement('trk');
					$gpx_trk = $gpx->appendChild($gpx_trk);
					
					$gpx_name = $dom_gpx->createElement('name');
					$gpx_name = $gpx_trk->appendChild($gpx_name);
					$gpx_name_text = $dom_gpx->createTextNode($name);
					$gpx_name->appendChild($gpx_name_text);
					
					$gpx_trkseg = $dom_gpx->createElement('trkseg');
					$gpx_trkseg = $gpx_trk->appendChild($gpx_trkseg);
				
					$coordinates = $coordinates->nodeValue;
					$coordinates = preg_split("/[\s\r\n]+/", $coordinates); //split the coords by new line
					foreach ($coordinates as $coordinate) {
						$latlng = explode(",", $coordinate);
						
						if (($lat = $latlng[1]) && ($lng = $latlng[0])) {
							$gpx_trkpt = $dom_gpx->createElement('trkpt');
							$gpx_trkpt = $gpx_trkseg->appendChild($gpx_trkpt);

							$gpx_trkpt_lat = $dom_gpx->createAttribute('lat');
							$gpx_trkpt->appendChild($gpx_trkpt_lat);
							$gpx_trkpt_lat_text = $dom_gpx->createTextNode($lat);
							$gpx_trkpt_lat->appendChild($gpx_trkpt_lat_text);
							
							$gpx_trkpt_lon = $dom_gpx->createAttribute('lon');
							$gpx_trkpt->appendChild($gpx_trkpt_lon);
							$gpx_trkpt_lon_text = $dom_gpx->createTextNode($lng);
							$gpx_trkpt_lon->appendChild($gpx_trkpt_lon_text);
							
							$gpx_time = $dom_gpx->createElement('time');
							$gpx_time = $gpx_trkpt->appendChild($gpx_time);
							$gpx_time_text = $dom_gpx->createTextNode(utcdate());
							$gpx_time->appendChild($gpx_time_text);
						}
					}
				}
			}
		}
		header("Content-Type: text/xml");
		echo $dom_gpx->saveXML();
	}
?>

Let me know if you find any issues.

In search of the elusive Google default marker

For a number of years now I have been developing a Google Maps plugin for WordPress <end of plug>, I have even created a script to dynamically generate coloured markers with custom text. This is a great solution for hosting your own markers, but is has a lot of overhead, having to host a custom Arial font and requiring the PHP GD library installed. And even then, I still relied on Google to provide the starting coloured marker .

Google does provide an alternative, custom text and colour, but there is one problem, what if I want the classic default Google Map’s marker default marker, the one with the large black dot. Well it isn’t there. And that is where my script, dare I say, exceeded Google.

The trick was adding the large black dot to the font. You know that ugly square box you sometimes see when you don’t have the correct fonts installed square box marker, I simply replaced this with the large black dot. Any character codes that aren’t available will simply return the default style marker default marker with my script.

So that’s my implementation, but how do I migrate from my script to Google’s while keeping the default style marker. I had to find an equivalent. All the obvious choices (bullet U+2022, bullet operator U+2219 and black circle U+25CF) didn’t work.

I started sifting through thousands of markers, looking for the closest representation to the default marker. What I found was kangxi radical one U+2F00, now don’t ask me why, but for some reason this produced a black dot style marker close enough default marker, though smaller than the default. This would have to do.

collection of markers

5000+ markers in a 1mb+ png file
5000+ markers in a html page (file name is the unicode)

Note: all above inline marker examples are hosted on Google or generated with my script (view the image name to find out more).

thydzik Google Map version 1.4.6.1

Latest offering has cleaned up JavaScript, improved error handling, improved RoboGEO handling of XML, but main features are.

  • Icons now support letters ‘A’ to ‘Z’.
  • Non clickable markers if no ‘html’ element is present.

In the below example Marker Z is not clickable.

thydzikgooglemap(example.xml)

Download the latest from the WordPress repository.

thydzikGoogleMap v1.4.5 – an inline Google map plugin for WordPress

thydzikGoogleMap v1.4.5 is now available with significant improvements, including

  • The Google Maps Javascript and thydzikGoogleMap Javascript is downloaded only as needed, speeding up page loading of all pages without maps.
  • Removal of <head> code means thydzikGoogleMap will only be present when called.
  • Compressed thydzikGoogleMap code.
  • Multiple maps can now be created in a single post!
  • Map type can be changed from default by providing an additional ‘map type’ parameter.

thydzikGoogleMap produces valid XHTML and allows for easy creation of Google Maps in your WordPress posts from XML map data.

Grab the latest from the WordPress repository.

Examples of the newest functionality below:

Using either: Normal, G_NORMAL_MAP, N or left out; i.e. thydzikGoogleMap(example.xml), thydzikGoogleMap will produce a default styled map

thydzikGoogleMap(example.xml)

Using either: SATELLITE, G_SATELLITE_MAP, S; i.e. thydzikgooglemap(example.xml, 4, S), thydzikGoogleMap will produce a satellite styled map. Note I have included a zoom of 4, and used the abreviation ‘S’.

thydzikgooglemap(example.xml, 4, S)

Using either: HYBRID, G_HYBRID_MAP, H; i.e. tHyDzIkGoOgLeMaP(example.xml,hYbRiD,450,225), thydzikGoolgeMap will produce a hybrid styled map. Note I have included a width and height, and proved that capitalisation is not of concern.

tHyDzIkGoOgLeMaP(example.xml, hYbRiD, 450,225)

Finally, using either: PHYSICAL, G_PHYSICAL_MAP, P, TERRAIN or T; i.e thydzikGoogleMap(example.xml,TERRAIN), thydzikGoogleMap will produce a terrain styled map.

thydzikGoogleMap(example.xml,TERRAIN)

As always, comments and suggestions welcome. In a future update I will try to incorporate rounded corners :)

thydzikGoogleMap v1.4

thydzikGoogleMap version 1.4 has been released with two major improvements.

  1. Manual zoom parameter added. Google uses an integer value from 0 to 17 (where 0 is the furthest away), to determine the map’s zoom level, this value can now be incorporated into thydzikGoogleMap as follows: thydzikGoogleMap(example.xml, 4). The zoom is an optional parameter and if left out the automatic zoom calculation will be used as before. The width and height of the map can still be added if desired as thydzikGoogleMap(example.xml, 4, 480, 640) or thydzikGoogleMap(example.xml, 480, 640, 4).
  2. The thydzikGoogleMap code is disabled if the site is viewed from a proxy, i.e. Google cache. Before a user viewing the blog would receive ‘The Google Maps API key used on this web site was registered for a different web site. You can generate a new key for this web site at http://code.google.com/apis/maps/.’ thydzikGoogleMap now detects this and disables the maps.

Example with the new zoom functionality

thydzikGoogleMap(example.xml, 4)

Future improvements will include

  • Option of choosing Map, Satellite or Terrain
  • Disabling all code if no thydzikGoogleMap are present
  • Creating multiple maps in a single blog post

Grab the latest from the WordPress repository.

thydzikGoogleMap v1.3

I have finally managed to get WordPress to update the version number. This problem was due to not updating the version number in the PHP file as well as the readme.txt.

Version 1.3 fixes a problem with thydzikGoogleMap not displaying correctly when a WordPress blog isn’t located in the domain folder.

I have seen a few users, using thydzikGoogleMap to display a single point or no points at all, thydzikGoogleMap isn’t really for this as it is not worth creating an XML file just for the single point. Plus I believe you can now simply embed a Google map with some simple code.

However, if you want full customization; including lines, numbered points, HTML in a point’s detail, then thydzikGoogleMap is exactly for you.

Comments and suggestions very welcome.

Download thydzikGoogleMap v1.3

thydzikGoogleMap – an inline Google map plugin for WordPress

thydzikGoogleMap is a WordPress plugin that creates inline Google maps in your WordPress posts. There are two main advantages over other existing Google maps plugins and they are:

  1. Ease of use, to create a Google map simply type thydzikGoogleMap(mapdata.xml, 600, 480) in your post on its own line.
  2. thydzikGoogleMap uses XML map data, this allows for maximum configurability, and supports multiple points and lines.

Please note, this is my first attempt at any ‘real’ php coding and my first attempt at creating a WordPress plugin. I am pretty sure I have not coded things optimally, the main thing is it does work. I have tried to minimise the return of errors and the plugin not working. Comments welcome on any suggestions or bugs.

thydzikGoogleMap(example.xml)

Few notes:

  • a markers folder is included with numbered pointers, these are used only when icon=”x” (where x is an integer), if this is excluded or pointers are alphabetical default Googles pointers will be used.
  • if width and height is excluded, the default width and height (460 and 345 respectively), found in the configuration page will be used.
  • thydzikGoogleMap automatically centres and zooms in on the points and lines, this may not always give the best results.
  • thydzikGoogleMap will produce a Google map only if the XML file is found, this was made so that examples i.e. thydzikGoogleMap(mapdata.xml) could be posted without producing a Google map.
  • thydzikGoogleMap searches post text using the_content and replaces valid thydzikGoogleMap with HTML and Javascript to produce a Google map. This might not be the best way to achieve this.
  • Only 1 Google map per post with be converted, however, multiple maps can exist when multiple posts are displayed.
  • thydzikGoogleMap produces valid XHTML.
  • thydzikGoogleMap has only been tested on the default Kubrick theme, WordPress version 2.3.2.

Download thydzikGoogleMap