; var N = (document.all) ? 0 : 1; var system = new Object(); system.mini = new Object(); system.mini_view = new Object(); system.view = new Object(); system.layersList = new Object(); system.searcher = new Object(); system.balloon = new Object(); system.layoutComponents = new Object(); system.init = function() { if (system.configOK == 0) { document.getElementById("loading_info").style.visibility = "hidden"; alert("Error:" + system.configErrorString); } else { document.getElementById("loading_info").style.visibility = "hidden"; system.body.loadingBoxShow(); if (system.numberOfMaps > 0) { if (system.srs != "") system.proj = new Proj4js.Proj(system.srs); system.mode = "move"; // jesli true przy kazdym generowaniu widoku ustawia wszystkie elementy na empty system.view.clearAllELements = true; system.layer_table = new Array(); // true/false - aktywna warstwa moze/nie moze byc w trybie identyfikacji system.mode_info = false; // true/false - aktywna warstwa moze/nie moze byc w trybie linkow www system.mode_wwwLinks = false; system.body.get_size(); // przypisanie zdarzen do layout'u if (window.opera) window.onscroll = function(){window.scrollTo(0, 0)}; window.oncontextmenu = emptyfunction; if (document.getElementById("elementsLayerContainer").addEventListener) document.getElementById("elementsLayerContainer").addEventListener('DOMMouseScroll', system.elementsLayer.wheel, false); document.getElementById("elementsLayerContainer").onmousewheel = system.elementsLayer.wheel; window.onresize = function() { // system.scale.set(system.map_id); system.view.set_parms(system.map_id); system.layersList.setPanelSize(); system.mini_view.recalculate_size(system.map_id); system.elementsLayer.initMap(); system.view.show(system.map_id); }; YAHOO.util.Event.addListener("miniContainer", "click", system.mini_view.MC); YAHOO.util.Event.addListener("main_body", "mouseout", system.body.mouse_out); document.getElementById('mini_view').onmouseover = function() {system.mini_view.mouseOver = true}; document.getElementById('mini_view').onmouseout = function() {system.mini_view.mouseOver = false}; system.mini_view.DD = new YAHOO.util.DD("mini_view", "", {scroll: false}); system.mini_view.DD.on("endDragEvent", system.mini_view.MU); YAHOO.util.Event.addListener("elementsLayerContainer", "dblclick", system.elementsLayer.mouseDblClick); YAHOO.util.Event.addListener("elementsLayerContainer", "click", system.elementsLayer.mouseClick); YAHOO.util.Event.addListener("elementsLayerContainer", "mousedown", system.elementsLayer.mouseDown); YAHOO.util.Event.addListener("elementsLayerContainer", "mousemove", system.elementsLayer.mouseMove); YAHOO.util.Event.addListener("elementsLayerContainer", "mouseup", system.elementsLayer.mouseUp); YAHOO.util.Event.addListener("elementsLayerContainer", "touchstart", system.elementsLayer.mouseDown); YAHOO.util.Event.addListener("elementsLayerContainer", "touchmove", system.elementsLayer.mouseMove); YAHOO.util.Event.addListener("elementsLayerContainer", "touchend", system.elementsLayer.mouseUp); // document.getElementById("elementsLayerContainer").addEventListener('mousedown', system.elementsLayer.mouseDown, false); // document.getElementById("elementsLayerContainer").addEventListener('mousemove', system.elementsLayer.mouseMove, false); // document.getElementById("elementsLayerContainer").addEventListener('mouseup', system.elementsLayer.mouseUp, false); // document.getElementById("elementsLayerContainer").addEventListener('touchstart', system.elementsLayer.mouseDown, false); // document.getElementById("elementsLayerContainer").addEventListener('touchmove', system.elementsLayer.mouseMove, false); // document.getElementById("elementsLayerContainer").addEventListener('touchend', system.elementsLayer.mouseUp, false); YAHOO.util.Event.addListener("elementsLayerContainer", "mouseout", function (){system.elementsLayer.mouseout = true}); document.getElementById("skala_select").onchange = system.scale.onchange; document.getElementById("layers_list_button").onclick = function() {system.layersList.visibility_switch(true)}; document.getElementById("link_caption").onclick = function() {document.getElementById('link_caption').select()}; document.getElementById("link_button").onclick = function() { window.oncontextmenu = emptyfunction; document.getElementById('link_layer').style.visibility = 'hidden'; systemMODE(system.prev_mode); }; document.getElementById("button_mini").onclick = system.mini_view.switch_visibility; document.getElementById("object_button").onclick = system.identification.object_info_switch_visibility; document.getElementById("bt_move").onclick = function() {systemMODE('move')}; document.getElementById("bt_move").onmouseover = function() {buttonCHANGE('move', 'on')}; document.getElementById("bt_move").onmouseout = function() {buttonCHANGE('move', 'off')}; document.getElementById("bt_onepoint_distance").onclick = function() {systemMODE('onepoint_distance')}; document.getElementById("bt_onepoint_distance").onmouseover = function() {buttonCHANGE('onepoint_distance', 'on')}; document.getElementById("bt_onepoint_distance").onmouseout = function() {buttonCHANGE('onepoint_distance', 'off')}; document.getElementById("bt_multipoint_distance").onclick = function() {systemMODE('multipoint_distance')}; document.getElementById("bt_multipoint_distance").onmouseover = function() {buttonCHANGE('multipoint_distance', 'on')}; document.getElementById("bt_multipoint_distance").onmouseout = function() {buttonCHANGE('multipoint_distance', 'off')}; document.getElementById("bt_area").onclick = function() {systemMODE('area')}; document.getElementById("bt_area").onmouseover = function() {buttonCHANGE('area', 'on')}; document.getElementById("bt_area").onmouseout = function() {buttonCHANGE('area', 'off')}; document.getElementById("bt_info").onclick = function() {if (system.mode_info) systemMODE('info')}; document.getElementById("bt_info").onmouseover = function() {if (system.mode_info) buttonCHANGE('info', 'on')}; document.getElementById("bt_info").onmouseout = function() {if (system.mode_info) buttonCHANGE('info', 'off')}; document.getElementById("bt_www_links").onclick = function() {if (system.mode_wwwLinks) systemMODE('www_links')}; document.getElementById("bt_www_links").onmouseover = function() {if (system.mode_wwwLinks) buttonCHANGE('www_links', 'on')}; document.getElementById("bt_www_links").onmouseout = function() {if (system.mode_wwwLinks) buttonCHANGE('www_links', 'off')}; document.getElementById("bt_link").onclick = function() {systemMODE('link', true)}; document.getElementById("bt_link").onmouseover = function() {buttonCHANGE('link', 'on')}; document.getElementById("bt_link").onmouseout = function() {buttonCHANGE('link', 'off')}; document.getElementById("bt_zoom_plus").onmouseover = function() {buttonCHANGE('zoom_plus', 'on')}; document.getElementById("bt_zoom_plus").onmouseout = function() {buttonCHANGE('zoom_plus', 'off')}; document.getElementById("bt_zoom_plus").onclick = function() {system.scale.zoom('plus')}; document.getElementById("bt_zoom_minus").onmouseover = function() {buttonCHANGE('zoom_minus', 'on')}; document.getElementById("bt_zoom_minus").onmouseout = function() {buttonCHANGE('zoom_minus', 'off')}; document.getElementById("bt_zoom_minus").onclick = function() {system.scale.zoom('minus')}; document.getElementById("bt_enable_layers").onclick = function() { system.layersList.allonoff(1); system.view.show(system.map_id); system.body.loadingBoxHide(); system.history.addView(); }; document.getElementById("bt_enable_layers").onmouseover = function() {buttonCHANGE('enable_layers', 'on')}; document.getElementById("bt_enable_layers").onmouseout = function() {buttonCHANGE('enable_layers', 'off')}; document.getElementById("bt_disable_layers").onclick = function() { system.layersList.allonoff(0); system.view.show(system.map_id); system.body.loadingBoxHide(); system.history.addView(); }; document.getElementById("bt_disable_layers").onmouseover = function() {buttonCHANGE('disable_layers', 'on')}; document.getElementById("bt_disable_layers").onmouseout = function() {buttonCHANGE('disable_layers', 'off')}; document.getElementById("bt_help").onclick = function() {systemMODE('help')}; document.getElementById("bt_help").onmouseover = function() {buttonCHANGE('help', 'on')}; document.getElementById("bt_help").onmouseout = function() {buttonCHANGE('help', 'off')}; document.getElementById("bt_legend").onmouseover = function() {buttonCHANGE('legend', 'on')}; document.getElementById("bt_legend").onmouseout = function() {buttonCHANGE('legend', 'off')}; document.getElementById("bt_legend").onmouseover = function() {buttonCHANGE('legend', 'on')}; document.getElementById("bt_legend").onmouseout = function() {buttonCHANGE('legend', 'off')}; document.getElementById("bt_prev_history").onmouseover = function() {buttonCHANGE('prev_history', 'on')}; document.getElementById("bt_prev_history").onmouseout = function() {buttonCHANGE('prev_history', 'off')}; document.getElementById("bt_next_history").onmouseover = function() {buttonCHANGE('next_history', 'on')}; document.getElementById("bt_next_history").onmouseout = function() {buttonCHANGE('next_history', 'off')}; document.getElementById("bt_prev_history").onclick = system.history.prevView; document.getElementById("bt_next_history").onclick = system.history.nextView; document.getElementById("bt_restart_map").onmouseover = function() {buttonCHANGE('restart_map', 'on')}; document.getElementById("bt_restart_map").onmouseout = function() {buttonCHANGE('restart_map', 'off')}; document.getElementById("bt_restart_map").onclick = function() {document.location.href = system.linkUrl}; if (system.printing.enabled == true) { document.getElementById("bt_print").onclick = function() { window.open ( 'controller.php?project_id=' + system.project_id + '&id=' + system.map_id + "," + system.layersList.actual_state_array + "," + system.view.middleRealPosX + "," + system.view.middleRealPosY + "&page_id=1002", '_blank' ) }; document.getElementById("bt_print").onmouseover = function() {buttonCHANGE('print', 'on')}; document.getElementById("bt_print").onmouseover = function() {buttonCHANGE('print', 'off')}; document.getElementById("bt_print").onmouseout = function() {buttonCHANGE('print', 'off')}; } else { document.getElementById("bt_print").style.display = 'none'; } document.getElementById("main_body").onselectstart = function() {return false}; document.getElementById("description_caption").innerHTML = str_replace('\n', '
', system.view.description); for (var mapId in system.maps) { if (mapId == 'remove' || mapId == 'indexOf') {continue;} document.getElementById("skala_select").options[mapId] = new Option(system.maps[mapId].name, mapId); } document.getElementById("skala_select").options[system.map_id ].selected = true; document.getElementById("docBody").style.background = system.bgcolor; document.getElementById("main_body").style.background = system.bgcolor; document.getElementById("elementsLayer").style.background = system.bgcolor; document.getElementById("elementsLayer2").style.background = system.bgcolor; document.getElementById("elementsLayerContainer").style.background = system.bgcolor; system.searcher.initSelection(); system.mini_view.recalculate_size(system.map_id); system.view.allow_map_change = true; system.mini_view.set_visibility(); system.identification.object_info_set_visibility(); systemMODE(system.mode); system.ruler.show(); // jesli jest wiecej skal niz 1 utworz slider if ((system.numberOfMaps - 1) > 0) { scaleSlider = new Slider (document.getElementById("scale_slider"), document.getElementById("scale_slider_input"), "vertical"); scaleSlider.setMinimum(0); scaleSlider.setMaximum(system.numberOfMaps - 1); scaleSlider.setValue(system.map_id); scaleSlider.onmouseup = function() { document.getElementById('skala_select').value = scaleSlider.getValue(); system.scale.onchange(); }; scaleSlider.onchange = function(){document.getElementById('skala_select').value = scaleSlider.getValue()}; document.getElementById('scale_area').style.visibility = "visible"; } else { document.getElementById('scale_area').style.visibility = "hidden"; } // przesuwa widok na srodek system.view.move(1,1); system.searcher.urlSearch(); system.scale.set(system.map_id); system.layersList.visibility_switch(false); document.getElementById(system.layersList.div).onmouseout = function() {system.layersList.mouseOverLayerId = -1;}; document.getElementById("buttons_layer").style.visibility = "visible"; document.getElementById("ruler").style.visibility = "visible"; document.getElementById("description").style.visibility = "visible"; document.getElementById("layers_list_button").style.visibility = "visible"; document.getElementById("button_mini").style.visibility = "visible"; document.getElementById("viewHistory").style.visibility = "visible"; system.helpPanel = new YAHOO.widget.Panel ("helpPanel", { width: system.body.width * 0.9, height: system.body.height * 0.9, draggable: false, // modal: true, dragOnly : true, fixedcenter: true, constraintoviewport: true, underlay: "shadow", close: true, visible: false, zIndex: 250 } ); system.helpPanel.setBody('
'); system.helpPanel.render(); system.wwwPanel = new YAHOO.widget.Panel ("wwwPanel", { width: system.body.width * 0.9, height: system.body.height * 0.9, draggable: false, modal: false, dragOnly : true, fixedcenter: true, constraintoviewport: true, underlay: "shadow", close: true, visible: false, zIndex: 250 } ); system.wwwPanel.hideEvent.subscribe(function(){document.getElementById("wwwIframe").src = "empty.html";}, 1); system.wwwPanel.render(); system.balloon.imagesPath = system.layoutPath + 'images/balloons'; system.balloon.preloadBallonImages(); if (system.startPanel.url != "") { system.startPanel.panel = new YAHOO.widget.Panel ("startPanel", { width: system.body.width * system.startPanel.width, height: system.body.height * system.startPanel.height, draggable: false, modal: false, dragOnly : true, fixedcenter: true, constraintoviewport: true, underlay: "shadow", close: true, visible: false, zIndex: 250 } ); system.startPanel.panel.render(); var htmlBody = ''; var iframeHeight = system.body.height * (system.startPanel.height) - 70; var iframeWidth = system.body.width * (system.startPanel.width) - 60; htmlBody+= '
'; htmlBody+= ''; htmlBody+= '
'; system.startPanel.panel.setBody(htmlBody); system.startPanel.panel.show(); if (system.startPanel.closeTime > 0) setTimeout("system.startPanel.panel.destroy()", system.startPanel.closeTime * 1000); } // dodaj strzlke polnocy if (system.northArrowVisibility == true) { var northArrowDiv = document.createElement('div'); var northArrowImage = new Image(41, 142); northArrowImage.src = "images/north_arrow.png"; northArrowDiv.setAttribute("id", 'northArrow'); northArrowDiv.appendChild(northArrowImage); northArrowDiv.style.position = "absolute"; northArrowDiv.style.left = 25; northArrowDiv.style.top = ""; northArrowDiv.style.right = ""; northArrowDiv.style.bottom = system.mini.height + 50; northArrowDiv.style.zIndex = 35; document.getElementById('main_body').appendChild(northArrowDiv); } if (system.maps[system.map_id].layersSwitcher && system.incomingLayers == false) { system.layersList.setLayersTheme(0, true, true); } system.history.init(); system.history.addView(); } else { system.body.loadingBoxHide(); alert('Projekt nie zawiera map lub brak prawa zapisu do podkatalogu projektu np. \\projects\\nazwa_projektu\\'); } } }; system.gotoProject = function (projectId) { document.location.href = "index.php?project_id=" + projectId + "&map_id=" + system.map_id + "&x=" + system.view.middleRealPosX + "&y=" + system.view.middleRealPosY; };/* Author: Mike Adair madairATdmsolutions.ca Richard Greenwood rich@greenwoodmap.com License: LGPL as per: http://www.gnu.org/copyleft/lesser.html $Id: Proj.js 2956 2007-07-09 12:17:52Z steven $ */ /** * Namespace: Proj4js * * Proj4js is a JavaScript library to transform point coordinates from one * coordinate system to another, including datum transformations. * * This library is a port of both the Proj.4 and GCTCP C libraries to JavaScript. * Enabling these transformations in the browser allows geographic data stored * in different projections to be combined in browser-based web mapping * applications. * * Proj4js must have access to coordinate system initialization strings (which * are the same as for PROJ.4 command line). Thes can be included in your * application using a def is a CS definition in PROJ.4 WKT format, for example: +proj="tmerc" //longlat, etc. +a=majorRadius +b=minorRadius +lat0=somenumber +long=somenumber */ Proj4js.defs = { // These are so widely used, we'll go ahead and throw them in // without requiring a separate .js file 'WGS84': "+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees", 'EPSG:4326': "+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees", 'EPSG:4269': "+title=long/lat:NAD83 +proj=longlat +a=6378137.0 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees" }; //+a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84", Proj4js.common = { PI : 3.141592653589793238, //Math.PI, HALF_PI : 1.570796326794896619, //Math.PI*0.5, TWO_PI : 6.283185307179586477, //Math.PI*2, FORTPI : 0.78539816339744833, R2D : 57.29577951308232088, D2R : 0.01745329251994329577, SEC_TO_RAD : 4.84813681109535993589914102357e-6, /* SEC_TO_RAD = Pi/180/3600 */ EPSLN : 1.0e-10, MAX_ITER : 20, // following constants from geocent.c COS_67P5 : 0.38268343236508977, /* cosine of 67.5 degrees */ AD_C : 1.0026000, /* Toms region 1 constant */ /* datum_type values */ PJD_UNKNOWN : 0, PJD_3PARAM : 1, PJD_7PARAM : 2, PJD_GRIDSHIFT: 3, PJD_WGS84 : 4, // WGS84 or equivalent PJD_NODATUM : 5, // WGS84 or equivalent SRS_WGS84_SEMIMAJOR : 6378137.0, // only used in grid shift transforms // ellipoid pj_set_ell.c SIXTH : .1666666666666666667, /* 1/6 */ RA4 : .04722222222222222222, /* 17/360 */ RA6 : .02215608465608465608, /* 67/3024 */ RV4 : .06944444444444444444, /* 5/72 */ RV6 : .04243827160493827160, /* 55/1296 */ // Function to compute the constant small m which is the radius of // a parallel of latitude, phi, divided by the semimajor axis. // ----------------------------------------------------------------- msfnz : function(eccent, sinphi, cosphi) { var con = eccent * sinphi; return cosphi/(Math.sqrt(1.0 - con * con)); }, // Function to compute the constant small t for use in the forward // computations in the Lambert Conformal Conic and the Polar // Stereographic projections. // ----------------------------------------------------------------- tsfnz : function(eccent, phi, sinphi) { var con = eccent * sinphi; var com = .5 * eccent; con = Math.pow(((1.0 - con) / (1.0 + con)), com); return (Math.tan(.5 * (this.HALF_PI - phi))/con); }, // Function to compute the latitude angle, phi2, for the inverse of the // Lambert Conformal Conic and Polar Stereographic projections. // ---------------------------------------------------------------- phi2z : function(eccent, ts) { var eccnth = .5 * eccent; var con, dphi; var phi = this.HALF_PI - 2 * Math.atan(ts); for (i = 0; i <= 15; i++) { con = eccent * Math.sin(phi); dphi = this.HALF_PI - 2 * Math.atan(ts *(Math.pow(((1.0 - con)/(1.0 + con)),eccnth))) - phi; phi += dphi; if (Math.abs(dphi) <= .0000000001) return phi; } alert("phi2z has NoConvergence"); return (-9999); }, /* Function to compute constant small q which is the radius of a parallel of latitude, phi, divided by the semimajor axis. ------------------------------------------------------------*/ qsfnz : function(eccent,sinphi,cosphi) { var con; if (eccent > 1.0e-7) { con = eccent * sinphi; return (( 1.0- eccent * eccent) * (sinphi /(1.0 - con * con) - (.5/eccent)*Math.log((1.0 - con)/(1.0 + con)))); } else { return(2.0 * sinphi); } }, /* Function to eliminate roundoff errors in asin ----------------------------------------------*/ asinz : function(x) { if (Math.abs(x)>1.0) { x=(x>1.0)?1.0:-1.0; } return Math.asin(x); }, // following functions from gctpc cproj.c for transverse mercator projections e0fn : function(x) {return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));}, e1fn : function(x) {return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));}, e2fn : function(x) {return(0.05859375*x*x*(1.0+0.75*x));}, e3fn : function(x) {return(x*x*x*(35.0/3072.0));}, mlfn : function(e0,e1,e2,e3,phi) {return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));}, srat : function(esinp, exp) { return(Math.pow((1.0-esinp)/(1.0+esinp), exp)); }, // Function to return the sign of an argument sign : function(x) { if (x < 0.0) return(-1); else return(1);}, // Function to adjust longitude to -180 to 180; input in radians adjust_lon : function(x) { x = (Math.abs(x) < this.PI) ? x: (x - (this.sign(x)*this.TWO_PI) ); return x; }, // IGNF - DGR : algorithms used by IGN France // Function to adjust latitude to -90 to 90; input in radians adjust_lat : function(x) { x= (Math.abs(x) < this.HALF_PI) ? x: (x - (this.sign(x)*this.PI) ); return x; }, // Latitude Isometrique - close to tsfnz ... latiso : function(eccent, phi, sinphi) { if (Math.abs(phi) > this.HALF_PI) return +Number.NaN; if (phi==this.HALF_PI) return Number.POSITIVE_INFINITY; if (phi==-1.0*this.HALF_PI) return -1.0*Number.POSITIVE_INFINITY; var con= eccent*sinphi; return Math.log(Math.tan((this.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0; }, fL : function(x,L) { return 2.0*Math.atan(x*Math.exp(L)) - this.HALF_PI; }, // Inverse Latitude Isometrique - close to ph2z invlatiso : function(eccent, ts) { var phi= this.fL(1.0,ts); var Iphi= 0.0; var con= 0.0; do { Iphi= phi; con= eccent*Math.sin(Iphi); phi= this.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts) } while (Math.abs(phi-Iphi)>1.0e-12); return phi; }, // Needed for Gauss Laborde // Original: Denis Makarov (info@binarythings.com) // Web Site: http://www.binarythings.com sinh : function(x) { var r= Math.exp(x); r= (r-1.0/r)/2.0; return r; }, cosh : function(x) { var r= Math.exp(x); r= (r+1.0/r)/2.0; return r; }, tanh : function(x) { var r= Math.exp(x); r= (r-1.0/r)/(r+1.0/r); return r; }, asinh : function(x) { var s= (x>= 0? 1.0:-1.0); return s*(Math.log( Math.abs(x) + Math.sqrt(x*x+1.0) )); }, acosh : function(x) { return 2.0*Math.log(Math.sqrt((x+1.0)/2.0) + Math.sqrt((x-1.0)/2.0)); }, atanh : function(x) { return Math.log((x-1.0)/(x+1.0))/2.0; }, // Grande Normale gN : function(a,e,sinphi) { var temp= e*sinphi; return a/Math.sqrt(1.0 - temp*temp); } }; /** datum object */ Proj4js.datum = Proj4js.Class({ initialize : function(proj) { this.datum_type = Proj4js.common.PJD_WGS84; //default setting if (proj.datumCode && proj.datumCode == 'none') { this.datum_type = Proj4js.common.PJD_NODATUM; } if (proj && proj.datum_params) { for (var i=0; i 3) { if (proj.datum_params[3] != 0 || proj.datum_params[4] != 0 || proj.datum_params[5] != 0 || proj.datum_params[6] != 0 ) { this.datum_type = Proj4js.common.PJD_7PARAM; proj.datum_params[3] *= Proj4js.common.SEC_TO_RAD; proj.datum_params[4] *= Proj4js.common.SEC_TO_RAD; proj.datum_params[5] *= Proj4js.common.SEC_TO_RAD; proj.datum_params[6] = (proj.datum_params[6]/1000000.0) + 1.0; } } } if (proj) { this.a = proj.a; //datum object also uses these values this.b = proj.b; this.es = proj.es; this.ep2 = proj.ep2; this.datum_params = proj.datum_params; } }, /****************************************************************/ // cs_compare_datums() // Returns 1 (TRUE) if the two datums match, otherwise 0 (FALSE). compare_datums : function( dest ) { if( this.datum_type != dest.datum_type ) { return false; // false, datums are not equal } else if( this.a != dest.a || Math.abs(this.es-dest.es) > 0.000000000050 ) { // the tolerence for es is to ensure that GRS80 and WGS84 // are considered identical return false; } else if( this.datum_type == Proj4js.common.PJD_3PARAM ) { return (this.datum_params[0] == dest.datum_params[0] && this.datum_params[1] == dest.datum_params[1] && this.datum_params[2] == dest.datum_params[2]); } else if( this.datum_type == Proj4js.common.PJD_7PARAM ) { return (this.datum_params[0] == dest.datum_params[0] && this.datum_params[1] == dest.datum_params[1] && this.datum_params[2] == dest.datum_params[2] && this.datum_params[3] == dest.datum_params[3] && this.datum_params[4] == dest.datum_params[4] && this.datum_params[5] == dest.datum_params[5] && this.datum_params[6] == dest.datum_params[6]); } else if( this.datum_type == Proj4js.common.PJD_GRIDSHIFT ) { return strcmp( pj_param(this.params,"snadgrids").s, pj_param(dest.params,"snadgrids").s ) == 0; } else { return true; // datums are equal } }, // cs_compare_datums() /* * The function Convert_Geodetic_To_Geocentric converts geodetic coordinates * (latitude, longitude, and height) to geocentric coordinates (X, Y, Z), * according to the current ellipsoid parameters. * * Latitude : Geodetic latitude in radians (input) * Longitude : Geodetic longitude in radians (input) * Height : Geodetic height, in meters (input) * X : Calculated Geocentric X coordinate, in meters (output) * Y : Calculated Geocentric Y coordinate, in meters (output) * Z : Calculated Geocentric Z coordinate, in meters (output) * */ geodetic_to_geocentric : function(p) { var Longitude = p.x; var Latitude = p.y; var Height = p.z ? p.z : 0; //Z value not always supplied var X; // output var Y; var Z; var Error_Code=0; // GEOCENT_NO_ERROR; var Rn; /* Earth radius at location */ var Sin_Lat; /* Math.sin(Latitude) */ var Sin2_Lat; /* Square of Math.sin(Latitude) */ var Cos_Lat; /* Math.cos(Latitude) */ /* ** Don't blow up if Latitude is just a little out of the value ** range as it may just be a rounding issue. Also removed longitude ** test, it should be wrapped by Math.cos() and Math.sin(). NFW for PROJ.4, Sep/2001. */ if( Latitude < -Proj4js.common.HALF_PI && Latitude > -1.001 * Proj4js.common.HALF_PI ) { Latitude = -Proj4js.common.HALF_PI; } else if( Latitude > Proj4js.common.HALF_PI && Latitude < 1.001 * Proj4js.common.HALF_PI ) { Latitude = Proj4js.common.HALF_PI; } else if ((Latitude < -Proj4js.common.HALF_PI) || (Latitude > Proj4js.common.HALF_PI)) { /* Latitude out of range */ Proj4js.reportError('geocent:lat out of range:'+Latitude); return null; } if (Longitude > Proj4js.common.PI) Longitude -= (2*Proj4js.common.PI); Sin_Lat = Math.sin(Latitude); Cos_Lat = Math.cos(Latitude); Sin2_Lat = Sin_Lat * Sin_Lat; Rn = this.a / (Math.sqrt(1.0e0 - this.es * Sin2_Lat)); X = (Rn + Height) * Cos_Lat * Math.cos(Longitude); Y = (Rn + Height) * Cos_Lat * Math.sin(Longitude); Z = ((Rn * (1 - this.es)) + Height) * Sin_Lat; p.x = X; p.y = Y; p.z = Z; return Error_Code; }, // cs_geodetic_to_geocentric() geocentric_to_geodetic : function (p) { /* local defintions and variables */ /* end-criterium of loop, accuracy of sin(Latitude) */ var genau = 1.E-12; var genau2 = (genau*genau); var maxiter = 30; var P; /* distance between semi-minor axis and location */ var RR; /* distance between center and location */ var CT; /* sin of geocentric latitude */ var ST; /* cos of geocentric latitude */ var RX; var RK; var RN; /* Earth radius at location */ var CPHI0; /* cos of start or old geodetic latitude in iterations */ var SPHI0; /* sin of start or old geodetic latitude in iterations */ var CPHI; /* cos of searched geodetic latitude */ var SPHI; /* sin of searched geodetic latitude */ var SDPHI; /* end-criterium: addition-theorem of sin(Latitude(iter)-Latitude(iter-1)) */ var At_Pole; /* indicates location is in polar region */ var iter; /* # of continous iteration, max. 30 is always enough (s.a.) */ var X = p.x; var Y = p.y; var Z = p.z ? p.z : 0.0; //Z value not always supplied var Longitude; var Latitude; var Height; At_Pole = false; P = Math.sqrt(X*X+Y*Y); RR = Math.sqrt(X*X+Y*Y+Z*Z); /* special cases for latitude and longitude */ if (P/this.a < genau) { /* special case, if P=0. (X=0., Y=0.) */ At_Pole = true; Longitude = 0.0; /* if (X,Y,Z)=(0.,0.,0.) then Height becomes semi-minor axis * of ellipsoid (=center of mass), Latitude becomes PI/2 */ if (RR/this.a < genau) { Latitude = Proj4js.common.HALF_PI; Height = -this.b; return; } } else { /* ellipsoidal (geodetic) longitude * interval: -PI < Longitude <= +PI */ Longitude=Math.atan2(Y,X); } /* -------------------------------------------------------------- * Following iterative algorithm was developped by * "Institut für Erdmessung", University of Hannover, July 1988. * Internet: www.ife.uni-hannover.de * Iterative computation of CPHI,SPHI and Height. * Iteration of CPHI and SPHI to 10**-12 radian resp. * 2*10**-7 arcsec. * -------------------------------------------------------------- */ CT = Z/RR; ST = P/RR; RX = 1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST); CPHI0 = ST*(1.0-this.es)*RX; SPHI0 = CT*RX; iter = 0; /* loop to find sin(Latitude) resp. Latitude * until |sin(Latitude(iter)-Latitude(iter-1))| < genau */ do { iter++; RN = this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0); /* ellipsoidal (geodetic) height */ Height = P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0); RK = this.es*RN/(RN+Height); RX = 1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST); CPHI = ST*(1.0-RK)*RX; SPHI = CT*RX; SDPHI = SPHI*CPHI0-CPHI*SPHI0; CPHI0 = CPHI; SPHI0 = SPHI; } while (SDPHI*SDPHI > genau2 && iter < maxiter); /* ellipsoidal (geodetic) latitude */ Latitude=Math.atan(SPHI/Math.abs(CPHI)); p.x = Longitude; p.y = Latitude; p.z = Height; return p; }, // cs_geocentric_to_geodetic() /** Convert_Geocentric_To_Geodetic * The method used here is derived from 'An Improved Algorithm for * Geocentric to Geodetic Coordinate Conversion', by Ralph Toms, Feb 1996 */ geocentric_to_geodetic_noniter : function (p) { var X = p.x; var Y = p.y; var Z = p.z ? p.z : 0; //Z value not always supplied var Longitude; var Latitude; var Height; var W; /* distance from Z axis */ var W2; /* square of distance from Z axis */ var T0; /* initial estimate of vertical component */ var T1; /* corrected estimate of vertical component */ var S0; /* initial estimate of horizontal component */ var S1; /* corrected estimate of horizontal component */ var Sin_B0; /* Math.sin(B0), B0 is estimate of Bowring aux variable */ var Sin3_B0; /* cube of Math.sin(B0) */ var Cos_B0; /* Math.cos(B0) */ var Sin_p1; /* Math.sin(phi1), phi1 is estimated latitude */ var Cos_p1; /* Math.cos(phi1) */ var Rn; /* Earth radius at location */ var Sum; /* numerator of Math.cos(phi1) */ var At_Pole; /* indicates location is in polar region */ X = parseFloat(X); // cast from string to float Y = parseFloat(Y); Z = parseFloat(Z); At_Pole = false; if (X != 0.0) { Longitude = Math.atan2(Y,X); } else { if (Y > 0) { Longitude = Proj4js.common.HALF_PI; } else if (Y < 0) { Longitude = -Proj4js.common.HALF_PI; } else { At_Pole = true; Longitude = 0.0; if (Z > 0.0) { /* north pole */ Latitude = Proj4js.common.HALF_PI; } else if (Z < 0.0) { /* south pole */ Latitude = -Proj4js.common.HALF_PI; } else { /* center of earth */ Latitude = Proj4js.common.HALF_PI; Height = -this.b; return; } } } W2 = X*X + Y*Y; W = Math.sqrt(W2); T0 = Z * Proj4js.common.AD_C; S0 = Math.sqrt(T0 * T0 + W2); Sin_B0 = T0 / S0; Cos_B0 = W / S0; Sin3_B0 = Sin_B0 * Sin_B0 * Sin_B0; T1 = Z + this.b * this.ep2 * Sin3_B0; Sum = W - this.a * this.es * Cos_B0 * Cos_B0 * Cos_B0; S1 = Math.sqrt(T1*T1 + Sum * Sum); Sin_p1 = T1 / S1; Cos_p1 = Sum / S1; Rn = this.a / Math.sqrt(1.0 - this.es * Sin_p1 * Sin_p1); if (Cos_p1 >= Proj4js.common.COS_67P5) { Height = W / Cos_p1 - Rn; } else if (Cos_p1 <= -Proj4js.common.COS_67P5) { Height = W / -Cos_p1 - Rn; } else { Height = Z / Sin_p1 + Rn * (this.es - 1.0); } if (At_Pole == false) { Latitude = Math.atan(Sin_p1 / Cos_p1); } p.x = Longitude; p.y = Latitude; p.z = Height; return p; }, // geocentric_to_geodetic_noniter() /****************************************************************/ // pj_geocentic_to_wgs84( p ) // p = point to transform in geocentric coordinates (x,y,z) geocentric_to_wgs84 : function ( p ) { if( this.datum_type == Proj4js.common.PJD_3PARAM ) { // if( x[io] == HUGE_VAL ) // continue; p.x += this.datum_params[0]; p.y += this.datum_params[1]; p.z += this.datum_params[2]; } else if (this.datum_type == Proj4js.common.PJD_7PARAM) { var Dx_BF =this.datum_params[0]; var Dy_BF =this.datum_params[1]; var Dz_BF =this.datum_params[2]; var Rx_BF =this.datum_params[3]; var Ry_BF =this.datum_params[4]; var Rz_BF =this.datum_params[5]; var M_BF =this.datum_params[6]; // if( x[io] == HUGE_VAL ) // continue; var x_out = M_BF*( p.x - Rz_BF*p.y + Ry_BF*p.z) + Dx_BF; var y_out = M_BF*( Rz_BF*p.x + p.y - Rx_BF*p.z) + Dy_BF; var z_out = M_BF*(-Ry_BF*p.x + Rx_BF*p.y + p.z) + Dz_BF; p.x = x_out; p.y = y_out; p.z = z_out; } }, // cs_geocentric_to_wgs84 /****************************************************************/ // pj_geocentic_from_wgs84() // coordinate system definition, // point to transform in geocentric coordinates (x,y,z) geocentric_from_wgs84 : function( p ) { if( this.datum_type == Proj4js.common.PJD_3PARAM ) { //if( x[io] == HUGE_VAL ) // continue; p.x -= this.datum_params[0]; p.y -= this.datum_params[1]; p.z -= this.datum_params[2]; } else if (this.datum_type == Proj4js.common.PJD_7PARAM) { var Dx_BF =this.datum_params[0]; var Dy_BF =this.datum_params[1]; var Dz_BF =this.datum_params[2]; var Rx_BF =this.datum_params[3]; var Ry_BF =this.datum_params[4]; var Rz_BF =this.datum_params[5]; var M_BF =this.datum_params[6]; var x_tmp = (p.x - Dx_BF) / M_BF; var y_tmp = (p.y - Dy_BF) / M_BF; var z_tmp = (p.z - Dz_BF) / M_BF; //if( x[io] == HUGE_VAL ) // continue; p.x = x_tmp + Rz_BF*y_tmp - Ry_BF*z_tmp; p.y = -Rz_BF*x_tmp + y_tmp + Rx_BF*z_tmp; p.z = Ry_BF*x_tmp - Rx_BF*y_tmp + z_tmp; } //cs_geocentric_from_wgs84() } }); /** point object, nothing fancy, just allows values to be passed back and forth by reference rather than by value. Other point classes may be used as long as they have x and y properties, which will get modified in the transform method. */ Proj4js.Point = Proj4js.Class({ /** * Constructor! Proj4js.Point * * Parameters: * - x {float} or {Array} either the first coordinates component or * the full coordinates * - y {float} the second component * - z {float} the third component, optional. */ initialize : function(x,y,z) { if (typeof x == 'object') { this.x = x[0]; this.y = x[1]; this.z = x[2] || 0.0; } else if (typeof x == 'string') { var coords = x.split(','); this.x = parseFloat(coords[0]); this.y = parseFloat(coords[1]); this.z = parseFloat(coords[2]) || 0.0; } else { this.x = x; this.y = y; this.z = z || 0.0; } }, /** * APIMethod: clone * Build a copy of a Proj4js.Point object. * * Return: * {Proj4js}.Point the cloned point. */ clone : function() { return new Proj4js.Point(this.x, this.y, this.z); }, /** * APIMethod: toString * Return a readable string version of the point * * Return: * {String} String representation of Proj4js.Point object. * (ex. "x=5,y=42") */ toString : function() { return ("x=" + this.x + ",y=" + this.y); }, /** * APIMethod: toShortString * Return a short string version of the point. * * Return: * {String} Shortened String representation of Proj4js.Point object. * (ex. "5, 42") */ toShortString : function() { return (this.x + ", " + this.y); } }); Proj4js.PrimeMeridian = { "greenwich": 0.0, //"0dE", "lisbon": -9.131906111111, //"9d07'54.862\"W", "paris": 2.337229166667, //"2d20'14.025\"E", "bogota": -74.080916666667, //"74d04'51.3\"W", "madrid": -3.687938888889, //"3d41'16.58\"W", "rome": 12.452333333333, //"12d27'8.4\"E", "bern": 7.439583333333, //"7d26'22.5\"E", "jakarta": 106.807719444444, //"106d48'27.79\"E", "ferro": -17.666666666667, //"17d40'W", "brussels": 4.367975, //"4d22'4.71\"E", "stockholm": 18.058277777778, //"18d3'29.8\"E", "athens": 23.7163375, //"23d42'58.815\"E", "oslo": 10.722916666667 //"10d43'22.5\"E" }; Proj4js.Ellipsoid = { "MERIT": {a:6378137.0, rf:298.257, ellipseName:"MERIT 1983"}, "SGS85": {a:6378136.0, rf:298.257, ellipseName:"Soviet Geodetic System 85"}, "GRS80": {a:6378137.0, rf:298.257222101, ellipseName:"GRS 1980(IUGG, 1980)"}, "IAU76": {a:6378140.0, rf:298.257, ellipseName:"IAU 1976"}, "airy": {a:6377563.396, b:6356256.910, ellipseName:"Airy 1830"}, "APL4.": {a:6378137, rf:298.25, ellipseName:"Appl. Physics. 1965"}, "NWL9D": {a:6378145.0, rf:298.25, ellipseName:"Naval Weapons Lab., 1965"}, "mod_airy": {a:6377340.189, b:6356034.446, ellipseName:"Modified Airy"}, "andrae": {a:6377104.43, rf:300.0, ellipseName:"Andrae 1876 (Den., Iclnd.)"}, "aust_SA": {a:6378160.0, rf:298.25, ellipseName:"Australian Natl & S. Amer. 1969"}, "GRS67": {a:6378160.0, rf:298.2471674270, ellipseName:"GRS 67(IUGG 1967)"}, "bessel": {a:6377397.155, rf:299.1528128, ellipseName:"Bessel 1841"}, "bess_nam": {a:6377483.865, rf:299.1528128, ellipseName:"Bessel 1841 (Namibia)"}, "clrk66": {a:6378206.4, b:6356583.8, ellipseName:"Clarke 1866"}, "clrk80": {a:6378249.145, rf:293.4663, ellipseName:"Clarke 1880 mod."}, "CPM": {a:6375738.7, rf:334.29, ellipseName:"Comm. des Poids et Mesures 1799"}, "delmbr": {a:6376428.0, rf:311.5, ellipseName:"Delambre 1810 (Belgium)"}, "engelis": {a:6378136.05, rf:298.2566, ellipseName:"Engelis 1985"}, "evrst30": {a:6377276.345, rf:300.8017, ellipseName:"Everest 1830"}, "evrst48": {a:6377304.063, rf:300.8017, ellipseName:"Everest 1948"}, "evrst56": {a:6377301.243, rf:300.8017, ellipseName:"Everest 1956"}, "evrst69": {a:6377295.664, rf:300.8017, ellipseName:"Everest 1969"}, "evrstSS": {a:6377298.556, rf:300.8017, ellipseName:"Everest (Sabah & Sarawak)"}, "fschr60": {a:6378166.0, rf:298.3, ellipseName:"Fischer (Mercury Datum) 1960"}, "fschr60m": {a:6378155.0, rf:298.3, ellipseName:"Fischer 1960"}, "fschr68": {a:6378150.0, rf:298.3, ellipseName:"Fischer 1968"}, "helmert": {a:6378200.0, rf:298.3, ellipseName:"Helmert 1906"}, "hough": {a:6378270.0, rf:297.0, ellipseName:"Hough"}, "intl": {a:6378388.0, rf:297.0, ellipseName:"International 1909 (Hayford)"}, "kaula": {a:6378163.0, rf:298.24, ellipseName:"Kaula 1961"}, "lerch": {a:6378139.0, rf:298.257, ellipseName:"Lerch 1979"}, "mprts": {a:6397300.0, rf:191.0, ellipseName:"Maupertius 1738"}, "new_intl": {a:6378157.5, b:6356772.2, ellipseName:"New International 1967"}, "plessis": {a:6376523.0, rf:6355863.0, ellipseName:"Plessis 1817 (France)"}, "krass": {a:6378245.0, rf:298.3, ellipseName:"Krassovsky, 1942"}, "SEasia": {a:6378155.0, b:6356773.3205, ellipseName:"Southeast Asia"}, "walbeck": {a:6376896.0, b:6355834.8467, ellipseName:"Walbeck"}, "WGS60": {a:6378165.0, rf:298.3, ellipseName:"WGS 60"}, "WGS66": {a:6378145.0, rf:298.25, ellipseName:"WGS 66"}, "WGS72": {a:6378135.0, rf:298.26, ellipseName:"WGS 72"}, "WGS84": {a:6378137.0, rf:298.257223563, ellipseName:"WGS 84"}, "sphere": {a:6370997.0, b:6370997.0, ellipseName:"Normal Sphere (r=6370997)"} }; Proj4js.Datum = { "WGS84": {towgs84: "0,0,0", ellipse: "WGS84", datumName: "WGS84"}, "GGRS87": {towgs84: "-199.87,74.79,246.62", ellipse: "GRS80", datumName: "Greek_Geodetic_Reference_System_1987"}, "NAD83": {towgs84: "0,0,0", ellipse: "GRS80", datumName: "North_American_Datum_1983"}, "NAD27": {nadgrids: "@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat", ellipse: "clrk66", datumName: "North_American_Datum_1927"}, "potsdam": {towgs84: "606.0,23.0,413.0", ellipse: "bessel", datumName: "Potsdam Rauenberg 1950 DHDN"}, "carthage": {towgs84: "-263.0,6.0,431.0", ellipse: "clark80", datumName: "Carthage 1934 Tunisia"}, "hermannskogel": {towgs84: "653.0,-212.0,449.0", ellipse: "bessel", datumName: "Hermannskogel"}, "ire65": {towgs84: "482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15", ellipse: "mod_airy", datumName: "Ireland 1965"}, "nzgd49": {towgs84: "59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993", ellipse: "intl", datumName: "New Zealand Geodetic Datum 1949"}, "OSGB36": {towgs84: "446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894", ellipse: "airy", datumName: "Airy 1830"} }; Proj4js.WGS84 = new Proj4js.Proj('WGS84'); Proj4js.Datum['OSB36'] = Proj4js.Datum['OSGB36']; //as returned from spatialreference.org Proj4js.Proj.gauss = { init : function() { sphi = Math.sin(this.lat0); cphi = Math.cos(this.lat0); cphi *= cphi; this.rc = Math.sqrt(1.0 - this.es) / (1.0 - this.es * sphi * sphi); this.C = Math.sqrt(1.0 + this.es * cphi * cphi / (1.0 - this.es)); this.phic0 = Math.asin(sphi / this.C); this.ratexp = 0.5 * this.C * this.e; this.K = Math.tan(0.5 * this.phic0 + Proj4js.common.FORTPI) / (Math.pow(Math.tan(0.5*this.lat0 + Proj4js.common.FORTPI), this.C) * Proj4js.common.srat(this.e*sphi, this.ratexp)); }, forward : function(p) { var lon = p.x; var lat = p.y; p.y = 2.0 * Math.atan( this.K * Math.pow(Math.tan(0.5 * lat + Proj4js.common.FORTPI), this.C) * Proj4js.common.srat(this.e * Math.sin(lat), this.ratexp) ) - Proj4js.common.HALF_PI; p.x = this.C * lon; return p; }, inverse : function(p) { var DEL_TOL = 1e-14; var lon = p.x / this.C; var lat = p.y; num = Math.pow(Math.tan(0.5 * lat + Proj4js.common.FORTPI)/this.K, 1./this.C); for (var i = Proj4js.common.MAX_ITER; i>0; --i) { lat = 2.0 * Math.atan(num * Proj4js.common.srat(this.e * Math.sin(p.y), -0.5 * this.e)) - Proj4js.common.HALF_PI; if (Math.abs(lat - p.y) < DEL_TOL) break; p.y = lat; } /* convergence failed */ if (!i) { Proj4js.reportError("gauss:inverse:convergence failed"); return null; } p.x = lon; p.y = lat; return p; } }; Proj4js.Proj.sterea = { dependsOn : 'gauss', init : function() { Proj4js.Proj['gauss'].init.apply(this); if (!this.rc) { Proj4js.reportError("sterea:init:E_ERROR_0"); return; } this.sinc0 = Math.sin(this.phic0); this.cosc0 = Math.cos(this.phic0); this.R2 = 2.0 * this.rc; if (!this.title) this.title = "Oblique Stereographic Alternative"; }, forward : function(p) { p.x = Proj4js.common.adjust_lon(p.x-this.long0); /* adjust del longitude */ Proj4js.Proj['gauss'].forward.apply(this, [p]); sinc = Math.sin(p.y); cosc = Math.cos(p.y); cosl = Math.cos(p.x); k = this.k0 * this.R2 / (1.0 + this.sinc0 * sinc + this.cosc0 * cosc * cosl); p.x = k * cosc * Math.sin(p.x); p.y = k * (this.cosc0 * sinc - this.sinc0 * cosc * cosl); p.x = this.a * p.x + this.x0; p.y = this.a * p.y + this.y0; return p; }, inverse : function(p) { var lon,lat; p.x = (p.x - this.x0) / this.a; /* descale and de-offset */ p.y = (p.y - this.y0) / this.a; p.x /= this.k0; p.y /= this.k0; if ( (rho = Math.sqrt(p.x*p.x + p.y*p.y)) ) { c = 2.0 * Math.atan2(rho, this.R2); sinc = Math.sin(c); cosc = Math.cos(c); lat = Math.asin(cosc * this.sinc0 + p.y * sinc * this.cosc0 / rho); lon = Math.atan2(p.x * sinc, rho * this.cosc0 * cosc - p.y * this.sinc0 * sinc); } else { lat = this.phic0; lon = 0.; } p.x = lon; p.y = lat; Proj4js.Proj['gauss'].inverse.apply(this,[p]); p.x = Proj4js.common.adjust_lon(p.x + this.long0); /* adjust longitude to CM */ return p; } }; /******************************************************************************* NAME TRANSVERSE MERCATOR PURPOSE: Transforms input longitude and latitude to Easting and Northing for the Transverse Mercator projection. The longitude and latitude must be in radians. The Easting and Northing values will be returned in meters. ALGORITHM REFERENCES 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United State Government Printing Office, Washington D.C., 1987. 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections", U.S. Geological Survey Professional Paper 1453 , United State Government Printing Office, Washington D.C., 1989. *******************************************************************************/ /** Initialize Transverse Mercator projection */ Proj4js.Proj.tmerc = { init : function() { this.e0 = Proj4js.common.e0fn(this.es); this.e1 = Proj4js.common.e1fn(this.es); this.e2 = Proj4js.common.e2fn(this.es); this.e3 = Proj4js.common.e3fn(this.es); this.ml0 = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, this.lat0); }, /** Transverse Mercator Forward - long/lat to x/y long/lat in radians */ forward : function(p) { var lon = p.x; var lat = p.y; var delta_lon = Proj4js.common.adjust_lon(lon - this.long0); // Delta longitude var con; // cone constant var x, y; var sin_phi=Math.sin(lat); var cos_phi=Math.cos(lat); if (this.sphere) { /* spherical form */ var b = cos_phi * Math.sin(delta_lon); if ((Math.abs(Math.abs(b) - 1.0)) < .0000000001) { Proj4js.reportError("tmerc:forward: Point projects into infinity"); return(93); } else { x = .5 * this.a * this.k0 * Math.log((1.0 + b)/(1.0 - b)); con = Math.acos(cos_phi * Math.cos(delta_lon)/Math.sqrt(1.0 - b*b)); if (lat < 0) con = - con; y = this.a * this.k0 * (con - this.lat0); } } else { var al = cos_phi * delta_lon; var als = Math.pow(al,2); var c = this.ep2 * Math.pow(cos_phi,2); var tq = Math.tan(lat); var t = Math.pow(tq,2); con = 1.0 - this.es * Math.pow(sin_phi,2); var n = this.a / Math.sqrt(con); var ml = this.a * Proj4js.common.mlfn(this.e0, this.e1, this.e2, this.e3, lat); x = this.k0 * n * al * (1.0 + als / 6.0 * (1.0 - t + c + als / 20.0 * (5.0 - 18.0 * t + Math.pow(t,2) + 72.0 * c - 58.0 * this.ep2))) + this.x0; y = this.k0 * (ml - this.ml0 + n * tq * (als * (0.5 + als / 24.0 * (5.0 - t + 9.0 * c + 4.0 * Math.pow(c,2) + als / 30.0 * (61.0 - 58.0 * t + Math.pow(t,2) + 600.0 * c - 330.0 * this.ep2))))) + this.y0; } p.x = x; p.y = y; return p; }, // tmercFwd() /** Transverse Mercator Inverse - x/y to long/lat */ inverse : function(p) { var con, phi; /* temporary angles */ var delta_phi; /* difference between longitudes */ var i; var max_iter = 6; /* maximun number of iterations */ var lat, lon; if (this.sphere) { /* spherical form */ var f = Math.exp(p.x/(this.a * this.k0)); var g = .5 * (f - 1/f); var temp = this.lat0 + p.y/(this.a * this.k0); var h = Math.cos(temp); con = Math.sqrt((1.0 - h * h)/(1.0 + g * g)); lat = Math.asinz(con); if (temp < 0) lat = -lat; if ((g == 0) && (h == 0)) { lon = this.long0; } else { lon = Proj4js.common.adjust_lon(Math.atan2(g,h) + this.long0); } } else { // ellipsoidal form var x = p.x - this.x0; var y = p.y - this.y0; con = (this.ml0 + y / this.k0) / this.a; phi = con; for (i=0;;i++) { delta_phi=((con + this.e1 * Math.sin(2.0*phi) - this.e2 * Math.sin(4.0*phi) + this.e3 * Math.sin(6.0*phi)) / this.e0) - phi; phi += delta_phi; if (Math.abs(delta_phi) <= Proj4js.common.EPSLN) break; if (i >= max_iter) { Proj4js.reportError("tmerc:inverse: Latitude failed to converge"); return(95); } } // for() if (Math.abs(phi) < Proj4js.common.HALF_PI) { // sincos(phi, &sin_phi, &cos_phi); var sin_phi=Math.sin(phi); var cos_phi=Math.cos(phi); var tan_phi = Math.tan(phi); var c = this.ep2 * Math.pow(cos_phi,2); var cs = Math.pow(c,2); var t = Math.pow(tan_phi,2); var ts = Math.pow(t,2); con = 1.0 - this.es * Math.pow(sin_phi,2); var n = this.a / Math.sqrt(con); var r = n * (1.0 - this.es) / con; var d = x / (n * this.k0); var ds = Math.pow(d,2); lat = phi - (n * tan_phi * ds / r) * (0.5 - ds / 24.0 * (5.0 + 3.0 * t + 10.0 * c - 4.0 * cs - 9.0 * this.ep2 - ds / 30.0 * (61.0 + 90.0 * t + 298.0 * c + 45.0 * ts - 252.0 * this.ep2 - 3.0 * cs))); lon = Proj4js.common.adjust_lon(this.long0 + (d * (1.0 - ds / 6.0 * (1.0 + 2.0 * t + c - ds / 20.0 * (5.0 - 2.0 * c + 28.0 * t - 3.0 * cs + 8.0 * this.ep2 + 24.0 * ts))) / cos_phi)); } else { lat = Proj4js.common.HALF_PI * Proj4js.common.sign(y); lon = this.long0; } } p.x = lon; p.y = lat; return p; } // tmercInv() };//source http://www.javascriptkit.com/javatutors/loadjavascriptcss.shtml function loadjscssfile(filename, filetype){ if (filetype=="js"){ //if filename is a external JavaScript file var fileref=document.createElement('script') fileref.setAttribute("type","text/javascript") fileref.setAttribute("src", filename) } else if (filetype=="css"){ //if filename is an external CSS file var fileref=document.createElement("link") fileref.setAttribute("rel", "stylesheet") fileref.setAttribute("type", "text/css") fileref.setAttribute("href", filename) } if (typeof fileref!="undefined") document.getElementsByTagName("head")[0].appendChild(fileref) } /* balloon.js -- a DHTML library for balloon tooltips $Id: balloon.js,v 1.20 2008/05/08 03:13:09 sheldon_mckay Exp $ See http://www.gmod.org/wiki/index.php/Popup_Balloons for documentation. Copyright (c) 2007 Sheldon McKay, Cold Spring Harbor Laboratory This balloon tooltip package and associated files not otherwise copyrighted are distributed under the MIT-style license: http://opensource.org/licenses/mit-license.php Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. If publications result from research using this SOFTWARE, we ask that CSHL and the author be acknowledged as scientifically appropriate. */ // These global variables are necessary to avoid losing scope when //setting the balloon timeout and for inter-object communication var currentBalloonClass; var balloonIsVisible; var balloonIsSticky; var balloonInvisibleSelects; var balloonIsSuppressed; var tooltipIsSuppressed; /////////////////////////////////////////////////// // Constructor for Balloon class // // Balloon configuration // // Reset these values for custom balloon designs // /////////////////////////////////////////////////// var Balloon = function() { // handler wywolywany po utworzeniu balloona this.afterBalloonCreate = function(){return false}; this.afterSetContents = function(){return false}; this.showLoading = false; // Location of optional ajax handler that returns tooltip contents this.helpUrl = null; this.posX = 0; this.posY = 0; this.eventElement = null; this.url = ''; // maxium allowed balloon width (px) this.minWidth = 150; // minimum allowed balloon width (px) this.maxWidth = 600; // maxium allowed balloon width (px) this.minHeight = 150; // minimum allowed balloon width (px) this.maxHeight = 600; // Default tooltip text size this.balloonTextSize = '90%'; // Delay before balloon is displayed (msec) this.delayTime = 500; // If fade-in/out is allowed this.allowFade = false; // time interval for fade-in (msec) this.fadeIn = 300; // time interval for fade-out (msec) this.fadeOut = 300; // Vertical Distance from cursor location (px) this.vOffset = 0; // text-padding within the balloon (px) this.padding = 10; // How long to display mousover balloons (msec) // false = 'always on' this.displayTime = 10000; // width of shadow (space aroung whole balloon; px) // This can be zero if there is no shadow and the // edges of the balloon are also the edges of the image this.shadow = 20; // whether the balloon should have a stem this.stem = true; // The height (px) of the stem and the extent to which the // stem image should overlaps the balloon image. this.stemHeight = 32; this.stemOverlap = 3; // track the cursor every time the mouse moves document.onmousemove = this.setActiveCoordinates; // scrolling aborts unsticky balloons document.onscroll = Balloon.prototype.hideTooltip; // make balloons go away if the page is unloading or waiting // to unload. window.onbeforeunload = function(){ Balloon.prototype.hideTooltip(1); balloonIsSuppressed = true; }; if (this.isIE()) { this.suppress = true; } } ////////////////////////////////////////////////////////////////////////// // This is the function that is called on mouseover. It has a built-in // // delay time to avoid balloons popping up on rapid mouseover events // ////////////////////////////////////////////////////////////////////////// Balloon.prototype.showTooltip = function(args) { this.posX = args.posX; this.posY = args.posY; this.imagesPath = args.imagesPath; this.showLoading = args.showLoading; // images of balloon body. If the browser is IE < 7, png alpha // channels will not work. An optional alternative image can be // provided. It should have the same dimensions as the default png image this.balloonImage = this.imagesPath + '/balloon.png'; // with alpha channels this.ieImage = this.imagesPath + '/balloon_ie.png'; // indexed color, transparent background // A stem for each of the four orientations this.upLeftStem = this.imagesPath + '/up_left.png'; this.downLeftStem = this.imagesPath + '/down_left.png'; this.upRightStem = this.imagesPath + '/up_right.png'; this.downRightStem = this.imagesPath + '/down_right.png'; // A close button for sticky balloons this.closeButton = this.imagesPath + '/close.png'; this.newWindowButton = this.imagesPath + '/new_window.png'; this.eventElement = args.eventElement; // Awful IE bug, page load aborts if the balloon is fired // before the page is fully loaded. if (this.isIE() && document.readyState.match(/complete/i)) { this.suppress = false; } // All balloons have been suppressed, go no further // if (this.suppress || balloonIsSuppressed) { // return false; // } // Non-sticky balloons suppressed if (tooltipIsSuppressed && !args.sticky) { return false; } // Sorry Konqueror, no fade-in for you! if (this.isKonqueror()) this.allowFade = false; // Check for mouseover (vs. mousedown or click) //var mouseOver = evt.type.match('mouseover','i'); var mouseOver = 0; // if the firing event is a click, fade-in and a non-sticky balloon make no sense if (!mouseOver) { args.sticky = true; this.fadeOK = false; } else { this.fadeOK = this.allowFade; } // Don't fire on mouseover if a non-sticky balloon is visible if (balloonIsVisible && !balloonIsSticky && mouseOver) return false; // Don't start a non-sticky balloon if a sticky one is visible if (balloonIsVisible && balloonIsSticky && !args.sticky) return false; // Ignore repeated firing of mouseover->mouseout events on // the same element (Safari) var el = this.getEventTarget(); if (args.sticky && mouseOver && this.isSameElement(el,this.currentElement)) return false; this.firingElement = el; // A new sticky balloon can erase an old one if (args.sticky) this.hideTooltip(1); // attach a mouseout event handler to the target element var closeBalloon = function() { var override = balloonIsSticky && !balloonIsVisible; Balloon.prototype.hideTooltip(override) } if (!mouseOver) el.onmouseup = function() {return false}; el.onmouseout = closeBalloon; balloonIsSticky = args.sticky; // force balloon width and/or height if requested this.width = args.width; this.height = args.height; this.hideTooltip(); // if this is IE < 7 use an alternative image id provided if (this.isOldIE() && this.ieImage) { this.balloonImage = this.ieImage; this.ieImage = null; } // look for a url in the balloon contents if (args.caption.match(/^url:/)) { var urlArray = args.caption.split(':'); args.caption = ''; this.activeUrl = urlArray[1]; } // or if the contents are to be retrieved from an element else if (args.caption.match(/^load:/)) { var load = args.caption.split(':'); if (!document.getElementById(load[1])) alert ('problem locating element '+load[1]); args.caption = document.getElementById(load[1]).innerHTML; this.loadedFromElement = true; } // or if the text is a bare hyperlink else if (args.caption.match(/^(https?:|\/|ftp:)\S+$/i)) { this.activeUrl = args.caption; args.caption = ''; } // request the contents synchronously (ie wait for result) this.currentHelpText = this.getContents(args.caption); this.loadedFromElement = false; // Put the balloon contents and images into a visible (but offscreen) // element so they will be preloaded and have a layout to // calculate the balloon dimensions if (!this.container) { this.container = document.createElement('div'); document.body.appendChild(this.container); this.setStyle(this.container,'position','absolute'); this.setStyle(this.container,'top',-8888); this.setStyle(this.container,'display','inline'); } else { this.setStyle(this.container,'display','inline'); } // this.container.innerHTML = unescape(this.currentHelpText); this.container.innerHTML = this.currentHelpText; // Also preload the balloon images if (!this.images) { this.images = document.createElement('div'); document.body.appendChild(this.images); this.setStyle(this.images,'position','absolute'); this.setStyle(this.images,'top',-8888); this.setStyle(this.images,'display','inline'); if (this.upLeftStem) this.images.innerHTML = ''; if (this.upRightStem) this.images.innerHTML += ''; if (this.downLeftStem) this.images.innerHTML += ''; if (this.downRightStem) this.images.innerHTML += ''; this.images.innerHTML += ''; this.images.innerHTML += ''; this.images.innerHTML += ''; } else { this.setStyle(this.images,'display','none'); } currentBalloonClass = this; // Capture coordinates for mousedown or click if (!mouseOver) this.setActiveCoordinates(); // make delay time short for onmousedown var delay = mouseOver ? this.delayTime : 1; this.timeoutTooltip = window.setTimeout(this.doShowTooltip,delay); } ///////////////////////////////////////////////////////////////////// // Tooltip rendering function ///////////////////////////////////////////////////////////////////// Balloon.prototype.doShowTooltip = function() { var self = currentBalloonClass; // Stop firing if a balloon is already being displayed if (balloonIsVisible) return false; // a short delay time might cause some intereference // with fade-out window.clearTimeout(self.timeoutFade); self.setStyle('balloon','display','none'); // make sure user-configured numbers are not strings self.parseIntAll(); // create the balloon object var balloon = self.makeBalloon(); // window dimensions var pageWidth = YAHOO.util.Dom.getViewportWidth(); var pageCen = Math.round(pageWidth/2); var pageHeight = YAHOO.util.Dom.getViewportHeight(); var pageLeft = YAHOO.util.Dom.getDocumentScrollLeft(); var pageTop = YAHOO.util.Dom.getDocumentScrollTop(); var pageMid = pageTop + Math.round(pageHeight/2); // balloon orientation var vOrient = self.activeTop > pageMid ? 'up' : 'down'; var hOrient = self.activeRight > pageCen ? 'left' : 'right'; // get the preloaded balloon contents var helpText = self.container.innerHTML; self.contents.innerHTML = '
' + helpText + '
'; // how and where to draw the balloon self.setBalloonStyle(vOrient,hOrient,pageWidth,pageLeft); // sticky balloons need a close control if (balloonIsSticky) { var topRight = document.getElementById('topRight'); var margin = Math.round(self.padding/2); var top = margin + self.shadow + 2; var marginLeft = 20 - margin; topRight.innerHTML = '\ '; /* top = top + 16; topRight.innerHTML += '\ '; */ } balloonIsVisible = true; // in IE < 7, hide