browse by category or date

In my recent project, one of its important feature was to be able to display all seaports that currently have ISO Tanks in the world map. To do that, first I need to have a database of seaports complete with the longitude & latitude position. Below is the data-entry form I created.

edit-port

You can slowly insert the data one-by-one, or you can just scrape the web 🙂

Since Google Map is using decimal Latitude/Longitude value, we need to create a method to convert from degree (e.g. 103° 50′ N) to decimal value (e.g. 103.833) . Here’s my code in C#:

// ---- Code SNIP -------
//Declare the Regex as part of the class member
private Regex rgxLatLon = new Regex("((?<degree>[0-9]+)°)((\\ )(?<minute>[0-9]+)')?((\\ )(?<second>[0-9]+)\")?((\\ )(?<dir>(E|S|N|W)))");
// ---- Code SNIP -------
private bool convDegDec(String raw, out double result)
{
	result = 0;
	var mLat = rgxLatLon.Match(raw);
	if (mLat.Success)
	{
		foreach (var g in mLat.Groups)
		{
			var deg = mLat.Groups["degree"].Value;
			if (!String.IsNullOrEmpty(deg))
				result = double.Parse(deg);
			var min = mLat.Groups["minute"].Value;
			if (!String.IsNullOrEmpty(min))
				result += (double.Parse(min) / 60);
			var sec = mLat.Groups["second"].Value;
			if (!String.IsNullOrEmpty(sec))
				result += (double.Parse(sec) / 3600);
			var dir = mLat.Groups["dir"].Value;
			if (dir == "S" || dir == "W")
				result = result * (-1);
		}
	}
	return mLat.Success;
}
// ---- Code SNIP -------

Final step is to actually render Google Maps, add the markers according to Seaports’ position, and display the necessary information when the marker is clicked. I won’t explain on how to use the Google Maps API because they already have a very good official guide.

Anyway, here’s how I render the map, markers and information window:

var map, info = {};
function initialize() {
	// Centralize the map to Singapore	
	var mapOptions = {
		center : new google.maps.LatLng(1.2666666666666666, 103.83333333333333),
		zoom : 6
	};

	// I have a div with id='map-canvas' as the map's placeholder
	map = new google.maps.Map(document.getElementById("map-canvas"),
			mapOptions);

	//get the Seaports and its Tanks count
	$.ajax({
		// the JSON webservice, add tick to prevent caching
		url : '/Tank/MapData?_tick=' + Math.random(),
		dataType : 'json'
	}).always(function (resp) {
		var obj = {};
		eval("obj = " + resp.responseText);

		/* Sample JSON object returned by /Tank/MapData: 
		{
			data : [{
					"CurPort" : "PKL",
					"CurrentPort" : "Port Klang",
					"decLat" : 3.0,
					"decLon" : 101.4,
					"TankCount" : 41
				}, {
					"CurPort" : "SIN",
					"CurrentPort" : "Singapore",
					"decLat" : 1.2666666666666666,
					"decLon" : 103.83333333333333,
					"TankCount" : 44
				}, {
					"CurPort" : "JKT",
					"CurrentPort" : "Jakarta",
					"decLat" : -6.1,
					"decLon" : 106.86666666666666,
					"TankCount" : 18
				},  {
					"CurPort" : "KUA",
					"CurrentPort" : "Kuantan ",
					"decLat" : 3.9666666666666668,
					"decLon" : 103.43333333333334,
					"TankCount" : 47
				}
			],
			total : 4
		}
		*/
		if (obj.data) {
			$.each(obj.data, function (i, p) {
				// set marker's position
				var myLatlng = new google.maps.LatLng(p.decLat, p.decLon);
				
				// the info window to show if the marker is clicked
				// the info window contains a hyperlink to SeaPort's details
				var infowindow = new google.maps.InfoWindow({
						content : "<div class='winInfo'><strong><a href='#' class='liPort' data-port='" + p.CurPort + "'>" + p.CurrentPort.toUpperCase() + "</a></strong><div>Tanks : " + p.TankCount + "</div></div>",
						disableAutoPan : true
					});
				
				// create the marker
				var marker = new google.maps.Marker({
						position : myLatlng,
						map : map,
						title : p.CurPort
					});

				// add the info window to global collection
				info[p.CurPort] = infowindow;

				// if marker is clicked, show the info window
				google.maps.event.addListener(marker, 'click', function () {
					info[marker.title].open(map, marker);
				});

				// by default, show the info window
				infowindow.open(map, marker);
			});

			// bind the click event on the document and use selector 
			// to ensure any new info window's hyperlink is clickable
			$(document).on('click', '.liPort', {}, function () {
				var port = $(this).attr('data-port');
				var title = $(this).text();
				top.Northwind.addTab({
					url : '/Tank/Overview?port=' + port,
					title : title,
					icon : 'icon-database'
				});
			});

			// refresh the map data every 30 seconds
			setInterval(function () {
				$.ajax({
					url : '/Tank/MapData?_tick=' + Math.random(),
					dataType : 'json'
				}).always(function (resp) {
					var obj = {};
					eval("obj = " + resp.responseText);
					if (obj.data) {
						$.each(obj.data, function (ii, pp) {
							var dPort = $(".liPort[data-port='" + pp.CurPort + "']");
							if (dPort.length > 0) {
								dPort.parent().next().html("<div>Tanks : " + pp.TankCount + "</div>");
							}
						});
					}
				});
			}, 30000);
		}
	});
}

