
/******************************************************************************
 *
 * Purpose: functions related to map navigation and mouse events  
 * Author:  Armin Burger
 *
 ******************************************************************************
 *
 * Copyright (c) 2003-2006 Armin BurgerrawT
 *
 * This file is part of p.mapper.
 *
 * p.mapper is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version. See the COPYING file.
 *
 * p.mapper is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with p.mapper; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 ******************************************************************************/


// will only work with modern browsers, NOT with 4.x versions          //
// Successfully tested with Mozilla 1.0+, Firefox, IE 5.5+, Opera 6+, Konqueror 3//

  
/*
 * GLOBAL VARIABLES
 ******************************************************/
var mouseDrag = false;    // TRUE when mouse is pressed
var maction;

var rightMouseButton = false;

var downX, downY;
var upX, upY;
var moveX, moveY;

//var offsX = 0; 	// horizontal image offset
//var offsY = 0;    // vertical image offset

var rBoxMinW = 8;   // Minimal width until to show refBox; below threshold switches to refCross
var rOffs = 13;     // Offset of refCross Image, adapt to Image size and refbox border

if (document.all) {
    var zBorder = 0;
} else {
    var zBorder = 4;
}

var refmapClick = false;
var mapcL, mapcT, mapcL, mapcR;
var mapElem; 

var isIE = (document.all) ? true : false;

var iquery_timer;


var m_offsX = 0;
var m_offsY = 0;




/*
 * DEFINE MOUSE ACTIONS, CALLED AS 'ONLOAD' SCRIPT
 ******************************************************/
// FOR MOUSE OVER MAP
function startUp() {
    refmapClick = false;
    
    // ENABLES ACTIONS FOR KEYBOARD KEYS
    // comment out if not wanted
    if (document.all) document.onkeydown = kp;
    document.onkeypress = kp;
    
    mapElem = $('map');
    if (mapElem) {
        mapElem.onmousedown = doMouseDown; 
        mapElem.onmouseup   = doMouseUp;
        mapElem.onmousemove = doMouseMove; 
                
        // ENABLES ACTIONS FOR MOUSE WHEEL
        if (isIE) {
            mapElem.onmousewheel = omw;
        } else {
            mapElem.addEventListener('DOMMouseScroll', omw, false);
        }
        mapElem.oncontextmenu = disableContextMenu;
        
        setCursorMinMax('map');
    }
    
}



// FOR MOUSE OVER REFERENCE MAP
function startUpRef() {
    clearTimeout(iquery_timer);  // necessary for iquery mode
    refmapClick = true;
    refElem = $('refmap');
    if (refElem) {
        refElem.onmousedown = doMouseDown; 
        refElem.onmouseup   = doMouseUp;
        refElem.onmousemove = doMouseMove;   
    
        // ENABLES ACTIONS FOR MOUSE WHEEL ON MAP
        if (isIE) {
            refElem.onmousewheel = omw;
        } else {
            refElem.addEventListener('DOMMouseScroll', omw, false);
        }
        
        setCursorMinMax('refmap');
    }
}


// MIN AND MAX VALUES FOR MOUSE
function setCursorMinMax(elem) {
    // MAP
    if (elem == 'map') {
        mapcL = rawL('mapZone') + rawL('map');
        mapcT = rawT('mapZone') + rawT('map');
        mapcR = mapcL + m_offsX + mapW;
        mapcB = mapcT + m_offsY + mapH;
    // REFERENCE MAP
    } else {
        var rm = $('refmap');
        mapcL = objL(rm) + objL(rm.parentNode);
        mapcT = objT(rm) + objT(rm.parentNode);
        mapcR = mapcL + refW + m_offsX;
        mapcB = mapcT + refH + m_offsY;
    }
    
    offsX = m_offsX + mapcL + 1; 		// horizontal image offset
    offsY = m_offsY + mapcT + 1; 
}


function checkCursorPosition(cX, cY) {
    if (cX >= mapcL && cX <= mapcR && cY >= mapcT && cY <= mapcB) {
        return true;
    } else {
        return false;
    }
}



/*
 * FUNCTIONS TO GET MOUSE POSITIONS
 ******************************************************/
