/* 
 GeoMarker is a SVG overlay for Google maps
 originally based on Bill Chadwick's BDCCArrow.js
 www.bdcc.co.uk/Gmaps/BdccGmapsBits.htm.
 GeoMarker provides overlays for diferent shapes
 using SVG. I hope to have some time to add VML support in the future
 for now it is only SVG and it works better with Firefox 3.x.

 
 Version: 0.6 20081121
   -Added vertical velocity error bars
   -Added handling to show text,symbol,arrow and error independently

 Version: 0.5 20080606
   -First debut on the web site 

 Victor Marcelo Santillan   2008
*/

var GMCounter;
var PI = Math.PI;
var Deg2Rad = PI/180; 
var Rad2Deg = 180/PI; 
var svgNS = "http://www.w3.org/2000/svg";
var path_symbols = { "triangle"   : "M 0 12 L 6 1 L 12 12 z",
                     "inv_triangle": "M 0 0 L 6 12 L 12 0 z",
                     "building": "M 0 12 h 12 v-1 h-3 v-11 h-6 v11 h-3 z",
			    	 "mast"    : "M 1 8 a6,7 0 0,1 12 0 h-5 v9 h-1 v-9 z",
				     "geodetic": "M 1 8 a6,7 0 0,1 12 0 h-6 v12 v-12 7 7 7 -7 7 7  -7 -7 z",
			    	 "gshadow" : "M 4 8 a6,7 0 0,1 12 0 h-6 v9 v-9 l -7 7 7 -7 7 7  -7 -7 z",
				     "tilted"  : "M 0 12 h 12 v-1 h-3 L 12 3 L 7 0 L 3 11 z",
				     "square"  : "M 0 0 h 11 v 11 h -11 z"
                    };

function make_path_str ( size,shape,hw ) {
  var y = Math.floor(size*0.8660);
  var x = Math.floor(size/2);
  var p ;
  with(Math){ switch(shape) {
	case 'inv_triangle': p="M 0 0 L "+ size + " 0 L "+ x + " " + y + " z ";
	                     break;
    case 'triangle': p="M 0 " + size +" L " + size +" "+ size + " L "+ x +" "+ (size-y)+"  z"; 
				     break;
	case 'building': x3=floor(size/3); p='M 0 '+size+' h '+size+' v-1 h-'+x3+'v -'+(size-1)+
	                   ' h-'+x3+' v '+(size-1)+' h-'+x3+' z';
	                 break;
	case 'arrow' : w=10; w3=3.5; w2=w3; tx=7; ty=hw||5; l=size-tx;//l=floor(l);
	               if ( (size - tx ) < 0 ) {
				       tl=0.3;
				       w3=hw*0.9;
					   w2=w3*0.3;
					   tx=size*tl;
					   ty=hw*0.3;
					   l=size*(1-tl);
				   }
	               //p =  floor(l) < 0 ? 'M 0 '+ty+' h '+size +' z' :
	               //p = 'M 0 '+w3+' h '+l+'v -'+w3+' l '+tx+' '+ty+ ' l -'+tx+' '+ty+ ' v -'+w3+' h -'+l+' z';
	               p = l < 0 ? 'M 0 '+hw+' h '+size +' z' : 'M 0 '+w3+' h '+l+' v -'+w2+' l '+tx+' '+ty+ ' l -'+tx+' '+ty+ ' v -'+w2+' h -'+l+' z';
				   break;
	case 'geodetic': p="M 1 8 a6,7 0 0,1 12 0 h-6 v12 v-12 l -7 7 7 -7 7 7  -7 -7 z";break;
	case 'gshadow' : p="M 4 8 a6,7 0 0,1 12 0 h-6 v9 v-9 l -7 7 7 -7 7 7  -7 -7 z";break;
	case 'tilted'  : p="M 0 12 h 12 v-1 h-3 L 12 3 L 7 0 L 3 11 z";break;
	case 'mast'    : p="M 1 8 a6,7 0 0,1 12 0 h-5 v9 h-1 v-9 z";break;
	case 'y_error_bar' : p="M 0 0 l 5 0 l 3 0 v" + 2*size + "h -3 h 5 ";
    default:break;
  }}
  return p   
}

