// This shows OS graticule as custom GOverlay on Google Maps. requires script LatLngToOSGB.js
// Bill Chadwick, http://www.bdcc.co.uk/Gmaps/BdccGmapBits.htm
// Modified by Ross Kennedy for Trailwise 9/2007 version 2.1

function OGBGraticule() { }

OGBGraticule.prototype = new GOverlay();

OGBGraticule.prototype.initialize = function(map) {
	this.map_=map; //our map object
	this.lines_=[]; //array for lines 
	this.divs_=[]; //array for labels
	this.color_="#0033ff"; //set colour
}

OGBGraticule.prototype.remove = function() {
	for(var i=0; i<this.lines_.length; i++) {
		if (this.lines_[i].grid) { //reentry protect
			this.map_.removeOverlay(this.lines_[i]);	
			this.lines_[i].grid=false;
		}
	}
	var div=this.map_.getPane(G_MAP_MARKER_SHADOW_PANE);
	for(i=0; i<this.divs_.length; i++) {
		if (this.divs_[i].grid) {
			div.removeChild(this.divs_[i]);
			this.divs_[i].grid=false;
		}
	}
}

OGBGraticule.prototype.copy = function() {
  return new OGBGraticule();
}

// Dummy auto redraw, cos it errors
OGBGraticule.prototype.redraw = function(force) {
	return;
}

// Redraw the graticule based on the current projection and zoom level
OGBGraticule.prototype.realdraw = function(force) {
 //clear old
	this.remove();

 //get corners
	var Gll_sw=this.map_.getBounds().getSouthWest();
	var Gll_ne=this.map_.getBounds().getNorthEast();
 //sanity limits to UK
	if (Gll_ne.lat()<49.0 || Gll_sw.lat()>61.0) {return}
	if (Gll_ne.lng()<-8.0 || Gll_sw.lng()>2.0) {return}

	var OGll_sw=WGS84ToOGB(Gll_sw.lat(),Gll_sw.lng(),0); //convert coords
	var EN_sw=LLtoNE(OGll_sw.lat,OGll_sw.lon);
	var OGll_ne=WGS84ToOGB(Gll_ne.lat(),Gll_ne.lng(),0);
	var EN_ne=LLtoNE(OGll_ne.lat,OGll_ne.lon);

	var west=EN_sw.east / 1000.0; //km
	var south=EN_sw.north / 1000.0;
	var east=EN_ne.east / 1000.0;
	var north=EN_ne.north / 1000.0;

	var ww=Math.max(east-west,north-south); // length side

	var d;//km initial/min interval
	ww /= 10;//want about 10 grid lines
	if(ww<2.0) {d=1.0} // min 1km
	else if(ww<3.0) {d=2.0}
	else if(ww<7.0) {d=5.0}
	else if(ww<13.0) {d=10.0}
	else if(ww<27.0) {d=20.0}
	else if(ww<70.0) {d=50.0}
	else {d=100.0} //max
 //round iteration limits to the computed grid interval
	east=Math.ceil(east/d)*d;
	west=Math.floor(west/d)*d;
	north=Math.ceil(north/d)*d;
	south=Math.floor(south/d)*d;
 //Sanity limit
	if (west<=0.0) {west=0.0}
	if (east>=700.0) {east=700.0}
	if (south<0.0) {south=0.0}
	if (north>1300.0) {north=1300.0}
      
	this.lines_=[];
	this.divs_=[];
	var i=0; //count lines
	var j=0; //count div labels
 //pane/layer to write on
	var mapDiv=this.map_.getPane(G_MAP_MARKER_SHADOW_PANE);

 //horizontal lines
	var s=south;
	while(s<=north) {
		var pts=[];
		if(d<10.0){ //under 10km squares draw as straight line
			pts[0]=this.GLatLngFromEN(east,s);
			pts[1]=this.GLatLngFromEN(west,s);
		} else { //over 10km squares draw as set of segments
			var e=west;
			var q=0;
			while(e<=east){
				pts[q]=this.GLatLngFromEN(e,s);
				q++;
				e += d;
			}
		}
		 //line
		this.lines_[i]=new GPolyline(pts,this.color_,1);
		this.lines_[i].grid=true;
		this.map_.addOverlay(this.lines_[i]);
		i++;
		 
		 //label at pos of second vert line
		var p=this.map_.fromLatLngToDivPixel(this.GLatLngFromEN(west+d+d,s));
		var dv=document.createElement("DIV");
		var x=p.x+3;
		var y=p.y-10;
		dv.style.position='absolute';
		dv.style.left=x.toString()+'px';
		dv.style.top=y.toString()+'px';
		dv.style.color=this.color_;
		dv.style.fontFamily='Arial';
		dv.style.fontSize='x-small';
		dv.style.cursor='help';
		 //make tooltip
		var nge=NE2NGR((Math.floor(west+0.04)+d+d+0.4)*1000.0,(Math.floor(s+0.04)+0.4)*1000.0);
		dv.title=nge.substr(0,5)+nge.substr(8,3);
		if(d>=100.0) {dv.title=nge.substr(0,2)} //square
		 //make label
		var km=(Math.round(s)%100).toString();
		if (km.length<2) {km='0'+km} //pad single digit
		if (d>=100.0) {km=dv.title} //alphas
		dv.innerHTML=km;
		mapDiv.insertBefore(dv,null);
		this.divs_[j]=dv;
		this.divs_[j].grid=true;
		j++;
		s += d;
	} //next horiz

 //vertical lines
	var e=west;
	while (e<=east) {
		var pts=[];
		if (d<10.0) {
			pts[0]=this.GLatLngFromEN(e,north);
			pts[1]=this.GLatLngFromEN(e,south);
		} else {
			var s=south;
			var q=0;
			while (s<=north) {
				pts[q]=this.GLatLngFromEN(e,s);
				q++;
				s += d;
			}
		}

		this.lines_[i]=new GPolyline(pts,this.color_,1);
		this.lines_[i].grid=true;
		this.map_.addOverlay(this.lines_[i]);
		i++;

		 //label on second horiz line
		var p=this.map_.fromLatLngToDivPixel(this.GLatLngFromEN(e,south+d+d));
		var dv=document.createElement("DIV");
		var y=p.y-10;
		dv.style.position='absolute';
		dv.style.left=p.x.toString()+'px';
		dv.style.top=y.toString()+'px';
		dv.style.color=this.color_;
		dv.style.fontFamily='Arial';
		dv.style.fontSize='x-small';
		dv.style.cursor='help';
		var nge=NE2NGR((Math.floor(e+0.04)+0.4)*1000.0,(Math.floor(south+0.04)+d+d+0.4)*1000.0);
		dv.title=nge.substr(0,5)+nge.substr(8,3);
		if (d>=100.0) {dv.title=nge.substr(0,2)}
		var km=(Math.round(e)%100).toString();
		if (km.length<2) {km="0"+km}
		if (d>=100.0) {km=dv.title}
		if (e != (west+d+d) ) { //avoid crossover
			dv.innerHTML=km;			
			mapDiv.insertBefore(dv,null);
			this.divs_[j]=dv;
			this.divs_[j].grid=true;
			j++;
		}
		e += d;
	} //next vert
} //end redraw

//from OS east,north in km to WGS84 Lat/Lon in a GLatLng
OGBGraticule.prototype.GLatLngFromEN = function(eastKm,northKm) {
		 var ogb=NEtoLL(eastKm*1000.0,northKm*1000.0);
		 var wg84=OGBToWGS84(ogb.lat,ogb.lon,0);
		 return new GLatLng(parseFloat(wg84.lat),parseFloat(wg84.lon));
}

