function jumpTo(lon, lat, zoom) {
    var x = Lon2Merc(lon);
    var y = Lat2Merc(lat);
    map.setCenter(new OpenLayers.LonLat(x, y), zoom);
    return false;
}
 
function Lon2Merc(lon) {
    return 20037508.34 * lon / 180;
}
 
function Lat2Merc(lat) {
    var PI = 3.14159265358979323846;
    lat = Math.log(Math.tan( (90 + lat) * PI / 360)) / (PI / 180);
    return 20037508.34 * lat / 180;
}
 
function addMarker(layer, lon, lat, popupContentHTML, showPopupOnLoad, iconId) {
 
    // Koordinaten in LonLat umwandeln
    var ll = new OpenLayers.LonLat(Lon2Merc(lon), Lat2Merc(lat));

    // Feature erstellen und konfigurieren (Popup und Marker)
    var feature = new OpenLayers.Feature(layer, ll);
    feature.closeBox = true;
    feature.popupClass = OpenLayers.Class(OpenLayers.Popup.FramedCloud, {minSize: new OpenLayers.Size(200, 120) } );
    //feature.popupClass = OpenLayers.Class(OpenLayers.Popup.Anchored, {'autoSize': true, 'minSize': new OpenLayers.Size(100, 40) } );
    feature.data.popupContentHTML = popupContentHTML;
    feature.data.overflow = "auto";
    feature.data.icon = makeIcon(iconId);
 
    // Marker erstellen
    var marker = feature.createMarker();
 
    /*
     * Handler Funktionen für die Mouse-Events
     */
    // Click
    var markerClick = function(evt) {
	// Wenn das Popup nicht sichtbar ist, dann kann es nicht fest sichtbar sein
	if (!this.popup.visible())
		this.popup.clicked = false;
	if (this.popup.clicked == true) {
		this.popup.clicked = false;
		this.popup.hide();
    	}
    	else {
		this.popup.clicked = true;
		if (!this.popup.visible())
			this.popup.show();
	}
        OpenLayers.Event.stop(evt);
    };
    // Hover
    var markerHover = function(evt) {
	// Wenn das Popup nicht sichtbar ist, dann kann es nicht fest sichtbar sein
	if (!this.popup.visible())
		this.popup.clicked = false;
	if (!this.popup.clicked)
		this.popup.show();

	OpenLayers.Event.stop(evt);
    }
    // Hover End
    var markerHoverEnd = function(evt) {
	if (!this.popup.clicked) {
		this.popup.hide();
	}
	OpenLayers.Event.stop(evt);
    }

    // Events auf den Marker registrieren und als Objekt das Feature übergeben
    marker.events.register("mousedown", feature, markerClick);
    if (showPopupOnHover) {
    	marker.events.register("mouseover", feature, markerHover);
    	marker.events.register("mouseout", feature, markerHoverEnd);
    }

    // Erstellten Marker der Ebene hinzufügen
    layer.addMarker(marker);

    // Popup erstellen, der Karte hinzufügen und anzeigen, falls gewünscht
    map.addPopup(feature.createPopup(feature.closeBox));
    
    if (showPopupOnLoad != true) {
	    // Wenn das Popup nicht angezeigt werden soll, verstecken und auf 'nicht angeklickt' setzen
	    feature.popup.hide();
	    feature.popup.clicked = false;
    } else {
	    // Das Popup wird direkt angezeigt und zwar solange bis man es explizit schließt
	    feature.popup.clicked = true;
    }

    return marker;
}

/*
 *
 * Creates a new marker icon
 *
 * using the icons-array (defined in the html-file)
 *
 * index
 * 0	address to the image
 * 1	width of the image
 * 2	height
 * 3	factor by which the image should be offset horizontally
 * 4	factor by which the image should be offset vertically
 *
 * please see the icon array itself for examples of values
 */
function makeIcon(iconId) {
	var size = new OpenLayers.Size(icons[iconId][1],icons[iconId][2]);
	var offset = new OpenLayers.Pixel(-(size.w*icons[iconId][3]), -(size.h*icons[iconId][4]));
	var icon = new OpenLayers.Icon(icons[iconId][0],size,offset);
	return icon;
}
 