//Auxiliary function to provide a graphic vector scale 
// generates a horizontal or vertical arrow given orient='h' or orient='v'
//of color 'color', and shifted dx,dy in the hor. and vert. directions.
// returns a SVG object
function vel_arrow ( dx,dy,len,orient,color ) {
   var svgG = document.createElementNS(svgNS,"g");
   var  vel = document.createElementNS(svgNS,"path");
   var azi = 0;
   if ( orient == 'h' ) azi = 0;
   if ( orient == 'v' ) azi = -90;
   svgG.setAttribute("transform"," translate("+dx+","+dy+") rotate("+azi+")");
   vel.setAttribute("stroke","black");
   vel.setAttribute("fill",color);
   vel.setAttribute("stroke-width",1);
   vel.setAttribute("d",make_path_str(len,'arrow') );
   svgG.appendChild(vel);
   return svgG
}

// vel_text returns a SVG text object 
// to add a text usually with the magnitude and units of the vel_arrow. 
// dx,dy are the shift in the hor. and vert. 
// color: text color
// sw   : stroke width of the text.
function vel_text ( dx,dy,text,color,sw ) {
   var svgT = document.createElementNS(svgNS,"text");
   svgT.setAttribute("x",dx);
   svgT.setAttribute("y",dy);
   svgT.setAttribute("font-size",'15px');
   svgT.setAttribute("stroke",color);
   svgT.setAttribute("stroke-width",sw);
   var t = document.createTextNode(text);
   svgT.appendChild(t);
   return svgT
}

// vel_scale  make vertical and horizontal arrows
// with a text containing the units and the magnitude
// of the vert. and hor. vectors.
// len: magnitude of the vector
// scl: scale to be applied
// units: text. used to specify the units.
// 
function vel_scale( div_name, len,scl,units ) {
   var dx = 1.2*len*scl;
   var dy = 1.2*len*scl;
   var s = Math.round(len*scl*1.2+90)+'px'; //len > 200 ? Math.round(len*1.1)+'px': '150px';
   var svgRoot = document.createElementNS(svgNS,"svg");
   var div = document.getElementById(div_name);
   div.innerHTML='';
   div.style.opacity = 1;
   div.style.width= s;
   div.style.height= s;
   div.appendChild(svgRoot);
   svgRoot.appendChild(vel_text(dx+2,dy-4,len+units,"white",2));
   svgRoot.appendChild(vel_text(dx+2,dy-4,len+units,"black",1));
   svgRoot.appendChild(vel_arrow(dx-14,dy,len*scl,'v','red'));
   //svgRoot.appendChild(vel_arrow(dx-14,dy,len*scl,'h','red'));
}


GeoMarker.prototype = new GOverlay();
function GeoMarker(point,hsize,vsize,rot,color,opacity,name,symbol,vector,scl) {
  this.point  =  point;
  this.hsize   =  hsize;
  this.vsize   =  vsize;
  this.size    = hsize > vsize ? hsize : vsize;
  rot = rot < 0 ? 360+rot:rot;
  this.rot     = rot ? rot-90 : 0; 
  this.color  =  color ; //|| "#FF0000";
  this.opacity = opacity ; //|| 0.5;
  //this.tooltip = name ;
  this.name = name;
  this.symbol = symbol;
  this.vector = vector;
  this.scl = scl ;
  if ( GMCounter == null ) 
    GMCounter = 0;
  else 
    GMCounter +=1;

  this.svgId = "GeoMarker" + GMCounter.toString();
  
  return this
}


GeoMarker.prototype.getPoint = function() {
  return this.point
}
GeoMarker.prototype.getLatLng = function() {
  return this.point
}
GeoMarker.prototype.getSize = function() {
  return this.size
}
GeoMarker.prototype.getTooltip = function() {
  return this.tooltip
}

GeoMarker.prototype.clicked = function() {
  GEvent.trigger(this,"click");
}

