// GPX2GM
// Darstellung von GPS-Daten aus einer GPX-Datei in Google Maps
// Version 3.5
// 28 5. 2009 Jürgen Berkemeier
// www.j-berkemeier.de

if(typeof(LargeMapControll)=="undefined") var LargeMapControll = true;
if(typeof(OverviewMapControl)=="undefined") var OverviewMapControl = true;
if(typeof(Legende)=="undefined") var Legende = false;
if(typeof(Legende_trk)=="undefined") var Legende_trk = true;
if(typeof(Legende_rte)=="undefined") var Legende_rte = true;
if(typeof(Legende_wpt)=="undefined") var Legende_wpt = true;
if(typeof(HP_verbinde)=="undefined") var HP_verbinde = false;

document.write('<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key='+key+'" type="text/javascript"><\/script>');

Array.prototype.sum=function() {
 for(var s=0,i=0;i<this.length;i++)s+=this[i];
 return s;
}

function makeMap(ID) {
  var dieses = this;
  var id = ID;
  var id_hp = ID+"_hp";
  var load = false
  var latmin=1000,latmax=-1000,lonmin=1000,lonmax=-1000;
  var zoom = 1;
  var osm_map;
  var bilder;
  var fname,maptype;
  var tcols = new Array("#ff0000","#00ff00","#0000ff","#ffff00","#ff00ff","#00ffff","#000000");
  var rcols = new Array("#800000","#008000","#000080","#808000","#800080","#008080","#808080");
  var tracks,waypoints,routes,tracklens,routlens,profile;
  var routeNames,trackNames;
  var GPX2GM_Path="";
  var scr = document.getElementsByTagName("script");
  for(var i=0;i<scr.length;i++) if(scr[i].src && scr[i].src.length) {
    var path = scr[i].src;
    var pos = path.search("GPX2GM.js");
    if(pos!=-1) {
      GPX2GM_Path = path.substring(0,pos);
      break;
    }
  }
  var icon = new GIcon();
  icon.image = GPX2GM_Path+"scenic.png";
  icon.shadow = GPX2GM_Path+"shadow.png";
  icon.iconSize = new GSize(21.0, 31.0);
  icon.shadowSize = new GSize(52.0, 29.0);
  icon.iconAnchor = new GPoint(5.0, 30.0);
  icon.infoWindowAnchor = new GPoint(10.0, 5.0);
  var markericon = new GIcon();
  var movemarker;
  markericon.image = GPX2GM_Path+"marker.gif";
  markericon.iconSize = new GSize(11.0, 11.0);
  markericon.iconAnchor = new GPoint(5.0, 5.0);
  var markerinfo = document.createElement("div");
  markerinfo.style.position = "absolute";
  markerinfo.style.visibility = "hidden";
  markerinfo.style.border = "1px solid black";
  markerinfo.style.backgroundColor = "white";
  var div = document.getElementById(id);
  var w = div.offsetWidth;
  var h = div.offsetHeight;
  var MapHead = document.createElement("div");
  MapHead.id = "map_head"+id;
  MapHead.style.margin = 0;
  MapHead.style.padding = 0;
//  MapHead.style.fontSize = "0.8em";
//  MapHead.style.lineHeight = "1.5em";
  MapHead.appendChild(document.createTextNode(": "));
  var mapdiv = document.createElement("div");
  mapdiv.id = "map_"+id;
  mapdiv.style.width = w+"px";
  while(div.hasChildNodes()) div.removeChild(div.firstChild);
  if(!Legende) MapHead.style.display="none";
  div.appendChild(MapHead);
  div.appendChild(mapdiv);
  if (Legende) mapdiv.style.height = h-mapdiv.offsetTop+MapHead.offsetTop+"px";
  else         mapdiv.style.height = h+"px";
  var map = new GMap2(document.getElementById("map_"+id));
  if(LargeMapControll) map.addControl(new GLargeMapControl());
  else                 map.addControl(new GSmallMapControl());
  if(OverviewMapControl) map.addControl(new GOverviewMapControl());
  map.addMapType(G_PHYSICAL_MAP);
  var copyrightCollection = new GCopyrightCollection('Kartendaten &copy; 2009 <a href="http://www.openstreetmap.org/">OpenStreetMap</a> Contributors');
  copyrightCollection.addCopyright(new GCopyright(1,new GLatLngBounds(new GLatLng(-90,-180),new GLatLng(90,180)),0,'(<a rel="license" href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>)'));
  var tilelayers_mapnik = new Array();
  tilelayers_mapnik[0] = new GTileLayer(copyrightCollection, 0, 18);
  tilelayers_mapnik[0].getTileUrl = function(a, z) { return "http://tile.openstreetmap.org/" + z + "/" + a.x + "/" + a.y + ".png"; };
  tilelayers_mapnik[0].isPng = function() { return true; };
  tilelayers_mapnik[0].getOpacity = function() { return 1.0; };
  osm_map = new GMapType(tilelayers_mapnik,new GMercatorProjection(19), "OSM",{ urlArg: 'mapnik', linkColor: '#000000' });
  map.addMapType(osm_map);
//  map.addControl(new GMapTypeControl());
  map.addControl(new GHierarchicalMapTypeControl());
//  map.addMapType(G_SATELLITE_3D_MAP); // benötigt Plugin
  map.addControl(new GScaleControl());
  map.enableScrollWheelZoom();
  map.getPane(G_MAP_FLOAT_PANE).appendChild(markerinfo);
//  GEvent.addListener(map,"maptypechanged",function(){dieses.rescale()});
  var hp = document.getElementById(id_hp);
  var hp_diag;
  if(hp) hp_diag = new plot(id_hp);
  this.Spur = function(fn,mpt) {
    if(mpt=="osm_map") maptype = osm_map;
    else maptype = mpt;
    if (fname!=fn) {
      fname = fn;
      GDownloadUrl(fname, function(data, responseCode) {
        if (responseCode != 200 && responseCode != 0 ) {
          alert("Beim Oeffnen der Datei "+fname+" ist der Fehler "+responseCode+" aufgetreten!");
          return;
        }
        dieses.parseGPX(data) ;
        dieses.setMapHead();
        zoom = map.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(latmin,lonmin),new GLatLng(latmax,lonmax))); // sw, ne
        dieses.rescale();
        map.setMapType(maptype);
//        dieses.show("wtr");
        dieses.checkBoxes()
      } );
    }
    else {
//      dieses.show("wtr");
      dieses.checkBoxes()
    }
  } // Spur
  var chkwpt,chktrk,chkrt;
  this.setMapHead = function() {
    var name = fname.replace(/.+\//,"");
    MapHead.innerHTML = name+": ";
    if(waypoints.length) {
      if(waypoints.length==1) var texte=new Array("Wegpunkt"+String.fromCharCode(160));
      else if(waypoints.length>1) var texte=new Array("Wegpunkte"+String.fromCharCode(160));
      chkwpt = new JB_CheckBoxGroup(MapHead.id,texte,ID+"_wpt",["black"],Legende_wpt,dieses.checkBoxes);
    }
    if(tracks.length) {
      var texte=new Array()
      if(tracks.length==1)
        texte[0] = "Track ("+Number(tracklens[0].toPrecision(10).toString(10))+"km) "+String.fromCharCode(160);
      else if(tracks.length>1) {
        texte[0] = "Tracks ("+Number(tracklens.sum().toPrecision(10).toString(10))+"km) "+String.fromCharCode(160);
        for(var i=0;i<tracks.length;i++) texte[i+1] = trackNames[i]+" ("+Number(tracklens[i].toPrecision(10).toString(10))+"km)";
      }
      chktrk = new JB_CheckBoxGroup(MapHead.id,texte,ID+"_trk",tcols,Legende_trk,dieses.checkBoxes);
    }
    if(routes.length) {
      var texte=new Array()
      if(routes.length==1)
        texte[0] = "Route ("+Number(routlens[0].toPrecision(10).toString(10))+"km) "+String.fromCharCode(160);
      else if(routes.length>1) {
        texte[0] = "Routen ("+Number(routlens.sum().toPrecision(10).toString(10))+"km) "+String.fromCharCode(160);
        for(var i=0;i<routes.length;i++) texte[i+1] = routeNames[i]+" ("+Number(routlens[i].toPrecision(10).toString(10))+"km)";
      }
      chkrt = new JB_CheckBoxGroup(MapHead.id,texte,ID+"_rt",rcols,Legende_rte,dieses.checkBoxes);
    }
  } // setMapHead
  this.checkBoxes = function(obj,ele) {
    var what="";
    if(chkwpt && chkwpt.status[0]) what += "w";
    if(chktrk && chktrk.status[0]) what += "t";
    if(chkrt  && chkrt.status[0] ) what += "r";
    dieses.show(what);
  }
  this.parseGPX = function(data) {
    var entf = new this.Entfernung();
    tracks = new Array();
    trackNames = new Array();
    tracklens = new Array() ;
    profile = new Array();
    load = false;
    latmin=1000;latmax=-1000;lonmin=1000;lonmax=-1000;
    var xml = GXml.parse(data);
    var trk = xml.documentElement.getElementsByTagName("trk"); // Tracks
    for(var k=0;k<trk.length;k++) {
      var trkseg = trk[k].getElementsByTagName("trkseg"); // Trackssegmente
      var name = trk[k].getElementsByTagName("name");
	  if(name.length && name[0].firstChild && name[0].firstChild.length)
        trackNames[k] = name[0].firstChild.data;
      else
        trackNames[k] = "Track "+k;
      for(var j=0;j<trkseg.length;j++) {
        var trkpts = trkseg[j].getElementsByTagName("trkpt"); // Trackpunkte
        var track = new Array();
        var profil = new Array();
		var hp_x0 = 0;
    	if(HP_verbinde && k>0) hp_x0 = tracklens.sum() ;
        var tracklen = 0;
	    for(var i=0;i<trkpts.length;i++) { // Trackdaten
          var lat = parseFloat(trkpts[i].getAttribute("lat"));
          var lon = parseFloat(trkpts[i].getAttribute("lon"));
          if(i==0) entf.init(lat,lon) ;
          tracklen += entf.rechne(lat,lon);
          if(lat<latmin) latmin=lat; if(lat>latmax) latmax=lat;
          if(lon<lonmin) lonmin=lon; if(lon>lonmax) lonmax=lon;
          track.push(new GLatLng(lat,lon));
          if(trkpts[i].getElementsByTagName("ele").length) {
            var h = parseFloat(trkpts[i].getElementsByTagName("ele")[0].firstChild.data);
            profil.push({x:tracklen+hp_x0,y:h,lat:lat,lon:lon});
          }
        }
      }
      tracks.push(track);
      tracklens.push(Math.round(tracklen*10)/10);
      profile.push(profil);
    }
    var rte = xml.documentElement.getElementsByTagName("rte"); // Routen
    routes = new Array();
    routeNames = new Array();
    routlens = new Array();
    for(var j=0;j<rte.length;j++) {
      var rtepts = rte[j].getElementsByTagName("rtept");
      var route = new Array();
      var routlen = 0;
      var name = rte[j].getElementsByTagName("name");
      if(name.length && name[0].firstChild && name[0].firstChild.length)
        routeNames[j] = name[0].firstChild.data;
      else
        routeNames[j] = "Route "+j;
      for(var i=0;i<rtepts.length;i++) { // Zwischenziele
        var lat = parseFloat(rtepts[i].getAttribute("lat"));
        var lon = parseFloat(rtepts[i].getAttribute("lon"));
        if(i==0) entf.init(lat,lon) ;
        routlen += entf.rechne(lat,lon);
        if(lat<latmin) latmin=lat; if(lat>latmax) latmax=lat;
        if(lon<lonmin) lonmin=lon; if(lon>lonmax) lonmax=lon;
        route.push(new GLatLng(lat,lon));
        var ext = rtepts[i].getElementsByTagName("extensions");
        if(ext.length) {
          var rpts = JB_GetElementsByTagNameNS(ext[0],"gpxx","rpt"); // Routenpunkte
          for(var k=0;k<rpts.length;k++) {
            var lat = parseFloat(rpts[k].getAttribute("lat"));
            var lon = parseFloat(rpts[k].getAttribute("lon"));
            routlen += entf.rechne(lat,lon);
            if(lat<latmin) latmin=lat; else if(lat>latmax) latmax=lat;
            if(lon<lonmin) lonmin=lon; else if(lon>lonmax) lonmax=lon;
            route.push(new GLatLng(lat,lon));
          }
        }
      }
      routes.push(route);
      routlens.push(Math.round(routlen*10)/10);
    }
    var wpts = xml.documentElement.getElementsByTagName("wpt"); // Waypoints
    waypoints = new Array();
    for(var i=0;i<wpts.length;i++) { // Wegpunktdaten
      var wpt = wpts[i];
      var lat = parseFloat(wpt.getAttribute("lat"));
      var lon = parseFloat(wpt.getAttribute("lon"));
      if(lat<latmin) latmin=lat; if(lat>latmax) latmax=lat;
      if(lon<lonmin) lonmin=lon; if(lon>lonmax) lonmax=lon;
      var waypoint = new Object();
      waypoint.lat = lat;
      waypoint.lon = lon;
      waypoint.name = "";
      waypoint.cmt = "";
      waypoint.desc = "";
      var name = wpt.getElementsByTagName("name");
      var cmt = wpt.getElementsByTagName("cmt");
      var desc = wpt.getElementsByTagName("desc");
      if(name.length && name[0].firstChild && name[0].firstChild.length)
        waypoint.name = name[0].firstChild.data;
      if(cmt.length && cmt[0].firstChild && cmt[0].firstChild.length)
        waypoint.cmt = cmt[0].firstChild.data;
      if(desc.length && desc[0].firstChild && desc[0].firstChild.length)
        waypoint.desc = desc[0].firstChild.data;
      waypoints.push(waypoint);
    }
    load = true;
  } // parseGPX
  this.showWpts = function() {
    if (load) {
      delete bilder; bilder = new Array();
      for(var i=0;i<waypoints.length;i++) {
        var waypoint = waypoints[i];
        if(checkImageName(waypoint.name)) {
          bilder[i] = new Image();
          bilder[i].src = waypoint.name;  // Bildurl steckt im Namen
          map.addOverlay(createImgMarker(waypoint));
        }
        else if (waypoint.name.length || waypoint.cmt.length)
          map.addOverlay(createTxtMarker(waypoint));
        else
          map.addOverlay(new GMarker(new GLatLng(waypoint.lat,waypoint.lon)));
      }
    }
  } // showWpts
  this.showTracks = function() {
    if (load) {
       if(hp) {
        if(tracks.length>1) {
		  for(var i=0;i<profile.length;i++) if(profile[i].length && chktrk.status[i+1]) hp_diag.scale(profile[i]);
		}
        else if(tracks.length==1)
		{
		  if(profile[0].length) hp_diag.scale(profile[0]);
		}
        hp_diag.frame(50,35,"Strecke in km","H<br />&ouml;<br />h<br />e<br />&nbsp;<br />i<br />n<br />&nbsp;<br />m");
      }
      if(tracks.length>1) {
        for(var i=0;i<tracks.length;i++) if(chktrk.status[i+1]) {
          map.addOverlay(new GPolyline(tracks[i],tcols[i%tcols.length],2,0.8));
          if(hp&&profile[i].length) hp_diag.plot(profile[i],tcols[i%tcols.length]);
        }
		if(HP_verbinde) {
		  var hp_t = new Array();
		  for(var i=0;i<profile.length;i++) if(chktrk.status[i+1]) hp_t = hp_t.concat(profile[i]);
		  if(hp_t.length) hp_diag.markeron(hp_t,dieses.markertstart,dieses.markerstop,dieses.markermove,"Linie") ;
		}
      }
      else if(tracks.length==1) {
        if(chktrk.status[0]) {
          map.addOverlay(new GPolyline(tracks[0],tcols[0],2,0.8));
          if(hp&&profile[0].length) {
            hp_diag.plot(profile[0],tcols[0]);
            hp_diag.markeron(profile[0],dieses.markertstart,dieses.markerstop,dieses.markermove,"Linie") ;
          }
        }
      }
    }
  } // showTracks
  this.showRoutes = function() {
    if (load) {
      if(routes.length>1) {
        for(var i=0;i<routes.length;i++) if(chkrt.status[i+1])
          map.addOverlay(new GPolyline(routes[i],rcols[i%tcols.length],2,0.8));
      }
      else if(routes.length==1) {
        if(chkrt.status[0])
          map.addOverlay(new GPolyline(routes[0],rcols[0],2,0.8));
      }
    }
  } // showRoutes
  this.show = function(what) {
    map.clearOverlays() ;
    if(hp) hp_diag.clear();
//    dieses.rescale();
    if (what.search("w") != -1 ) dieses.showWpts();
    if (what.search("t") != -1 ) dieses.showTracks();
    if (what.search("r") != -1 ) dieses.showRoutes();
  } // show
  this.rescale = function() {
    if(load) {
      map.setCenter(new GLatLng((latmax+latmin)/2,(lonmax+lonmin)/2), zoom);
    }
  } // rescale
  this.Entfernung = function() {
    var ls,bs;
    this.init = function(b,l) {
      ls = l;
      bs = b;
    }
    this.rechne = function(b,l) {
      var e = new GLatLng(bs,ls).distanceFrom(new GLatLng(b,l));
      ls = l;
      bs = b;
      return e/1000;
    }
  } // Entfernung
  this.markertstart = function() {
    movemarker = new GMarker(new GLatLng(profile[0][0].lat,profile[0][0].lon),markericon);
    map.addOverlay(movemarker);
    markerinfo.style.visibility = "visible";
  } // markerstart
  this.markerstop = function() {
    map.removeOverlay(movemarker);
    markerinfo.style.visibility = "hidden";
  } // markerstop
  this.markermove = function(p,a) {
    markerinfo.innerHTML = "Strecke:&nbsp;"+a.x.toFixed(1)+"km<br />H&ouml;he:&nbsp;"+Math.round(a.y)+"m";
    map.removeOverlay(movemarker);
    movemarker = new GMarker(new GLatLng(a.lat,a.lon),markericon);
    map.addOverlay(movemarker);
    var point=map.getCurrentMapType().getProjection().fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true),map.getZoom());
    var offset=map.getCurrentMapType().getProjection().fromLatLngToPixel(movemarker.getPoint(),map.getZoom());
    var anchor=movemarker.getIcon().iconAnchor;
    var width=movemarker.getIcon().iconSize.width;
    var height=markerinfo.clientHeight;
    var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(offset.x - point.x - anchor.x + width, offset.y - point.y -anchor.y -height));
    pos.apply(markerinfo);
  } // markermove 
  var createImgMarker = function(waypoint) {
    var marker = new GMarker(new GLatLng(waypoint.lat,waypoint.lon),icon);
    GEvent.addListener(marker, "click", function() {
      marker.openInfoWindowHtml("<img src='"+waypoint.name+"'\/><br\/>"+waypoint.cmt);
    });
    return marker;
  } // createImgMarker
  var createTxtMarker = function(waypoint) {
    var marker = new GMarker(new GLatLng(waypoint.lat,waypoint.lon),{title:waypoint.name});
    GEvent.addListener(marker, "click", function() {
      marker.openInfoWindowHtml("<strong>"+waypoint.name+"<\/strong><br\/>"+waypoint.cmt);
    });
    return marker;
  } // createTxtMarker
  var checkImageName = function(url) {
    var ext = url.substr(url.lastIndexOf(".")+1).toLowerCase();
    return (ext=="jpg" || ext=="jpeg" || ext=="png" || ext=="gif") ;
  } //  checkImageName
} // makeMap