// For MouseDown
function getDownXY(e) {
    if (document.all) {
		eX = event.clientX;
        eY = event.clientY;
	} else {
		eX = e.pageX;
		eY = e.pageY;
	}
	// subtract offsets
        
    downX = eX - offsX;
    downY = eY - offsY;
    
    mapElem.onmouseup   = doMouseUp;
    mapElem.onmousemove = doMouseMove;
    mapElem.ondblclick  = doMouseDblClick;  // used for measure area, comment out if area measurement not wanted

    //alert (downX + ' - ' + downY);

    return false;	
}


// For MouseUp
function getUpXY(e) {
    if (document.all) {
        eX = event.clientX;
        eY = event.clientY;
    } else {
        eX = e.pageX;
        eY = e.pageY;
    }
    // subtract offsets from left and top and don't go outside of map
    
    if (!refmapClick) {
        upX = Math.min(eX - offsX, mapW);
        upY = Math.min(eY - offsY, mapH);
    } else {
        upX = eX - offsX;
        upY = eY - offsY;
        //alert('offsX ' + offsX);
        //var pleft = $('refmap').parentNode;
        //alert (objL(pleft));
    }

    return false;
}


// For MouseMove
function getMoveXY(e) {
    if (document.all) {
        moveX = event.clientX;
        moveY = event.clientY;
    } else {
        moveX = e.pageX;
        moveY = e.pageY;
    }
    // subtract offsets from left and top
    /*moveX = Math.min(moveX - offsX, mapW);
    moveY = Math.min(moveY - offsY, mapH); */
    moveX = moveX - offsX;
    moveY = moveY - offsY;             
}


/*
 * BASIC MOUSE FUNCTIONS: DOWN, UP, MOVE
 ******************************************************/

function doMouseDown(e) {
    e = (e)?e:((event)?event:null);
    
    if (enableRightMousePan) {
        if (e.button == 2) {
            rightMouseButton = true;
            setCursor(true);
        } else {
            rightMouseButton = false;
        }
    }

    // ENABLES ACTIONS FOR KEYBOARD KEYS
    // comment out if not wanted
    if (document.all) document.onkeydown = kp;
    document.onkeypress = kp;
    
    mouseDrag = true;
    getDownXY(e);
    
    if (refmapClick) {
        if (downX < 1 || downY < 1 || downX > refW || downY > refH) {        // Don't go ouside of map
            return false;
        } else {
            moveRefBox('shift');
        }
    }

    return false;
}


function doMouseUp(e) {
    e = (e)?e:((event)?event:null);
    //alert (rightMouseButton);
    
    mouseDrag = false;
    getUpXY(e);

    var varform = $("varform");

    // Click in main map
    if (!refmapClick) {

        maction = varform.maction.value;

        if (rightMouseButton) {
            maction = 'pan';
        }
        
        if (maction == 'measure') {
            //alert(upX + ' - ' + upY);
            measureDrawSymbols(e, upX, upY, 0);

        } else if (maction == 'pan'){
            var diffX = upX - downX;
            var diffY = upY - downY;
            // pan with click
            if (diffX == 0 && diffY == 0) {
                var newX = upX;
                var newY = upY;
            // pan with drag
            } else {
                var newX = (mapW / 2) - diffX ;
                var newY = (mapH / 2) - diffY;
            }
            
            zoombox_apply(newX, newY, newX, newY);
            
            //Reset after right-mouse pan
            maction = varform.maction.value;
            rightMouseButton = false;
            setCursor(false);
        
        } else if (maction == 'click'){
            zoombox_apply(downX, downY, downX, downY);
                
        } else if (maction == 'move'){
            // do nothing
            return false;

        } else {
            zoombox_apply(Math.min(downX,upX), Math.min(downY,upY), Math.max(downX,upX), Math.max(downY,upY));
        }

    // Click in reference map
    } else {
        
        if (upX < 1 || upY < 1 || upX > refW || upY > refH) {   // Don't go ouside of map
            alert(upX + ' ref out');
            return false;
        } else {
            //alert(upX +', '+ upY +', '+ upX +', '+ upY);
            zoombox_apply(upX, upY, upX, upY);
        }
    }
    
    return false;    
}


function doMouseMove(e) {
    e = (e)?e:((event)?event:null);
    
    getMoveXY(e);
    /* * Draw a zoombox when mouse is pressed and zoom-in or select function are active
       * move map layer when pan function is active
       * do nothing for all others                                                      */

    // Actions in MAIN MAP
    if (!refmapClick) {
    	var varform = $("varform");
        if (varform) {
            maction = varform.maction.value;
        }
        
        if (rightMouseButton) {
            maction = 'pan';
        }

        
        // Display coordinates of current cursor position
        displayCoordinates();        
        	
        
        switch (maction) {
            //# zoom-in, select
            case 'box':
                if (mouseDrag == true) { 
                    startZoomBox(e, moveX, moveY);
                } else if (varform.mode.value == 'nquery') {
                    try {
                        if (combinedSelectIquery) {
                            clearTimeout(iquery_timer);
                            iquery_timer = setTimeout("applyIquery(" + moveX + "," + moveY + ")", 300);
                        }
                    } catch(e) {
                        return false;
                    }
                }
                break;
    
            //# zoom-out, identify
            case 'click':
                hideLayer('zoombox');
                break;
    
            //# pan with drag
            case 'pan':
                hideLayer('zoombox');
                startPan(e, moveX, moveY);
                break;
    
            //# measure
            case 'measure':
                showLayer('measureLayer');
                showLayer('measureLayerTmp');
                redrawAll(moveX , moveY);                
                break;
                
            //# move
            case 'move':
                if (varform.mode.value == 'iquery') {    //# iquery
                    clearTimeout(iquery_timer);
                    iquery_timer = setTimeout("applyIquery(" + moveX + "," + moveY + ")", 300);
                }
                break;
        }
        
    // Actions in REFERENCE MAP
    } else {
        hideLayer('zoombox');
        if (mouseDrag) {
            moveRefBox('move');
        }
    }
    
    return false;    
}


// For DOUBLE CLICK 
// currently only used for measure function: end measure, calculate polygon area
function doMouseDblClick(e) {
    getUpXY(e);
    var varform = $("varform");
    maction = varform.maction.value;
    if (maction == 'measure') {
        measureDrawSymbols(e, upX, upY, 1);
    }
}  




/*
 * FUNCTIONS FOR ZOOM BOX && PAN MOVING MAP
 ******************************************************/

// DRAG ZOOM BOX (ZOOM IN, SELECT)
function startZoomBox(e, moveX, moveY) {
    if (mouseDrag == true) {
        if (checkCursorPosition(moveX + offsX, moveY + offsY)) {
            showLayer('zoombox');
            var boxL = Math.min(moveX, downX);
            var boxT = Math.min(moveY, downY);
            var boxW = Math.abs(moveX - downX);
            var boxH = Math.abs(moveY - downY);

            var theZoomBox = $("zoombox");            
            theZoomBox.style.left   = boxL+"px";
            theZoomBox.style.top    = boxT+"px";
            theZoomBox.style.width  = boxW+"px";
            theZoomBox.style.height = boxH+"px";
        }
    }
    return false;
}

// PAN
function startPan(e, moveX, moveY) {
    if (mouseDrag == true) {
        
        if (checkCursorPosition(moveX + offsX, moveY + offsY)) {
            var mapL = moveX - downX;
            var mapT = moveY - downY;
    
            var theMapImg = $("mapimg");
            var theMapImgL = $("mapimgLayer");
            
            var clipT = 0;
            var clipR = mapW;
            var clipB = mapH;
            var clipL = 0;
            
            theMapImgL.style.top  = mapT+"px";
            theMapImgL.style.left = mapL+"px";
            
            if (mapT > 0) {
                clipB = mapH - parseInt(theMapImgL.style.top);
            } else {
                clipT = -1 * parseInt(theMapImgL.style.top);     
            }
            
            if (mapL > 0) {
                clipR = mapW - parseInt(theMapImgL.style.left);
            } else {
                clipL = -1 * parseInt(theMapImgL.style.left);
            }
            
    
            var clipRect = 'rect(' + clipT + 'px ' 
                                   + clipR + 'px '
                                   + clipB + 'px ' 
                                   + clipL + 'px)'; 
            //window.status = clipRect;
            theMapImgL.style.clip = clipRect;

        }
    }
    return false;
}


/*
 * FUNCTIONS FOR REFERENCE MAP RECTANGLE
 ******************************************************/
function setRefBox(boxL, boxT, boxW, boxH) {
    //showLayer('refbox');
		var mode = '';
		mode = $("varform");
		 //Bei der Suche müssen die JavaScript "Pfade" angepasst werden, da die Attributeaus einem Popup-Window aufgerufen werden
		 //Sonst wird die ReferenzKarte nicht aktualisiert
		if (mode==null) {
		var rBox   = opener.$("refbox");
    var sBox   = opener.$("sliderbox");
    var rCross = opener.$("refcross");
    
    if (rBox) {
        rBox.style.left   = boxL + "px";
        rBox.style.top    = boxT + "px";
        rBox.style.width  = boxW + "px"; //Math.max(4, boxW);
        rBox.style.height = boxH + "px"; //Math.max(4, boxH);
    }
    
    if (rCross) {
        if (boxW < rBoxMinW) {
            rBox.style.visibility = "hidden";
            rCross.style.visibility = "visible";
            setRefCross(rCross, boxL, boxT, boxW, boxH);
        } else {
            rCross.style.visibility = "hidden";
            rBox.style.visibility = "visible";
        }
    }
    
    if (sBox) {
        sBox.style.visibility = "hidden";
    }
		}
		else {
    var rBox   = $("refbox");
    var sBox   = $("sliderbox");
    var rCross = $("refcross");
    
    if (rBox) {
        rBox.style.left   = boxL + "px";
        rBox.style.top    = boxT + "px";
        rBox.style.width  = boxW + "px"; //Math.max(4, boxW);
        rBox.style.height = boxH + "px"; //Math.max(4, boxH);
    }
    
    if (rCross) {
        if (boxW < rBoxMinW) {
            rBox.style.visibility = "hidden";
            rCross.style.visibility = "visible";
            setRefCross(rCross, boxL, boxT, boxW, boxH);
        } else {
            rCross.style.visibility = "hidden";
            rBox.style.visibility = "visible";
        }
    }
    
    if (sBox) {
        sBox.style.visibility = "hidden";
    }
		}
}

// MOVE RECTANGLE WITH MOUSE PAN
function moveRefBox(moveAction) {
    var rBox   = $("refbox");
    var rCross = $("refcross");

    var boxL = objL(rBox);
    var boxT = objT(rBox);
    var boxW = objW(rBox);
    var boxH = objH(rBox);
    
    if (moveAction == 'shift') {
        var newX = downX; 
        var newY = downY;        
    } else {
        var newX = moveX; 
        var newY = moveY; 
    }
    
    boxLnew = newX - (boxW / 2) - 1; 
    boxTnew = newY - (boxH / 2) - 1;
    
    if (boxLnew < 0 || boxTnew < 0 || (boxLnew + boxW) > refW || (boxTnew + boxH) > refH) {
        return false;
    } else {
        rBox.style.left = boxLnew+"px";
        rBox.style.top  = boxTnew+"px";
        window.status = (boxLnew + boxW + ' - ' + refW);
        
        if (boxW < rBoxMinW) {
            setRefCross(rCross, boxLnew, boxTnew, boxW, boxH);
        }
    }
}


// Change position of reference cross
// => symbol used when refbox below threshold
function setRefCross(rCross, boxL, boxT, boxW, boxH) {	
    boxcX = parseInt(boxL) + parseInt((boxW / 2));
    boxcY = parseInt(boxT) + parseInt((boxH / 2));
    rCross.style.left = Math.round((boxcX - rOffs))+"px";
    rCross.style.top  = Math.round((boxcY - rOffs))+"px";    
}



// SET DIV LAYER VISIBLE - HIDDEN
function showLayer(elementID) {
    $(elementID).style.visibility = "visible";
}

function hideLayer(elementID) {
    $(elementID).style.visibility = "hidden";
}



/*******************************************************************
 * Resize map image while zooming with slider
 * called from sliderMove() in slider.js
 ********************************************/