//Create div for GM
GeoMarker.prototype.initialize = function ( map ) {
   var div = document.createElement("DIV");
   div.id = this.name; //this.tooltip;
   //div.title = this.name; //this.tooltip;
   //div.style.cursor = "";
   div.style.opacity = 1 
   this.map = map;
   this.dx = this.size;
   this.dy = this.size;
   this.dh = 0;
   this.dv = 0;
   this.sig = 0;
   if ( this.vector != null ) {
      this.sig = this.vector.x_sig >= this.vector.y_sig ? this.vector.x_sig :this.vector.y_sig;
	  this.sig*=this.scl*2;
      this.vector.len = Math.sqrt(this.vector.x*this.vector.x + this.vector.y*this.vector.y);
      //this.vector.len = Math.ceil(this.vector.len)*this.scl;
      this.vector.len *= this.scl;
      this.dx = this.size > this.vector.len ? this.size: this.vector.len+7;
	  this.dx += this.sig;
      this.dy = this.size > this.vector.len ? this.size: this.vector.len+7;
	  this.dy += this.sig;
   }
   

   //add to pane 
   map.getPane(G_MAP_MARKER_PANE).appendChild(div);
   //map.getPane(G_MAP_MARKER_MOUSE_TARGET_PANE).appendChild(div);

   //save for later
   this.div = div;

   var w = 20*(this.dx+this.sig);
       w = w < 20 ? 50 : w;
   var h = 20*(this.dy+this.sig);
       h = h < 20 ? 50 : h;
       	   
   // do only svg for firefox for now
   this.svgRoot = document.createElementNS(svgNS, "svg");
   this.svgRoot.setAttribute("width", w  );
   this.svgRoot.setAttribute("height",h );
   this.svgRoot.setAttribute("stroke",this.color);
   this.svgRoot.setAttribute("fill",this.color);
   this.svgRoot.setAttribute("stroke-opacity",1);
   this.svgRoot.setAttribute("fill-opacity",this.opacity);
   
   this.div.appendChild(this.svgRoot);
   //this.map.getPane(G_MAP_MAP_PANE).appendChild(this.svgRoot);
   
   
   this.svgRoot.appendChild(this.svgSymbol(this.symbol)); 
   if ( this.vector != null ) {
     if ( this.vector.symbol.label ) 
      this.svgRoot.appendChild(this.svgText(Math.ceil(this.hsize/2+6),0));
   }
   else if ( this.name != '' ) {
      this.svgRoot.appendChild(this.svgText(Math.ceil(this.hsize/2+6),0));
   }


   //var cb = GEvent.callback(this,this.clicked);
   //this.clickH = GEvent.addDomListener(this.div,"click",function(event){cb()} );
}

GeoMarker.prototype.svgSymbol=function(symbol) {
   switch(symbol) {
    // case 'vector_ellipse': this.vector.symbol=false; return this.svgVectorEllipse();break;
     case 'symbol_vector_ellipse': return this.svgVectorEllipse();break;
     case 'symbol_vector_y_error_bar': return this.svgVectorYErrorBar();break;
     case 'circle': return this.svgCircle();break;
	 case 'ellipse': return this.svgEllipse();break;
	 case 'geodetic': this.dh=4;this.dv=14;return this.svgGeodetic();
	 case 'rect': return this.svgRect();break;
	 case 'square': this.vsize=this.size;this.hsize=this.size;return this.svgRect();break;
	 case 'triangle':
	 case 'inv_triangle' :
	 case 'building': this.dh=this.size/2; this.dv=this.size; return this.svgPath(symbol);break;
	 case 'tilted'  : this.dh=3; this.dv=12; return this.svgPath(symbol);break;
	 case 'mast'    :this.dh=4; this.dv=14; return this.svgPath(symbol);break;
     default:alert('Unknown symbol:|'+symbol+'|');break;
   }
}

GeoMarker.prototype.svgRect = function() {
   var dh = this.hsize/2;
   var dv = this.vsize/2;
   var trans='';
       trans += ' translate('+(this.dx-dh)+','+(this.dy-dv)+') ';
       trans += "rotate("+this.rot+") ";
   var Rect = document.createElementNS(svgNS, "rect");
   Rect.setAttribute("transform",trans );
   Rect.setAttribute("fill",this.color );
   Rect.setAttribute("stroke","black");
   Rect.setAttribute("stroke-width",1);
   Rect.setAttribute("height",this.hsize);
   Rect.setAttribute("width",this.vsize);
   return Rect
}

GeoMarker.prototype.svgCircle = function() {
   var dh = this.size/2;
   var dv = this.size/2;
   var trans = ' translate('+(this.dx)+','+(this.dy)+') ';
   var Circle = document.createElementNS(svgNS,"circle");
   var r = Math.round(this.size/2)
   Circle.setAttribute("transform",trans );
   Circle.setAttribute("cx",0);
   Circle.setAttribute("cy",0);
   Circle.setAttribute("r",r);
   Circle.setAttribute("fill",this.color);
   Circle.setAttribute("stroke","black");
   Circle.setAttribute("stroke-width",1);
   return Circle
}

GeoMarker.prototype.svgVectorYErrorBar = function () {
   var azi = Rad2Deg*Math.atan2( this.vector.x,this.vector.y)-90; 
       //azi = -90;
   var rho = this.vector.corr;
   var rho2 = rho*rho;
   var sx = this.vector.x_sig;
   var sy = this.vector.y_sig;
   var sxy = rho*Math.sqrt(sx*sy);
   var phi = Rad2Deg*Math.atan2(2*rho2*sx*sy,(sx*sx-sy*sy));
       phi = rho ? phi-90 : 0;
	   phi=-90
   var len = this.vector.len;// - 7;
       //len = len < 0 ? 0 : len
   var trans = ' translate('+(this.dx)+','+(this.dy)+') ';
   var rot   = ' rotate('+azi+') ';
   var svgG = document.createElementNS(svgNS,"g"); 
      svgG.setAttribute("transform",trans + rot );
   var Circle = document.createElementNS(svgNS,"circle");
       var r = 5;
       Circle.setAttribute("cx",0);
       Circle.setAttribute("cy", (len ? r : 0) );
       Circle.setAttribute("r",r);
       Circle.setAttribute("stroke","black");
       Circle.setAttribute("fill",this.color);
       Circle.setAttribute("stroke-width",1);
       Circle.setAttribute("style","overflow:visible");
   var Arrow = document.createElementNS(svgNS,"path");
    Arrow.setAttribute("stroke","black");
    Arrow.setAttribute("fill",this.vector.color);
    Arrow.setAttribute("fill-opacity",0.8);
    Arrow.setAttribute("stroke-width",1);
    //Arrow.setAttribute("style","overflow:visible");

     var YErrorBar = document.createElementNS(svgNS,"rect");
     var rx = 8; //Math.ceil(this.vector.x_sig*this.scl*2);
     var ry = this.vector.y_sig*this.scl*2;
         rx = len  ? rx  : 0;
         ry = len  ? ry :  0;
	 var arrow_path = "M 0 0 z";
     var a_tip_len = 0; //arrow tip length 
	 var a_hw =0 ;     // arrow half with
	 if ( len ) {
		a_hw = r;
		arrow_path=make_path_str(this.vector.len,'arrow',a_hw);
		a_tip_len = 0; //6;
	 } 
	 Arrow.setAttribute("d",arrow_path );
     var cx = len+a_tip_len - Math.floor(ry/2) ;
     var cy = 1; //a_hw;
     //var rot_e   = ' rotate('+azi+') ';
     var rot_e   = ' rotate('+((-1)*azi+phi)+') ';
	 rot_e = '';
     var trans_e = ' translate('+cx+','+cy+') ';
      YErrorBar.id=this.svgId+"_y_error_bar";
      YErrorBar.setAttribute("transform", trans_e+rot_e);
      YErrorBar.setAttribute("width",ry);
      YErrorBar.setAttribute("height",rx);
      YErrorBar.setAttribute("fill","gray");
      YErrorBar.setAttribute("fill-opacity",0.4);
      YErrorBar.setAttribute("stroke","black");
      YErrorBar.setAttribute("stroke-width",1);
      YErrorBar.setAttribute("stroke-opacity",1);
	  
      
	  //svgG.appendChild(this.svgSymbol('circle'));
	  if ( this.vector.symbol.site )  { svgG.appendChild(Circle);    }
	  if ( this.vector.symbol.error ) { svgG.appendChild(YErrorBar); }
	  if ( this.vector.symbol.arrow )  { svgG.appendChild(Arrow);     }
	  return svgG
}



GeoMarker.prototype.svgVectorEllipse = function () {
   var azi = Rad2Deg*Math.atan2( this.vector.x,this.vector.y)-90; 
   /*
	sin(2*phi)=2*Sxy^2/w
	cos(2*phi)=(Sx^2-Sy^2)/w
	rho = Sxy/sqrt(Sx*Sy)
	Sxy=rho*sqrt(Sx*Sy)
	phi=atan2(2*rho^2*Sx*Sy,(Sx^2-Sy^2))
	*/
   var rho = this.vector.corr;
   var rho2 = rho*rho;
   var sx = this.vector.x_sig;
   var sy = this.vector.y_sig;
   var sxy = rho*Math.sqrt(sx*sy);
   var phi = Rad2Deg*Math.atan2(2*rho2*sx*sy,(sx*sx-sy*sy));
       phi = rho ? phi-90 : 0;
   var len = this.vector.len;// - 7;
       //len = len < 0 ? 0 : len
   var trans = ' translate('+(this.dx)+','+(this.dy)+') ';
   var rot   = ' rotate('+azi+') ';
   var svgG = document.createElementNS(svgNS,"g"); 
      svgG.setAttribute("transform",trans + rot );
   var Circle = document.createElementNS(svgNS,"circle");
       var r = 5;
       Circle.setAttribute("cx",0);
       Circle.setAttribute("cy", (len ? r : 0) );
       Circle.setAttribute("r",r);
       Circle.setAttribute("stroke","black");
       Circle.setAttribute("fill",this.color);
       Circle.setAttribute("stroke-width",1);
       Circle.setAttribute("style","overflow:visible");
   var Arrow = document.createElementNS(svgNS,"path");
    Arrow.setAttribute("stroke","black");
    Arrow.setAttribute("fill",this.vector.color);
    Arrow.setAttribute("fill-opacity",0.8);
    Arrow.setAttribute("stroke-width",1);
    //Arrow.setAttribute("style","overflow:visible");

     var Ellipse = document.createElementNS(svgNS,"ellipse");
     var rx = Math.ceil(this.vector.x_sig*this.scl*2);
     var ry = Math.ceil(this.vector.y_sig*this.scl*2);
         rx = len  ? rx  : 0;
         ry = len  ? ry :  0;
	 var arrow_path = "M 0 0 z";
     var a_tip_len = 0; //arrow tip length 
	 var a_hw =0 ;     // arrow half with
	 if ( len ) {
		a_hw = r;
		arrow_path=make_path_str(this.vector.len,'arrow',a_hw);
		a_tip_len = 0; //6;
	 } 
	 Arrow.setAttribute("d",arrow_path );
     var cx = len+a_tip_len  ;
     var cy = a_hw;
     var rot_e   = ' rotate('+((-1)*azi+phi)+') ';
     var trans_e = ' translate('+cx+','+cy+') ';
      Ellipse.id=this.svgId+"_arrow_ellipse";
      Ellipse.setAttribute("transform", trans_e+rot_e);
      Ellipse.setAttribute("cx", 0 );
      Ellipse.setAttribute("cy", 0 ); 
      Ellipse.setAttribute("rx",rx);
      Ellipse.setAttribute("ry",ry);
      Ellipse.setAttribute("fill","gray");
      Ellipse.setAttribute("fill-opacity",0.4);
      Ellipse.setAttribute("stroke","black");
      Ellipse.setAttribute("stroke-width",1);
      Ellipse.setAttribute("stroke-opacity",1);
	  
      
	  //svgG.appendChild(this.svgSymbol('circle'));
	  if ( this.vector.symbol.site  )  { svgG.appendChild(Circle);    }
	  if ( this.vector.symbol.arrow  )  { svgG.appendChild(Arrow);     }
	  if ( this.vector.symbol.error ) { svgG.appendChild(Ellipse);   }
	  //if ( this.vector.symbol ) { svgG.appendChild(Circle); }
	  //svgG.appendChild(Ellipse);
	  //svgG.appendChild(Arrow);
	  return svgG
}


GeoMarker.prototype.svgEllipse = function( ) {
   var dh = this.hsize/2;
   var dv = this.vsize/2;
   var Ellipse = document.createElementNS(svgNS,"ellipse");
   var trans =  "translate("+(this.dx)+" "+(this.dy)+") ";
       trans += "rotate("+this.rot+") ";
   Ellipse.setAttribute("transform",trans);
   Ellipse.setAttribute("cx",0);
   Ellipse.setAttribute("cy",0);
   Ellipse.setAttribute("rx",dh);
   Ellipse.setAttribute("ry",dv);
   Ellipse.setAttribute("fill",this.color);
   Ellipse.setAttribute("stroke","black");
   Ellipse.setAttribute("stroke-width",1);
   return Ellipse
}