// call initialize() when map is fully loaded
google.maps.event.addDomListener(window, 'load', initialize);

Here’s how the map will look like:

google-map-sea

Good luck on your implementation. I hope it helps, cheers!

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

To compare the content of two folders in Windows you can use diff command.

diff-cmd

Normally, to compare to files you use this command:


C:\Users\hardono>diff file1.txt file2.txt

To compare two folder, use the parameter -rq:


C:\Users\hardono>diff -rq T:\ C:\Projects\Java\TMS

Below is the result’s snippet:

Only in C:\Projects\Java\TMS: .git
Files T:\checkpassword.asp and C:\Projects\Java\TMS/checkpassword.asp differ
Files T:\contact/Thumbs.db and C:\Projects\Java\TMS/contact/Thumbs.db differ
Only in T:\: crystalreportviewers10
Only in C:\Projects\Java\TMS/etrack: _notes
Files T:\etrack/trucker_pictures/Thumbs.db and C:\Projects\Java\TMS/etrack/trucker_pictures/Thumbs.db differ
Only in C:\Projects\Java\TMS/etrack/trucker_pictures: _notes
Files T:\images/Thumbs.db and C:\Projects\Java\TMS/images/Thumbs.db differ
Only in T:\invoice: testing.asp
Only in C:\Projects\Java\TMS/jobsummary: _notes
Files T:\jobsummary/daily_cargo_report.asp and C:\Projects\Java\TMS/jobsummary/daily_cargo_report.asp differ
Only in C:\Projects\Java\TMS/misc: _notes
Only in T:\misc/songs: newyearsong-old.mp3
Only in C:\Projects\Java\TMS/misc_new: _notes
Only in T:\misc_new/songs: newyearsong-old.mp3

If you receive error like below, it means you haven’t install Git.
diff-cmd-error

You can download Git for Windows from http://msysgit.github.io/

Once you’ve have installed it, don’t forget to add C:\Program Files (x86)\Git\bin or C:\Program Files\Git\bin (depending on the version you installed) to System’s Environment variable:

system-properties-advanced-environment-variables

I hope it helps, cheers!

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant:

Kinda late to the party 😀 But anyway, as you can judge yourself, there is no nipple exposed in her US debut video. I believe it’s just a PR to increase the YouTube view counts.

agnez-mo-coke-bottle

As for Agnes’ aspiration to go International, somehow it reminds me of Sun Ho. I wonder how much money Agnes spent on this project. I hope she didn’t burn so much cash like Sun Ho did.

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Possibly relevant: