// A HTML widget for showing 3 North pointers, Grid, True and Magnetic

function BdccNorthWidget(div, gridColour, magColour, trueColour, backColour) {



	this.gridColour = gridColour || "#000000";

	this.magColour = magColour || "#FF0000";

	this.trueColour = trueColour || "#0000FF";

	this.backColour = backColour || null;

	this.container = div;

}



BdccNorthWidget.prototype.destroy = function() {

  if((this.div != null)&&(this.container != null))

	   this.container.removeChild(this.div);



}



BdccNorthWidget.prototype.draw = function(convergence, declination) {



	//origin for all 3 north lines is centre bottom + 10% of height

	

	this.destroy();

	this.div = document.createElement("DIV");

    this.container.appendChild(this.div);

	this.div.style.position='absolute';

	this.div.style.width = this.container.offsetWidth + 'px';

	this.div.style.height = this.container.offsetHeight + 'px';

	this.div.style.top = 0 + 'px';

	this.div.style.left = 0 + 'px';

	this.div.style.border = '0px';

	if(!this.backColour)

	    this.div.style.background = 'none';	

	else

	    this.div.style.background = this.backColour;	

		





    //draw reference line - grid north

    var title = "Grid North";

	var p1x = this.div.offsetWidth / 2;

	var p1y = this.div.offsetHeight * 0.9;

	var p2y = this.div.offsetHeight * 0.1;

	var l = p1y - p2y;

	var p2x = p1x;



    this.buildLine(this.div,p2x,p2y-1,p1x,p1y,this.gridColour,2,0.99,title);

    this.buildLine(this.div,p2x,p2y,p2x-5,p2y+8,this.gridColour,2,0.99,title);

    this.buildLine(this.div,p2x+1,p2y,p2x+6,p2y+8,this.gridColour,2,0.99,title);



    //When convergence is +ve, True north is West of Grid north.

    var label;

    var d;

    var m;

    if(convergence >= 0){

        title = "True North is " + convergence.toFixed(2) + " degrees West of Grid North";

        d = Math.floor(convergence);

        m = Math.round((convergence - d)*60.0);

        if (m < 10)

            m = '0' + m.toString();

        label = d+ "W" + m + "'";

    }

    else{

        title = "True North is " + (-convergence.toFixed(2)) + " degrees East of Grid North";

        d = Math.floor(-convergence);

        m = Math.round(((-convergence) - d)*60.0);

        if (m < 10)

            m = '0' + m.toString();

        label = d+ "E" + m + "'";

    }

    var theta = convergence*Math.PI/45.0; // scale x 4

    p2x = Math.round(p1x - (l * 0.9 * Math.sin(theta)));

    p2y = Math.round(p1y - (l * 0.9 * Math.cos(theta)));

    this.buildLine(this.div,p2x,p2y,p1x,p1y,this.trueColour,1,0.99,title);



    theta -= Math.PI/6;

    var hdx1 = Math.round(8*Math.sin(theta));

    var hdy1 = Math.round(8*Math.cos(theta));

    theta += Math.PI*2/6;

    var hdx2 = Math.round(8*Math.sin(theta));

    var hdy2 = Math.round(8*Math.cos(theta));

    this.buildLine(this.div,p2x,p2y,p2x+hdx1,p2y+hdy1,this.trueColour,1,0.99,title);

    this.buildLine(this.div,p2x,p2y,p2x+hdx2,p2y+hdy2,this.trueColour,1,0.99,title);





	var dv = document.createElement("DIV");

	this.div.appendChild(dv);

	dv.style.position = "absolute";

	dv.style.border = "none";

	dv.style.padding = '1px';

	dv.style.color = this.trueColour;

	dv.style.background = "#8F8F8F";

	dv.style.fontFamily='Arial, Helvetica, sans-serif';

	dv.style.fontSize='8pt';

	dv.innerHTML = label;

	dv.style.left = "0px";

	dv.title = title;

	dv.style.top = this.div.offsetHeight - dv.offsetHeight + 'px';



    //When declination is +ve, Magnetic North is East of True North

    var mag2Grid = convergence - declination;

    if(mag2Grid >= 0){

        title = "Magnetic North is " + mag2Grid.toFixed(2) + " degrees West of Grid North";

        label = mag2Grid.toFixed(2) + "W";

        d = Math.floor(mag2Grid);

        m = Math.round((mag2Grid - d)*60.0);

        if (m < 10)

            m = '0' + m.toString();

        label = d+ "W" + m + "'";

    }

    else{

        title = "Magnetic North is " + (-mag2Grid.toFixed(2)) + " degrees East of Grid North";

        d = Math.floor(-mag2Grid);

        m = Math.round(((-mag2Grid) - d)*60.0);

        if (m < 10)

            m = '0' + m.toString();

        label = d+ "E" + m + "'";

    }

    theta = mag2Grid*Math.PI/45.0;//scale x 4

    p2x = Math.round(p1x - (l * 0.8 * Math.sin(theta)));

    p2y = Math.round(p1y - (l * 0.8 * Math.cos(theta)));

    this.buildLine(this.div,p2x,p2y,p1x,p1y,this.magColour,1,0.99,title);



    theta -= Math.PI/6;

    var hdx1 = Math.round(8*Math.sin(theta));

    var hdy1 = Math.round(8*Math.cos(theta));

    theta += Math.PI*2/6;

    var hdx2 = Math.round(8*Math.sin(theta));

    var hdy2 = Math.round(8*Math.cos(theta));

    this.buildLine(this.div,p2x,p2y,p2x+hdx1,p2y+hdy1,this.magColour,1,0.99,title);

    this.buildLine(this.div,p2x,p2y,p2x+hdx2,p2y+hdy2,this.magColour,1,0.99,title);





	var dv = document.createElement("DIV");

	this.div.appendChild(dv);

	dv.style.position = "absolute";

	dv.style.border = "none";

	dv.style.padding = '1px';

	dv.style.color = this.magColour;

	dv.style.fontFamily='Arial, Helvetica, sans-serif';

	dv.style.fontSize='8pt';

	dv.style.background = "#8F8F8F";

	dv.innerHTML = label;

	dv.style.top = this.div.offsetHeight - dv.offsetHeight + 'px';

	dv.style.left = this.div.offsetWidth - dv.offsetWidth + 'px';

	dv.title = title;



}