function getCycleTileURL(bounds) {
   var res = this.map.getResolution();
   var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
   var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
   var z = this.map.getZoom();
   var limit = Math.pow(2, z);
 
   if (y < 0 || y >= limit)
   {
     return null;
   }
   else
   {
     x = ((x % limit) + limit) % limit;
 
     return this.url + z + "/" + x + "/" + y + "." + this.type;
   }
}


/*
 * Für den Layer-Switcher mit Buttons
 */
function setLayer(id) {
	if (document.getElementById("layers") != null) {
		for (var i=0;i<layers.length;++i)
			document.getElementById(layers[i][1]).className = "";
	}
	varName = layers[id][0];
	name = layers[id][1];
	map.setBaseLayer(varName);
	if (document.getElementById("layers") != null)
		document.getElementById(name).className = "active";
}

/*
 *
 * Icons und Marker
 *
 */

/*
 * Neues Icon setzen (Wert und Bild austauschen)
 */
function chooseIcon(id,iconId) {
	document.getElementById("marker"+id+"Icon").value = iconId;
	/* set the new image file */
	document.getElementById("marker"+id+"IconImage").src = icons[iconId][0];
	/*if (markers[id] != null) {
		markers[id].icon = makeIcon(iconId);
		markers[id].draw();
	}*/
	toggleIconChooser();
}
function getIconIdByMarkerId(id) {
	var iconId = document.getElementById("marker"+id+"Icon").value;
	if (iconId == null)
		return -1;
	return iconId;
}
function toggleIconChooser() {
	var state = document.getElementById('iconChooser').className;
	if (state == 'hide') {
		// Chooser anzeigen
		document.getElementById('iconChooser').className = '';
	}
	else {
		// Chooser verstecken
		document.getElementById('iconChooser').className = 'hide';
	}
}

function highlightMarkerReset() {
	for (var i=0;i<markers.length;++i) {
		markers[i].setOpacity(0.5);
	}
}

function highlightMarker(id) {
	highlightMarkerReset();
	if (markers[id] != null)
		markers[id].setOpacity(1);
}

/*
 * ClickHandler zum Marker-Koordinaten Auswählen
 */
OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {                
                defaultHandlerOptions: {
                    'single': true,
                    'double': false,
                    'pixelTolerance': 0,
                    'stopSingle': false,
                    'stopDouble': false
                },

                initialize: function(options) {
                    this.handlerOptions = OpenLayers.Util.extend(
                        {}, this.defaultHandlerOptions
                    );
                    OpenLayers.Control.prototype.initialize.apply(
                        this, arguments
                    ); 
                    this.handler = new OpenLayers.Handler.Click(
                        this, {
                            'click': this.trigger
                        }, this.handlerOptions
                    );
                }, 

                trigger: function(e) {
                    var lonlat = map.getLonLatFromViewPortPx(e.xy).transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
                    //alert("You clicked near " + lonlat.lat + " N, " +
                    //                          + lonlat.lon + " E");
		    

		    if (getStatus() == 0 || getStatus() == 1) {
		    	document.getElementById("marker"+clickTarget+"Lat").value = lonlat.lat;
		    	document.getElementById("marker"+clickTarget+"Lon").value = lonlat.lon;

		    // Man könnte auch den neuen Marker in das markers-Array schreiben..
		     /*if (tempMarker != null)
			    layer_markers.removeMarker(tempMarker);
			*/
		    var iconId = getIconIdByMarkerId(clickTarget);
		    if (iconId == -1)
			    iconId = 0;
		    if (markers[clickTarget] != null) {
		    	layer_markers.removeMarker(markers[clickTarget]);
		    	//markers[clickTarget].setOpacity(0.2);
			markers[clickTarget] = addMarker(layer_markers,lonlat.lon,lonlat.lat,"Temporärer Marker",false,iconId);
		    }
		    else {
			var tempMarker = addMarker(layer_markers,lonlat.lon,lonlat.lat,"Temporärer Marker",false,iconId);
			markers[clickTarget] = tempMarker;
		    }
		    
		    setStatus(1);
		    }
		    else {
			
			addToGeometry(lonlat.lon,lonlat.lat);
			
			}
                }

            });

function chooseMarkerCoordinates(target) {
	clickTarget = target;
	click.activate();
	setStatus(0);
	highlightMarker(target);
}
function stopChoosingMarkerCoordinates() {
	click.deactivate();
	clickTarget = '';
	setStatus(-1);
}

/*
 * Get current geometry style from form and create a style object
 */

function getGeometryStyle() {
	var strokeColor = document.getElementById("geometry"+currentGeometry+"StrokeColor").value;
	var strokeWidth = document.getElementById("geometry"+currentGeometry+"StrokeWidth").value;
	var fillColor = document.getElementById("geometry"+currentGeometry+"FillColor").value;
	var fillOpacity = document.getElementById("geometry"+currentGeometry+"FillOpacity").value;

	var style = new Object();
	style['fill'] = true;
	style['fillColor'] = fillColor;
	style['fillOpacity'] = fillOpacity;
	style['strokeColor'] = strokeColor;
	style['strokeWidth'] = strokeWidth;
	return style;
}

/*
 * Styles for points of the current geometry
 */
var pointStyleNormal = {
		fill: true,
		fillColor: "#000000",
		fillOpacity: 1,
                strokeColor: "#000000",
                strokeWidth: 1,
		strokeOpacity: 1,
                pointRadius: 4,
                pointerEvents: "visiblePainted"
            };

var pointStyleEnd = {
		fill: true,
		fillColor: "#000000",
		fillOpacity: 1,
                strokeColor: "#000000",
                strokeWidth: 1,
		strokeOpacity: 1,
                pointRadius: 6,
                pointerEvents: "visiblePainted"
            };

/*
 * Initialize some needed vars
 */

// Holds the current geometry object to work on
tempGeometry = null;
// Holds an array of the coordinates of the edited geometry
tempGeometryData = new Array();
// Holds the points objects that are used to draw the geometries points
tempGeometryPoints = new Array();
// The current type (line, polygon) of the geometry
tempGeometryType = '';


/*
 * This function should be called when starting to edit a feature
 */

function startEditingGeometry(target) {
	currentGeometry = target;
	layer_vectors.setOpacity(0.4);
	layer_vectors.redraw();
	layer_vectors_edit.setVisibility(true);
	startAddingGeometryPoints();
	loadGeometry();
}
function startAddingGeometryPoints() {
	modifyFeature.deactivate();
	click.activate();
	setStatus(2);
	drawGeometry();
}
function startEditingGeometryPoints() {
	click.deactivate();
	modifyFeature.activate();
	setStatus(3);
	drawGeometry();
}
/*
 * This function should be called when finishing editing a feature (also called by setStatus())
 */
function stopEditingGeometry() {
	/*
	 * When called while in editing mode, do some things you should not do
	 * when called via setStatus() (like set the status)
	 */
	if (getStatus() == 2 || getStatus() == 3) {
		click.deactivate();
		modifyFeature.deactivate();
		setStatus(-1);
	}
	layer_vectors.setOpacity(1);
	layer_vectors_edit.setVisibility(false);
	drawGeometry();
}
/*
 * Adds a lon,lat to the current geometry
 */
function addToGeometry(lon,lat) {
	tempGeometryData.push([lon,lat]);
	drawGeometry();
	

	//var lonlat = new OpenLayers.LonLat(lon,lat).transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"))
	
	//tempGeometry.geometry.addPoint(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));
	//layer_vectors.drawFeature(tempGeometry);


	saveGeometry();
}
/*
 * Removes the last point from the geometry
 */
function undoLastGeometryCoordinate() {
	tempGeometryData.pop();
	drawGeometry();
	saveGeometry();
}
/*
 * Handles hovering over the button that calls the above function
 */
function undoLastGeometryCoordinateHover(out) {
	if (out == true) {
		if (getStatus() != 2) {
			removePointsOfGeometry();
		}
	}
	else {
		drawPointsOfGeometry();
	}
}
/*
 * Is called when the ModifyFeature-Control finished editing the feature ("afterfeaturemodified"-event)
 */
function featureModified(event) {
	var components = tempGeometry.geometry.components;
	//alert(var_dump(components[0]));
	
	// If there is another geomety object inside, use that one (for polygons, since they contain a LinearRing that holds the points)
	if (tempGeometryType == "polygon")
		components = components[0].components;

	// Empty the current array of coordinates and get them from the modified feature
	tempGeometryData = new Array();
	for (var i=0;i<components.length;++i)
	{
		var lonlat = new OpenLayers.LonLat(components[i].x,components[i].y).transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326"));
		//alert(var_dump(lonlat));
		tempGeometryData.push([lonlat.lon,lonlat.lat]);
	}

	// If geometry is a polygon, remove the last point, since that one is cloned from the first, else just save it
	if (tempGeometryType == "polygon")
		undoLastGeometryCoordinate();
	else
		saveGeometry();
}

/*
 * Writes the current geometry coordinates into the form, should be called everytime the geometry is changed
 */
function saveGeometry() {
	var saveTo = document.getElementById("geometry"+currentGeometry+"Coordinates");
	saveTo.value = '';
	for (var i=0;i<tempGeometryData.length;++i) {
		saveTo.value = saveTo.value+tempGeometryData[i][0]+" "+tempGeometryData[i][1]+"|";
	}
	var numPoints = document.getElementById("geometryNumPoints");
	numPoints.innerHTML = tempGeometryData.length;
}
/*
 * Loads the geometry from the form and draws it on the edit layer
 */
function loadGeometry() {
	var loadFrom = document.getElementById("geometry"+currentGeometry+"Coordinates");
	// Array leeren, falls noch was drin ist
	tempGeometryData = new Array();
	var coordinates = loadFrom.value.split("|");
	//alert(loadFrom.value);
	for (var i=0;i<coordinates.length;++i) {
		var temp = coordinates[i].split(" ");
		if (temp.length == 2) {
			tempGeometryData.push(temp);
		}
	}
	// Read from the form the type of geometry
	if (document.getElementById("geometry"+currentGeometry+"TypeLine").checked == true)
		tempGeometryType = 'line';
	else if (document.getElementById("geometry"+currentGeometry+"TypePolygon").checked == true)
		tempGeometryType = 'polygon';
	
	drawGeometry();
}
function drawGeometry() {

	// Determine which layer to draw on and whether to draw the points of the geometry (based on the mode)
	var drawOnLayer = layer_vectors_edit;
	if (getStatus() == 2) {
		drawPointsOfGeometry(tempGeometryData);
	}
	else {
		if (getStatus() != 3) {
			drawOnLayer = layer_vectors;
		}
		removePointsOfGeometry();
	}

	// Check if the current feature has been drawn in a different layer and if so, remove it
	if (inArray(geometries[currentGeometry],layer_vectors.features) == true)
	{
		layer_vectors.removeFeatures(geometries[currentGeometry]);
	}
	if (inArray(tempGeometry,layer_vectors.features) == true)
	{
		layer_vectors.removeFeatures(tempGeometry);
	}
	if (inArray(tempGeometry,layer_vectors_edit.features) == true)
	{
		layer_vectors_edit.removeFeatures(tempGeometry);
	}

	if (tempGeometryType == "line") {
		//alert(tempGeometryData);
		tempGeometry = drawLine(tempGeometryData,getGeometryStyle(),tempGeometry,drawOnLayer);
	}
	if (tempGeometryType == "polygon") {
		tempGeometry = drawPolygon(tempGeometryData,getGeometryStyle(),tempGeometry,drawOnLayer);
	}
	//alert(var_dump(tempGeometry));
}


/*
 * Aktuelle Kartenansicht übernehmen
 */
function setCurrentMapView() {
	var lonlat = map.getCenter();
	lonlat = OpenLayers.Layer.SphericalMercator.inverseMercator(lonlat.lon,lonlat.lat);
	document.getElementById("lat").value = lonlat.lat;
	document.getElementById("lon").value = lonlat.lon;
	document.getElementById("zoom").value = map.getZoom();
}

/*
 * Aktuelle Kartenansicht nach jeder Bewegung der Karte speichern
 */
function mapEvent(event) {
	var lonlat = map.getCenter();
	lonlat = OpenLayers.Layer.SphericalMercator.inverseMercator(lonlat.lon,lonlat.lat);
	document.getElementById("latCurrent").value = lonlat.lat;
	document.getElementById("lonCurrent").value = lonlat.lon;
	document.getElementById("zoomCurrent").value = map.getZoom();
}

/*
 * Koordinatenwahl-Status
 */



currentStatus = -1
function setStatus(id) {
	currentStatus = id
	var newtext;
	if (id == -1)
		newtext = '';
	else
		newtext = "<b>"+statusText[id]+"</b>";

	if (id != 2 && id != 3) {
		stopEditingGeometry();
	}

	document.getElementById("status").innerHTML = newtext;
}
function getStatus() {
	return currentStatus
}




/*
 * Formularbereiche ein- und ausblenden
 */
function toggleSection(name,showText,hideText) {
	var section = document.getElementById("section_"+name);
	var sectionForm = document.getElementById("sectionForm_"+name);
	var sectionLink = document.getElementById("sectionLink_"+name);
	if (section == null)
		return false;

	if (section.className == "hide") {
		// Ist versteckt, also aufdecken
		section.className = "show";
		if (sectionForm != null)
			sectionForm.value = "show";
		if (sectionLink != null)
			sectionLink.innerHTML = hideText;
	} else {
		// Sollte aufgedeckt sein, also verstecken
		section.className = "hide";
		if (sectionForm != null)
			sectionForm.value = "hide";
		if (sectionLink != null)
			sectionLink.innerHTML = showText;
	}
}


function drawLine(coordinates,style,replace,layer) {
	var linePoints = createPointsArrayFromCoordinates(coordinates);

	var line = new OpenLayers.Geometry.LineString(linePoints);
	var vector = new OpenLayers.Feature.Vector(line,null,style);

	if (layer == null)
		layer = layer_vectors;

	if (replace != null) {
		layer.removeFeatures(replace);
	}
	layer.addFeatures(vector);
	return vector;
}
function drawPolygon(coordinates,style,replace,layer) {
	var points = createPointsArrayFromCoordinates(coordinates);

	var linearRing = new OpenLayers.Geometry.LinearRing(points);
	var polygon = new OpenLayers.Geometry.Polygon([linearRing]);
	var vector = new OpenLayers.Feature.Vector(polygon,null,style);

	if (layer == null)
		layer = layer_vectors;

	if (replace != null)
		layer.removeFeatures(replace);
	layer.addFeatures(vector);
	return vector;
}
function removePointsOfGeometry() {
	layer_vectors_edit.removeFeatures(tempGeometryPoints);
	tempGeometryPoints = new Array();
}
function drawPointsOfGeometry(coordinates) {

	if (coordinates == null)
		coordinates = tempGeometryData;

	// Remove old points if needed
	removePointsOfGeometry();

	// Create points and add features
	var points = createPointsArrayFromCoordinates(coordinates);
	for (var i=0;i<points.length;++i) {
		var style = pointStyleNormal;
		if (i == points.length - 1) {
			style = pointStyleEnd;
		}
		var vector = new OpenLayers.Feature.Vector(points[i],null,style);
		layer_vectors_edit.addFeatures(vector);
		tempGeometryPoints.push(vector);
	}
}
function createPointsArrayFromCoordinates(coordinates) {
	var points = new Array();
	for (var i=0;i<coordinates.length;++i) {
		var lonlat = new OpenLayers.LonLat(coordinates[i][0],coordinates[i][1]).transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"))
		points.push(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat))
	}
	return points;	
}

function inArray(checkObject,inArray) {
	check = false;
	for (var i=0;i<inArray.length;++i) {
		if (inArray[i] == checkObject)
			check = true;
	}
	return check;
}
































function var_dump(obj) {
   if(typeof obj == "object") {
      return "Type: "+typeof(obj)+((obj.constructor) ? "\nConstructor: "+obj.constructor : "")+"\nValue: " + obj;
   } else {
      return "Type: "+typeof(obj)+"\nValue: "+obj;
   }
}//end function var_dump