function JB_GetElementsByTagNameNS(ele,namespace,name) {
  var alltags = ele.getElementsByTagName("*");
  var tagname = namespace.toLowerCase()+":"+name.toLowerCase()
  var tags = new Array();
  for(var i=0;i<alltags.length;i++) if(alltags[i].nodeName.toLowerCase()==tagname) tags.push(alltags[i]);
  return tags;
} // JB_GetElementsByTagNameNS(ele,namespace,name)

function JB_CheckBoxGroup(id,Texte,Label,Farbe,def_stat,clickFunc) {
  var dieses = this;
  var nbx = Texte.length;
  this.nboxen = nbx;
  this.status = new Array(nbx); for(var i=0;i<nbx;i++) this.status[i] = def_stat ;
  var ele;
  var box=document.createElement("div");
  box.style.position = "absolute";
  box.style.display = "inline";
  box.style.height = "1.4em";
  box.style.overflow = "hidden";
  box.style.backgroundColor = "";
  box.style.zIndex = 1000;
  box.style.margin = "0";
  box.style.padding = "0";
  box.onmouseover = function() {
    this.style.height = "";
    this.style.overflow = "";
    this.style.backgroundColor = "white";
    this.style.paddingRight = "0.3em";
    this.style.paddingBottom = "0.2em";
  };
  box.onmouseout  = function() {
    this.style.height = "1.4em";
    this.style.overflow = "hidden";
    this.style.backgroundColor = "";
    this.style.paddingRight = "";
    this.style.paddingBottom = "";
  };
  for(var i=0;i<nbx;i++) {
    ele = document.createElement("input");
    ele.type = "checkbox";
    ele.id = Label + i;
    ele.nr = i;
    if(i==0) ele.onclick = function() {
      var l = nbx;
      var n = Label;
      var status = this.checked;
      dieses.status[this.nr] = status;
      for(var j=1;j<l;j++) {
        document.getElementById(n+j).checked=status;
        dieses.status[j] = status;
      }
      clickFunc(dieses,this);
    };
    else     ele.onclick = function() {
      var l = nbx;
      var n = Label;
      var status = false;
      for(var j=1;j<l;j++) status |= document.getElementById(n+j).checked;
      document.getElementById(n+"0").checked = status;
      dieses.status[0] = status==true;
      dieses.status[this.nr] = this.checked;
      clickFunc(dieses,this);
    };
    box.appendChild(ele);
    ele.checked = def_stat;
    ele=document.createElement("span");
    if(i==0 && nbx==1) ele.style.color=Farbe[0];
    else if(i) ele.style.color=Farbe[(i-1)%Farbe.length];
    ele.appendChild(document.createTextNode(Texte[i]));
    box.appendChild(ele);
    if(i<Texte.length-1) box.appendChild(document.createElement("br"));
  }
  ele=document.getElementById(id);
  ele.appendChild(box);
  var spn=document.createElement("span"); // Platzhalter
  spn.appendChild(document.createTextNode(" X "+Texte[0]+" "));
  spn.style.visibility="hidden";
  ele.appendChild(spn);
} // JB_CheckBoxGroup

function JB_addEvent(oTarget, sType, fpDest) {
  var oOldEvent = oTarget[sType];
  if (typeof oOldEvent != "function") {
    oTarget[sType] = fpDest;
  } else {
    oTarget[sType] = function(e) {
      oOldEvent(e);
      fpDest(e);
    }
  }
} // addEvent

// gra
// Version vom 28.5.09
// Jürgen Berkemeier
// www.j-berkemeier.de
function gra(ID) {
 var feld=document.getElementById(ID);
 var dv=document.createElement("div");
 var cont=feld.appendChild(dv);
 var buf=document.createElement("div");
 this.w=parseInt(feld.offsetWidth-1);
 this.h=parseInt(feld.offsetHeight-1);
 var maxbuf=1;
 var bufsize=1;
 var sp = document.createElement("div");
 var col="#000000";
 sp.style.position="absolute";
 sp.style.width="1px";
 sp.style.height="1px";
 sp.style.overflow="hidden";
 sp.style.left="0px";
 sp.style.top="0px";
 sp.style.backgroundColor=col;
 this.setbuf=function(siz) {
  bufsize=maxbuf=Math.max(1,siz);
 }
 this.flush=function() {
  cont.appendChild(buf);
  buf=document.createElement("div");
  bufsize=maxbuf;
 }
 this.punkt=function(x,y,c) {
  if (x<0 || y<0 || x>this.w || y>this.h) return;
  if(c!=col) {col=c;sp.style.backgroundColor=col;}
  var pkt = sp.cloneNode(true);
  pkt.style.left=Math.round(x)+"px";
  pkt.style.top=Math.round(this.h-y)+"px";
  buf.appendChild(pkt);
  bufsize--; if(!bufsize) this.flush();
 } // punkt
 this.ver_linie=function(x,y1,y2,c) {
  if (x<0 || x>this.w) return;
  if ( (y1<0&&y2<0) || (y1>this.h&&y2>this.h) ) return;
  if(c!=col) {col=c;sp.style.backgroundColor=col;}
  y1=Math.max(0,Math.min(this.h,y1));
  y2=Math.max(0,Math.min(this.h,y2));
  var vl = sp.cloneNode(true);
  vl.style.left=Math.round(x)+"px";
  vl.style.top=Math.round(this.h-Math.max(y1,y2))+"px";
  vl.style.height=Math.round(Math.abs(y2-y1)+1)+"px";
  buf.appendChild(vl);
  bufsize--; if(!bufsize) this.flush();
 } // ver_linie
 this.hor_linie=function(x1,x2,y,c) {
  if (y<0 || y>this.h) return;
  if ( (x1<0&&x2<0) || (x1>this.w&&x2>this.w) ) return;
  if(c!=col) {col=c;sp.style.backgroundColor=col;}
  x1=Math.max(0,Math.min(this.w,x1));
  x2=Math.max(0,Math.min(this.w,x2));
  var hl = sp.cloneNode(true);
  hl.style.left=Math.round(Math.min(x1,x2))+"px";
  hl.style.top=Math.round(this.h-y)+"px";
  hl.style.width=Math.round(Math.abs(x2-x1)+1)+"px";
  buf.appendChild(hl);
  bufsize--; if(!bufsize) this.flush();
 } // hor_linie
 this.linie=function(xs,ys,xe,ye,c) {
//  var flag=(maxbuf==1);
//  if(flag) maxbuf=1000;
  xs=Math.round(xs); xe=Math.round(xe);
  ys=Math.round(ys); ye=Math.round(ye);
  var dx=xe-xs;
  var dy=ye-ys;
  if (dx==0 && dy==0) this.punkt(xs,ys,c)
  else if (dx==0) this.ver_linie(xs,ys,ye,c);
  else if (dy==0) this.hor_linie(xs,xe,ys,c);
  else {
   var adx=Math.abs(dx);
   var ady=Math.abs(dy);
   var d=Math.min(adx,ady);
   dx=dx/d;
   dy=dy/d;
   if (adx==ady) {
    for(var x=xs,y=ys,i=0;i<=d;x+=dx,y+=dy,i++) this.punkt(x,y,c) ;
   }
   else if (adx<ady) {
    var dd=dy/Math.abs(dy);
    this.ver_linie(xs,ys,ys+dy/2-dd,c);
    for(var x=xs+dx,y=ys+dy/2,i=1;i<d;x+=dx,y+=dy,i++) this.ver_linie(x,y,y+dy-dd,c) ;
    this.ver_linie(xe,ye-(dy+dd)/2,ye,c);
   }
   else {
    var dd=dx/Math.abs(dx);
    this.hor_linie(xs,xs+dx/2-dd,ys,c);
    for(var x=xs+dx/2,y=ys+dy,i=1;i<d;x+=dx,y+=dy,i++) this.hor_linie(x,x+dx-dd,y,c) ;
    this.hor_linie(xe-(dx+dd)/2,xe,ye,c);
   }
  }
//  if(flag) {maxbuf=1;this.flush();}
 } // linie
 this.text=function(x,y,size,color,text,align) {
  var align_h = "m";
  var align_v = "m";
  if(align && align.length) {
   align_h = align.substr(0,1);
   if(align.length>1) align_v = align.substr(1,1);
  }
  var pkt = document.createElement("div");
  pkt.style.position = "absolute";
  pkt.style.fontSize = size+"px";
  pkt.style.color = color;
  pkt.style.textAlign = "center";
  pkt.innerHTML = text;
  cont.appendChild(pkt);
  switch(align_h) {
   case "l": default: pkt.style.left = Math.round(x) + "px"; break;
   case "m": pkt.style.left = Math.round(x) - pkt.offsetWidth/2 + "px"; break
   case "r": pkt.style.left = Math.round(x) - pkt.offsetWidth + "px"; break
  }
  switch(align_v) {
   case "o": default: pkt.style.top = Math.round(this.h-y) + "px"; break;
   case "m": pkt.style.top = Math.round(this.h-y) - pkt.offsetHeight/2 + "px"; break;
   case "u": pkt.style.top = Math.round(this.h-y) - pkt.offsetHeight + "px"; break;
  }
 } // text
 this.del=function() {
  feld.removeChild(cont);
  delete cont;
  delete buf;
  var dv=document.createElement("div");
  cont=feld.appendChild(dv);
  buf=document.createElement("div");
  bufsize=maxbuf;
 } // del
} // gra

// plot
// Version vom 12. 2. 2009
// Jürgen Berkemeier
// www.j-berkemeier.de
var plot = function(id) {
  var JB_log10 = function(x) { return Math.log(x)/Math.LN10; }
  var JB_toString = function(n) { return Number(n.toPrecision(15)).toString(10); }
  var JB_makediv = function(parentnode,id,x0,y0,width,height) {
    var ele = document.createElement("div");
    ele.id = id;
    ele.style.position = "absolute";
    ele.style.left = x0 + "px";
    ele.style.top = y0 + "px";
    ele.style.width = width + "px";
    ele.style.height = height + "px";
    parentnode.appendChild(ele);
    return ele;
  }
  var plotid = id+"plot";
  var plotidm = id+"plotm";
  var idxlabel = id+"xlabel";
  var idylabel = id+"ylabel";
  var xmin=0,xmax=0,ymin=0,ymax=0;
  var xfak=0,yfak=0;
  var dx,dy,fx,fy;
  var gr = null;
  var xlabel = null;
  var ylabel = null;
  var feld = document.getElementById(id) ;
  var w = parseInt(feld.offsetWidth-1);
  var h = parseInt(feld.offsetHeight-1);
  var ifeld = document.createElement("div");
  ifeld.style.position = "absolute";
  ifeld.style.width = w + "px";
  ifeld.style.height = h + "px";
  feld.appendChild(ifeld);

  this.scale = function(a) {
    if(xmin==xmax) {
      xmax = xmin = a[0].x;
      ymax = ymin = a[0].y;
    }
    for(var i=0;i<a.length;i++) {
      var t = a[i];
      if(t.x<xmin) xmin = t.x;
      if(t.x>xmax) xmax = t.x;
      if(t.y<ymin) ymin = t.y;
      if(t.y>ymax) ymax = t.y;
    }
    if(xmax==xmin) { xmin -= 0.5; xmax += 0.5; }
    dx = xmax - xmin ;
    fx = Math.pow(10,Math.floor(JB_log10(dx))-1);
    xmin = Math.floor(xmin/fx)*fx;
    xmax = Math.ceil(xmax/fx)*fx;
    if(ymax==ymin) { ymin -= 0.5; ymax += 0.5; }
    dy = ymax - ymin ;
    fy = Math.pow(10,Math.floor(JB_log10(dy))-1);
    ymin = Math.floor(ymin/fy)*fy;
    ymax = Math.ceil(ymax/fy)*fy;
  } // plot.scale
  this.clear = function() {
    ifeld.innerHTML = "";
    xmax = xmin = ymax = ymin = xfak = yfak = 0;
  } // plot.clear
  this.frame = function(x0,y0,xl,yl) {
    ifeld.innerHTML = "";
    JB_makediv(ifeld,plotid,x0,0,w-x0,h-y0);
    JB_makediv(ifeld,idxlabel,x0,h-y0,w-x0,y0);
    JB_makediv(ifeld,idylabel,0,0,x0,h-y0);
    JB_makediv(ifeld,plotidm,x0,0,w-x0,h-y0);
    xlabel=new gra(idxlabel);
    ylabel=new gra(idylabel);
    gr=new gra(plotid);
    gr.setbuf(1000);
    xfak = gr.w/(xmax-xmin);
    yfak = gr.h/(ymax-ymin);
    xlabel.text(xlabel.w/2,0,16,"black",xl,"mu");
    ylabel.text(5,ylabel.h/2,16,"black",yl,"mm");
    var tx = 100*dx/gr.w;
    var ty = gr.h<250 ?  50*dy/gr.h : 100*dy/gr.h;
    var tx10 = Math.pow(10,Math.floor(JB_log10(tx)));
    tx = Math.round(tx/tx10);
    var ty10 = Math.pow(10,Math.floor(JB_log10(ty)));
    ty = Math.round(ty/ty10);
    tx = Number(String(tx).replace(/3/,"2").replace(/[4567]/,"5").replace(/[89]/,"10"));
    ty = Number(String(ty).replace(/3/,"2").replace(/[4567]/,"5").replace(/[89]/,"10"));
    tx *= tx10;
    ty *= ty10;
    var mxmin = Math.ceil(xmin/tx)*tx;
    var mymin = Math.ceil(ymin/ty)*ty;
    for(var x=mxmin;x<=xmax;x+=tx) {
      gr.linie((x-xmin)*xfak,0,(x-xmin)*xfak,gr.h,"gray");
      xlabel.text((x-xmin)*xfak,xlabel.h,14,"black",JB_toString(x),"mo");
    }
    for(var y=mymin;y<=ymax;y+=ty) {
      gr.linie(0,(y-ymin)*yfak,gr.w,(y-ymin)*yfak,"gray");
      ylabel.text(ylabel.w,(y-ymin)*yfak,14,"black",JB_toString(y),"rm");
    }
    var rahmen=new gra(plotid);
    rahmen.linie(       0,       0,rahmen.w,       0,"black");
    rahmen.linie(rahmen.w,       0,rahmen.w,rahmen.h,"black");
    rahmen.linie(rahmen.w,rahmen.h,       0,rahmen.h,"black");
    rahmen.linie(       0,rahmen.h,       0,       0,"black");
  } // plot.frame
  this.plot = function(a,col) {
    for(var i=0;i<a.length-1;i++)
      gr.linie(
       (a[i].x-xmin)*xfak,
       (a[i].y-ymin)*yfak,
       (a[i+1].x-xmin)*xfak,
       (a[i+1].y-ymin)*yfak,
       col);
    gr.flush();
  } // plot.plot)
  this.markeron = function(a,callback_over,callback_out,callback_move,markertype) {
    var dieses = this;
    var posx=0;
    var mele = document.getElementById(plotidm);
    var pele = document.getElementById(plotid);
    var marker = document.createElement("div");
    marker.style.position = "absolute";
    marker.style.display = "none";
    if(markertype=="Punkt") {
      marker.style.fontSize = "32px";
      var txt=document.createTextNode(String.fromCharCode(8226)) ; // Kreis als Zeichen: &bull; oder &#8226; evtl auch 8729
      marker.appendChild(txt);
    }
    else {
      marker.style.top = "0";
      marker.style.height = gr.h + "px" ;
      marker.style.width = "1px";
      marker.style.backgroundColor = "black";
    }
    pele.appendChild(marker);
    mele.onmouseover = function(e) {
      if(!e) e = window.event;
      e.cancelBubble = true;
      if (e.stopPropagation) e.stopPropagation();
      marker.style.display = "";
      mele.onmousemove = function(e) {
        if(!e) e = window.event;
        e.cancelBubble = true;
        if (e.stopPropagation) e.stopPropagation();
        posx = e.layerX ? e.layerX : e.offsetX;
        var x = posx/xfak+xmin;
        var al = a.length;
        var p,pi;
        if(x<=a[0].x) pi=0;
        else if(x>=a[al-1].x) pi=al-1;
        else {
          p = al/2;
          pi = Math.floor(p);
          var dp = Math.ceil(p/2);
          do {
            var apx = a[pi].x;
            if(x<apx) p -= dp;
            else if(x>apx) p += dp;
            else break;
            pi = Math.floor(p);
            dp = dp/2;
          } while(dp>=0.5) ;
        }
        if(markertype=="Punkt") {
          marker.style.left = Math.round((a[pi].x-xmin)*xfak) - marker.offsetWidth/2 + "px";
          marker.style.top = Math.round(gr.h - (a[pi].y-ymin)*yfak) - marker.offsetHeight/2 + "px";
        }
        else {
          marker.style.left = Math.round((a[pi].x-xmin)*xfak) + "px";
        }
        if(callback_move && typeof(callback_move)=="function") callback_move(pi,a[pi]);
        return false;
      }
      if(callback_over && typeof(callback_over)=="function") callback_over();
      return false;
    }
    mele.onmouseout = function(e) {
      if(!e) e = window.event;
      marker.style.display = "none";
      mele.onmousemove = null;
      if(callback_out && typeof(callback_out)=="function") callback_out();
      return false;
    }
  } // plot.markeron
  this.markeroff = function() {
    var ele = document.getElementById(plotid);
    ele.onmousemove = null;
    ele.onmouseout = null;
  } // plot.markeroff
} // plot

JB_addEvent(window,"onload",function() {
  if(document.getElementsByTagName && GBrowserIsCompatible()) {
    var Map_Nr=0;
    var chkTyp = function(typString) {
      if(typString=="Karte") return G_NORMAL_MAP ;
      if(typString=="Satellit") return G_SATELLITE_MAP ;
      if(typString=="Hybrid") return G_HYBRID_MAP ;
      if(typString=="Oberflaeche") return G_PHYSICAL_MAP ;
      if(typString=="OSM") return "osm_map";
      return G_SATELLITE_MAP;
    } // chkTyp
    var divs = document.getElementsByTagName("div");
    var typ = G_SATELLITE_MAP;
    for(var i=0;i<divs.length;i++) {
      var div = divs[i];
      if(div.className) {
        var Klasse = div.className;
        var CN = Klasse.toLowerCase().indexOf("gpxview");
        if(CN>-1) {
          if(div.id) var Id = div.id;
          else {
            var Id = "map"+(Map_Nr++);
            div.id = Id;
          }
          var GPX = Klasse.substring(CN).split()[0];
          GPX = GPX.split(":") ;
          if(GPX.length==3) {
            typ = chkTyp(GPX[2]);
          }
          if(GPX[1].length) {
            window["Karte_"+Id] = new makeMap(Id);
            window["Karte_"+Id].Spur(GPX[1],typ);
          }
        }
      }
    }
    var buttons = document.getElementsByTagName("button");
    for(var i=0;i<buttons.length;i++) {
      var button = buttons[i];
      if(button.className) {
        var Klasse = button.className;
        var CN = Klasse.toLowerCase().indexOf("gpxview");
        if(CN>-1) {
          var cmd = Klasse.substring(CN).split()[0];
          cmd = cmd.split(":") ;
          if(cmd.length>2) {
            var Id = cmd[1];
            switch(cmd[2]) {
              case "skaliere":
                ( function() {
                  var mapid = "Karte_"+Id;
                  button.onclick = function(){window[mapid].rescale()};
                } )();
                break;
              case "lade":
                if(cmd.length>3) {
                  if(cmd.length>4) typ = chkTyp(cmd[4]);
                  else typ = G_SATELLITE_MAP;
                  ( function() {
                    var fn = cmd[3];
                    var mapid = "Karte_"+Id;
                    var tp = typ;
                    button.onclick = function(){window[mapid].Spur(fn,tp)};
                  } )();
                }
                break;
              default:
                break;
            }
          }
        }
      }
    }
    JB_addEvent(window,"onunload",GUnload);
  }
  else alert("Ihr Browser unterstützt nicht die benötigten Methoden!");
});