//Create a div holding a set of horz and vert line segments making up the line between p1 and p2

//Uses this.sx,sy,ex,ey,steep



BdccNorthWidget.prototype.buildLine = function(cntnr,x0,y0,x1,y1,colour,width,opacity,title) {





  //Bresenham algorithm for line drawing see - wikipedia



  this.steep = false;

  if(Math.abs(y1 - y0) > Math.abs(x1 - x0))

	this.steep = true;



  if (this.steep){

		 var t = x0;

		 x0 = y0;

		 y0 = t;

		

		 t = x1;

		 x1 = y1;

		 y1 = t;

  }

  if (x0 > x1){

		 var t = x0;

		 x0 = x1;

		 x1 = t;



		 t = y0;

		 y0 = y1;

		 y1 = t;

  }



  var deltax = x1 - x0;

  var deltay = Math.abs(y1 - y0);

  var error = 0;

  var ystep;

  var y = y0;



  if (y0 < y1)

	ystep = 1;

  else

	ystep = -1;

	



  //start and end coords of each horz/vertical line segment

  //We want to use the min of divs





  //initial coord of first line segment

  if (this.steep){

     this.sx = y0;

     this.sy = x0;

  }

  else{

     this.sy = y0;

     this.sx = x0;

  }





  var div = null;//a div whose background is a horz or vert line segment

  var last = false;//force last plot



  //main Bresenham loops

  if (this.steep){

      for( var x = x0; x <= x1; x++){

    		

	     if (x == x1)

		    last = true;

			

         div = this.plotLinePoint(y,x,last,colour,width,opacity,title);



	     if(div != null)

		    cntnr.appendChild(div);

         //else point being held over until horz/vert segment ends



         error = error + deltay;

         if ((2*error) >= deltax){

             y = y + ystep;

             error = error - deltax;

         }

      }

  }

  else{

      for( var x = x0; x <= x1; x++){

    		

	     if (x == x1)

		    last = true;

			

         div = this.plotLinePoint(x,y,last,colour,width,opacity,title);



	     if(div != null)

		    cntnr.appendChild(div);

         //else point being held over until horz/vert segment ends



         error = error + deltay;

         if ((2*error) >= deltax){

             y = y + ystep;

             error = error - deltax;

         }

      }

   }

}





//Plot a point that is part of a horizontal or vertical line

//only emit a div if a horz or vert segment has been completed.

//Uses this.sx,sy,ex,ey,steep



BdccNorthWidget.prototype.plotLinePoint = function(x,y,last,colour,width,opacity,title) {

	

		 this.ey = y;//end coords of line segment

		 this.ex = x;

		 var w2 = width / 2;



		 if((x == this.sx)&&(!last))

			return null;//same x coord as last point

		 if((y == this.sy)&&(!last))

			return null;//same y coord as last point



		 		

		 //swap start and end to get +ve width and height

		 var ox = this.ex;

		 if(this.ex < this.sx){

			var t = this.ex;

			this.ex = this.sx;

			this.sx = t;

		 } 		



		 var oy = this.ey;

		 if(this.ey < this.sy){

			var t = this.ey;

			this.ey = this.sy;

			this.sy = t;

		 } 	

		

		 //establish width/height of div

		 var w = this.ex - this.sx;

		 var h = this.ey - this.sy;

		

		 var x = this.sx;

		 var y = this.sy;

         if(this.steep){

            w = width;

            x -= w2;//centre the line segment according to the line width

            }

         else{

            h = width;

            y -= w2;//centre the line segment according to the line width

            }



	     this.sx = ox;//restore original bresenham coords of segment start

	     this.sy = oy;

		

         //actually make the div		 		

		 var div = document.createElement("DIV");

		 div.title = title;

	     var ds = div.style;

	

	     ds.position = "absolute";

	     ds.overflow = "hidden";

	     ds.backgroundColor = colour;

	     ds.left = x + "px";

	     ds.top = y + "px";

	     ds.width = w + "px";

	     ds.height = h + "px";

	     	

	     if(opacity != 1.0){

	        ds.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + Math.round(opacity * 100) +")";

	        ds.opacity = opacity;

	     }

	     	

	     return div;

}