function resizeMap(sizeFactor) {
    //alert(sizeFactor);
    var theMapImg = $('mapImg');
    var theMapLay = $('mapimgLayer');
    
    var oldW = mapW;
    var oldH = mapH;
    var newW = oldW * sizeFactor;
    var newH = oldH * sizeFactor;
    
    var newLeft = (oldW - newW) / 2;
    var newTop  = (oldH - newH) / 2;

    theMapImg.style.width  = newW+"px";
    theMapImg.style.height = newH+"px";
    theMapLay.style.left   = newLeft+"px"; 
    theMapLay.style.top    = newTop+"px";
    
    if (sizeFactor > 1) {
        var diffW = parseInt((newW - oldW) / 2);
        var diffH = parseInt((newH - oldH) / 2);
        clipT = diffH;
        clipR = diffW + oldW;
        clipB = diffH + oldH;
        clipL = diffW;

        var clipRect = 'rect(' + clipT + 'px ' 
                               + clipR + 'px '
                               + clipB + 'px ' 
                               + clipL + 'px)'; 
        //window.status = clipRect;
        theMapLay.style.clip = clipRect;
        
        theMapLay.style.width   = newW+"px";
        theMapLay.style.height  = newH+"px";
    } 
}


function resizeRefBox(sizeFactor) { 
    var refZoomBox = $('refbox');
    var refSliderBox = $('refsliderbox');
    
    if (refSliderBox) {
        refSliderBox.style.visibility = "visible";
    }
    
    if (refZoomBox) {
        var refBoxBorderW = 1;  // adapt to border width in CSS

        var oldRefW = parseInt(refZoomBox.style.width);
        var oldRefH = parseInt(refZoomBox.style.height);
        var oldRefLeft = parseInt(refZoomBox.style.left);
        var oldRefTop = parseInt(refZoomBox.style.top);
        
        var newRefW = Math.round(oldRefW / sizeFactor);
        var newRefH = Math.round(oldRefH / sizeFactor);
        
        var newRefLeft = parseInt(oldRefLeft + ((oldRefW - newRefW) / 2) + refBoxBorderW);
        var newRefTop  = parseInt(oldRefTop + ((oldRefH - newRefH) / 2) + refBoxBorderW);
        
        refSliderBox.style.left   = newRefLeft+"px";
        refSliderBox.style.top    = newRefTop+"px";
        refSliderBox.style.width  = newRefW+"px";
        refSliderBox.style.height = newRefH+"px";
    }
}



/*
 * KEYBOARD FUNCTIONS
 * original script taken from http://ka-map.maptools.org/
 ******************************************************************/
function kp(e) {
    e = (e)?e:((event)?event:null);
    if(e) {
        var charCode=(e.charCode)?e.charCode:e.keyCode;
        //alert(charCode);
        var b=true;
        var nStep = 16;
        switch(charCode){        
          case 63232://safari up arrow
          case 38://up arrow
            arrowpan('n');
            break;
          case 63233://safari down arrow
          case 40://down arrow
            arrowpan('s');
            break;
          case 63234://safari left arrow
          case 37:// left arrow
            arrowpan('w');
            break;
          case 63235://safari right arrow
          case 39://right arrow
            arrowpan('e');
            break;
          case 63276://safari pageup
          case 33://pageup
            gofwd();
            break;
          case 63277://safari pagedown
          case 34://pagedown
            goback();
            break;
          case 63273://safari home (left)
          case 36://home
            zoomfullext();
            break;
          case 63275://safari end (right)
          case 35://end
            slideBy(-viewportWidth/2,0);
            break;
          case 43:
            //if (!navigator.userAgent.match(/Opera|Konqueror/i))  
            zoompoint(2, '');
            break;
          case 45:
            zoompoint(-2, '');
            break;
          case 46://delete last point in editing mode
            delLastPoint();
          break;
          default:
            b=false;
        }
    }
}



/*
 * MOUSEWHEEL FUNCTIONS (zoom in/out)
 * only works with IE
 ******************************************************************/
function omw(e) {
    e = (e)?e:((event)?event:null);
    if(e) {
        var wD = e.wheelDelta ? e.wheelDelta : e.detail*-1;
        clearTimeout(resize_timer);
        if (wD < 0) {
            //zoompoint(2, '');
            resize_timer = setTimeout("zoompoint(2, '')",300);  
            return false;
        } else if (wD > 0) {
            //zoompoint(-2, '');
            resize_timer = setTimeout("zoompoint(-2, '')",300);  
            return false;
        }
    }
}



function disableContextMenu(e) {
    e = (e)?e:((event)?event:null);
    return false;
}




/* 
 * FUNCTIONS FOR COODINATE DIPLAY FUNCTIONS
 ***********************************************/