GeoMarker.prototype.svgPath = function( shape ) {
   var trans = '';
       trans += ' translate('+(this.dx-this.dh)+','+(this.dy-this.dv)+') ';
       //if ( this.rot ) { trans += ' rotate('+this.rot+') '; }
   var svgG = document.createElementNS(svgNS,"g"); 
   var Path = document.createElementNS(svgNS,"path");
   var path_string = make_path_str(this.size,shape);
   svgG.setAttribute("transform",trans );
   Path.setAttribute("d",path_string);
   Path.setAttribute("fill",this.color);
   Path.setAttribute("stroke","black");
   Path.setAttribute("stroke-width",1);
   svgG.appendChild(Path)
   return svgG
}

GeoMarker.prototype.svgGeodetic = function() {
   var svgG = document.createElementNS(svgNS,"g");
   var Geod = document.createElementNS(svgNS,"path");
   var trans = "translate("+(this.dx-this.dh)+","+(this.dy-this.dv)+")";
   svgG.setAttribute("transform",trans);
   Geod.setAttribute("d","M 1 8 a6,7 0 0,1 12 0 h-6 v9 v-9 l -7 7 7 -7  7 7  -7 -7 z");
   Geod.setAttribute("fill",this.color);
   Geod.setAttribute("stroke","black");
   Geod.setAttribute("stroke-width",1);
   var Geod2 = document.createElementNS(svgNS,"path");
   Geod2.setAttribute("d","M 4 8 a6,7 0 0,1 12 0 h-6 v9 v-9 l -7 7 7 -7  7 7  -7 -7 z");
   Geod2.setAttribute("fill","white");
   Geod2.setAttribute("stroke","white");
   Geod2.setAttribute("stroke-width",1);
   svgG.appendChild(Geod2);
   svgG.appendChild(Geod);
   return svgG
}

GeoMarker.prototype.svgText = function (h,v) {
    var dh = h || (this.hsize/2+6);
    var dv = v || 0;
    var font_family = 'Verdana';
    var font_size = '10';
	var font_style = 'normal';
    var svgG = document.createElementNS(svgNS,"g");
    var svgLabel = document.createElementNS(svgNS,"text");
    svgLabel.setAttribute("x",this.dx + dh );
    svgLabel.setAttribute("y",this.dy + dv );
    svgLabel.setAttribute("font-size",font_size);
    svgLabel.setAttribute("stroke",'black');
    svgLabel.setAttribute("stroke-width",1);
	var labeltext = document.createTextNode(this.name);
	var svgLabel2 = document.createElementNS(svgNS,"text");
	var labeltext2 = document.createTextNode(this.name);
    svgLabel2.setAttribute("x",this.dx + dh );
    svgLabel2.setAttribute("y",this.dy + dv );
    svgLabel2.setAttribute("font-size",font_size);
    svgLabel2.setAttribute("stroke",'white');
    svgLabel2.setAttribute("stroke-width",2);
	
	svgLabel2.appendChild(labeltext2);
    svgLabel.appendChild(labeltext);
    svgG.appendChild(svgLabel2);
    svgG.appendChild(svgLabel);
	return svgG

}


GeoMarker.prototype.remove = function() {
   //GEvent.removeListener(this.clickH);
   this.div.parentNode.removeChild(this.div);
}

GeoMarker.prototype.copy = function() { 
   return new  GeoMarker(this.point,
                         this.hsize,
                         this.vsize,
						 this.rot,
						 this.color,
						 this.opacity,
						 this.name,
						 this.symbol,this.vector,this.scl );
}
GeoMarker.prototype.redraw = function(force) {
  if ( ! force ) return;
  var p = this.map.fromLatLngToDivPixel(this.point);
  var x2 = p.x + this.dx;
  var y2 = p.y + this.dy;
  //var style =  "position:absolute; top:"+(p.y-this.size);
  //    style += "px; left:" + (p.x-this.size) + "px";
  var style =  "position:absolute; top:"+(p.y - this.dx);
      style += "px; left:" + (p.x - this.dy) + "px";
  this.svgRoot.setAttribute("style",style);
}