// GET MAP COORDINATES FOR MOUSE MOVE
function getCoords(mouseX, mouseY, convert2latlon) {
    var x_geo = minx_geo + ((mouseX/mapW) * xdelta_geo);
    var y_geo = maxy_geo - ((mouseY/mapH) * ydelta_geo);
    
    if (convert2latlon) {
        // Just for ETRS-LAEA projection: convert from LAEA to latlon coordinates
        var mpoint = laea2latlon(x_geo, y_geo);
    
    } else {
        // Display mouse position in MAP coordinates 
        var mpoint = new Object();
        mpoint.x = x_geo;
        mpoint.y = y_geo;
    }
    
    return  mpoint;
}




// DISPLAY MAP COORDINATES FOR MOUSE MOVE
function displayCoordinates() {
    var mode = '';
		mode = $("varform");
		var x_geo = minx_geo + ((moveX/mapW) * xdelta_geo);
    var mpoint = getCoords(moveX, moveY, false);
    //var mpoint = getCoords(moveX, moveY, true);
    
    // Round values (function 'roundN()' in 'measure.js')
    var rfactor = 0;
    var px = isNaN(mpoint.x) ? '' : roundN(mpoint.x, rfactor);
    var py = isNaN(mpoint.y) ? '' : roundN(mpoint.y, rfactor);
    
    // Display in status bar
    /*
    var mapCoords = 'X: ' + px + '  Y: ' + py;
    window.status = mapCoords;
    */
    // Display in DIV over MAP 
    $('xcoord').innerHTML = 'X: ' + px; // + ' &deg;';
    $('ycoord').innerHTML = 'Y: ' + py; // + ' &deg;';
}



// Convert XY coordinates from ETRS-LAEA to lat/lon
function laea2latlon(X, Y) {
    var a   = 6378137;
    var f   = 1 / 298.257222101;
    var e2  = (2*f) - (f*f);
    var e   = Math.sqrt(e2);
    var ph0 = 52 / 180 * Math.PI ;
    var la0 = 10 / 180 * Math.PI;
    var X0  = 4321000.0;
    var Y0  = 3210000.0;
    
    
    var q0 = (1-e2) *  ((Math.sin(ph0) / (1 - (e2 * Math.pow(Math.sin(ph0), 2)))) - ((1/(2*e)) * Math.log((1 - (e * Math.sin(ph0))) / (1 + (e * Math.sin(ph0))))));    
    
    var qp = (1-e2) *  ( (1 / (1-e2)) - ((1/(2*e)) * Math.log((1-e)/(1+e)) ) ) ;
    
    var beta0 = Math.asin(q0/qp);
    
    var Rq = a * Math.sqrt(qp/2);
    
    var D  =  (a * Math.cos(ph0)) / (Math.sqrt(1 - (e2 * Math.pow(Math.sin(ph0), 2))) * (Rq * Math.cos(beta0))  );
    
    var p = Math.sqrt(Math.pow((X-X0)/D, 2) + Math.pow(D * (Y-Y0), 2));
    
    var C = 2 * Math.asin(p / (2*Rq));
    
    var beta_ = Math.asin((Math.cos(C) * Math.sin(beta0))  +  (((D * (Y-Y0)) * Math.sin(C) * Math.cos(beta0)) / p));
    
    
    // Latitude
    var lat1 = ((e2/3) + ((31*Math.pow(e2, 2)) / 180) + ((517*Math.pow(e2, 3)) / 5040)) * Math.sin(2*beta_);
    var lat2 = (((23*Math.pow(e2, 2)) / 360) + ((251*Math.pow(e2, 3)) / 3780)) * Math.sin(4*beta_);
    var lat3 = ((761*Math.pow(e2, 3)) / 45360) * Math.sin(6*beta_);
    var lat = (beta_ + lat1 + lat2 + lat3) * (180/Math.PI);
    
    
    //Longitude
    var lon = (la0 + Math.atan( ((X-X0) * Math.sin(C)) / ((D * p * Math.cos(beta0) * Math.cos(C)) - (D*D * (Y-Y0) * Math.sin(beta0) * Math.sin(C))))) * (180/Math.PI);  
    
    
    // Return Point
    var mpoint = new Object();
    mpoint.x = lon;
    mpoint.y = lat;
    
    return mpoint;
}


